---
category: index
bucket: lessons
generated: true
---

# Lessons Index

Generated by `goat-flow index`; do not edit by hand. Each row below maps one lesson entry to its source file with a grep-friendly `(search: "...")` anchor. Re-run `goat-flow index` after adding, editing, renaming, or resolving entries - `goat-flow stats --check` fails while this file is stale. Live entry counts and freshness come from `goat-flow stats`.

- [Agent proposed disabling gruff-ts rules to silence high-volume advisory findings](agent-behavior.md) (search: "## Lesson: Agent proposed disabling gruff-ts rules to silence high-volume advisory findings") - User ran `npx gruff-ts summary` in `/home/devgoat/projects/goat-flow` and asked the agent to "deeply analyse these findings and tell me what you agree that should be fixed." The summary reported 1643…
- [Agent parsed "use X to find Y" as "audit X for Y" when X was a CLI tool](agent-behavior.md) (search: "## Lesson: Agent parsed") - User in cwd `/home/devgoat/projects/goat-flow` asked to use `/home/devgoat/projects/gruff-workspace/gruff-ts` to find low-quality tests.
- [Agent cited gitignored content as evidence in committed docs](agent-behavior.md) (search: "## Lesson: Agent cited gitignored content as evidence in committed docs") - A 2026-05-11 documentation audit found four committed surfaces citing paths under `.goat-flow/scratchpad/` (gitignored by design) as authoritative evidence:
- [Agent ignored explicit "next step" command in pasted output](agent-behavior.md) (search: "## Lesson: Agent ignored explicit") - User pasted goat-flow setup output with a clearly labeled "Next step (recommended): Run `goat-flow audit . --harness`" section.
- [Commit subjects paraphrased the diff with weak verbs](agent-behavior.md) (search: "## Lesson: Commit subjects paraphrased the diff with weak verbs") - Audit of the last 10 commit messages on `dev` (HEAD `0366419`..`82db04b`, 2026-04-25..2026-04-29) showed 7 of 10 subjects led with *enhance, improve, streamline,* or *clarify* and carried no body.
- [Retrieval terms must name the concrete failure class](agent-behavior.md) (search: "## Lesson: Retrieval terms must name the concrete failure class") - During the M10 retrieval proof, the plan-oriented query `support matrix|agent matrix|registry canonicality` returned zero learning-loop hits for M12 work even though the relevant trap already existed…
- [Recurring terminal bugs must start with learning-loop retrieval](agent-behavior.md) (search: "## Lesson: Recurring terminal bugs must start with learning-loop retrieval") - While fixing the dashboard Workspace terminal bug where Claude Code received a large Quality prompt as `[Pasted text #N +... lines]` but did not auto-submit, multiple agents worked the browser…
- [Step 0 retrieval was advisory; required emission makes the skip visible](agent-behavior.md) (search: "## Lesson: Step 0 retrieval was advisory; required emission makes the skip visible") - Agents skipped the learning loop and re-tripped on documented traps.
- [Quality assessors can reopen ADR-settled skill modes](agent-behavior.md) (search: "## Lesson: Quality assessors can reopen ADR-settled skill modes") - Quality assessment agents recommended "quick critique mode" or "allow lightweight critique for smaller artifacts" as a Top 5 improvement.
- [Confused install-copy path pair for a directory move](agent-behavior.md) (search: "## Lesson: Confused install-copy path pair for a directory move") - User proposed `.goat-flow/skill-docs/` as a new installed-state location for the three reference files at `workflow/skills/reference/` (`skill-preamble.md`, `skill-conventions.md`,…
- [When deny hook blocks a command, use the unblocked equivalent](agent-behavior.md) (search: "## Lesson: When deny hook blocks a command, use the unblocked equivalent") - Agent needed to delete `.github/skills/goat-onboard/` and `.github/skills/goat-reflect/`.
- [Installed skill files are not templates](agent-behavior.md) (search: "## Lesson: Installed skill files are not templates") - The historical scanner system (removed per ADR-013) flagged AP18 (ADAPT comments in installed skills), causing a -2pt deduction on all 3 agents.
- [Agent used setup script as source of truth instead of package.json](agent-behavior.md) (search: "## Lesson: Agent used setup script as source of truth instead of package.json") - Investigating CI test failures on Node 20, the agent read `setup-initial.sh` (which checks for Node 22+) and concluded the project requires Node 22 - contradicting `package.json` `engines.node:…
- [Structural audit pass does not mean the project is correct](agent-behavior.md) (search: "## Lesson: Structural audit pass does not mean the project is correct") - goat-flow once scored 100% on its own scanner system (removed per ADR-013) while `preflight-checks.sh` failed with 8 errors.
- [Single-source-of-truth claims need a cold-path review pass](agent-behavior.md) (search: "## Lesson: Single-source-of-truth claims need a cold-path review pass") - M12 moved agent support metadata into `workflow/manifest.json`, but a follow-up code review still found residual parallel authority surfaces: Codex got a fictional `post_turn: "Stop"` event in the…
- [Sanitizing shell variable capture breaks `set -u` when variable is scoped inside a conditional](agent-behavior.md) (search: "## Lesson: Sanitizing shell variable capture breaks `set -u` when variable is scoped inside a conditional") - `preflight-checks.sh` had a flaky test: `node --input-type=module` commands occasionally emitted stray diagnostic output containing `[` characters, which `grep` interpreted as regex, producing `grep:…
- [Line-number evidence in footguns/lessons creates silent maintenance debt](agent-behavior.md) (search: "## Lesson: Line-number evidence in footguns/lessons creates silent maintenance debt") - Three independent Gemini quality reports in one session flagged stale `file:line` references across footgun entries.
- [Remove redundant local references after promoting shared doctrine](agent-behavior.md) (search: "## Lesson: Remove redundant local references after promoting shared doctrine") - M12 promoted browser-use guidance into the canonical shared playbook `.goat-flow/skill-docs/playbooks/browser-use.md`, but the first implementation kept four per-skill browser-use compatibility files…
- [Verify agent capabilities against official docs, not assumptions](agent-behavior.md) (search: "## Lesson: Verify agent capabilities against official docs, not assumptions") - Codex was assumed to lack PreToolUse hook support, so its profile left the hook field empty and a parallel Starlark execpolicy workaround was built.
- [Sub-agent delegation is universal across goat-flow's four supported agents](agent-behavior.md) (search: "## Lesson: Sub-agent delegation is universal across goat-flow's four supported agents") - Quality reports proposed a pre-check before routing to `/goat-critique`, assuming delegation might be unavailable.
- [End-of-task rules must be treated as deliverables](agent-behavior.md) (search: "## Lesson: End-of-task rules must be treated as deliverables") - Multiple incidents shared the same shape: the agent skipped an AI testing gate after completing milestone tasks, treated an AI gate's "14/14 checks passed" as proof real-world setup worked, skipped…
- [Fresh-eyes critique reruns need section-only evidence after a leak-scan discard](agent-behavior.md) (search: "## Lesson: Fresh-eyes critique reruns need section-only evidence after a leak-scan discard") - During a full `goat-critique` run, a fresh-eyes sub-agent stayed within the artifact but returned evidence links echoing the artifact's `.goat-flow/...` path.
- [Agent wedged its own shell in /tmp and tried to bypass the guard instead of recovering](agent-behavior.md) (search: "## Lesson: Agent wedged its own shell in /tmp and tried to bypass the guard instead of recovering") - While evaluating a GitHub PR, the agent staged scratch files in `/tmp` and ran `cd /tmp` to fetch them.
- [Dashboard audit cache survives code changes because signature doesn't cover compiled JS](agent-frontend.md) (search: "## Lesson: Dashboard audit cache survives code changes because signature doesn't cover compiled JS") - After fixing `buildScope` in `src/cli/audit/audit.ts` to exclude metric failures from harness scope status, rebuilding (`npm run build`), and reloading the dashboard, the dashboard still showed 94%…
- [When a mockup exists, match it element-for-element](agent-frontend.md) (search: "## Lesson: When a mockup exists, match it element-for-element") - User provided an HTML mockup with exact structure (`.left` div containing title + agent strip + detected config, `.right` div with prompt card) and screenshots.
- [Mockup parity includes visible copy and live bindings](agent-frontend.md) (search: "## Lesson: Mockup parity includes visible copy and live bindings") - In M05b Home redesign, the first implementation copied the broad section order but missed the mockup's top rollup identity row.
- [UI state matrices must include partial data states](agent-frontend.md) (search: "## Lesson: UI state matrices must include partial data states") - The M05b Home view treated every non-passing setup audit as the same "not installed" state.
- [Mockup parity includes exact structure and visual spacing](agent-frontend.md) (search: "## Lesson: Mockup parity includes exact structure and visual spacing") - A static HTML mockup defined the exact visual design for the dashboard homepage.
- [CLI agents cannot diagnose rendered CSS - ask for browser inspection](agent-frontend.md) (search: "## Lesson: CLI agents cannot diagnose rendered CSS - ask for browser inspection") - The dashboard's donut chart had a dark hairline border that the user asked to remove.
- [Check repo-provided browser tooling before declaring no browser](agent-frontend.md) (search: "## Lesson: Check repo-provided browser tooling before declaring no browser") - User asked the agent to view two static site pages (`docs/site/goat-flow-landing.html` and `docs/site/goat-flow-harness-engineering.html`).
- [Do not use error-colored toasts for expected loading states](agent-frontend.md) (search: "## Lesson: Do not use error-colored toasts for expected loading states") - While making the Workspace terminal launch feel more responsive, the first UX pass added a toast saying `Launching Terminal...` even though launch was a normal expected action and the button itself…
- [Bare task paths are context, not implementation approval](agent-routing.md) (search: "## Lesson: Bare task paths are context, not implementation approval") - A user sent only a bare gitignored task directory path.
- [Never override explicit skill invocation with your own judgment about artifact size](agent-routing.md) (search: "## Lesson: Never override explicit skill invocation with your own judgment about artifact size") - User invoked `/goat-critique` to brainstorm a better name and description for a quality mode label.
- [Version bumps require explicit confirmation](agent-routing.md) (search: "## Lesson: Version bumps require explicit confirmation") - While cleaning up zero-point rubric checks, the agent also bumped `package.json`, `RUBRIC_VERSION`, and skill frontmatter above the current `0.8.0` line.
- ["Update the plan" means write the plan, not execute it](agent-routing.md) (search: "## Lesson:") - User asked to "create M31 plan" and then later to "update this plan" with a detailed design spec.
- [Don't overcomplicate clear requests - a spec is not ambiguous](agent-routing.md) (search: "## Lesson: Don't overcomplicate clear requests - a spec is not ambiguous") - User asked to list all audit checks in config.yaml.
- [Agreeing with contradictory statements instead of holding a position](agent-routing.md) (search: "## Lesson: Agreeing with contradictory statements instead of holding a position") - User said preflight-checks.sh shouldn't validate goat-flow audit checks.
- [Session-log contract is conditional, not per-skill-invocation](agent-routing.md) (search: "## Lesson: Session-log contract is conditional, not per-skill-invocation") - Earlier skill templates said "If `.goat-flow/logs/` exists → write session summary" in a closing protocol that fired after every skill run.
- [Dispatcher keeps getting excluded from patterns and glob matches](agent-routing.md) (search: "## Lesson: Dispatcher keeps getting excluded from patterns and glob matches") - Three separate incidents where the dispatcher was missed by glob/iteration patterns: `find -name 'goat-*.md'` skipped `goat.md`, CI template `for skill in ...; do goat-$skill` produced `goat-goat`,…
- [Verification prompts must not assume goat skills are the only skills](agent-routing.md) (search: "## Lesson: Verification prompts must not assume goat skills are the only skills") - M1 human testing gate prompt said "List all directories in .claude/skills/.
- [Quality findings must respect local-state and reporting-only contracts](agent-routing.md) (search: "## Lesson: Quality findings must respect local-state and reporting-only contracts") - During a quality follow-up, the agent treated the active-plan marker pointing at a missing subdir as a MAJOR setup defect.
- ["Add a footgun" means a documentation entry, not runtime code](agent-routing.md) (search: "## Lesson:") - In a consumer project, the user asked to "add a footgun" documenting a Mercure CORS trap.
- [Explicit skill invocation IS delegation consent - never ask again](agent-routing.md) (search: "## Lesson: Explicit skill invocation IS delegation consent - never ask again") - User invoked `/goat-critique` which requires spawning three sub-agents (Phase 1).
- [Plan-only critique requests must not mutate artifacts](agent-routing.md) (search: "## Lesson: Plan-only critique requests must not mutate artifacts") - User invoked `$goat-critique make this less than 500 words: workflow/skills/goat/SKILL.md`.
- [Respect punctuation preferences immediately](agent-routing.md) (search: "## Lesson: Respect punctuation preferences immediately") - The agent restored em dashes in several text files while cleaning up verification side effects, even though the user's preference is to use plain hyphens instead.
- [Audit check skip semantics need both unit and integration fixture updates](audit-contracts.md) (search: "## Lesson: Audit check skip semantics need both unit and integration fixture updates") - While making `instruction-file-skill-docs-pointer` fail when the shared skill-docs/playbook pack is absent, the focused unit test was updated but the first full `npm test` run still failed four…
- [Additive audit report fields need renderer defaults](audit-contracts.md) (search: "## Lesson: Additive audit report fields need renderer defaults") - M09 added `AuditReport.enforcement` and updated the main audit fixtures, but the first full `npm test` run failed in an older contract fixture that called `renderAuditText` with a minimal report…
- [Audit fixture expectations must follow detector semantics](audit-contracts.md) (search: "## Lesson: Audit fixture expectations must follow detector semantics") - Historical scanner/rubric changes and current audit detector changes both invalidated "known failing" fixture expectations even when the implementation was correct.
- [Generic skill quality rules must be portable outside goat-flow](audit-contracts.md) (search: "## Lesson: Generic skill quality rules must be portable outside goat-flow") - The skill-quality evaluator treated `.goat-flow/skill-docs/skill-preamble.md` and the goat-flow Proof Gate as universal requirements, then told uploaded standalone skills to inherit them.
- [Quality-report recommendations need ADR reconciliation before gate changes](audit-contracts.md) (search: "## Lesson: Quality-report recommendations need ADR reconciliation before gate changes") - Four same-agent harness quality reports correctly observed that several concern signals were partly structural, then suggested making missing post-turn hooks, task-state semantics, or learning-loop…
- [Test cross-contamination via global env vars / module-level state silently flaps in parallel CI](coordination.md) (search: "## Lesson: Test cross-contamination via global env vars / module-level state silently flaps in parallel CI") - Tests modifying global state via env vars contaminated each other when CI ran in parallel.
- [Phase 0 normalisation catches council false findings before they create work](coordination.md) (search: "## Lesson: Phase 0 normalisation catches council false findings before they create work") - A five-council synthesis (Claude x2, ChatGPT, Gemini, Codex) produced findings for the v1.4 programme.
- [AI council version-baseline claims are an axis where reviewers hallucinate](coordination.md) (search: "## Lesson: AI council version-baseline claims are an axis where reviewers hallucinate") - The council synthesis stated "installed skills are v1.3.1" across multiple findings (CC-2, OP-5).
- [goat-flow correction loop runs at higher precision than council input](coordination.md) (search: "## Lesson: goat-flow correction loop runs at higher precision than council input") - Across Phase 0 and Phase 1 of the v1.4 programme, the framework's structured intake filtered three corrections from council input: one false finding (OP-5), one over-stated finding (OP-7), and one…
- [CF coordination cardinality forecast was directionally correct but per-skill bucket was larger than expected](coordination.md) (search: "## Lesson: CF coordination cardinality forecast was directionally correct but per-skill bucket was larger than expected") - Council synthesis estimated CF item Phase C split at ~6 preamble / ~10 shared-vocab / ~6 per-skill.
- [Phase 2 per-plan execution averaged better than forecast when programme document resolved ambiguity upfront](coordination.md) (search: "## Lesson: Phase 2 per-plan execution averaged better than forecast when programme document resolved ambiguity upfront") - Across 5 Phase 2 per-plan sessions, forecasts predicted a total of ~4 open questions requiring decisions.
- [Phase 3 verification catches state drift invisible to plan-level reasoning](coordination.md) (search: "## Lesson: Phase 3 verification catches state drift invisible to plan-level reasoning") - Phase 3 verification ran `wc -w` and `git show` against live repo state and found two issues that five council passes and three Phase 2 sessions missed: (1) goat-critique SKILL.md was at 2532 words…
- [Verification phases must cross-reference between artifacts, not just check each internally](coordination.md) (search: "## Lesson: Verification phases must cross-reference between artifacts, not just check each internally") - Phase 3 verification checked word counts, parity, rubric citations, npm test - all internal to individual files.
- [Phase totals must be derivable from phase breakdowns](coordination.md) (search: "## Lesson: Phase totals must be derivable from phase breakdowns") - Programme headline stated ~33 weekends (council's estimate).
- [Prove hook capability before marking an agent unsupported](dashboard-testing.md) (search: "## Lesson: Prove hook capability before marking an agent unsupported") - The Hooks dashboard first used `not supported`, then `unavailable`, for Antigravity on `gruff-code-quality` after Antigravity already had project-local hook wiring.
- [Dashboard release QA should avoid real agent runners unless runner behavior is the target](dashboard-testing.md) (search: "## Lesson: Dashboard release QA should avoid real agent runners unless runner behavior is the target") - During v1.6.0 browser-use manual dashboard QA, clicking Workspace `Open terminal` launched a real Claude Code session in the selected project.
- [Slow verification can expose unrelated dashboard doc drift](dashboard-testing.md) (search: "## Lesson: Slow verification can expose unrelated dashboard doc drift") - While double-checking an unrelated Codex config fix, `npm run test:slow` failed in `checkDrift: installer round-trip fixture` because the temp repo's preflight reported `Dashboard view names drift…
- [Dashboard readers must preserve fields used by score logic](dashboard-testing.md) (search: "## Lesson: Dashboard readers must preserve fields used by score logic") - The Home, Quality, and Setup pages showed every harness concern at 100 and "All checks passing", but still showed each agent at 94%.
- [VM helper tests need same-realm assertions](dashboard-testing.md) (search: "## Lesson: VM helper tests need same-realm assertions") - M03 added a VM-loaded browser helper test for `dashboard-custom-prompts.ts`.
- [VM helper timer harnesses must fake every timer primitive they exercise](dashboard-testing.md) (search: "## Lesson: VM helper timer harnesses must fake every timer primitive they exercise") - PR #44's CI `Test` step stayed in progress far past the usual runtime even after the dashboard terminal unit suite had printed its passing suite summary locally.
- [Dashboard HTML source tests should not depend on attribute order](dashboard-testing.md) (search: "## Lesson: Dashboard HTML source tests should not depend on attribute order") - While fixing Prompts custom-editor selection, the first focused prompt-source test failed because it searched for `<div class="gf-validation-summary"` even though the template puts Alpine attributes…
- [Dashboard row metadata should not widen UI sort contracts](dashboard-testing.md) (search: "## Lesson: Dashboard row metadata should not widen UI sort contracts") - While adding stable dashboard project identity, `npm run typecheck` failed after `ProjectEntry` gained optional identity metadata and `paths?: string[]`.
- [VM-loaded dashboard helper tests must treat `Error` objects as cross-realm too](dashboard-testing.md) (search: "## Lesson: VM-loaded dashboard helper tests must treat `Error` objects as cross-realm too") - While adding a focused unit test for `dashboardLaunchInTerminal()`, the runtime behavior was correct but the failure-path assertion still failed.
- [Classic dashboard script splits need Knip ignore coverage](dashboard-testing.md) (search: "## Lesson: Classic dashboard script splits need Knip ignore coverage") - Splitting `src/dashboard/app.ts` into additional classic browser scripts passed dashboard typecheck and server asset tests, but `npx knip --no-progress` flagged the new script-tag files as unused…
- [Dashboard asset tests can read stale dist copies](dashboard-testing.md) (search: "## Lesson: Dashboard asset tests can read stale dist copies") - M02 added metadata to `src/dashboard/preset-prompts.json` and the JSON/unit checks passed, but the focused `dashboard assets` integration test failed because `/assets/preset-prompts.json` served the…
- [Built dashboard browser smoke needs a restarted server after template edits](dashboard-testing.md) (search: "## Lesson: Built dashboard browser smoke needs a restarted server after template edits") - While adding the Plans active-plan toggle, the built dashboard browser smoke kept showing the old direct Alpine handlers after `npm run build:dashboard`.
- [Dashboard classic scripts need Knip registration](dashboard-testing.md) (search: "## Lesson: Dashboard classic scripts need Knip registration") - M03 added `src/dashboard/dashboard-custom-prompts.ts` as a browser classic-script helper and loaded it from `src/dashboard/index.html`.
- [Dashboard audit-route fixes need route-scoped verification, not the full server suite](dashboard-testing.md) (search: "## Lesson: Dashboard audit-route fixes need route-scoped verification, not the full server suite") - While fixing the Home page's multi-minute `Auditing...` stall, the first focused verification tried to use the entire `test/integration/dashboard-server.test.ts` suite as the gate.
- [Shell-backed performance probes must use the real shell environment](dashboard-testing.md) (search: "## Lesson: Shell-backed performance probes must use the real shell environment") - While optimizing `/api/quality`, my first localhost timing probes inside the default environment made the route look subsecond and led to a bad footgun draft: `/api/quality` appeared to take about…
- [Dashboard endpoint benchmarks need HTTP client warmup](dashboard-testing.md) (search: "## Lesson: Dashboard endpoint benchmarks need HTTP client warmup") - While adding `scripts/profile-dashboard-audit.mjs`, the first cached `/api/audit?quality=true` benchmark reported about `1375ms` even though the server-side profile spans totaled only about `17ms`.
- [UTF-8 punctuation sweeps need post-replacement grep](filesystem-io.md) (search: "## Lesson: UTF-8 punctuation sweeps need post-replacement grep") - During a repo-wide em-dash-to-hyphen replacement, the first command exited zero but changed nothing because Perl's default byte-mode input did not match the Unicode codepoint pattern.
- [Non-fatal filesystem tests should assert behavior before errno text](filesystem-io.md) (search: "## Lesson: Non-fatal filesystem tests should assert behavior before errno text") - While adding M08 evidence-envelope tests, the first focused run failed because the non-fatal append-failure test expected `ENOTDIR` or "not a directory".
- [Nested template literals hide entire code regions from gruff-ts masking](gruff-cleanup.md) (search: "## Lesson: Nested template literals hide entire code regions from gruff-ts masking") - `waste.unused-import` flagged `rename` in `test/integration/dashboard-projects-api.test.ts` even though `await rename(root, moved)` was plainly used later in the file.
- [Do not convert a fix request into threshold tuning](gruff-cleanup.md) (search: "## Lesson: Do not convert a fix request into threshold tuning") - During the gruff cleanup, the user asked to fix `size` warnings.
- [Gruff JSON captures must not go through noisy npm output](gruff-cleanup.md) (search: "## Lesson: Gruff JSON captures must not go through noisy npm output") - During the M01 gruff cleanup, redirecting `npm run gruff-ts -- analyse --format json --fail-on none .` to `/tmp/goat-flow-gruff-ts-before.json` produced invalid JSON because npm wrote its script…
- [Gruff error-behavior comments need rule vocabulary](gruff-cleanup.md) (search: "## Lesson: Gruff error-behavior comments need rule vocabulary") - During M01 gruff cleanup, extracting `src/cli/facts/fs.ts` cache helpers added comments that said "read errors cache and return null", "stat errors cache and return false", and "readdir errors cache…
- [Do not leave generated gruff defaults after an init probe](gruff-cleanup.md) (search: "## Lesson: Do not leave generated gruff defaults after an init probe") - After running `gruff-ts init --force` as a probe, I left the generated default `.gruff-ts.yaml` in place while continuing hook work.
- [Verify a gruff path-ignore by directory scan, not by naming the file](gruff-cleanup.md) (search: "## Lesson: Verify a gruff path-ignore by directory scan, not by naming the file") - After adding `*.css` / `/*.css` to `paths.ignore` in `.gruff-ts.yaml`, I tried to verify it by running `gruff-ts analyse src/dashboard/styles.css` directly.
- [Confirm gruff unused-import findings before deleting imports](gruff-cleanup.md) (search: "## Lesson: Confirm gruff unused-import findings before deleting imports") - During the gruff findings cleanup, I treated `waste.unused-import` findings as safe mechanical removals.
- [Check staged deletions after bulk gruff rewrites](gruff-cleanup.md) (search: "## Lesson: Check staged deletions after bulk gruff rewrites") - During the gruff naming cleanup, a mechanical rewrite left unrelated test files staged as deleted.
- [Run cheap style gates before expensive gruff verification](gruff-cleanup.md) (search: "## Lesson: Run cheap style gates before expensive gruff verification") - During the gruff naming cleanup, the full `npm test` run reached the installer round-trip fixture and failed its temp-repo preflight because local style gates still had issues: ESLint flagged a…
- [Size refactors must preserve browser script load graphs in tests](gruff-cleanup.md) (search: "## Lesson: Size refactors must preserve browser script load graphs in tests") - While splitting dashboard and terminal classic-script files to clear gruff `size` findings, the first focused terminal-launch suite failed because the VM test helper still loaded only the old…
- [Static source-shape tests must follow helper extractions](gruff-cleanup.md) (search: "## Lesson: Static source-shape tests must follow helper extractions") - During M01 dashboard state-fragment gruff cleanup, extracting the detached-terminal predicate from `dashboardAppFragment02` into `isTerminalDetached` cleared targeted gruff but the focused VM suite…
- [Dashboard asset renames need a clean dist build](gruff-cleanup.md) (search: "## Lesson: Dashboard asset renames need a clean dist build") - While renaming dashboard app fragment files, `npm run build:dashboard` compiled the new descriptive `dashboard-app-*.js` files but left the old generated numbered fragment assets in `dist/dashboard`.
- [Gruff cleanup automation must fit the hook surface](gruff-cleanup.md) (search: "## Lesson: Gruff cleanup automation must fit the hook surface") - During the same size cleanup, several long inline Node shell snippets were blocked by the guardrail hook before they could run.
- [Split tests must import their former shared scope explicitly](gruff-cleanup.md) (search: "## Lesson: Split tests must import their former shared scope explicitly") - After splitting audit-drift integration cases out of the old grouped file, the renamed files ran as standalone test modules and failed with `ReferenceError: describe is not defined`, followed by…
- [Hook tests should inspect executable lines when checking failure masking](hook-testing.md) (search: "## Lesson: Hook tests should inspect executable lines when checking failure masking") - A focused post-turn hook test failed because it searched an entire shell script for `|| true`.
- [Secret-scanner tests must not embed literal secret-shaped fixtures](hook-testing.md) (search: "## Lesson: Secret-scanner tests must not embed literal secret-shaped fixtures") - After `post-turn-safety` became the default Stop hook, the current Codex Stop command blocked this repo because the changed safety-hook test source embedded literal secret-shaped fixtures.
- [Drift render helpers must apply every hook toggle](hook-testing.md) (search: "## Lesson: Drift render helpers must apply every hook toggle") - While reducing ESLint complexity in `expectedHookConfig`, I replaced the Copilot hook-toggle loop with `Array.some`.
- [deny-dangerous self-test missed a whole false-positive class while green](hook-testing.md) (search: "## Lesson: deny-dangerous self-test missed a whole false-positive class while green") - A downstream agent hit `Policy destructive: Complex command substitution` on benign `$()` inside a `for` loop, yet `deny-dangerous.sh --self-test=smoke` reported `executed=23, skipped=0` PASS.
- [Copilot JSON hook probes must use Copilot-shaped payloads](hook-testing.md) (search: "## Lesson: Copilot JSON hook probes must use Copilot-shaped payloads") - During M07-M10 verification, I first tried to manually prove the no-jq Copilot deny path by setting `HOOK_OUTPUT_MODE=json` and invoking `deny-dangerous.sh --check`.
- [Codex sandbox hook probes must distinguish direct Bash from Node child-process](hook-testing.md) (search: "## Lesson: Codex sandbox hook probes must distinguish direct Bash from Node child-process") - During the v1.9.1 quality follow-up, I first rejected a Codex sandbox finding after `codex sandbox --permissions-profile goat-flow ... bash .goat-flow/hooks/deny-dangerous/deny-dangerous-self-test.sh…
- [Manual hook matrices must avoid live-guard self-interference](hook-testing.md) (search: "## Lesson: Manual hook matrices must avoid live-guard self-interference") - During a manual pass over `.goat-flow/hooks/deny-dangerous.sh` and `.goat-flow/hooks/gruff-code-quality.sh`, my first all-in-one shell harness was blocked by the active PreToolUse guard for having…
- [Format patched hook test fixtures before full preflight](hook-testing.md) (search: "## Lesson: Format patched hook test fixtures before full preflight") - While porting gruff-py's native changed-region hook path into `workflow/hooks/gruff-code-quality.sh`, the focused hook test, shellcheck, and typecheck passed, but the first `bash…
- [Restoring coverage by cloning a monolith is not a real split](hook-testing.md) (search: "## Lesson: Restoring coverage by cloning a monolith is not a real split") - While restoring lost pre-M10 monolith coverage after the guardrail split, I copied the old parser/checker body into all three split hooks: `patterns-shell.sh`, `patterns-paths.sh`, and…
- [Keep generated Bash regexes out of inline conditionals](hook-testing.md) (search: "## Lesson: Keep generated Bash regexes out of inline conditionals") - While regenerating the self-contained split hooks, inline Bash EREs lost escaping for `>`, `|`, `<<<`, and quote classes.
- [Dynamic hook helpers need explicit ShellCheck handling](hook-testing.md) (search: "## Lesson: Dynamic hook helpers need explicit ShellCheck handling") - After extracting `deny-dangerous.sh`, I expected `# shellcheck source=deny-dangerous.sh` above the runtime-computed source line to satisfy linting.
- [Shared hook helpers need missing-dependency runtime tests](hook-testing.md) (search: "## Lesson: Shared hook helpers need missing-dependency runtime tests") - After splitting the guard hooks through `deny-dangerous.sh`, PreToolUse started reporting hook failures with exit code 127 when a thin policy hook could not load the shared helper.
- [Codex hook commands must use the git-root wrapper shape](hook-testing.md) (search: "## Lesson: Codex hook commands must use the git-root wrapper shape") - The live Codex hook config kept reporting three PreToolUse failures with exit code 127 even after the scripts themselves passed.
- [Configured hook smoke must verify the registered guard path](hook-testing.md) (search: "## Lesson: Configured hook smoke must verify the registered guard path") - M12 found that audit and preflight smoke tests launched hook scripts directly, so they could pass even when an agent config contained a stale command string or a command shape that exited before the…
- [Hook parser regressions need false-positive grammar probes](hook-testing.md) (search: "## Lesson: Hook parser regressions need false-positive grammar probes") - M12 closed three parser gaps that the headline block tests missed: `pwsh --command` was allowed while single-dash PowerShell eval forms were blocked, `git --git-dir /tmp/repo push` was allowed while…
- [Missing-helper self-tests must close stdin](hook-testing.md) (search: "## Lesson: Missing-helper self-tests must close stdin") - `deny-dangerous-self-test.sh --self-test=full` hung on an interactive terminal while copying a thin hook into a temp directory without `deny-dangerous.sh`.
- [Normalize agent hook payload variants before field access](hook-testing.md) (search: "## Lesson: Normalize agent hook payload variants before field access") - While adding Antigravity hook payload support, I changed the guardrail jq extractor to read `.toolArgs.command` directly.
- [Hook write-block tests must vary valid CLI grammar](hook-testing.md) (search: "## Lesson: Hook write-block tests must vary valid CLI grammar") - The first GitHub CLI write-block fix covered the reported `gh issue comment ... --body-file ...` command, `gh api` writes, direct read-only controls, and one pre-topic `--repo` form.
- [Boundary payload names are not placeholder debt](naming.md) (search: "## Lesson: Boundary payload names are not placeholder debt") - During the M00 gruff cleanup, `naming.identifier-quality` reported 124 advisory findings.
- [Accept abbreviations only when the domain is obvious](naming.md) (search: "## Lesson: Accept abbreviations only when the domain is obvious") - The M00 short-variable pass found a mix of real rename targets (`r`, `af`, `a`, `b`, `m`) and project-standard abbreviations (`md`, `ws`, `fd`, `ms`, `tc`, `rl`).
- [One-letter rename sweeps can corrupt regex flags](naming.md) (search: "## Lesson: One-letter rename sweeps can corrupt regex flags") - During the M00 short-variable pass, a mechanical `m`→`manifestJson` word-boundary rewrite in `test/unit/manifest.test.ts` also rewrote the `m` regex flag on manifest markdown assertions.
- [Boolean state prefixes differ from domain flags](naming.md) (search: "## Lesson: Boolean state prefixes differ from domain flags") - During the M00 boolean-prefix pass, gruff reported 156 advisory findings across dashboard state, CLI flags, hook JSON, setup-detect DTOs, and tests.
- [Test-file rename sweeps need a focused test rerun](naming.md) (search: "## Lesson: Test-file rename sweeps need a focused test rerun") - During the gruff cleanup, a local `c`→`concern` rename in `test/unit/audit-command.test.ts` updated the first two assertions but left three later `c.*` references in the same loop.
- [Multi-agent critique finds findings single reviewers miss - but synthesis is the expensive part](review-feedback.md) (search: "## Lesson: Multi-agent critique finds findings single reviewers miss - but synthesis is the expensive part") - A multi-agent critique run on goat-flow v1.1.0 surfaced more defects than any single reviewer caught alone.
- [Blindly applying review feedback without verifying findings](review-feedback.md) (search: "## Lesson: Blindly applying review feedback without verifying findings") - After receiving 8 critic reviews of the goat-flow framework, the agent started fixing every cited `file:line` without first checking whether the findings were still valid.
- [14 self-dogfooding bugs survived 9 rounds of critique and 17 milestones](review-feedback.md) (search: "## Lesson: 14 self-dogfooding bugs survived 9 rounds of critique and 17 milestones") - After M17, 6 external critics independently reviewed the goat-flow framework itself (not installed projects).
- [Blindly applying critique recommendations without verifying claims](review-feedback.md) (search: "## Lesson: Blindly applying critique recommendations without verifying claims") - A critique agent claimed `.goat-flow/architecture.md` (search: `20 build checks`) had the wrong build-check breakdown: "says 7+9, actual code shows 12+4." The claim was accepted at face value and the…
- [Structural audit passing hides cold-path content drift (8-critique finding)](review-feedback.md) (search: "## Lesson: Structural audit passing hides cold-path content drift (8-critique finding)") - Eight independent critiques (3 Claude, 5 Codex) reviewed the goat-flow v1.1.0 setup on its own repo.
- [Cross-critique review catches cold-path drift that single reviews and preflight miss](review-feedback.md) (search: "## Lesson: Cross-critique review catches cold-path drift that single reviews and preflight miss") - A single diff review of 89 files on feat/1.1.0 found 2 cross-reference breakages (setup prompt, code-map skill tree).
- [Verification rationalization anti-patterns](review-feedback.md) (search: "## Lesson: Verification rationalization anti-patterns") - The 5 hallucination red-flags in AGENTS.md:51-58 forbid claims without evidence (tests pass, completion, fix verification, hedged claims, check passed).
- [External code-review bots that re-run verification commands in their own sandbox produce false-positive Critical findings](review-feedback.md) (search: "## Lesson: External code-review bots that re-run verification commands in their own sandbox produce false-positive Critical findings") - Triaging bot review feedback on PR #44, CodeRabbit raised three findings tagged Critical 🔴 / Major 🟠 across multiple inline comments: - `npm run typecheck` exits non-zero with `TS2307: Cannot find…
- [Ordering findings ("section X must be first") are grep-position-independent - rate them by how the artifact is consumed](review-feedback.md) (search: "## Lesson: Ordering findings (") - A 3-agent goat-critique of `workflow/skills/playbooks/` reached HIGH consensus that the README's "first section MUST be `## Availability Check`" rule was violated by `gruff-code-quality.md` (leads…
- [Agents given broad setup tasks rewrite shared docs as agent-specific](setup-and-migration.md) (search: "## Lesson: Agents given broad setup tasks rewrite shared docs as agent-specific") - Gemini CLI was asked to set up GOAT Flow.
- [Setup agents propagate errors from existing instruction files](setup-and-migration.md) (search: "## Lesson: Setup agents propagate errors from existing instruction files") - Rampart's CLAUDE.md had `redaction.rs` (doesn't exist - redaction is Python only).
- [Agents under line pressure cut "small but required" sections](setup-and-migration.md) (search: "## Lesson: Agents under line pressure cut") - Both rampart and sus-form-detector agents dropped Sub-Agent Objectives (f) and Communication When Blocked (g) when compressing CLAUDE.md toward the line target.
- [Agents resolve contradictions by following whichever source they read first](setup-and-migration.md) (search: "## Lesson: Agents resolve contradictions by following whichever source they read first") - A retired pre-v1.1 system-spec document showed the old 5-step execution loop while `workflow/setup/reference/execution-loop.md` had the updated 6-step version with SCOPE.
- [Removing a concept requires full-repo grep, not just code grep](setup-and-migration.md) (search: "## Lesson: Removing a concept requires full-repo grep, not just code grep") - Shape removed from scanner code (ADR-002) but `[APP / LIBRARY / SCRIPT COLLECTION]` survived in 9 setup/workflow/doc files.
- [Optional setup fields need harness verification too](setup-and-migration.md) (search: "## Lesson: Optional setup fields need harness verification too") - `toolchain` and `ask_first` were removed from the shipped 1.1.0 config scaffold and setup flow to keep base setup smaller, and a 1.2.0 revisit task was added.
- [Optional workflow state must not become audit or quality gates](setup-and-migration.md) (search: "## Lesson: Optional workflow state must not become audit or quality gates") - The dashboard rated Recovery low because audit treated unchecked `.goat-flow/plans/` milestone checkboxes as degraded recovery.
- [Installed settings.json deny patterns drifted from workflow templates undetected](setup-and-migration.md) (search: "## Lesson: Installed settings.json deny patterns drifted from workflow templates undetected") - Multi-agent quality reports found `.claude/settings.json` had `Bash(*git push*--force*)` while the workflow template (`workflow/hooks/agent-config/claude.json`) had the correct `Bash(*git push*)`.
- [mv/rename overwrites destination file without checking if it exists](setup-and-migration.md) (search: "## Lesson: mv/rename overwrites destination file without checking if it exists") - User asked to rename `TODO_improvements_v0.3.md` to `TODO_improvements_v0.4.md`.
- [The session shell's `grep` is a ugrep wrapper that silently skips gitignored paths](test-execution-environment.md) (search: "## Lesson: The session shell's `grep` is a ugrep wrapper that silently skips gitignored paths") - During the M02b review, `grep -rl "plan-checkbox-guard" .goat-flow --include="*.md"` returned nothing even though `.goat-flow/plans/1.12.0/M02b-plan-checkbox-guard.md` and ADR-038 matched when…
- [Hook tests should feed stdin through files when child `cat` must see EOF](test-execution-environment.md) (search: "## Lesson: Hook tests should feed stdin through files when child `cat` must see EOF") - While implementing M02b, the retired plan checkbox guard integration test repeatedly timed out when it invoked the hook with `spawnSync("bash", [HOOK_PATH], { input: payload })`.
- [Directory targets can break Node's test runner](test-execution-environment.md) (search: "## Lesson: Directory targets can break Node's test runner") - While executing `.goat-flow/plans/1.12.0/M01-verification-score-spike-and-decision.md`, the milestone's baseline command `node --import tsx --test test/unit/` failed before running tests: Node…
- [Test runners need CI-runtime reproduction when local Node is newer](test-execution-environment.md) (search: "## Lesson: Test runners need CI-runtime reproduction when local Node is newer") - PR #48 local verification ran on Node 22 and passed the programmatic `node:test` runner path.
- [Real-timer terminal smoke tests need isolated verification](test-execution-environment.md) (search: "## Lesson: Real-timer terminal smoke tests need isolated verification") - During `docs.missing-internal-function-doc` cleanup, a combined focused command that grouped the dashboard smoke test with heavier unit suites failed `uses the fallback deadline when runner output…
- [Browser terminal fixes need live runner proof, not just timer-unit proof](test-execution-environment.md) (search: "## Lesson: Browser terminal fixes need live runner proof, not just timer-unit proof") - While fixing dashboard setup prompt submission, the focused terminal unit tests passed but the browser-use reproduction still stopped at Claude's `[Pasted text #1 +18 lines]` composer placeholder.
- [`node --import <abs-path>` on Windows needs a file:// URL](test-execution-environment.md) (search: "## Lesson: `node --import <abs-path>` on Windows needs a file:// URL") - Two `runCLI` test helpers (`test/unit/quality-command.test.ts`, `test/integration/quality-history-diff.test.ts`) passed `join(PROJECT_ROOT, "node_modules", "tsx", "dist", "loader.mjs")` to…
- [Windows test runs require explicit EPERM handling for symlink fixtures](test-execution-environment.md) (search: "## Lesson: Windows test runs require explicit EPERM handling for symlink fixtures") - Three tests (`main-module guard via symlink`, `skips symlink entries in skill walk roots`, `rejects upload paths that escape through symlinked components`) call `fs.symlinkSync()` to build fixtures.
- [`npm test -- <file>` can still run the full suite](test-execution-environment.md) (search: "## Lesson: `npm test -- <file>` can still run the full suite") - A focused verification run used `npm test -- test/unit/quality-command.test.ts`, expecting only the quality prompt tests to run.
- [Test suite must exercise the published invocation path](test-execution-environment.md) (search: "## Lesson: Test suite must exercise the published invocation path") - Commit 918ca3e wrapped the bare `main().catch(...)` call in an `import.meta.url` guard to prevent side effects on import.
- [Source-mode CLI proof does not refresh the package binary](test-execution-environment.md) (search: "## Lesson: Source-mode CLI proof does not refresh the package binary") - A static detector patch made `node --import tsx src/cli/cli.ts audit . --harness --agent claude` pass, but the exact user-facing reproduction `npx goat-flow audit . --harness --agent claude` still…
- [Focused TypeScript tests in this repo need the `tsx` loader](test-execution-environment.md) (search: "## Lesson: Focused TypeScript tests in this repo need the `tsx` loader") - The first focused verification run used `node --test test/smoke/dashboard-endpoints.test.ts` and failed with `ERR_MODULE_NOT_FOUND` while resolving the source module at `src/cli/server/terminal.ts`.
- [Serve local HTML over localhost for browser-use evidence](test-execution-environment.md) (search: "## Lesson: Serve local HTML over localhost for browser-use evidence") - During M12 browser-use verification, `browser-use open file:///home/devgoat/projects/goat-flow/docs/site/goat-flow-landing.html` succeeded at navigation but `browser-use state` returned `Empty DOM…
- [Browser-use installer smoke must exercise the wrapper path](test-execution-environment.md) (search: "## Lesson: Browser-use installer smoke must exercise the wrapper path") - While fixing browser-use availability, `browser-use doctor` and direct Python Playwright launch passed, but `browser-use open https://example.com` failed with a 30s `BrowserStartEvent` timeout.
- [Shared npm build scripts must avoid shell builtins on Windows](test-execution-environment.md) (search: "## Lesson: Shared npm build scripts must avoid shell builtins on Windows") - `npm run dashboard` failed on Windows during `build:dashboard` with `The syntax of the command is incorrect.` even though Git's Unix tools were available on `PATH`.
- [A hook's silent output is not proof of non-execution - verify through the test harness](test-execution-environment.md) (search: "## Lesson: A hook's silent output is not proof of non-execution - verify through the test harness") - Proving the gruff-code-quality hook no longer discovers binaries from the removed `*/.venv/bin` glob or `target/debug` paths (ADR-032), I wrote ad-hoc bash repros that ran the old and new hook…
- [`git archive` is not a clean-clone proof when tests require `.git`](test-execution-environment.md) (search: "## Lesson: `git archive` is not a clean-clone proof when tests require `.git`") - During M09 clean-checkout verification, `git archive HEAD | tar -x` produced a no-`dist/` tree, but `npm test` failed five deny-hook audit tests.
- [`npx vitest` is not this repo's runner and trips on `_temp/stryker-tmp` sandboxes](test-execution-environment.md) (search: "## Lesson: `npx vitest` is not this repo's runner and trips on `_temp/stryker-tmp` sandboxes") - Verifying goat-debug skill edits, I ran `npx vitest run test/contract/skill-hardening-contracts.test.ts test/unit/check-content-quality.test.ts`.
- [Migration-output fixtures must match the collision branch](test-fixtures.md) (search: "## Lesson: Migration-output fixtures must match the collision branch") - While adding the M04 installer migration fixtures, the first `setup-install.test.ts` run failed because the legacy skill-doc test expected a whole-directory move message.
- [CI must use package test scripts after suite splits](test-fixtures.md) (search: "## Lesson: CI must use package test scripts after suite splits") - PR #45 split the audit-drift and dashboard integration tests into standalone files and updated `package.json` so fast tests exclude stateful dashboard suites while `test:slow` runs them serially.
- [Workflow parser refactors need both fixture coverage and typecheck](test-fixtures.md) (search: "## Lesson: Workflow parser refactors need both fixture coverage and typecheck") - While tightening CI-validation checks, the first pass on the workflow `run:` parser read the wrong regex capture group and then used a router heuristic that only matched commands containing the word…
- [Rubric honesty changes need both in-memory and disk-backed fixture sync](test-fixtures.md) (search: "## Lesson: Rubric honesty changes need both in-memory and disk-backed fixture sync") - Tightened `2.2.2` so a registered stop hook only passes when it also runs real validation commands.
- [New blocking checks can break passing fixtures even when the scanner is correct](test-fixtures.md) (search: "## Lesson: New blocking checks can break passing fixtures even when the scanner is correct") - Added a new deny-hook check for pipe-to-shell blocking.
- [Snapshot fixtures can carry metadata beyond the typed numeric contract](test-fixtures.md) (search: "## Lesson: Snapshot fixtures can carry metadata beyond the typed numeric contract") - A backfill for missing v1.2.0–v1.2.4 manifest snapshots added a repo-integration test that `deepEqual`ed `loadSnapshotFacts()` output against numeric expectations.
- [Stats fixtures need real files for line-reference assertions](test-fixtures.md) (search: "## Lesson: Stats fixtures need real files for line-reference assertions") - While adding ADR-024 enforcement to `stats --check`, the first integration test fixture used `package.json` with a line suffix to trigger an `invalid-line-ref` finding.
- [Snapshot-table updates must verify the snapshot files, not infer from live state](test-fixtures.md) (search: "## Lesson: Snapshot-table updates must verify the snapshot files, not infer from live state") - While updating the preset catalog contract after intentionally removing built-in prompts, I added v1.3.1, v1.3.2, and v1.4.0 to the snapshot-claim test expectations.
- [Audit check tests should assert the public failure field](test-fixtures.md) (search: "## Lesson: Audit check tests should assert the public failure field") - While tightening the execution-loop smoke check, the first focused `test/unit/audit-command.test.ts` run failed because the new regression asserted that `CheckResult.failure.message` would contain…
- [Fixture-heavy tests need a higher setup-bloat threshold](test-fixtures.md) (search: "## Lesson: Fixture-heavy tests need a higher setup-bloat threshold") - During the M00 gruff cleanup, `test-quality.setup-bloat` reported 158 advisory findings at the default 12-line threshold.
- [Formatter verification must preserve repo style flags](verification-preflight.md) (search: "## Lesson: Formatter verification must preserve repo style flags") - While tightening scanner messages, verification included a `prettier --write` pass on three rubric files without the repo's single-quote flag.
- [Repo-wide preflight can be blocked by unrelated formatter drift](verification-preflight.md) (search: "## Lesson: Repo-wide preflight can be blocked by unrelated formatter drift") - After deleting the dedicated setup validator and rewiring preflight around the remaining script surface, focused verification passed (`shellcheck`, `npm run typecheck`, targeted smoke/unit tests, and…
- [Temp-repo preflight harnesses inherit formatting debt from copied test files](verification-preflight.md) (search: "## Lesson: Temp-repo preflight harnesses inherit formatting debt from copied test files") - The new M14 round-trip integration test cloned the repo into a tmpdir, patched the temp copy, and ran `bash scripts/preflight-checks.sh`.
- [Preflight PASS output still needs exit-status proof](verification-preflight.md) (search: "## Lesson: Preflight PASS output still needs exit-status proof") - During the M04 directory restructure closeout, `bash scripts/preflight-checks.sh` rendered `PASS 49 checks · 0 warnings · 54.0s`, but the process returned exit code 1.
- [New server helper files still count as repo-wide formatting debt](verification-preflight.md) (search: "## Lesson: New server helper files still count as repo-wide formatting debt") - Extracting setup-detection helpers out of `src/cli/server/dashboard.ts` passed `npm run typecheck` and the focused dashboard integration suite, but `bash scripts/preflight-checks.sh` still failed.
- [New tests need formatter gate before verification claims](verification-preflight.md) (search: "## Lesson: New tests need formatter gate before verification claims") - Added source coverage for the M01 security preset contract and the focused test passed, but `npx prettier --check src/dashboard/preset-prompts.json <changed test file>` failed on the new file.
- [Slow installer round-trip catches prompt/test lint debt](verification-preflight.md) (search: "## Lesson: Slow installer round-trip catches prompt/test lint debt") - After fixing quality-prompt and audit-provenance issues, `npm run test:slow` failed in `checkDrift: installer round-trip fixture` because the temp repo's preflight reported one ESLint error and one…
- [Final verification gates need supported scopes and captured logs](verification-preflight.md) (search: "## Lesson: Final verification gates need supported scopes and captured logs") - During the M30-M34 closeout, I ran an ad hoc ESLint command that included ignored test files and a `.mjs` helper outside the TypeScript ESLint project, producing a tooling failure unrelated to the…
- [New dependency-audit gates need a baseline audit first](verification-preflight.md) (search: "## Lesson: New dependency-audit gates need a baseline audit first") - While adding `npm audit` to preflight and CI, the first fresh audit failed on the existing direct `ws@8.20.0` dependency.
- [Dependency-audit gates can mutate lockfile metadata](verification-preflight.md) (search: "## Lesson: Dependency-audit gates can mutate lockfile metadata") - During M08 self-review, `package-lock.json` appeared in `git status` only after the final `npm test` / `bash scripts/preflight-checks.sh` verification pass.
- [Format touched TypeScript tests before repo-wide preflight](verification-preflight.md) (search: "## Lesson: Format touched TypeScript tests before repo-wide preflight") - While implementing quality-assessment follow-ups, focused tests and `npm run typecheck` passed, but the first `bash scripts/preflight-checks.sh` run failed at Prettier with `2 unformatted files`.
- [Untracked source-shadow files can poison lint, formatter, and drift gates together](verification-preflight.md) (search: "## Lesson: Untracked source-shadow files can poison lint, formatter, and drift gates together") - A tiny Prompts view color tweak looked unrelated to the TypeScript gates, but the first verification rerun still failed preflight and the installer round-trip fixture.
- [Shared hook refactors need both hook-local proof and repo-wide preflight](verification-preflight.md) (search: "## Lesson: Shared hook refactors need both hook-local proof and repo-wide preflight") - A guardrail-hook hardening pass looked correct after the first edit, but the canonical self-test immediately failed because `BASH_REMATCH` was reused after a recursive command-check helper.
- [Hook renames must include learning-loop and router-table drift](verification-preflight.md) (search: "## Lesson: Hook renames must include learning-loop and router-table drift") - The M10 split from the old command-safety hook to three guardrail hooks passed focused hook self-tests and the fast test suite, but `bash scripts/preflight-checks.sh` still failed.
- [New harness checks need count locks and provenance date proof](verification-preflight.md) (search: "## Lesson: New harness checks need count locks and provenance date proof") - Adding the `evidence-before-claims` harness metric passed focused check tests, but the full suite still failed because a provenance-schema count lock expected the old registered-check total.
- [Learning-loop content gates need tracked, durable paths](verification-preflight.md) (search: "## Lesson: Learning-loop content gates need tracked, durable paths") - Multiple verification failures came from citing paths that were not durable repo truth: gitignored task files in ADRs, ignored `.goat-flow` paths hidden by normal `rg`, unresolved optional skill-path…
- [Pipe input cannot share stdin with heredoc scripts](verification-preflight.md) (search: "## Lesson: Pipe input cannot share stdin with heredoc scripts") - While adding npm override review logic to `scripts/dependency-update.sh`, the first verification run failed ShellCheck with `SC2259` because the code piped `npm view ... --json` into `node…
- [Preflight TypeScript gates include Knip binary policy and touched-test formatting](verification-preflight.md) (search: "## Lesson: Preflight TypeScript gates include Knip binary policy and touched-test formatting") - During the M07-M10 closeout, focused hook checks, typecheck, focused tests, `npm test`, and `npm publish --dry-run` were clean, but the first full `bash scripts/preflight-checks.sh` still failed in…
- [Verification grep patterns must not carry Markdown backticks into Bash](verification-preflight.md) (search: "## Lesson: Verification grep patterns must not carry Markdown backticks into Bash") - During the M04 review-cleanup verification, a stale-path `rg` sweep embedded a Markdown-formatted fragment inside a double-quoted shell pattern.
- [Hook fallback fixes must preserve the caller-visible failure signal](verification-testing.md) (search: "## Lesson: Hook fallback fixes must preserve the caller-visible failure signal") - During PR #47 follow-up fixes, the first deny-dangerous fallback patch set the unsafe JSON status inside helper functions called through command substitution.
- [Gruff-driven direct imports must preserve facade proof](verification-testing.md) (search: "## Lesson: Gruff-driven direct imports must preserve facade proof") - During `test-quality` cleanup, gruff's nearby-test requirement pushed several tests from public facade imports to implementation-module imports.
- [Security parser fixes need focused parser proof](verification-testing.md) (search: "## Lesson: Security parser fixes need focused parser proof") - During the M00 security cleanup, I replaced dynamic `bash -lc` hook smoke execution with fixed-vector guard-script execution.
- [Gruff side-effect comments must name the side effect](verification-testing.md) (search: "## Lesson: Gruff side-effect comments must name the side effect") - During the M00 gruff docs continuation, the first internal-helper comment batch cleared `docs.missing-internal-function-doc` but left the full snapshot at only 175 findings down because gruff then…
- [Cache-behaviour tests need observable contracts](verification-testing.md) (search: "## Lesson: Cache-behaviour tests need observable contracts") - While replacing a flaky Quality cache timing assertion, my first counter-based test tried to observe deny-hook self-test executions by monkeypatching `child_process.execFileSync`.
- [Reference-pack wording fixes must check word budget immediately](verification-testing.md) (search: "## Lesson: Reference-pack wording fixes must check word budget immediately") - Wording/schema edits repeatedly breached ADR-023 word caps: `skill-quality-testing/tdd-iteration.md` hit 3022/3008 words, `skill-preamble.md` exceeded 1500, and on 2026-05-22 proof-class fields…
- [Source-regex dashboard tests must tolerate formatter reflow](verification-testing.md) (search: "## Lesson: Source-regex dashboard tests must tolerate formatter reflow") - While fixing dashboard terminal paste submission, focused `test/unit/dashboard-terminal-launch.test.ts` first passed.
- [Regressions caught too late - tests run at milestone granularity, not edit granularity](verification-testing.md) (search: "## Lesson: Regressions caught too late - tests run at milestone granularity, not edit granularity") - Claude Insights reported 68 buggy-code friction events across 112 sessions (61% of sessions had at least one).
- [Semantic drift checks must normalize natural-language lists before claiming mismatch](verification-testing.md) (search: "## Lesson: Semantic drift checks must normalize natural-language lists before claiming mismatch") - A new semantic-drift check was added for the runner list in `docs/dashboard.md`.
- [Filtered manifest ids still need explicit indexed-lookup proof in TypeScript](verification-testing.md) (search: "## Lesson: Filtered manifest ids still need explicit indexed-lookup proof in TypeScript") - A manifest-backed registry cleanup reused one `loadManifest().agents` snapshot per public call and filtered configured ids with `isKnownAgentId()`.
- [guardrail self-test needs no-space redirect and false-positive probes](verification-testing.md) (search: "## Lesson: guardrail self-test needs no-space redirect and false-positive probes") - `bash .claude/hooks/deny-dangerous-self-test.sh --self-test=full` passed, but live repros still showed a bypass for `echo foo>.env`, `echo foo>>.env`, `echo foo>|.env`, and `echo foo>.env.example`…
- [Shell metacharacters in verification searches can corrupt source files](verification-testing.md) (search: "## Lesson: Shell metacharacters in verification searches can corrupt source files") - During M05b verification, a malformed `rg` command accidentally left a literal `>` outside the quoted search pattern.
- [Contract tests pin doctrine wording and path semantics](verification-testing.md) (search: "## Lesson: Contract tests pin doctrine wording and path semantics") - While removing one forbidden phrase and changing dashboard quality report ownership, the first full `npm test` run failed two contract-style checks: `test/contract/skill-hardening-contracts.test.ts`…
- [Split transient preflight test failures from task regressions](verification-testing.md) (search: "## Lesson: Split transient preflight test failures from task regressions") - A quality-report fix removed the ESLint error that had been blocking `bash scripts/preflight-checks.sh`.
- [Temp cleanup must satisfy destructive-command hooks](verification-testing.md) (search: "## Lesson: Temp cleanup must satisfy destructive-command hooks") - While smoke-testing `scripts/install-browser-tools.sh` wrapper-guard behavior, a temp-directory cleanup command used `rm -rf "$tmpdir"`.
- [Hook regex edits need syntax probes before self-test fanout](verification-testing.md) (search: "## Lesson: Hook regex edits need syntax probes before self-test fanout") - While hardening the git-mutation guardrail against quoted and wrapper-prefixed `git push` bypasses, the first focused self-test failed every safe case because a Bash `[[ =~ ]]` expression with an…
- [Scanner hardening must test block and allow cases together](verification-testing.md) (search: "## Lesson: Scanner hardening must test block and allow cases together") - During M08 post-turn safety hardening, live probes showed three false negatives: bare `sk-...` tokens, `export API_KEY=...`, and quoted credential assignments containing `#`.
- [Scanner scope gates need parser-shape fixtures for each claimed file family](verification-testing.md) (search: "## Lesson: Scanner scope gates need parser-shape fixtures for each claimed file family") - While reducing `post-turn-safety` generic credential-assignment false positives, I scoped `scan_env_assignment` to env/config-shaped files and included Dockerfiles in that scope.
- [Coverage classification by filename misjudges in both directions](verification-testing.md) (search: "## Lesson: Coverage classification by filename misjudges in both directions") - While authoring a worked Audit example for the goat-qa skill, I classified `src/cli/audit/` coverage from same-name unit-test files alone: I marked `check-goat-flow.ts` NONE (no…
- [Stryker sandboxes need local-state ignores and mutation-safe test selection](verification.md) (search: "## Lesson: Stryker sandboxes need local-state ignores and mutation-safe test selection") - The first `scripts/mutation-test.sh` audit-engine run failed before mutation testing because Stryker copied gitignored `.goat-flow/scratchpad` content into its sandbox.
- [Gruff comment fixes must satisfy both humans and the analyzer](verification.md) (search: "## Lesson: Gruff comment fixes must satisfy both humans and the analyzer") - During gruff docs cleanup, comments in `src/cli/server/decoders.ts` made sense to a maintainer but still failed `docs.magic-threshold-without-rationale`, `docs.missing-error-behavior-doc`, and…
- [Gruff hook compatibility probes need real configs and wrapper PATH](verification.md) (search: "## Lesson: Gruff hook compatibility probes need real configs and wrapper PATH") - While verifying `workflow/hooks/gruff-code-quality.sh` against `/home/devgoat/projects/gruff-workspace/gruff-go`, `gruff-php`, `gruff-py`, and `gruff-rs`, the first hook-shaped probes failed or…
- [Gruff doc comments can expose hidden complexity warnings](verification.md) (search: "## Lesson: Gruff doc comments can expose hidden complexity warnings") - Adding a maintainer comment to `src/dashboard/app.ts` `_uploadTerminalImages` cleared a docs finding but exposed new `complexity.npath` and `design.god-function` warnings.
- [docs.missing-internal-function-doc must not be silenced; baseline the residue](verification.md) (search: "## Lesson: docs.missing-internal-function-doc must not be silenced; baseline the residue") - Gruff-ts reported 337 `docs.missing-internal-function-doc` findings across 73 files.
- [RegExp constructor assertions need a real escape helper](verification.md) (search: "## Lesson: RegExp constructor assertions need a real escape helper") - While adding a hook smoke test for extension-based gruff binary selection, the first assertion escaped path separators for a `RegExp` constructor with `replaceAll("/", "\\\\/")`.
- [Harness fixture counts must match the reported unit](verification.md) (search: "## Lesson: Harness fixture counts must match the reported unit") - During the gruff documentation pass on `src/cli/audit/harness/check-verification.ts`, the focused evidence-before-claims test failed because the fixture expected `4 present instruction file` even…
- [Validators can require explicit inventories and phrases despite README pointers](verification.md) (search: "## Lesson: Validators can require explicit inventories and phrases despite README pointers") - Replacing explicit playbook filenames in `.goat-flow/architecture.md` with a README pointer failed `skill-playbook-inventory-drift`; replacing instruction Key Resources examples with only an index…
- [Header-only edits leave bodies contradicting the new scope](verification.md) (search: "## Lesson: Header-only edits leave bodies contradicting the new scope") - I updated status/dependency headers across several milestone files and reframed M11, but left body sections, deferred items, field names, and one filename contradicting the new scope.
- [Browser-verifying local source needs `npm run dev`, not `npx goat-flow dashboard`](verification.md) (search: "## Lesson: Browser-verifying local source needs `npm run dev`, not `npx goat-flow dashboard`") - Verifying the new dashboard skill-quality workbench in a browser, ran `npx goat-flow dashboard .` to launch the dashboard.
- [Behavior-scope changes need assertion updates before the first focused run](verification.md) (search: "## Lesson: Behavior-scope changes need assertion updates before the first focused run") - Several behavior-scope changes updated the main implementation but missed adjacent assertions: setup remediation still expected `--harness --agent codex`, `/goat-plan` prompts still expected…
- [Defensive session rechecks can conflict with TypeScript narrowing](verification.md) (search: "## Lesson: Defensive session rechecks can conflict with TypeScript narrowing") - While chunking dashboard terminal initial prompt writes, the first `npm run typecheck` failed with `TS2367` because the loop checked `session.status === "terminated"` after an earlier guard had…
- ["Double check" means read the files, not re-run the tests](verification.md) (search: "## Lesson:") - User asked to "double check" multiple times.
- [New validators must run against the live repo before closeout](verification.md) (search: "## Lesson: New validators must run against the live repo before closeout") - M06 added decision-file validation and the fixture tests passed, but the first live `node --import tsx src/cli/cli.ts stats . --check` run failed against existing ADR files and one stale lesson…
- [Agent doesn't tick milestone checkboxes (recurrence x4, unresolved)](verification.md) (search: "## Lesson: Agent doesn't tick milestone checkboxes (recurrence x4, unresolved)") - The agent completes milestone tasks but ticks zero checkboxes.
- [Heading regexes can silently truncate router-table checks](verification.md) (search: "## Lesson: Heading regexes can silently truncate router-table checks") - Tightened `2.4.3` to parse the Router Table directly, but the first extractor used a multiline regex with `$` in the lookahead.
- [Path normalization can invalidate later path-shape heuristics](verification.md) (search: "## Lesson: Path normalization can invalidate later path-shape heuristics") - After normalizing router references by trimming trailing slashes, the follow-up `2.4.3` filter still looked for the literal substring `/skills/`.
- [Parallel sessions need concurrency-safe file patterns](verification.md) (search: "## Lesson: Parallel sessions need concurrency-safe file patterns") - Observed during parallel Claude sessions: two agents writing to the same learning-loop file simultaneously.
- [Manifest canonical vs stale_names misclassification silently broke skill installs](verification.md) (search: "## Lesson: Manifest canonical vs stale_names misclassification silently broke skill installs") - `workflow/manifest.json` and `src/cli/constants.ts` both listed only `"goat"` as canonical even though the installer and repo shipped seven skills.
- [Redundant context files survive architecture changes because nobody measures token cost](verification.md) (search: "## Lesson: Redundant context files survive architecture changes because nobody measures token cost") - RULES.md (432 words, 6 sections) loaded on every `/goat` dispatch was almost entirely duplicated from CLAUDE.md and skill-preamble.md.
- [Dashboard API reviews need invalid-path assertions, not just happy-path shape checks](verification.md) (search: "## Lesson: Dashboard API reviews need invalid-path assertions, not just happy-path shape checks") - The new dashboard HTTP integration suite initially focused on successful responses and basic endpoint reachability.
- [New dashboard assets must work in both built and source-run server paths](verification.md) (search: "## Lesson: New dashboard assets must work in both built and source-run server paths") - Moving the dashboard preset catalog into `src/dashboard/preset-prompts.json` compiled cleanly and updated the production build copy step, but the first focused verification run failed every…
- [Shared runtime helpers must be re-owned explicitly during server splits](verification.md) (search: "## Lesson: Shared runtime helpers must be re-owned explicitly during server splits") - Extracting the dashboard terminal concern into `src/cli/server/dashboard-terminal.ts` compiled most of the new code, but the first verification run still failed `npm run typecheck`.
- [Repeated doc claims need grep verification after the first patch](verification.md) (search: "## Lesson: Repeated doc claims need grep verification after the first patch") - A small doc-only fix changed one `Sessions rail (cap=7)` claim to `cap=10`, but the first patch missed a second occurrence later in the same release note and briefly introduced a copy-edit typo in…
- [Copilot instruction line caps count trailing newlines](verification.md) (search: "## Lesson: Copilot instruction line caps count trailing newlines") - A v1.3.0 version-bump pass added one Essential Commands line to `.github/copilot-instructions.md`.
- [Runtime hook messages must stay paired with agent-config templates](verification.md) (search: "## Lesson: Runtime hook messages must stay paired with agent-config templates") - Updated `.github/hooks/hooks.json` to improve the PowerShell fallback message, then the first `bash scripts/preflight-checks.sh` run failed `Agent Config Parity` because…
