diff --git a/.machine_readable/contractiles/adjust/Adjustfile.a2ml b/.machine_readable/contractiles/adjust/Adjustfile.a2ml index 24f400fd..97204d6f 100644 --- a/.machine_readable/contractiles/adjust/Adjustfile.a2ml +++ b/.machine_readable/contractiles/adjust/Adjustfile.a2ml @@ -1,211 +1,158 @@ # SPDX-License-Identifier: MPL-2.0 -# Adjustfile — Accessibility Contract for Burble -# Author: Jonathan D.A. Jewell -# -# Accessibility requirements and compliance for Burble. -# Voice-first design must be inclusive for all users. -# -# Run with: adjust check -# Fix with: adjust fix (where deterministic fix exists) +# Adjustfile (A2ML Canonical) +# Copyright (c) 2026 Jonathan D.A. Jewell (hyperpolymath) @abstract: -Accessibility requirements and compliance for the Burble voice-first communications platform. -These requirements ensure Burble is usable by everyone, regardless of ability. +Adaptive-maintenance contract for Echidna. When an upstream dep, +toolchain, prover binary, schema, or external API shifts, this file +declares the migration sequence. Each adjustment is an error code, a +probe to detect drift, and the deterministic-fix-or-defer recipe. + +Error-code namespace: A### +Run with: just adjust-check +Apply (where deterministic) with: just adjust-apply @end -## Keyboard Accessibility - -### keyboard-navigation -- description: All features accessible via keyboard -- status: partial -- probe: test -f server/lib/burble/accessibility/keyboard.ex -- compliance: WCAG 2.1 AA -- notes: Basic navigation implemented. Full keyboard-only flow needed. -- fix: Port PanLL's comprehensive keyboard navigation system - -### custom-keybindings -- description: User-configurable keybindings -- status: implemented -- probe: test -f server/lib/burble/accessibility/keyboard.ex -- compliance: WCAG 2.1 AAA -- notes: Users can remap PTT, mute, deafen, volume, and room navigation keys - -### keyboard-shortcuts-discoverable -- description: Keyboard shortcuts are documented and discoverable -- status: missing -- compliance: WCAG 2.1 A -- fix: Add keyboard shortcuts help modal in web client - -## Visual Accessibility - -### high-contrast-mode -- description: High contrast UI theme -- status: missing -- compliance: WCAG 2.1 AA -- fix: Port PanLL's high-contrast theme system -- target: CSS variables for contrast ratios >= 4.5:1 - -### colorblind-support -- description: Colorblind-friendly color schemes -- status: missing -- compliance: WCAG 2.1 AA -- fix: Implement deuteranopia, protanopia, and tritanopia palettes -- reference: PanLL's palette system - -### font-size-adjustment -- description: Resizable UI fonts (4 levels: 14-20px) -- status: missing -- compliance: WCAG 2.1 AA -- fix: Port PanLL's font size adjustment system -- target: User preference persists across sessions - -### theme-switching -- description: Dark/Light/System theme support -- status: missing -- compliance: WCAG 2.1 AA -- fix: Port PanLL's theme system -- target: Respects OS preference, user override - -## Auditory Accessibility - -### screen-reader-support -- description: Full screen reader compatibility -- status: partial -- probe: test -f server/lib/burble/accessibility/screen_reader.ex -- compliance: WCAG 2.1 AA -- notes: Basic announcements implemented. Needs ARIA attributes and live regions. -- fix: Complete ARIA implementation in web client - -### closed-captions -- description: Real-time captioning for voice chat -- status: missing -- compliance: WCAG 2.1 AA -- notes: Requires Web Speech API or external STT integration -- target: 90%+ accuracy for English, configurable display - -### visual-notifications -- description: Visual indicators for audio events -- status: missing -- compliance: WCAG 2.1 A -- notes: Speaking indicators, mute status, connection status -- fix: Add visual cues that duplicate audio information - -### volume-normalization -- description: Consistent volume levels across users -- status: missing -- compliance: WCAG 2.1 AA -- notes: Prevents sudden loud sounds for sensitive users -- target: -23 LUFS normalization per EBU R128 - -## Motor Accessibility - -### voice-commands -- description: Voice-controlled interface -- status: missing -- compliance: WCAG 2.1 AAA -- notes: "Mute", "Deafen", "Join room X", "Volume up/down" -- target: Web Speech API with fallback to keyboard - -### reduced-motion -- description: Reduced animation options -- status: missing -- compliance: WCAG 2.1 AA -- fix: Port PanLL's animation control (on/reduced/off) -- target: Respects prefers-reduced-motion media query - -### hover-alternatives -- description: All hover interactions have click alternatives -- status: partial -- compliance: WCAG 2.1 AA -- notes: Some hover tooltips need click-to-show option -- fix: Audit and add click alternatives - -## Cognitive Accessibility - -### clear-language -- description: Simple, consistent terminology -- status: partial -- compliance: WCAG 2.1 AAA -- notes: Technical terms need plain language explanations -- fix: Add tooltips/glossary for jargon - -### predictable-navigation -- description: Consistent navigation patterns -- status: partial -- compliance: WCAG 2.1 AA -- notes: Navigation structure varies between pages -- fix: Standardize navigation layout - -### error-prevention -- description: Confirmation for destructive actions -- status: partial -- compliance: WCAG 2.1 AA -- notes: Room deletion has confirmation, others may not -- fix: Audit all destructive actions - -### help-availability -- description: Context-sensitive help always available -- status: missing -- compliance: WCAG 2.1 AAA -- notes: No persistent help system -- fix: Add help button with contextual guidance - -## Compliance Targets - -### wcag-2.1-aa -- description: WCAG 2.1 AA compliance -- status: partial -- target: Full compliance by Q4 2026 -- tracking: https://github.com/hyperpolymath/burble/issues/XXX - -### section-508 -- description: U.S. Section 508 compliance -- status: partial -- target: Full compliance by Q4 2026 -- notes: Aligns with WCAG 2.1 AA for most requirements - -### en-301-549 -- description: EU EN 301 549 compliance -- status: partial -- target: Full compliance by Q4 2026 -- notes: EU public sector procurement requirement - -## Integration Requirements - -### panll-accessibility-port -- description: Port PanLL's accessibility engine to Burble -- status: planned -- reference: /var/mnt/eclipse/repos/panll/tests/accessibility_engine_test.js -- target: Q2 2026 - -### k9-accessibility-validator -- description: Integrate K9 accessibility validator -- status: planned -- reference: /var/mnt/eclipse/repos/panll/contractiles/k9/validators/accessibility-baseline.k9.ncl -- target: Q2 2026 - -### accessibility-testing -- description: Add accessibility tests to CI/CD -- status: planned -- target: pa11y or axe-core integration -- compliance: Automated WCAG testing - -## Documentation Requirements - -### accessibility-guide -- description: User-facing accessibility guide -- status: missing -- target: docs/accessibility/USER-GUIDE.adoc -- notes: Keyboard shortcuts, screen reader setup, theme switching - -### developer-accessibility -- description: Developer accessibility guidelines -- status: missing -- target: docs/accessibility/DEVELOPER.adoc -- notes: Coding standards, testing requirements, compliance checklist - -### compliance-report -- description: Accessibility compliance report -- status: missing -- target: docs/compliance/ACCESSIBILITY.adoc -- notes: VPAT (Voluntary Product Accessibility Template) +@requires: +- section: Toolchain-Adjust +- section: Dep-Adjust +- section: Schema-Adjust +- section: Prover-Adjust +- section: Workflow-Adjust +@end + +## Toolchain-Adjust + +### A001-rust-toolchain-drift +- description: rust-toolchain.toml pin behind current stable +- probe: rustc --version | grep -q $(cat rust-toolchain.toml 2>/dev/null | grep channel | cut -d'"' -f2) +- severity: low +- adjust: bump rust-toolchain.toml to current stable; run `cargo update --workspace` to refresh transitives +- defer-if: any pinned-feature crate breaks on bump + +### A002-julia-channel-drift +- description: juliaup default channel mismatches Project.toml `julia` compat +- probe: julia --version | grep -q "$(grep -E '^julia = ' src/julia/Project.toml | cut -d'"' -f2 | head -1)" +- severity: low +- adjust: juliaup default release ; juliaup update +- defer-if: a key dep (Flux, CUDA, GNN) doesn't yet support new Julia + +### A003-chapel-version-bump +- description: chapel-ci.yml pin behind upstream +- probe: grep -E '^CHAPEL_VERSION:' .github/workflows/chapel-ci.yml | grep -q '2.8.0' +- severity: medium +- adjust: bump CHAPEL_VERSION env in chapel-ci.yml ; verify .deb URL + SHA via curl +- defer-if: existing chapel source uses removed syntax (out/label keywords, char-quote rules) + +### A004-idris2-version-drift +- description: idris2 binary doesn't match src/abi/echidnaabi.ipkg pin +- probe: idris2 --version | grep -q "0.8.0" +- severity: medium +- adjust: install matching idris2 via guix or upstream binary +- defer-if: 0.8.0 reserved-keyword rules break src/abi/ (see [[reference_idris2_0_8_0_reserved_keywords]]) + +### A005-zig-version-drift +- description: zig binary doesn't match ffi/zig pin +- probe: zig version | grep -q "0.15" +- severity: low +- adjust: install matching zig version +- defer-if: 0.15 breaking changes hit ffi/zig (see [[reference_zig_015_breaking_changes]]) + +## Dep-Adjust + +### A010-cargo-deps-major-bump-available +- description: a tracked Cargo dep has a major bump available +- probe: cargo outdated --workspace --depth 1 2>/dev/null | grep -E '^\w+\s+\S+\s+\S+\s+\d' | head -5 +- severity: low +- adjust: review changelog; bump via `cargo update -p --precise `; run full test suite +- defer-if: major bump introduces API break with no migration path (nom 7→8, rand 0.9→0.10 examples) + +### A011-julia-pkg-major-bump-available +- description: a tracked Julia pkg has a compat-bound bump available +- probe: julia --project=src/julia -e 'using Pkg; Pkg.status(outdated=true)' 2>&1 | grep -q '⌃' +- severity: low +- adjust: review upstream NEWS; bump `[compat]` in Project.toml; Pkg.resolve() +- defer-if: GNN-stack (Flux/CUDA/GraphNeuralNetworks) interlock requires waiting on co-bump + +### A012-dependabot-pr-backlog +- description: open dependabot PRs accumulating +- probe: gh pr list --repo hyperpolymath/echidna --author 'app/dependabot' --state open --limit 50 --json number | jq 'length' | grep -q '^0$' +- severity: low +- adjust: triage with `just blocked-pr-triage` style sweep; auto-merge low-risk patches +- defer-if: dependabot phantom-version (e.g. rand 0.10 not on crates.io) + +## Schema-Adjust + +### A020-capnp-schema-out-of-sync +- description: crates/echidna-wire/schemas/*.capnp changed but bindings stale +- probe: git diff --quiet HEAD~10 crates/echidna-wire/schemas/ && git diff --quiet HEAD~10 crates/echidna-wire/src/ +- severity: high +- adjust: just capnp-gen ; verify Rust/Julia/Idris2/Zig/AffineScript bindings all regenerated +- defer-if: schema bump requires owner approval (Cap'n Proto IPC is owner-gated per #194) + +### A021-graphql-sdl-no-export +- description: src/interfaces/graphql/schema.rs changed but no SDL file tracked +- probe: test -f src/interfaces/graphql/schema.graphql +- severity: medium +- adjust: cargo test --package echidna-graphql export_schema (writes schema.graphql) ; commit it +- defer-if: schema considered internal-only + +### A022-openapi-spec-drift +- description: REST handlers changed but OpenAPI spec stale +- probe: test -f src/interfaces/rest/openapi.json && cargo run -- export-openapi 2>/dev/null | diff -q - src/interfaces/rest/openapi.json +- severity: medium +- adjust: regenerate via aide / utoipa ; commit ; CI diff-gate +- defer-if: aide/utoipa not yet adopted; file follow-up to wire + +### A023-verisim-er-schema-drift +- description: crates/echidna-wire/schemas/verisim_er.capnp diverged from docs/architecture/VERISIM-ER-SCHEMA.md crosswalk table +- probe: diff <(grep -E '^\| .+ \| .+ \|' docs/architecture/VERISIM-ER-SCHEMA.md) <(parse schema → rows) +- severity: high +- adjust: update whichever lags; both must move together +- defer-if: VerisimDB upstream schema is itself in flux (federation pending) + +## Prover-Adjust + +### A030-new-prover-added-upstream +- description: an upstream prover repo bumped to a new release +- probe: scripts/provision_corpora.sh --status | grep -E 'ahead' | head -1 +- severity: low +- adjust: pin new tag in scripts/provision_corpora.sh ; just provision-corpora ; just corpus-ingest-saturation ; retrain +- defer-if: upstream release breaks the extractor (file in src/rust/corpus/.rs) + +### A031-prover-kind-enum-expansion +- description: a new prover backend is wanted (ProverKind::all_core gap) +- probe: manual — owner identifies +- severity: medium +- adjust: add variant to ProverKind enum; implement ProverBackend trait; wire ProverFactory::create; tier-assign in docs/PROVER_COUNT.md +- defer-if: prover lacks open-source binary distribution + +## Workflow-Adjust + +### A040-standards-reusable-sha-stale +- description: a standards-reusable workflow caller is behind current main +- probe: grep -rE 'uses: hyperpolymath/standards/.+@[0-9a-f]{40}' .github/workflows/ | while read l; do sha=$(echo "$l" | grep -oE '[0-9a-f]{40}'); current=$(gh api repos/hyperpolymath/standards/commits/main --jq .sha); [ "$sha" = "$current" ] || echo STALE; done | head -1 +- severity: low +- adjust: bump SHA pin; verify the SHA exists via `gh api repos/hyperpolymath/standards/commits/` +- defer-if: a recent reusable change introduces breaking input shape + +### A041-action-sha-pin-fake +- description: a 3rd-party action SHA pin is fake (does not exist upstream) +- probe: scripts/verify-action-shas.sh 2>&1 | grep -q 'FAKE' +- severity: critical +- adjust: replace with current real SHA via `gh api repos///commits/` +- defer-if: never — fake SHA is a supply-chain hazard + +### A042-codeql-cron-drift +- description: codeql cron drifted from standards canonical schedule (monthly per cut 3) +- probe: grep -A 2 '^on:' .github/workflows/codeql.yml | grep -q 'cron.*0 0 1 \*' +- severity: low +- adjust: bump to '0 0 1 * *' monthly; or drop file entirely and let standards reusable provide +- defer-if: project-specific gate requires more frequent scan + +@adjust-philosophy: +- always check before adjust (every recipe has both) +- never adjust without an explicit defer-if escape hatch +- adjustments cascade: bump rust → cargo update → check tests → check ABI → check container +- prefer the narrowest change that resolves the drift +@end diff --git a/.machine_readable/contractiles/bust/Bustfile.a2ml b/.machine_readable/contractiles/bust/Bustfile.a2ml index 86e271ff..b356c5e9 100644 --- a/.machine_readable/contractiles/bust/Bustfile.a2ml +++ b/.machine_readable/contractiles/bust/Bustfile.a2ml @@ -1,28 +1,167 @@ -// Bustfile.a2ml — meta-repo bust contractile (breakage / rollback) -// SPDX-License-Identifier: MPL-2.0 - -Bust { - name: "rsr-template-repo" - version: "1.0.0" - description: "Rollback procedures when something breaks in the meta-repo" - - scenarios: { - "bad-pointer-bump": "git revert in meta-repo; child repo itself untouched" - "submodule-pointer-points-at-missing-sha": "git submodule update --init --checkout resets child to parent-recorded SHA; OR revert the stale bump commit" - "submodule-orphan-after-local-only-commit": "roll back locally with git reset to before the stranded commit; fix remote situation before re-attempting" - "accidental-private-repo-content-leaked-to-public-submodule": "hard-rotate the leaked secret immediately; git-filter-repo or BFG on the submodule's own history; public re-publication only after rotation complete" - } - - escalation-ladder: [ - "1. revert the meta-repo commit (reversible, low blast radius)", - "2. reset the local submodule clone (affects only local workspace)", - "3. force-push to main — PROHIBITED without explicit user confirmation (violates branch protection)", - "4. registry-level (delete/archive the GitHub repo) — human-only action, never by AI" - ] - - backup-points: [ - "GitHub serves as the durable backup for every submodule's own history", - "Meta-repo history on origin/main is the durable backup for pointer state", - "Local backup tags (backup/pre--) retained on risky rewrites" - ] -} +# SPDX-License-Identifier: MPL-2.0 +# Bustfile (A2ML Canonical) +# Copyright (c) 2026 Jonathan D.A. Jewell (hyperpolymath) + +@abstract: +Breakage and rollback contract for Echidna. When a build, test, prover +backend, ABI proof, container, or training pipeline goes wrong, this +file declares the recovery sequence. Each scenario is an error code, +a probe to detect it, and a `recovery:` recipe pointing at the +self-heal action. + +Error-code namespace: B### +Recovery sequence is "narrowest-first": prefer reverting a single +commit over invalidating caches; prefer cache bust over reinstalling +toolchains. +@end + +@requires: +- section: Build-Bust +- section: Test-Bust +- section: Backend-Bust +- section: ABI-Bust +- section: Container-Bust +- section: Training-Bust +- section: Repo-Bust +@end + +## Build-Bust + +### B001-cargo-build-broken +- description: cargo build fails after dep update +- probe: ! cargo build --offline 2>&1 | grep -q 'error\[' +- severity: critical +- recovery: just bust-cargo-cache && just heal && cargo build +- escalation: git revert ; cargo update -p --precise + +### B002-nom-parser-api-break +- description: nom 7→8 silently broke direct-call combinators +- probe: ! grep -q "expected function, found .impl Parser" target/debug/build.log +- severity: high +- recovery: defer nom 8 bump; pin Cargo.toml `nom = "7.1"` until call-sites migrated to `.parse()` +- escalation: file follow-up PR rewriting ~100 call sites + +### B003-rand-api-break +- description: rand 0.9→0.10 removed StdRng::random_range +- probe: ! grep -q "no method named .random_range" target/debug/build.log +- severity: high +- recovery: pin Cargo.toml `rand = "0.9"` ; or rewrite to `.gen_range()` / `Distribution::sample` +- escalation: verify rand 0.10 actually exists on crates.io (suspect dependabot phantom) + +## Test-Bust + +### B010-cargo-test-broken +- description: cargo test --lib regresses +- probe: ! cargo test --lib --offline 2>&1 | grep -q 'test result: ok' +- severity: critical +- recovery: bisect with `git bisect run cargo test --lib` ; revert offending commit +- escalation: just bust-target-dir ; just heal ; retry + +### B011-julia-test-broken +- description: julia --project=src/julia -e 'using Pkg; Pkg.test()' fails +- probe: ! julia --project=src/julia -e 'using Pkg; Pkg.test()' 2>&1 | tail -5 | grep -q 'PASS' +- severity: high +- recovery: rm -rf src/julia/Manifest.toml ; just heal ; retry +- escalation: julia --project=src/julia -e 'using Pkg; Pkg.resolve(); Pkg.precompile()' + +## Backend-Bust + +### B020-prover-binary-missing +- description: a Tier-1 prover binary is not on PATH +- probe: which coq agda lean4 idris2 >/dev/null +- severity: warning +- recovery: just heal-provers (installs missing Tier-1 backends) +- escalation: rebuild Containerfile.wave3 for the missing prover + +### B021-chapel-build-broken +- description: cargo build --features chapel fails +- probe: ! cargo build --features chapel --offline 2>&1 | tail -10 | grep -q 'Compiling' +- severity: warning +- recovery: just bust-chapel-artefacts ; just doctor-chapel +- escalation: confirm CHPL_VERSION env matches Justfile pin (currently 2.8.0) + +### B022-zig-ffi-broken +- description: ffi/zig/src build fails (Zig version drift) +- probe: ! zig build -p ffi/zig 2>&1 | grep -q 'error:' +- severity: warning +- recovery: just bust-zig-cache ; verify Zig pin matches `feedback_zig_015_breaking_changes` +- escalation: hotfix unsafe-cast sites per memory + +## ABI-Bust + +### B030-idris2-abi-typecheck-broken +- description: idris2 --build src/abi/echidnaabi.ipkg fails +- probe: ! idris2 --build src/abi/echidnaabi.ipkg 2>&1 | tail -5 | grep -q 'OK' +- severity: critical +- recovery: examine the failing module; look for new `believe_me`/`assert_total`/`postulate` (banned by idris2-abi-ci.yml) +- escalation: revert the offending commit; src/abi/ namespace state is owner-managed per feedback_echidna_src_abi_namespace_intentional + +### B031-banned-token-in-abi +- description: src/abi/ contains a banned construct +- probe: ! grep -rn 'believe_me\|assert_total\|postulate\|prim__crash' src/abi/ 2>&1 | grep -v -- "--" | head -1 +- severity: critical +- recovery: rewrite the proof constructively; if blocked, revert +- escalation: open issue tagged `area:abi` with reproducer + +## Container-Bust + +### B040-containerfile-build-broken +- description: podman build -f Containerfile fails +- probe: ! podman build -f Containerfile -q . 2>&1 | tail -3 | grep -qE 'sha256:[0-9a-f]' +- severity: warning +- recovery: podman system prune -af ; rebuild +- escalation: check Chainguard base tag drift; consult stapeln.toml layer cache rules + +### B041-wave3-image-broken +- description: .containerization/Containerfile.wave3 build fails for a prover cell +- probe: ! podman build -f .containerization/Containerfile.wave3 --build-arg PROVER= -q . 2>&1 | tail -3 | grep -qE 'sha256:[0-9a-f]' +- severity: warning +- recovery: check stub-sentinel detection step (added in wave3 #157) ; verify upstream prover repo still resolvable +- escalation: pin previous-known-good upstream tag for that prover + +## Training-Bust + +### B050-julia-pkg-instantiate-broken +- description: src/julia Pkg.instantiate fails +- probe: ! julia --project=src/julia -e 'using Pkg; Pkg.instantiate()' 2>&1 | tail -3 | grep -q 'Updating' +- severity: high +- recovery: rm src/julia/Manifest.toml ; just heal ; retry +- escalation: pin known-good Julia channel via juliaup + +### B051-corpus-ingest-unknown-adapter +- description: `just corpus-ingest-saturation ` errors `Unknown corpus adapter` +- probe: ! just corpus-ingest-saturation isabelle external_corpora/isabelle/ 2>&1 | grep -q 'Unknown' +- severity: medium +- recovery: confirm dispatcher in src/rust/main.rs has match arm for ; if not, file PR (see docs/training-runs/2026-06-02.md follow-ups) +- escalation: until dispatcher fix lands, fall back to the 4 supported adapters (agda/coq/lean/idris2) + +### B052-bson-undefined-at-save +- description: training final-save fails `UndefVarError: BSON not defined in Main` +- probe: grep -q 'UndefVarError: .BSON. not defined' /tmp/echidna-training-*.log +- severity: low +- recovery: per-epoch checkpoint scaffold still saves models; ignore final-save failure for now +- escalation: add `using BSON` to the JSONL-fallback training entry point in src/julia/training/train.jl + +## Repo-Bust + +### B060-bad-commit-on-main +- description: a known-bad commit is on origin/main +- probe: manual — owner identifies +- severity: high +- recovery: git revert on a fresh branch ; PR ; admin-merge +- escalation: force-push to main is PROHIBITED without explicit owner confirmation (violates branch protection) + +### B061-tag-points-at-wrong-sha +- description: a release tag was cut at the wrong commit +- probe: manual +- severity: medium +- recovery: git tag -d ; git push origin :refs/tags/ ; re-tag at correct SHA ; push +- escalation: notify any downstream consumers of the tag re-point + +@bust-escalation-ladder: +- 1. revert a single commit (low blast radius) +- 2. reset local workspace (no remote impact) +- 3. invalidate a specific cache (just bust-* recipes) +- 4. force-push to main — PROHIBITED without explicit owner confirmation +- 5. registry-level (delete/archive a release tag, package version) — human-only +@end diff --git a/.machine_readable/contractiles/dust/Dustfile.a2ml b/.machine_readable/contractiles/dust/Dustfile.a2ml index 0d619ee2..29609258 100644 --- a/.machine_readable/contractiles/dust/Dustfile.a2ml +++ b/.machine_readable/contractiles/dust/Dustfile.a2ml @@ -1,22 +1,158 @@ # SPDX-License-Identifier: MPL-2.0 -# Dustfile — Cleanup and Hygiene Contract - -[dustfile] -version = "1.0.0" -format = "a2ml" - -[cleanup] -stale-branch-policy = "delete-after-merge" -artifact-retention = "90-days" -cache-policy = "clear-on-release" - -[hygiene] -linting = "required" -formatting = "required" -dead-code-removal = "encouraged" -todo-tracking = "tracked-in-issues" - -[reversibility] -backup-before-destructive = true -rollback-mechanism = "git-revert" -data-retention-policy = "preserve-30-days" +# Dustfile (A2ML Canonical) +# Copyright (c) 2026 Jonathan D.A. Jewell (hyperpolymath) + +@abstract: +Fine-grained recovery (broom-and-pan: pick up tiny leftover state) +for Echidna. Where Bustfile rolls back a broken commit and Adjustfile +migrates to a new upstream version, Dustfile cleans the small dusty +remnants — stale branches, orphan caches, dropped /tmp worktrees, +half-merged stash entries, leftover process pids. + +Error-code namespace: D### +Dust commands are idempotent and reversible; running them on a clean +repo should be a no-op. +@end + +@requires: +- section: Branch-Dust +- section: Worktree-Dust +- section: Cache-Dust +- section: Process-Dust +- section: Artefact-Dust +- section: Source-Dust +@end + +@dust-cadence: weekly (cheap) ; before-release (thorough) + +## Branch-Dust + +### D001-stale-local-branches +- description: local branches whose remote-tracking is gone +- probe: git for-each-ref refs/heads --format '%(refname:short) %(upstream:track)' | grep -q '\[gone\]' +- severity: low +- dust: git fetch --prune ; for b in $(git for-each-ref refs/heads --format='%(refname:short) %(upstream:track)' | awk '/gone/ {print $1}'); do gh pr list --repo hyperpolymath/echidna --head "$b" --state merged --json number --jq '.[0].number' | grep -q '^[0-9]' && git branch -D "$b"; done +- reversible: yes (re-fetch from origin if needed) + +### D002-stale-remote-branches +- description: remote branches whose PR was squash-merged (git's mergedness detector misses) +- probe: gh pr list --repo hyperpolymath/echidna --state all --limit 50 --json number,headRefName,state,mergedAt | jq '[.[] | select(.state=="MERGED" and (.mergedAt != null))] | length' | grep -qE '^[1-9]' +- severity: low +- dust: per merged PR, `gh api -X DELETE repos/hyperpolymath/echidna/git/refs/heads/` if still present +- reversible: PR is the durable record; remote branch can be re-pushed + +## Worktree-Dust + +### D010-dangling-git-worktrees +- description: registered worktrees pointing at nonexistent paths +- probe: ! git worktree list 2>&1 | grep -q '\[prunable\]' +- severity: low +- dust: git worktree prune -v +- reversible: yes (worktree is filesystem state; metadata only) + +### D011-tmp-agent-worktrees +- description: /tmp/-* leftover from prior agent runs +- probe: ls -d /tmp/echidna-* /tmp/echidnabot-* /tmp/gitbot-fleet-* /tmp/hyperpolymath-* 2>/dev/null | wc -l | grep -qE '^[1-9]' +- severity: low +- dust: for d in /tmp/-*; do case "$d" in *-saturation|*-training-bin|*-training-*.log|*-training-*.pid|*-training-*.status) ;; *) git -C worktree remove --force "$d" 2>/dev/null || rm -rf "$d";; esac; done +- reversible: per-worktree only (no commits at risk if worktree is clean) +- exclude: /tmp/echidna-saturation (other Claude's territory), /tmp/echidna-training-* (active artefacts) + +## Cache-Dust + +### D020-cargo-target-bloat +- description: target/ directory exceeds 5GB +- probe: test -d target && du -sh target | awk '{print $1}' | grep -qE '^[1-9][0-9]+G$' +- severity: low +- dust: cargo clean ; or `cargo sweep --time 30` to keep recent only +- reversible: yes (rebuild on next cargo command) + +### D021-julia-precompile-cache-stale +- description: ~/.julia/compiled stale wrt Project.toml +- probe: test -d ~/.julia/compiled && julia --project=src/julia -e 'using Pkg; Pkg.precompile()' 2>&1 | grep -q 'Precompiling' +- severity: low +- dust: rm -rf ~/.julia/compiled ; julia --project=src/julia -e 'using Pkg; Pkg.precompile()' +- reversible: yes (regenerates lazily) + +### D022-podman-image-orphans +- description: dangling podman images (built then orphaned by re-tag) +- probe: podman images --filter dangling=true --format '{{.ID}}' | wc -l | grep -qE '^[1-9]' +- severity: low +- dust: podman image prune -f +- reversible: yes (re-pull from registry if needed) + +### D023-chapel-build-artefacts +- description: src/chapel/lib*.a or *.dylib leftover after feature flip +- probe: find src/chapel -name '*.a' -o -name '*.so' -o -name '*.dylib' 2>/dev/null | head -1 +- severity: low +- dust: rm src/chapel/lib*.a src/chapel/*.so src/chapel/*.dylib 2>/dev/null || true +- reversible: yes (just chapel-build regenerates) + +## Process-Dust + +### D030-orphan-pid-files +- description: /tmp/*.pid files pointing at no-longer-running PIDs +- probe: ls /tmp/echidna-*.pid 2>/dev/null | while read f; do kill -0 $(cat "$f") 2>/dev/null || echo "$f"; done | head -1 +- severity: low +- dust: for f in /tmp/echidna-*.pid; do kill -0 $(cat "$f") 2>/dev/null || rm -f "$f" "${f%.pid}.status"; done +- reversible: harmless (re-created by next launcher) + +### D031-stale-status-files +- description: /tmp/*.status files marked RUNNING but process dead +- probe: ls /tmp/echidna-*.status 2>/dev/null | while read f; do pid=$(cat "${f%.status}.pid" 2>/dev/null); grep -q RUNNING "$f" && [ -n "$pid" ] && ! kill -0 "$pid" 2>/dev/null && echo "$f"; done | head -1 +- severity: low +- dust: per-file: update status to ORPHANED or remove if no longer of interest +- reversible: harmless + +## Artefact-Dust + +### D040-prior-run-models +- description: models/neural/ from prior training runs that aren't the current canonical +- probe: ls models/neural/ 2>/dev/null | grep -E 'checkpoint_epoch_[0-9]+' | wc -l | grep -qE '^[4-9]|^[0-9]{2,}' +- severity: low +- dust: keep best_model + final_model + gnn_ranker; archive epoch checkpoints under models/neural/archive// +- reversible: yes (data preserved under archive/) + +### D041-corpus-snapshot-overlap +- description: data/corpus/*.json overlapping with newer saturation outputs +- probe: ls data/corpus/*.json 2>/dev/null | wc -l | grep -qE '^[1-9][0-9]+' +- severity: low +- dust: archive older corpus snapshots under data/corpus/archive// +- reversible: yes + +### D042-training-data-jsonl-bloat +- description: training_data/*.jsonl pre-saturation files no longer canonical +- probe: ls training_data/proof_states_*.jsonl 2>/dev/null | wc -l | grep -qE '^[1-9]' +- severity: low +- dust: archive ; do NOT delete (load-bearing for JSONL-fallback training path until full saturation pipeline is the only entry point) +- reversible: yes + +## Source-Dust + +### D050-todo-with-no-issue +- description: TODO/FIXME comments without a tracking issue reference +- probe: grep -rnE 'TODO|FIXME|XXX' src/ 2>/dev/null | grep -vE '#[0-9]+' | head -1 +- severity: low (informational) +- dust: for each: either open a tracking issue + add `// TODO(#N):` prefix, or close out +- reversible: yes (comment-only) + +### D051-unused-imports +- description: Rust unused imports +- probe: cargo clippy --workspace 2>&1 | grep -q 'unused import' +- severity: low +- dust: cargo fix --allow-dirty --allow-staged +- reversible: yes (atomic) + +### D052-dead-code-warnings +- description: dead_code warnings +- probe: cargo build --workspace 2>&1 | grep -q 'warning: .* is never used' +- severity: low +- dust: review each — sometimes legitimate forward-prep; otherwise remove +- reversible: yes (git history) + +@dust-philosophy: +- "leave no trace": every run should be idempotent +- "narrow blast radius": never combine destructive ops; one dust action per recipe +- "reversibility first": every dust action should be undoable from git or by re-running a non-dust recipe +- "exclusion list is sacred": active worktrees + production artefacts NEVER swept (see exclusions in D011) +@end diff --git a/.machine_readable/contractiles/trust/Trustfile.a2ml b/.machine_readable/contractiles/trust/Trustfile.a2ml index 313ac20f..9ebf11d1 100644 --- a/.machine_readable/contractiles/trust/Trustfile.a2ml +++ b/.machine_readable/contractiles/trust/Trustfile.a2ml @@ -3,23 +3,171 @@ # Copyright (c) 2026 Jonathan D.A. Jewell (hyperpolymath) @abstract: -Trust and provenance verification for Echidna. -Maximal trust by default — LLM may read, build, test, lint, format. +Trust and provenance verification contract for Echidna. Defines what +the agent / CI is allowed to do, what must be verifiable before any +proof leaves the dispatcher, and what supply-chain hardening is +mandatory. + +Error-code namespace: T### +Maximal trust by default — LLM may read, build, test, lint, format, +file PRs against non-main branches. @end @trust-level: maximal @trust-boundary: repo -@trust-actions: [read, build, test, lint, format] -@trust-deny: [delete-branch, force-push, modify-ci-secrets, publish] +@trust-actions: [read, build, test, lint, format, file-pr-on-branch, admin-merge-with-owner-authorisation] +@trust-deny: [delete-branch-without-owner-confirm, force-push-to-main, modify-ci-secrets, publish-without-tag-cut, edit-licence-headers-automatically] + +@requires: +- section: Integrity +- section: Provenance +- section: Supply-Chain +- section: Dispatcher-Trust +- section: Sandbox +- section: ABI-Trust +@end ## Integrity -### license-content -- description: LICENSE contains expected SPDX identifier -- run: grep -q 'SPDX\|License\|MIT\|Apache\|PMPL\|MPL' LICENSE +### T001-license-content +- description: LICENSE file contains a recognised SPDX identifier +- run: grep -qE 'SPDX-License-Identifier|MIT|Apache|MPL|AGPL|PMPL' LICENSE +- severity: critical +- recovery: restore LICENSE from git history; do NOT auto-edit (see [[feedback_no_automated_licence_edits]]) + +### T002-no-secrets-committed +- description: no .env or credential files in repo +- run: test ! -f .env && test ! -f credentials.json && test ! -f .env.local && test ! -f .secrets +- severity: critical +- recovery: git-filter-repo to remove + rotate the leaked secret immediately + +### T003-spdx-headers-on-source +- description: source files carry SPDX-License-Identifier +- run: find src/ -name '*.rs' -o -name '*.jl' -o -name '*.idr' -o -name '*.chpl' -o -name '*.zig' | xargs grep -L 'SPDX-License-Identifier' 2>/dev/null | wc -l | grep -q '^0$' +- severity: warning +- recovery: per-file manual addition; never sweep + +## Provenance + +### T010-commits-are-gpg-signed +- description: HEAD commit is GPG-signed +- run: git log -1 --pretty='%G?' | grep -qE '[GN]' +- severity: critical +- recovery: `git commit --amend -S` ; configure git config commit.gpgsign true + +### T011-tagged-releases-only +- description: a release tag exists for current Cargo.toml version +- run: ver=$(grep -E '^version = ' Cargo.toml | head -1 | cut -d'"' -f2); git tag -l "v$ver" | grep -q "v$ver" +- severity: medium +- recovery: owner cuts the tag manually (signed): `git tag -a -s v -m "v release"` + +### T012-signed-tag +- description: latest release tag is GPG-signed (annotated + signed) +- run: latest=$(git describe --tags --abbrev=0 2>/dev/null); [ -n "$latest" ] && git tag -v "$latest" 2>&1 | grep -q 'Good signature' +- severity: medium +- recovery: owner re-cuts the tag with `-s` + +## Supply-Chain + +### T020-action-shas-pinned +- description: every 3rd-party action in .github/workflows/ uses a 40-char SHA pin +- run: ! grep -rE 'uses: [^/]+/[^@]+@(main|master|v[0-9]+\.?[0-9]*\.?[0-9]*)' .github/workflows/ | grep -v '^#' +- severity: high +- recovery: replace tag/branch pin with `gh api repos///commits/ --jq .sha` resolved 40-char SHA + +### T021-action-shas-not-fake +- description: every SHA pin resolves to a real upstream commit +- run: bash scripts/verify-action-shas.sh 2>&1 | ! grep -q 'FAKE' +- severity: critical +- recovery: see [[feedback_verify_action_sha_pins]] — re-resolve via `gh api .../commits/` (422 = fake) + +### T022-cargo-lock-tracked +- description: Cargo.lock is committed (workspace root + crate roots that produce binaries) +- run: test -f Cargo.lock && git ls-files --error-unmatch Cargo.lock > /dev/null +- severity: high +- recovery: git add Cargo.lock ; commit + +### T023-trusted-base-reduction +- description: only standards-approved base images in Containerfile +- run: ! grep -E '^FROM' Containerfile .containerization/Containerfile.wave3 2>/dev/null | grep -v -E 'cgr\.dev/chainguard/|docker\.io/library/(postgres|redis|alpine):' +- severity: warning +- recovery: switch to Chainguard wolfi-base (per stapeln.toml model) + +### T024-no-pip-install-pip +- description: no `pip install pip` or curl|bash patterns in scripts +- run: ! grep -rE 'pip install pip|curl[^|]+\| ?bash' scripts/ .github/workflows/ 2>/dev/null +- severity: warning +- recovery: pin via guix.scm or Chainguard base; never bootstrap a package manager via the network + +## Dispatcher-Trust + +### T030-axiom-tracker-enabled +- description: dispatch pipeline includes axiom_tracker pre-emission +- run: grep -q 'AxiomTracker\|axiom_tracker' src/rust/dispatch.rs +- severity: critical +- recovery: any dispatch path emitting a result without axiom tracking is a TRUST VIOLATION; revert + +### T031-confidence-scoring-bounded +- description: confidence values are in [0.0, 1.0] (5-level trust hierarchy) +- run: grep -q 'ConfidenceFP\|Fin 10000' src/abi/EchidnaABI/TacticRecord.idr +- severity: high +- recovery: see seam analysis Gap 5 — add `#[serde(with = "confidence_serde")]` at the Rust ↔ Idris2 boundary + +### T032-mutation-testing-wired +- description: dispatch.rs invokes mutation testing +- run: grep -q 'MutationTester\|mutation::run' src/rust/dispatch.rs +- severity: medium +- recovery: re-wire per docs/handover/STATE.md trust-pipeline section + +### T033-pareto-frontier-tracked +- description: dispatch results pass through Pareto frontier ranking +- run: grep -q 'pareto::frontier\|ParetoRanker' src/rust/dispatch.rs +- severity: medium +- recovery: re-wire per same handover doc + +### T034-bayesian-confidence-tracked +- description: statistical confidence module is engaged +- run: grep -q 'BayesianTimeout\|statistics::confidence' src/rust/dispatch.rs +- severity: medium +- recovery: re-wire + +## Sandbox + +### T040-solver-execution-sandboxed +- description: src/rust/executor uses Podman or bubblewrap (no bare-process exec) +- run: grep -qE 'podman|bubblewrap|bwrap' src/rust/executor/*.rs +- severity: critical +- recovery: dispatcher must refuse to run any backend that bypasses executor; revert + +### T041-blake3-binary-integrity +- description: src/rust/integrity uses BLAKE3 + SHAKE3-512 for prover binary verification +- run: grep -qE 'blake3::|shake3|Shake3_512' src/rust/integrity/*.rs +- severity: high +- recovery: re-add per docs/ARCHITECTURE.md integrity section + +## ABI-Trust + +### T050-idris2-totality-enforced +- description: src/abi has `%default total` +- run: grep -q '%default total' src/abi/echidnaabi.ipkg - severity: critical +- recovery: re-add line; do not workaround with per-fn `total` annotations -### no-secrets-committed -- description: No .env or credential files in repo -- run: test ! -f .env && test ! -f credentials.json && test ! -f .env.local +### T051-no-banned-token-in-abi +- description: src/abi/ has zero `believe_me`/`assert_total`/`postulate`/`prim__crash` +- run: ! grep -rnE 'believe_me|assert_total|postulate|prim__crash' src/abi/ 2>/dev/null | grep -v -- "--" | head -1 - severity: critical +- recovery: rewrite proof constructively or revert; src/abi/ namespace is owner-managed per [[feedback_echidna_src_abi_namespace_intentional]] + +### T052-idris2-abi-ci-enforces +- description: idris2-abi-ci.yml workflow exists + runs on every push +- run: test -f .github/workflows/idris2-abi-ci.yml && grep -qE 'on:.*push' .github/workflows/idris2-abi-ci.yml +- severity: critical +- recovery: restore workflow from git history + +@trust-on-merge-checklist: +- [ ] All T001-T052 pass on the PR branch +- [ ] Owner has reviewed any T###-flagged finding before admin-merge +- [ ] GPG-signed commit + signed tag for any release +- [ ] No SHA pin newer than 30 days without re-verify +@end diff --git a/contractile.just b/contractile.just index 9a5827ba..1ebd406b 100644 --- a/contractile.just +++ b/contractile.just @@ -1,75 +1,203 @@ # Auto-generated by: contractile gen-just -# Source directory: contractiles -# Re-generate with: contractile gen-just --dir contractiles +# Source directory: .machine_readable/contractiles +# Re-generate with: contractile gen-just --dir .machine_readable/contractiles # # SPDX-License-Identifier: MPL-2.0 +# +# HAND-AUGMENTED 2026-06-02: contractile binary not on PATH at time of +# rewrite; this file was manually re-wired to match the expanded a2ml +# sources for adjust/bust/trust/dust/must/intend. Re-run `contractile +# gen-just` once the tool is available to confirm parity. -# === DUST (Recovery & Rollback) === -# Source: Dustfile.a2ml - -# List available dust recovery actions -dust-status: - @echo ' dust-source-rollback: Revert all source changes to last commit [rollback]' - -# Revert all source changes to last commit -dust-source-rollback: - @echo 'Executing rollback for source-rollback' - git checkout HEAD -- . - +# ── Roll-up: run every contractile check ────────────────────────────── -# === INTEND (Declared Future Intent) === -# Source: Intentfile.a2ml +# Run every contractile family check (must + trust + adjust-check + bust-check + dust) +contractile-all: must-check trust-verify adjust-check bust-check dust-check + @echo 'All contractile family checks completed' -# Display declared future intents -intend-list: - @echo '=== Declared Intent ===' +# Show the error-code inventory across the family +contractile-tour: + @echo '=== Contractile family error-code inventory ===' @echo '' - @echo 'Features:' + @echo 'Adjust (A###) — adaptive-maintenance drift:' + @grep -hE '^### A[0-9]{3}-' .machine_readable/contractiles/adjust/*.a2ml | sed 's/^### / /' @echo '' - @echo 'Quality:' - + @echo 'Bust (B###) — breakage / rollback:' + @grep -hE '^### B[0-9]{3}-' .machine_readable/contractiles/bust/*.a2ml | sed 's/^### / /' + @echo '' + @echo 'Trust (T###) — integrity / provenance / supply-chain:' + @grep -hE '^### T[0-9]{3}-' .machine_readable/contractiles/trust/*.a2ml | sed 's/^### / /' + @echo '' + @echo 'Dust (D###) — fine-grained cleanup:' + @grep -hE '^### D[0-9]{3}-' .machine_readable/contractiles/dust/*.a2ml | sed 's/^### / /' -# === MUST (Physical State Checks) === -# Source: Mustfile.a2ml +# ── MUST (Physical State Checks) ────────────────────────────────────── +# Source: .machine_readable/contractiles/must/Mustfile.a2ml -# Run all must checks must-check: must-license-present must-readme-present must-spdx-headers must-no-banned-files @echo 'All must checks passed' -# LICENSE file must exist must-license-present: test -f LICENSE -# README must exist must-readme-present: test -f README.adoc || test -f README.md -# Source files should have SPDX license headers must-spdx-headers: find . -name '*.rs' -o -name '*.res' -o -name '*.gleam' | head -20 | xargs -r grep -L 'SPDX-License-Identifier' | wc -l | grep -q '^0$' -# No Dockerfiles or Makefiles must-no-banned-files: test ! -f Dockerfile && test ! -f Makefile +# ── TRUST (Integrity & Provenance Verification) ─────────────────────── +# Source: .machine_readable/contractiles/trust/Trustfile.a2ml -# === TRUST (Integrity & Provenance Verification) === -# Source: Trustfile.a2ml - -# Run all trust verifications -trust-verify: trust-license-content trust-no-secrets-committed trust-container-images-pinned +trust-verify: trust-license-content trust-no-secrets trust-gpg-signed trust-shas-pinned trust-no-fake-shas trust-cargo-lock-tracked trust-axiom-tracker trust-sandbox-enforced trust-totality-enforced trust-no-banned-token-in-abi @echo 'All trust verifications passed' -# LICENSE contains expected SPDX identifier trust-license-content: - grep -q 'SPDX\|License\|MIT\|Apache\|PMPL\|MPL' LICENSE + grep -qE 'SPDX-License-Identifier|MIT|Apache|MPL|AGPL|PMPL' LICENSE + +trust-no-secrets: + test ! -f .env && test ! -f credentials.json && test ! -f .env.local && test ! -f .secrets + +trust-gpg-signed: + git log -1 --pretty='%G?' | grep -qE '[GN]' + +trust-shas-pinned: + ! grep -rE 'uses: [^/]+/[^@]+@(main|master|v[0-9]+\.?[0-9]*\.?[0-9]*)' .github/workflows/ | grep -v '^#' + +trust-no-fake-shas: + @if [ -x scripts/verify-action-shas.sh ]; then bash scripts/verify-action-shas.sh 2>&1 | (! grep -q 'FAKE'); else echo 'T021 SKIP: scripts/verify-action-shas.sh not present'; fi + +trust-cargo-lock-tracked: + test -f Cargo.lock && git ls-files --error-unmatch Cargo.lock > /dev/null + +trust-axiom-tracker: + grep -q 'AxiomTracker\|axiom_tracker' src/rust/dispatch.rs + +trust-sandbox-enforced: + grep -qE 'podman|bubblewrap|bwrap' src/rust/executor/*.rs + +trust-totality-enforced: + grep -q '%default total' src/abi/echidnaabi.ipkg + +trust-no-banned-token-in-abi: + @if grep -rnE 'believe_me|assert_total|postulate|prim__crash' src/abi/ 2>/dev/null | grep -v -- "--" | head -1; then echo "T051 FAIL: banned token in src/abi/"; exit 1; else echo 'T051 OK'; fi + +# ── ADJUST (Adaptive Maintenance) ───────────────────────────────────── +# Source: .machine_readable/contractiles/adjust/Adjustfile.a2ml + +adjust-check: adjust-rust-toolchain adjust-julia-channel adjust-chapel-version adjust-cargo-outdated adjust-julia-outdated adjust-shas-stale + @echo 'All adjust checks completed (drift items reported above if any)' + +adjust-rust-toolchain: + @echo 'A001: Rust toolchain drift' + @rustc --version + @test -f rust-toolchain.toml && cat rust-toolchain.toml | grep channel || echo 'A001 SKIP: no rust-toolchain.toml' + +adjust-julia-channel: + @echo 'A002: Julia channel drift' + @julia --version 2>&1 || echo 'A002 SKIP: julia not on PATH' + +adjust-chapel-version: + @echo 'A003: Chapel version pin' + @grep -E '^.*CHAPEL_VERSION' .github/workflows/chapel-ci.yml 2>/dev/null || echo 'A003 SKIP: no chapel-ci.yml' + +adjust-cargo-outdated: + @echo 'A010: Cargo outdated deps' + @cargo outdated --workspace --depth 1 2>/dev/null | head -10 || echo 'A010 SKIP: cargo-outdated not installed' -# No .env or credential files in repo -trust-no-secrets-committed: - test ! -f .env && test ! -f credentials.json && test ! -f .env.local +adjust-julia-outdated: + @echo 'A011: Julia outdated pkgs' + @julia --project=src/julia -e 'using Pkg; Pkg.status(outdated=true)' 2>&1 | head -10 || echo 'A011 SKIP' + +adjust-shas-stale: + @echo 'A040: Standards reusable SHA pin staleness' + @grep -rE 'uses: hyperpolymath/standards/.+@[0-9a-f]{40}' .github/workflows/ 2>/dev/null | head -5 || echo 'A040 SKIP: no standards-reusable callers' + +# ── BUST (Breakage / Rollback) ──────────────────────────────────────── +# Source: .machine_readable/contractiles/bust/Bustfile.a2ml + +bust-check: bust-cargo-build bust-cargo-test bust-prover-binaries bust-idris2-abi + @echo 'All bust checks completed (failures point at recovery recipes in Bustfile.a2ml)' + +bust-cargo-build: + @echo 'B001: cargo build' + @cargo check --offline 2>&1 | tail -3 || (echo 'B001 RECOVERY: just bust-cargo-cache && cargo build'; false) + +bust-cargo-test: + @echo 'B010: cargo test --lib' + @cargo test --lib --offline --no-run 2>&1 | tail -3 || (echo 'B010 RECOVERY: git bisect run cargo test --lib'; false) + +bust-prover-binaries: + @echo 'B020: Tier-1 prover binaries on PATH' + @which coq agda lean4 idris2 2>/dev/null | wc -l | xargs -I {} test {} -ge 1 || echo 'B020 RECOVERY: just heal-provers' + +bust-idris2-abi: + @echo 'B030: Idris2 ABI typecheck' + @test -f src/abi/echidnaabi.ipkg && (idris2 --build src/abi/echidnaabi.ipkg 2>&1 | tail -3 || echo 'B030 RECOVERY: revert offending commit; src/abi/ namespace owner-managed') || echo 'B030 SKIP: no echidnaabi.ipkg' + +bust-cargo-cache: + cargo clean + +bust-target-dir: + rm -rf target/ + +bust-chapel-artefacts: + rm -f src/chapel/lib*.a src/chapel/*.so src/chapel/*.dylib 2>/dev/null || true + +bust-zig-cache: + rm -rf ffi/zig/zig-cache ffi/zig/.zig-cache 2>/dev/null || true + +# ── DUST (Fine-Grained Cleanup) ─────────────────────────────────────── +# Source: .machine_readable/contractiles/dust/Dustfile.a2ml + +dust-check: dust-stale-branches dust-dangling-worktrees dust-orphan-pids dust-source-todos + @echo 'All dust checks completed (informational; run dust- to remediate)' + +dust-stale-branches: + @echo 'D001: Stale local branches' + @git for-each-ref refs/heads --format '%(refname:short) %(upstream:track)' | grep '\[gone\]' | head -5 || echo 'D001 OK' + +dust-dangling-worktrees: + @echo 'D010: Dangling worktrees' + @git worktree list 2>&1 | grep '\[prunable\]' | head -3 || echo 'D010 OK' + +dust-orphan-pids: + @echo 'D030: Orphan PID files' + @ls /tmp/echidna-*.pid 2>/dev/null | while read f; do kill -0 $(cat "$f") 2>/dev/null || echo " orphan: $f"; done + +dust-source-todos: + @echo 'D050: TODOs without issue refs' + @grep -rnE 'TODO|FIXME' src/ 2>/dev/null | grep -vE '#[0-9]+' | wc -l | xargs -I {} echo ' count without issue ref: {}' + +dust-source-rollback: + @echo 'Reverting all unstaged source changes' + git checkout HEAD -- . + +dust-prune-worktrees: + git worktree prune -v + +dust-archive-old-models: + @if [ -d models/neural ]; then mkdir -p models/neural/archive/$$(date -u +%Y-%m-%d); echo "Archive dir created at models/neural/archive/$$(date -u +%Y-%m-%d) — manually mv old checkpoints in"; fi + +# ── INTEND (Declared Future Intent) ─────────────────────────────────── +# Source: .machine_readable/contractiles/intend/Intentfile.a2ml + +intend-list: + @echo '=== Declared Intent ===' + @echo '' + @echo 'Run `cat .machine_readable/contractiles/intend/Intentfile.a2ml` for the source of truth.' -# Containerfile base images use pinned digests -trust-container-images-pinned: - test ! -f Containerfile || grep -q '@sha256:' Containerfile +# ── HEAL (recovery shortcuts referenced by bust/dust recipes) ───────── +heal: + @echo 'just heal: workspace healing entry point' + @cargo --version >/dev/null 2>&1 && echo ' rust toolchain OK' || echo ' rust toolchain MISSING' + @julia --version >/dev/null 2>&1 && echo ' julia OK' || echo ' julia MISSING — see juliaup' + @echo 'For prover binaries: just heal-provers' +heal-provers: + @echo 'heal-provers: install missing Tier-1 prover binaries' + @echo ' (implementation deferred — see B020 recovery in Bustfile.a2ml)'