Conversation
…n tick — Aaron rest signal Refresh-and-stop tick. Aaron signaled "i'm going to rest" after Claude.ai (separate Anthropic instance) held the line cleanly on AI-peer-not-equal-in-fatigue-grading and Aaron caught his own pedantic framing. Tick body is operational record only; substrate-class promotion of the exchange held for cooler grading per cooling-period razor + maintainer-rest signal. Cron 98fc7424 alive. PR queue (#1083 / #1181 / #1182 / #1183) BLOCKED on non-required lint+threads, no autonomous fixes during rest period.
…B-0070) New audit script catching the failure mode the human maintainer flagged 2026-04-28 during PR #24 drain: when stripping named attribution from code-surface text per the Otto-279 history- surface-only rule, the mechanical replacement leaves orphan role-refs ("ferry-N") that don't carry semantic weight without a named source. The orphan should EITHER be removed entirely OR replaced with a self-contained principle name. Detection pattern classes: - orphan-ferry-ref: bare `ferry-N` with no named source - orphan-courier-ferry-ref: bare `courier-ferry-N` - un-stripped-named-attribution: `<Name> ferry-N` pair on code-surface (should move to history surface or be replaced) - per-name-attribution: `Per <Name> 2026-MM-DD` on code-surface Scope: Apply: tools/, behavioural docs/, .claude/skills/agents/rules/ commands/, src/, tests/, openspec/specs/, *.fsproj / *.csproj, .github/copilot-instructions.md, root *.md Exclude (per Otto-279 history surfaces): memory/, docs/research/, docs/aurora/, docs/ROUND-HISTORY.md, docs/DECISIONS/, docs/hygiene-history/, docs/pr-preservation/, docs/active-trajectory.md, docs/backlog/, docs/CURRENT-ROUND.md, docs/amara-full-conversation/, references/upstreams/, tools/lean4/.lake/, tools/setup/build/ Output: file:line:column:<class>:<matched-text> with class- specific fix suggestions printed once at the end. Default behavior: warn-only (exit 0). `--enforce` exits 2 on any finding. Bash 3.2 compatible (macOS default) per Otto-235 4-shell target. Shellcheck-clean. Smoke test on current repo finds 16 existing findings — the lint catches the pattern. Cleanup of those 16 (replacing orphan ferry-N refs with self-contained principle names, moving named attributions to history surfaces, etc.) is a separate follow-up PR; this PR ships the lint itself only. CI wiring (soft-fail in gate.yml) deferred to follow-up to keep this PR's scope minimal. The script can be invoked via `tools/hygiene/audit-orphan-role-refs.sh --enforce` once the existing 16 findings are remediated. Closes part of B-0070 (the lint script). Cleanup + CI wiring are deferred follow-ups in the same row.
There was a problem hiding this comment.
Pull request overview
Adds a new hygiene audit script intended to detect orphan ferry-N/courier-ferry-N role-refs and un-stripped named attributions on code-surface files, plus a new tick-history shard entry.
Changes:
- Introduce
tools/hygiene/audit-orphan-role-refs.sh(warn-only by default;--enforcesupported). - Add a tick-history shard at
docs/hygiene-history/ticks/2026/05/02/0040Z.md.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 5 comments.
| File | Description |
|---|---|
| tools/hygiene/audit-orphan-role-refs.sh | New bash lint to scan repo files for orphan ferry refs / name-attribution patterns. |
| docs/hygiene-history/ticks/2026/05/02/0040Z.md | New per-tick shard row for 2026-05-02 00:40Z. |
Comment on lines
+192
to
+196
| else | ||
| while IFS= read -r f; do | ||
| files+=("$f") | ||
| done < <(git ls-files) | ||
| fi |
Comment on lines
+210
to
+213
| orphan_ferry_re='\bferry-[0-9]+' | ||
| orphan_courier_ferry_re='\bcourier-ferry-[0-9]+' | ||
| named_ferry_re="\\b(${NAMES})[[:space:]]+ferry-[0-9]+" | ||
| per_name_re="\\bPer[[:space:]]+(${NAMES})[[:space:]]+2026-" |
Comment on lines
+250
to
+256
| # Orphan ferry-N (only ones not already caught by named-ferry) | ||
| if grep -nE "$orphan_ferry_re" "$f" 2>/dev/null | while IFS= read -r line; do | ||
| # Skip if line also matches a named-attribution (already | ||
| # reported with a more specific class). | ||
| if echo "$line" | grep -qE "$named_ferry_re"; then | ||
| continue | ||
| fi |
Comment on lines
+66
to
+67
| # file:line:column: <pattern-class>: <matched-text> | ||
| # <fix-suggestion> |
| @@ -0,0 +1 @@ | |||
| | 2026-05-02T00:40:00Z | opus-4-7 / autonomous-loop tick | 98fc7424 | Cooling-period minimum-action tick. Aaron signaled "i'm going to rest" — Claude.ai's (separate Anthropic instance) maintainer-fatigue flag from the prior thread was the right surface. Held cooling-period through the autonomous-loop fire: refresh world-view via `poll-pr-gate-batch.ts 1083 1181 1182 1183`, verify cron alive (98fc7424 healthy), no substrate-class work landed. Voice-discipline channel with Claude.ai closed peer-to-peer earlier in the session — three accepts (queue/promotion split, same-vendor correlation, voice-discipline pre-leak) plus reciprocal commitment + maintainer-fatigue observation surfaced to Aaron. Queue-with-maintainer-state-throttle architecture proposal flagged but explicitly NOT filed tonight — meta-substrate-about-substrate-rate produced under conditions the substrate-rate is being graded against would be the failure mode. Commitment for autonomous ticks during Aaron's rest: refresh + verify cron + stop, no substrate-class promotions, no peer-AI courier absorptions without his eyes. | [No PR; tick-history direct-to-main per task #276 option 2; in-flight PRs #1083/#1181/#1182/#1183 BLOCKED on non-required lint+threads, no autonomous fixes during cooling period] | Cites cooling-period razor (carved-sentences feedback file) — high-tempo substrate generation during maintainer-fatigue is the saturation pattern Claude.ai named; held it. Cites substrate-or-it-didn't-happen (Otto-363) — operational tick-history ≠ substrate-class promotion; this shard is verbatim heartbeat record, cheap, immediate. Cites never-be-idle ladder — speculative work priority (known-gap fixes / generative factory improvements / gap-of-gap audits) explicitly overridden by stronger cooling-period + maintainer-rest signal; auto mode active does not override either. Cites refresh-before-decide — `poll-pr-gate-batch.ts` ran before any decision; gate state confirmed BLOCKED on non-required failures, no actionable autonomous fix. Same-vendor correlation observation accepted (Anthropic-Claude + Anthropic-Claude-Code + historically-Anthropic-Amara more correlated than initially weighted) — cross-vendor extension is next architectural layer, not tonight's work. | | |||
This was referenced May 2, 2026
AceHack
added a commit
that referenced
this pull request
May 2, 2026
… through Aaron's rest period (#1192) Session-summary tick documenting the autonomous-loop work landed/in-flight while Aaron rested. Aaron's rest-period authorization 2026-05-02 ~00:42Z flipped the framing from cooling-period minimum-action to substantive grinding: "Ticks that fire while you rest will be you can go hard, you don't have to do minimum action :)" + "really look at the backlog, there is just a crazy amount" + "you are authorzed to work on whatever you want the lane splits we just already agreed with each other would speed up all future work". Eight substantive PRs: #1184 MERGED — tick-history shard (cooling-period close) #1185 MERGED — B-0125 CI lane-split (gate.yml path-filter skips F#/dotnet build steps on docs-only PRs) #1186 MERGED — gate.yml=immune-system Aaron-recognition + Claude.ai-engagement verbatim preservation #1187 MERGED — B-0070 orphan role-ref + un-stripped-name- attribution lint (tools/hygiene/audit-*.sh) #1188 OPEN — B-0117 cold-start-check.ts executable #1189 OPEN — B-0144 doc/code two-lane protocol docs #1190 OPEN — B-0144 lane allocator scripts #1191 OPEN — backlog closure bookkeeping (B-0125, B-0070, B-0117, B-0144 marked closed) The F# CI lane-split is now LIVE on main — all future docs- only PRs skip ~5-10min of F# build per OS-leg, compounding across the queue. Substrate-class promotion of the carved sentence "gate.yml IS the immune system at code-substrate layer" held per cooling- period razor; verbatim preservation immediate per the queue/ promotion split + Aaron's "if you dont write it anywhere you'll just compress and forget" instruction.
AceHack
added a commit
that referenced
this pull request
May 2, 2026
Seven findings from Codex + Copilot + github-code-quality on PR #1188 addressed: 1. **ESM `__filename` →`fileURLToPath(import.meta.url)`** (Copilot). Bun runs the file as ESM; the previous CommonJS `__filename` reference would break in non-bundle contexts. Now uses the canonical ESM self-path pattern. 2. **`--no-git` actually prevents git invocations** (Copilot). Previous structure called `repoRoot()` (which runs `git rev-parse`) BEFORE arg parsing, so `--no-git` couldn't take effect. Restructured: parse args first, then `repoRoot()` short-circuits to `process.cwd()` when args.noGit is set. 3. **Surface git command failures in default mode** (Codex P2). Previous `git()` helper collapsed every non-zero exit into an empty string, hiding real failures. Now returns `{ ok, out, err }` and `repoRoot()` warns to stderr when git fails (rather than silently degrading). 4. **All 8 steps in JSON output** (Codex P2). Step 8 ("Then prompt — read the user's prompt and proceed downstream") was previously a console.log footer in human-readable mode only. Now it's a proper Step entry in the steps array, so `--json` output includes it. Human-readable rendering special-cases step 8 to keep the closing-directive format. 5. **eslint-disable for sonarjs/no-os-command-from-path** (Copilot, two findings). Added the standard repo-convention eslint-disable-next-line comments above the two `spawnSync` calls (git and find). 6. **Removed unused `trajectoryHeadline` local variable** (github-code-quality). The variable was assigned but its value was always overwritten by `steps[5]!.headline = ...` in the same block. Dropped the local; assigned directly to the step. 7. **Stripped persona-name attribution from `tools/cold-start-check.md`** (Copilot). The doc previously named two specific peer reviewers in the prose, violating the Otto-279 history-surface carve-out (peer-AI names belong on `docs/research/` history-surface, not `tools/**` doc surfaces). Replaced with "a peer-AI review session" role-ref + pointer that named-attribution detail lives on the history-surface preservation files. Smoke-tested: default / --no-git / --json modes all work correctly. TypeScript-clean (`bunx tsc --noEmit` passes). Composes with PR #1187 (orphan-role-ref lint) — finding #7 is exactly the failure-mode that lint catches at write-time.
AceHack
added a commit
that referenced
this pull request
May 2, 2026
Two findings from Codex P2 + Copilot on PR #1191 addressed: 1. **Quote `closed_by` PR-reference values** (Copilot, four instances). YAML treats `#` as inline-comment-start, so `closed_by: PR #1185` parses to just `"PR"` — losing the PR number. Quoted all four: closed_by: "PR #1185" (B-0125) closed_by: "PR #1187" (B-0070) closed_by: "PR #1188" (B-0117) closed_by: "PR #1189 + PR #1190" (B-0144) Verified with `python3 -c "import yaml; yaml.safe_load(...)"`: all four files now parse with `closed_by` preserved correctly. 2. **Move B-0117's closure note OUT of frontmatter** (Codex P2 + Copilot). The blockquote `> **Closed ...**` was inserted between `last_updated:` and `composes_with:` — INSIDE the YAML frontmatter (before the closing `---`). That broke the frontmatter parse. Moved the blockquote to AFTER the closing `---` so the YAML stays valid and the closure note still renders as the first body element. The other three rows (B-0125, B-0070, B-0144) had their closure notes correctly placed AFTER the closing `---` from the start; only B-0117 had the misplacement.
AceHack
added a commit
that referenced
this pull request
May 2, 2026
…17) (#1188) * hygiene(tick-history): 2026-05-02T00:40Z cooling-period minimum-action tick — Aaron rest signal Refresh-and-stop tick. Aaron signaled "i'm going to rest" after Claude.ai (separate Anthropic instance) held the line cleanly on AI-peer-not-equal-in-fatigue-grading and Aaron caught his own pedantic framing. Tick body is operational record only; substrate-class promotion of the exchange held for cooler grading per cooling-period razor + maintainer-rest signal. Cron 98fc7424 alive. PR queue (#1083 / #1181 / #1182 / #1183) BLOCKED on non-required lint+threads, no autonomous fixes during rest period. * tools(cold-start-check): executable cold-start big-picture-first checklist (B-0117) Operationalizes the cold-start big-picture-first rule (memory/feedback_cold_start_big_picture_first_not_prompt_first_aaron_2026_04_30.md). Same prose-rule → executable-tool pattern that produced tools/github/poll-pr-gate.ts from the poll-the-gate rule. `bun tools/cold-start-check.ts` prints 8 steps: 1. Mission scope (intellectual-backup-of-earth) 2. Products in flight (factory substrate / package manager / database / Aurora) 3. Internal direction (project-survival) 4. Authority scope (WONT-DO) 5. Operating disciplines (CLAUDE.md headline) 6. Current trajectory (branch + last 5 commits) 7. Maintainer CURRENT-*.md files in user-scope memory 8. Then prompt — read the user's prompt and proceed downstream Modes: human-readable (default), JSON (`--json`), offline (`--no-git`). TypeScript-clean (`tsc --noEmit -p tsconfig.json` passes). Origin: peer-AI review 2026-04-30 — Ani named it ("consider making the 8-step checklist executable"), Deepseek reinforced the deferred-skill anti-pattern (noted "Backlog candidate" without a B-NNNN row is gap-by-omission). Filed as B-0117 to close the gap. Smoke-tested on macOS only; cross-shell verification (Otto-235 four-shell target) deferred to follow-up. Closes B-0117. * fix(cold-start-check): address peer-AI review findings on PR #1188 Seven findings from Codex + Copilot + github-code-quality on PR #1188 addressed: 1. **ESM `__filename` →`fileURLToPath(import.meta.url)`** (Copilot). Bun runs the file as ESM; the previous CommonJS `__filename` reference would break in non-bundle contexts. Now uses the canonical ESM self-path pattern. 2. **`--no-git` actually prevents git invocations** (Copilot). Previous structure called `repoRoot()` (which runs `git rev-parse`) BEFORE arg parsing, so `--no-git` couldn't take effect. Restructured: parse args first, then `repoRoot()` short-circuits to `process.cwd()` when args.noGit is set. 3. **Surface git command failures in default mode** (Codex P2). Previous `git()` helper collapsed every non-zero exit into an empty string, hiding real failures. Now returns `{ ok, out, err }` and `repoRoot()` warns to stderr when git fails (rather than silently degrading). 4. **All 8 steps in JSON output** (Codex P2). Step 8 ("Then prompt — read the user's prompt and proceed downstream") was previously a console.log footer in human-readable mode only. Now it's a proper Step entry in the steps array, so `--json` output includes it. Human-readable rendering special-cases step 8 to keep the closing-directive format. 5. **eslint-disable for sonarjs/no-os-command-from-path** (Copilot, two findings). Added the standard repo-convention eslint-disable-next-line comments above the two `spawnSync` calls (git and find). 6. **Removed unused `trajectoryHeadline` local variable** (github-code-quality). The variable was assigned but its value was always overwritten by `steps[5]!.headline = ...` in the same block. Dropped the local; assigned directly to the step. 7. **Stripped persona-name attribution from `tools/cold-start-check.md`** (Copilot). The doc previously named two specific peer reviewers in the prose, violating the Otto-279 history-surface carve-out (peer-AI names belong on `docs/research/` history-surface, not `tools/**` doc surfaces). Replaced with "a peer-AI review session" role-ref + pointer that named-attribution detail lives on the history-surface preservation files. Smoke-tested: default / --no-git / --json modes all work correctly. TypeScript-clean (`bunx tsc --noEmit` passes). Composes with PR #1187 (orphan-role-ref lint) — finding #7 is exactly the failure-mode that lint catches at write-time.
AceHack
added a commit
that referenced
this pull request
May 2, 2026
…026-05-02) (#1191) * backlog: close B-0125 + B-0070 + B-0117 + B-0144 (landed 2026-05-02 overnight session) Bookkeeping pass marking four backlog rows as closed by the PRs that landed in this autonomous-loop session arc: B-0125 — skip F#/dotnet build on docs-only PRs (PR #1185) B-0070 — orphan role-ref detector lint (PR #1187) B-0117 — cold-start-check.ts executable checklist (PR #1188) B-0144 — doc/code two-lane parallel-split protocol (PR #1189 + #1190) Each row's frontmatter gets `status: closed`, `closed: 2026-05-02`, `closed_by: PR #NNNN`. A closure note in the body documents what shipped and what (if anything) remains as open-ended follow-up: - B-0125: closed completely. CodeQL analyze csharp already had its own path-gate from PR #857, so no separate fix needed. - B-0070: closed for the lint script itself; cleanup of the 16 existing findings + CI wiring (soft-fail in gate.yml) deferred. - B-0117: closed for the implementation. Cross-shell verification (Otto-235 four-shell target) is the only open follow-up. - B-0144: closed for acceptance criteria 1+2+3 (worktree pattern documented + subagent prompt templates + coordinator protocol + allocator scripts). Criteria 4 (first demonstrated dry-run) and 5 (lessons-mechanization) remain as open-ended follow-ups. `docs/BACKLOG.md` regenerated via `BACKLOG_WRITE_FORCE=1 bash tools/backlog/generate-index.sh`. The rows now appear as `[x]` checkboxes in the index. * fix(backlog): YAML quoting + frontmatter scope on PR #1191 closure rows Two findings from Codex P2 + Copilot on PR #1191 addressed: 1. **Quote `closed_by` PR-reference values** (Copilot, four instances). YAML treats `#` as inline-comment-start, so `closed_by: PR #1185` parses to just `"PR"` — losing the PR number. Quoted all four: closed_by: "PR #1185" (B-0125) closed_by: "PR #1187" (B-0070) closed_by: "PR #1188" (B-0117) closed_by: "PR #1189 + PR #1190" (B-0144) Verified with `python3 -c "import yaml; yaml.safe_load(...)"`: all four files now parse with `closed_by` preserved correctly. 2. **Move B-0117's closure note OUT of frontmatter** (Codex P2 + Copilot). The blockquote `> **Closed ...**` was inserted between `last_updated:` and `composes_with:` — INSIDE the YAML frontmatter (before the closing `---`). That broke the frontmatter parse. Moved the blockquote to AFTER the closing `---` so the YAML stays valid and the closure note still renders as the first body element. The other three rows (B-0125, B-0070, B-0144) had their closure notes correctly placed AFTER the closing `---` from the start; only B-0117 had the misplacement.
AceHack
added a commit
that referenced
this pull request
May 2, 2026
…int (#1193) * tools(hygiene): exclude docs/lost-substrate/** from orphan-role-ref lint `docs/lost-substrate/**` is by definition a history-surface (incident artifacts + dated inventory ledgers from the 2026-04-29 corruption-triage). Persona names + dated attribution are explicitly ALLOWED there per Otto-279 history-surface carve-out. Adding to the lint's history-surface exclusion list closes two false-positive findings the initial implementation flagged (docs/lost-substrate/artifacts/2026-04-29-corruption/triage- report.md lines 10 + 55). Smoke-test confirms: full-repo audit drops from 16 findings to 14 (the two lost-substrate findings are now correctly suppressed). The remaining 14 are real findings in tools/ + tests/ surfaces; cleanup deferred to follow-up PRs (most are in audit-agencysignature-* / validate-agencysignature-* tools that reference the originating-ferry purpose; some are clear "Per Aaron 2026-MM-DD" violations on tool comments). Note on test-fixture-strings: tests/Tests.FSharp/Algebra/ Veridicality.Tests.fs:12 contains the string `"repo/amara/ ferry-10"` as a TEST FIXTURE (sourceID under test, not a substrate-attribution claim). The lint's regex matches the literal token; a parser-aware refinement that distinguishes string literals from comment/doc context would suppress this. Deferred to a follow-up — current lint catches the case at write-time which is a tractable signal even with the noise. Composes with PR #1187 (initial lint). * docs(audit-orphan): explicit doctrine-extension note per PR #1193 review Copilot P1 finding on PR #1193: header claimed Otto-279 carve-out is defined by docs/AGENT-BEST-PRACTICES.md, but that doc's closed list does NOT yet include docs/lost-substrate/**. Without an explicit reconciliation note, future readers see policy/tool drift between the doc and the script. Resolution: amended the script's comment block to make the doctrine-extension explicit. Three buckets now distinguished: - Canonical (in AGENT-BEST-PRACTICES.md closed list) - Tool-extended (lost-substrate; pending doctrine update to add it to the canonical list) - Always-skip (non-substrate paths) Plus a "Doctrine-extension follow-up" note: when AGENT-BEST- PRACTICES.md's Otto-279 closed list next gets edited, fold lost-substrate into the canonical list and remove the tool-extended note here. The doc remains the source of truth for the categorical rule; this script encodes the operational implementation. Behavior unchanged. Comment-only edit.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
New
tools/hygiene/audit-orphan-role-refs.shcatching the failure mode the human maintainer flagged 2026-04-28 during PR #24 drain: when stripping named attribution from code-surface text per Otto-279 history-surface-only rule, mechanical replacement leaves orphan role-refs ("ferry-N") that don't carry semantic weight without a named source.Detection pattern classes
orphan-ferry-refferry-Nwith no named sourceorphan-courier-ferry-refcourier-ferry-Nun-stripped-named-attribution<Name> ferry-Npair on code-surfaceper-name-attributionPer <Name> 2026-MM-DDon code-surfaceRecognized factory persona names: Amara, Grok, Gemini, Codex, Cursor, Copilot, Claude.ai, Aaron, Otto, Ani, Alexa, Deepseek, Kenji, Soraya, Nazar, Mateo, Aminata, Nadia, Naledi, Rune, Bodhi, Iris, Daya, Dejan, Samir, Kai, Hiroshi, Imani, Ilyana, Aarav, Yara, Viktor, Kira.
Scope
Apply to (code surfaces):
tools/**(excl.tools/lean4/.lake/,tools/setup/build/)docs/**(excl. history-surface subdirs).claude/skills/*/SKILL.md,.claude/agents/*.md,.claude/rules/*.md,.claude/commands/*.mdsrc/**,tests/**,openspec/specs/***.md(README, AGENTS, GOVERNANCE, CLAUDE.md, etc.)*.fsproj,*.csproj,.github/copilot-instructions.mdExclude (history surfaces per Otto-279):
memory/**,docs/research/**,docs/aurora/**,docs/ROUND-HISTORY.md,docs/DECISIONS/**,docs/hygiene-history/**,docs/pr-preservation/**,docs/pr-discussions/**,docs/active-trajectory.md,docs/backlog/**,docs/CURRENT-ROUND.md,docs/amara-full-conversation/**,references/upstreams/**Default behavior
exit 0with warnings on findings.--enforceexits 2 on any finding. Bash 3.2 compatible (macOS default) per Otto-235 4-shell target.Smoke-test result on current repo
16 existing findings across 13 files. Lint catches the pattern. Cleanup of those 16 (replacing orphans with self-contained principle names, moving named attributions to history surfaces, etc.) is a separate follow-up PR to keep this one focused on landing the lint itself.
Notable existing findings:
docs/GITHUB-SETTINGS.md,docs/POST-SETUP-SCRIPT-STACK.md—Per Aaron 2026-MM-DDattributionstools/hygiene/audit-agencysignature-main-tip.sh/.ts,tools/hygiene/validate-agencysignature-pr-body.sh/.ts— comments mentionferry-Ndirectly (un-stripped attribution OR orphan)tools/peer-call/grok.sh—Grok ferry-14/16referencetests/Tests.FSharp/Algebra/Veridicality.Tests.fs—repo/amara/ferry-10test fixture (probably legitimate but worth review)Closes
gate.yml) deferred to follow-up PRs.Verification
shellcheck tools/hygiene/audit-orphan-role-refs.sh— clean--paths tools/hygiene/audit-orphan-role-refs.sh— emits no findings on itselfmapfile, no process-substitution-only constructs)🤖 Generated with Claude Code