Skip to content

Commit a19ca32

Browse files
committed
merge(core-math-canonical-zero←main): resolve docs guard conflicts; keep 2025-10-29 geom fat-AABB intent and 2025-10-28 math PR #13 entry
2 parents ab46f7a + 75261ee commit a19ca32

File tree

123 files changed

+5988
-113
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

123 files changed

+5988
-113
lines changed

.devcontainer/devcontainer.json

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
{
2+
"name": "echo-dev",
3+
"image": "mcr.microsoft.com/devcontainers/base:ubuntu-24.04",
4+
"features": {
5+
"ghcr.io/devcontainers/features/common-utils:2": {
6+
"username": "vscode",
7+
"installZsh": false
8+
},
9+
"ghcr.io/devcontainers/features/rust:1": {
10+
"profile": "minimal",
11+
"components": ["rustfmt", "clippy"]
12+
},
13+
"ghcr.io/devcontainers/features/node:1": {
14+
"version": "20"
15+
},
16+
"ghcr.io/devcontainers/features/github-cli:1": {}
17+
},
18+
"customizations": {
19+
"vscode": {
20+
"extensions": [
21+
"rust-lang.rust-analyzer",
22+
"serayuzgur.crates",
23+
"tamasfe.even-better-toml",
24+
"vadimcn.vscode-lldb"
25+
]
26+
}
27+
},
28+
"mounts": [
29+
"source=devcontainer-cargo-cache,target=/usr/local/cargo,type=volume",
30+
"source=devcontainer-rustup-cache,target=/usr/local/rustup,type=volume"
31+
],
32+
"containerEnv": {
33+
"CARGO_TERM_COLOR": "always"
34+
},
35+
"overrideCommand": false,
36+
"postCreateCommand": "/bin/bash .devcontainer/post-create.sh"
37+
}

.devcontainer/post-create.sh

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
#!/usr/bin/env bash
2+
set -euo pipefail
3+
4+
echo "[devcontainer] Installing default toolchain (1.71.1 via rust-toolchain.toml)..."
5+
if ! command -v rustup >/dev/null 2>&1; then
6+
curl --proto '=https' --tlsv1.2 --retry 10 --retry-connrefused --location --silent --show-error --fail https://sh.rustup.rs | sh -s -- --default-toolchain none -y
7+
export PATH="$HOME/.cargo/bin:$PATH"
8+
fi
9+
10+
rustup toolchain install 1.71.1 --profile minimal
11+
# Do not override default; let rust-toolchain.toml control selection for this repo.
12+
# Ensure components/targets are available for the default toolchain (1.71.1).
13+
rustup component add --toolchain 1.71.1 rustfmt clippy || true
14+
rustup target add --toolchain 1.71.1 wasm32-unknown-unknown || true
15+
16+
echo "[devcontainer] Priming cargo registry cache (optional)..."
17+
cargo fetch || true
18+
19+
echo "[devcontainer] Done. Run 'cargo test -p rmg-core' or 'make ci-local' to validate."

.editorconfig

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
root = true
2+
3+
[*]
4+
charset = utf-8
5+
end_of_line = lf
6+
insert_final_newline = true
7+
trim_trailing_whitespace = true
8+
indent_style = space
9+
indent_size = 4
10+
11+
[*.{md,mdx}]
12+
trim_trailing_whitespace = false
13+
14+
[*.{ts,tsx,js,json}]
15+
indent_size = 2
16+

.githooks/commit-msg

100644100755
File mode changed.

.githooks/pre-commit

100644100755
Lines changed: 34 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#!/usr/bin/env bash
22
set -euo pipefail
33

4+
45
if [[ "${SKIP_HOOKS:-}" == 1 ]]; then
56
exit 0
67
fi
@@ -49,8 +50,27 @@ if command -v rustup >/dev/null 2>&1; then
4950
fi
5051
fi
5152

52-
# 3) Format check (fast)
53-
cargo fmt --all -- --check
53+
# 3) Format (auto-fix if opted in)
54+
_auto_fmt="${ECHO_AUTO_FMT:-1}"
55+
case "${_auto_fmt}" in
56+
1|true|TRUE|yes|YES|on|ON)
57+
echo "pre-commit: ECHO_AUTO_FMT=${_auto_fmt} → running cargo fmt (auto-fix)"
58+
cargo fmt --all || { echo "pre-commit: cargo fmt failed" >&2; exit 1; }
59+
# Re-stage only staged files that were reformatted
60+
if STAGED=$(git diff --cached --name-only); then
61+
if [[ -n "$STAGED" ]]; then
62+
echo "$STAGED" | xargs -r git add --
63+
fi
64+
fi
65+
;;
66+
0|false|FALSE|no|NO|off|OFF)
67+
cargo fmt --all -- --check || { echo "pre-commit: cargo fmt check failed" >&2; exit 1; }
68+
;;
69+
*)
70+
# Unknown value → safest is check-only
71+
cargo fmt --all -- --check || { echo "pre-commit: cargo fmt check failed" >&2; exit 1; }
72+
;;
73+
esac
5474

5575
# 4) Docs guard (scaled): only require docs when core public API changed
5676
STAGED=$(git diff --cached --name-only)
@@ -60,12 +80,19 @@ if [[ -n "$CORE_API_CHANGED" ]]; then
6080
echo "$STAGED" | grep -Fx 'docs/decision-log.md' >/dev/null || { echo 'pre-commit: docs/decision-log.md must be updated when core API changes.' >&2; exit 1; }
6181
fi
6282

63-
# 5) Lockfile guard: ensure lockfile version is v3 (compatible with MSRV cargo)
83+
# 5) Lockfile guard: ensure lockfile version is v3 (current cargo format)
6484
if [[ -f Cargo.lock ]]; then
65-
VER_LINE=$(grep -n '^version = ' Cargo.lock | head -n1 | awk -F'= ' '{print $2}')
66-
if [[ "$VER_LINE" != "3" && "$VER_LINE" != "3\r" ]]; then
67-
echo "pre-commit: Cargo.lock must be generated with Cargo 1.68 (lockfile v3)." >&2
68-
echo "Run: cargo +1.68.0 generate-lockfile" >&2
85+
# Normalize detected lockfile version (strip quotes/CR/whitespace)
86+
VER_LINE=$(grep -n '^version = ' Cargo.lock | head -n1 | awk -F'= ' '{print $2}' | tr -d '\r' | tr -d '"' | xargs)
87+
if [[ "$VER_LINE" != "3" ]]; then
88+
# Determine pinned toolchain (normalize), fallback to rust-toolchain.toml if unset
89+
_PINNED_RAW="${PINNED:-}"
90+
if [[ -z "$_PINNED_RAW" ]]; then
91+
_PINNED_RAW=$(awk -F '"' '/^channel/ {print $2}' rust-toolchain.toml 2>/dev/null || echo "")
92+
fi
93+
PINNED_NORM=$(printf "%s" "$_PINNED_RAW" | tr -d '\r' | xargs)
94+
echo "pre-commit: Cargo.lock must be lockfile format v3 (found '$VER_LINE')." >&2
95+
echo "Run: cargo +${PINNED_NORM} generate-lockfile" >&2
6996
exit 1
7097
fi
7198
fi

.githooks/pre-push

100644100755
Lines changed: 62 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
#!/usr/bin/env bash
22
set -euo pipefail
3-
PINNED="${PINNED:-1.68.0}"
3+
PINNED="${PINNED:-1.71.1}"
4+
# MSRV floor for library checks (override with MSRV env)
5+
MSRV="${MSRV:-1.71.1}"
46

57
for cmd in cargo rustup rg; do
68
if ! command -v "$cmd" >/dev/null 2>&1; then
@@ -15,34 +17,76 @@ if [[ "${SKIP_HOOKS:-}" == 1 ]]; then
1517
exit 0
1618
fi
1719

18-
echo "[pre-push] fmt"
19-
cargo +"$PINNED" fmt --all -- --check
20+
echo "[pre-push] fmt (default toolchain)"
21+
cargo fmt --all -- --check
2022

21-
echo "[pre-push] clippy (workspace)"
22-
cargo +"$PINNED" clippy --all-targets -- -D warnings -D missing_docs
23+
echo "[pre-push] clippy (workspace, default toolchain)"
24+
cargo clippy --all-targets -- -D warnings -D missing_docs
2325

24-
echo "[pre-push] tests (workspace)"
25-
cargo +"$PINNED" test --workspace
26+
echo "[pre-push] tests (workspace, default toolchain)"
27+
cargo test --workspace
2628

27-
# MSRV check for rmg-core
28-
echo "[pre-push] MSRV check (rmg-core @ $PINNED)"
29-
if rustup run "$PINNED" cargo -V >/dev/null 2>&1; then
30-
cargo +"$PINNED" check -p rmg-core --all-targets
29+
echo "[pre-push] Testing against MSRV ${MSRV} (core libraries)"
30+
# If any participating crate declares a rust-version greater than MSRV, skip MSRV checks entirely.
31+
CORE_RV=$(awk -F '"' '/^rust-version/ {print $2}' crates/rmg-core/Cargo.toml 2>/dev/null || echo "")
32+
GEOM_RV=$(awk -F '"' '/^rust-version/ {print $2}' crates/rmg-geom/Cargo.toml 2>/dev/null || echo "")
33+
if { [[ -n "$CORE_RV" ]] && printf '%s\n%s\n' "$MSRV" "$CORE_RV" | sort -V | tail -n1 | grep -qx "$CORE_RV" && [[ "$CORE_RV" != "$MSRV" ]]; } \
34+
|| { [[ -n "$GEOM_RV" ]] && printf '%s\n%s\n' "$MSRV" "$GEOM_RV" | sort -V | tail -n1 | grep -qx "$GEOM_RV" && [[ "$GEOM_RV" != "$MSRV" ]]; }; then
35+
echo "[pre-push] Skipping MSRV block: one or more crates declare rust-version > ${MSRV} (core=${CORE_RV:-unset}, geom=${GEOM_RV:-unset})"
3136
else
32-
echo "[pre-push] MSRV toolchain $PINNED not installed. Install via: rustup toolchain install $PINNED" >&2
33-
exit 1
37+
if ! rustup run "$MSRV" cargo -V >/dev/null 2>&1; then
38+
echo "[pre-push] MSRV toolchain ${MSRV} not installed. Install via: rustup toolchain install ${MSRV}" >&2
39+
exit 1
40+
fi
41+
# Only run MSRV tests for crates that declare rust-version <= MSRV; skip otherwise.
42+
msrv_ok() {
43+
local crate="$1"
44+
local rv
45+
rv=$(awk -F '"' '/^rust-version/ {print $2}' "crates/${crate}/Cargo.toml" 2>/dev/null || echo "")
46+
if [[ -z "$rv" ]]; then
47+
return 0
48+
fi
49+
# If declared rust-version is greater than MSRV, skip.
50+
if printf '%s\n%s\n' "$MSRV" "$rv" | sort -V | tail -n1 | grep -qx "$rv" && [[ "$rv" != "$MSRV" ]]; then
51+
echo "[pre-push] Skipping MSRV test for ${crate} (rust-version ${rv} > MSRV ${MSRV})"
52+
return 1
53+
fi
54+
# If crate depends on workspace rmg-core whose rust-version exceeds MSRV, skip as well
55+
if grep -qE '^rmg-core\s*=\s*\{[^}]*path\s*=\s*"\.\./rmg-core"' "crates/${crate}/Cargo.toml" 2>/dev/null; then
56+
local core_rv
57+
core_rv=$(awk -F '"' '/^rust-version/ {print $2}' "crates/rmg-core/Cargo.toml" 2>/dev/null || echo "")
58+
if [[ -n "$core_rv" ]] && printf '%s\n%s\n' "$MSRV" "$core_rv" | sort -V | tail -n1 | grep -qx "$core_rv" && [[ "$core_rv" != "$MSRV" ]]; then
59+
echo "[pre-push] Skipping MSRV test for ${crate} (depends on rmg-core ${core_rv} > MSRV ${MSRV})"
60+
return 1
61+
fi
62+
fi
63+
return 0
64+
}
65+
if msrv_ok rmg-core; then cargo +"$MSRV" test -p rmg-core --all-targets; fi
66+
if msrv_ok rmg-geom; then cargo +"$MSRV" test -p rmg-geom --all-targets; fi
3467
fi
3568

36-
# Rustdoc warnings guard (core API)
37-
echo "[pre-push] rustdoc warnings gate (rmg-core)"
69+
# Rustdoc warnings guard (public crates)
70+
echo "[pre-push] rustdoc warnings gate (rmg-core @ $PINNED)"
3871
RUSTDOCFLAGS="-D warnings" cargo +"$PINNED" doc -p rmg-core --no-deps
72+
echo "[pre-push] rustdoc warnings gate (rmg-geom @ $PINNED)"
73+
RUSTDOCFLAGS="-D warnings" cargo +"$PINNED" doc -p rmg-geom --no-deps
3974

4075
# Banned patterns
4176
echo "[pre-push] scanning banned patterns"
42-
# Match any crate-level allow(...) that includes missing_docs; exclude telemetry.rs explicitly
43-
if rg -n '#!\[allow\([^]]*missing_docs[^]]*\)\]' --glob '!crates/rmg-core/src/telemetry.rs' crates >/dev/null; then
77+
# Forbid crate-level allow(missing_docs) in library source files, but allow in tests and build scripts
78+
if rg -n '#!\[allow\([^]]*missing_docs[^]]*\)\]' \
79+
crates \
80+
--glob 'crates/**/src/**/*.rs' \
81+
--glob '!**/telemetry.rs' \
82+
--glob '!**/tests/**' \
83+
--glob '!**/build.rs' >/dev/null; then
4484
echo "pre-push: crate-level allow(missing_docs) is forbidden (except telemetry.rs)." >&2
45-
rg -n '#!\[allow\([^]]*missing_docs[^]]*\)\]' --glob '!crates/rmg-core/src/telemetry.rs' crates | cat >&2 || true
85+
rg -n '#!\[allow\([^]]*missing_docs[^]]*\)\]' crates \
86+
--glob 'crates/**/src/**/*.rs' \
87+
--glob '!**/telemetry.rs' \
88+
--glob '!**/tests/**' \
89+
--glob '!**/build.rs' | cat >&2 || true
4690
exit 1
4791
fi
4892
if rg -n "\#\[unsafe\(no_mangle\)\]" crates >/dev/null; then

.githooks/pre-rebase

100644100755
File mode changed.

.github/workflows/ci.yml

Lines changed: 6 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,7 @@ jobs:
1515
- uses: actions/checkout@v4
1616
with:
1717
submodules: false
18-
- uses: dtolnay/rust-toolchain@stable
19-
with:
20-
toolchain: stable
21-
override: true
18+
- uses: dtolnay/rust-toolchain@1.71.1
2219
- uses: Swatinem/rust-cache@v2
2320
with:
2421
workspaces: |
@@ -33,19 +30,14 @@ jobs:
3330
- uses: actions/checkout@v4
3431
with:
3532
submodules: false
36-
- uses: dtolnay/rust-toolchain@stable
33+
- uses: dtolnay/rust-toolchain@1.71.1
3734
with:
38-
toolchain: stable
3935
components: clippy
40-
- name: rustup override stable
41-
run: rustup toolchain install stable && rustup override set stable
4236
- uses: Swatinem/rust-cache@v2
4337
with:
4438
workspaces: |
4539
.
4640
- name: cargo clippy
47-
env:
48-
RUSTUP_TOOLCHAIN: stable
4941
run: cargo clippy --all-targets -- -D warnings -D missing_docs
5042

5143
test:
@@ -55,19 +47,13 @@ jobs:
5547
- uses: actions/checkout@v4
5648
with:
5749
submodules: false
58-
- uses: dtolnay/rust-toolchain@stable
59-
with:
60-
toolchain: stable
61-
- name: rustup override stable
62-
run: rustup toolchain install stable && rustup override set stable
50+
- uses: dtolnay/rust-toolchain@1.71.1
6351
- uses: Swatinem/rust-cache@v2
6452
with:
6553
workspaces: |
6654
.
67-
- name: cargo test
68-
env:
69-
RUSTUP_TOOLCHAIN: stable
70-
run: cargo test
55+
- name: cargo test (workspace)
56+
run: cargo test --workspace
7157
- name: PRNG golden regression (rmg-core)
7258
run: cargo test -p rmg-core --features golden_prng -- tests::next_int_golden_regression
7359

@@ -103,20 +89,6 @@ jobs:
10389
exit 1;
10490
}
10591
106-
msrv:
107-
name: MSRV (rmg-core @ 1.68)
108-
runs-on: ubuntu-latest
109-
steps:
110-
- uses: actions/checkout@v4
111-
with:
112-
submodules: false
113-
- uses: dtolnay/rust-toolchain@1.68.0
114-
- uses: Swatinem/rust-cache@v2
115-
with:
116-
workspaces: |
117-
.
118-
- name: cargo check (rmg-core)
119-
run: cargo check -p rmg-core --all-targets
12092
12193
rustdoc:
12294
name: Rustdoc (rmg-core warnings gate)
@@ -125,13 +97,7 @@ jobs:
12597
- uses: actions/checkout@v4
12698
with:
12799
submodules: false
128-
- uses: dtolnay/rust-toolchain@stable
129-
with:
130-
toolchain: stable
131-
- name: rustup override stable
132-
run: rustup toolchain install stable && rustup override set stable
100+
- uses: dtolnay/rust-toolchain@1.71.1
133101
- uses: Swatinem/rust-cache@v2
134102
- name: rustdoc warnings gate
135-
env:
136-
RUSTUP_TOOLCHAIN: stable
137103
run: RUSTDOCFLAGS="-D warnings" cargo doc -p rmg-core --no-deps

AGENTS.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,12 @@ Welcome to the **Echo** project. This file captures expectations for any LLM age
2626
- Respect determinism: preferably no random seeds without going through the Echo PRNG.
2727
- Run `cargo clippy --all-targets -- -D missing_docs` and `cargo test` before every PR; CI will expect a zero-warning, fully documented surface.
2828

29+
### Git Hooks & Local CI
30+
- Install repo hooks once with `make hooks` (configures `core.hooksPath`).
31+
- Formatting: pre-commit auto-fixes with `cargo fmt` by default. Set `ECHO_AUTO_FMT=0` to run check-only instead.
32+
- Toolchain: pre-commit verifies your active toolchain matches `rust-toolchain.toml`.
33+
- Docs Guard: when core API files change, the hook requires updating `docs/execution-plan.md` and `docs/decision-log.md` (mirrors the CI check).
34+
2935
## Git Real
3036
1. **NEVER** use `--force` with any git command. If you think you need it, stop and ask the human for help.
3137
2. **NEVER** use rebase. Embrace messy distributed history; plain merges capture the truth, rebases rewrite it.

CONTRIBUTING.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,10 @@ Echo is a deterministic, renderer-agnostic engine. We prioritize:
2222
1. Clone the repo and run `cargo check` to ensure the Rust workspace builds.
2323
2. Read `docs/architecture-outline.md` and `docs/execution-plan.md`.
2424
3. Review `AGENTS.md` for collaboration norms before touching runtime code.
25+
4. Optional: develop inside the devcontainer for toolchain parity with CI.
26+
- Open in VS Code → "Reopen in Container" (requires the Dev Containers extension).
27+
- The container includes Rust 1.71.1 (via rust-toolchain.toml), clippy/rustfmt, Node, and gh.
28+
- Post-create installs toolchain 1.71.1 (no override); wasm32 target and components are added to 1.71.1.
2529

2630
## Branching & Workflow
2731
- Keep `main` pristine. Create feature branches like `echo/<feature>` or `timeline/<experiment>`.
@@ -53,6 +57,14 @@ Echo is a deterministic, renderer-agnostic engine. We prioritize:
5357
- TypeScript tooling (when active) lives in `reference/typescript/`; follow local lint configs when reactivated.
5458
- Avoid non-deterministic APIs (no wall-clock, no uncontrolled randomness). Use Echo’s deterministic services.
5559

60+
### Git Hooks (recommended)
61+
- Install repo hooks once: `make hooks` (configures `core.hooksPath` to `.githooks`).
62+
- Pre-commit runs:
63+
- cargo fmt (auto-fix by default; set `ECHO_AUTO_FMT=0` for check-only)
64+
- Toolchain pin verification (matches `rust-toolchain.toml`)
65+
- A minimal docs-guard: when core API files change, it requires updating `docs/execution-plan.md` and `docs/decision-log.md` (mirrors CI)
66+
- To auto-fix formatting on commit: `ECHO_AUTO_FMT=1 git commit -m "message"`
67+
5668
## Communication
5769
- Major updates should land in `docs/execution-plan.md` and `docs/decision-log.md`; rely on GitHub discussions or issues for longer-form proposals.
5870
- Respect the temporal theme—leave the codebase cleaner for the next timeline traveler.

0 commit comments

Comments
 (0)