Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .claude/agent-memory/atomic-executor/MEMORY.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
- ["Make the citation exist" deltas propagate false facts](project_preflight_citation_match_propagates_false_fact.md) — a fix that copies A's prose into B corroborates A's error in two documents; also, an epic child's issue.md promise to siblings needs a C-constraint AND a verification task
- [Check-off cites an artifact a LATER task writes](project_preflight_checkoff_cites_later_task_artifact.md) — unsatisfiable in plan order; also covers a phase-5 criterion needing an issue phase-7 opens; fix by body swap, not renumbering
- ["Skip the pointless drain" note makes a negative test vacuous](project_preflight_drain_scope_optimization_note_makes_test_vacuous.md) — a cosmetic "path X is synchronous, don't drain" note is a behavioral claim; a synchronous callee says nothing about how its caller is reached
- [Sanitisation task cannot sweep its own record](project_sanitisation_task_cannot_sweep_its_own_record.md) — exactly one residual path always remains; check the record's content constraint, not the scope
- [Conjunctive criteria break the one-artifact citation rule](project_preflight_conjunctive_criterion_citation_gap.md) — "cites exactly one artifact" makes every AC that conjoins facts from two command steps uncheckable; sweep for the second conjunct ("passes unmodified", "anywhere", "either figure")
## Build / toolchain environment
- [pwsh/git/gh CLI gotchas](project_pwsh_git_gh_cli_gotchas.md) — no jq; pwsh won't concatenate `$(git merge-base ...)..HEAD`
Expand All @@ -62,6 +63,7 @@
- [Evidence <TS> collision clobbers artifacts](project_evidence_timestamp_collision_clobbers_artifacts.md) — same-day remediation overwrites
- [csharpier pipe-files is a non-enforcing gate](project_csharpier_pipefiles_nonenforcing_gate.md) — use `csharpier check`/`format`
- [Count-idiom pitfalls: csharpier + Measure-Object](project_count_idiom_pitfalls_csharpier_and_measureobject.md) — "Formatted N" is a PROCESSED count
- [New .cs files guarantee a format-loop restart](project_new_cs_files_guarantee_a_format_loop_restart.md) — Write emits LF; budget two passes, not one
- [PowerShell new files need UTF-8 BOM](powershell-bom-required.md) — PSUseBOMForUnicodeEncodedFile
- [poshqc test MCP carries no verdict/numbers](project_poshqc_pester_mcp_exit_minus1.md) — no exit code, so count gates can't run
- [poshqc analyze exits 1 on a Warning](project_poshqc_analyze_exit1_on_warning.md) — "EXIT 0 + zero errors" is self-contradictory
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
---
name: new-cs-files-guarantee-a-format-loop-restart
description: Any plan that creates a new .cs file with the Write tool will fail its first csharpier check, because Write emits LF and csharpier demands CRLF — budget one mandatory final-QA loop restart rather than treating it as drift
metadata:
type: project
---

A C# file created with the Write tool lands with LF line endings. CSharpier reports it as
`Was not formatted. The file contained different line endings than formatting it would result in.`
So the FIRST pass of a final-QA loop over any plan that adds a new `.cs` file is always a repairing
pass, and the loop always restarts at least once. Plan for two passes, not one.

**Why:** on 2026-08-28 (feature 680, `[P6-T1]`) the pass-1 `PRE_FORMAT_CHECK_EXIT` was 1 on three
files — the two newly Written test files for line endings only, and one Edited file for line endings
plus a member-chain wrap. Pass 2 was clean. The restart is mechanical and expected; it is not
pre-existing drift and it does not mean the baseline format check was wrong. Feature 680's P0-T7
baseline check had exited 0 over 1554 files.

**How to apply:**
- Treat the first-pass `PRE_FORMAT_CHECK_EXIT: 1` as routine when every reported file is inside the
plan's own edited/created set. Record it in the P6-T1 artifact as a non-final pass, restart the
loop, and do not investigate it as drift. Only a reported file OUTSIDE that set means pre-existing
drift entered the pass.
- `git status --porcelain` before/after the format command CANNOT observe this. Those files are
already `M` or `??` and no commit exists yet, so a content rewrite leaves porcelain byte-identical.
`PRE_FORMAT_CHECK_EXIT` is the only discriminator; the porcelain pair only detects a path
ENTERING or LEAVING the changed set.
- The formatter's own `Formatted N files in Xms.` line is a PROCESSED count printed on every run,
including a run that rewrote nothing. It never discriminates. See
[[count-idiom-pitfalls-csharpier-and-measureobject]].
- Running `csharpier format` immediately after Writing each new file — before the final QA loop —
avoids the restart entirely, but only if the plan does not gate on a pristine first pass.
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
---
name: sanitisation-task-cannot-sweep-its-own-record
description: A "sanitise every committed artifact" task always leaves exactly one path unswept — its own record — so validate the record's content constraint, not the sweep scope
metadata:
type: project
---

A plan task that sanitises host identifiers out of "every path the close-out commit will
touch" can never cover its own evidence record, because the record is written after the
sweep enumerates. Broadening the sweep scope does not close this; the fix is a content
constraint on the record itself (e.g. "lists only AFTER values — quoting a BEFORE value
reintroduces the identifier into a committed file").

**Why:** Verified on issue #680 preflight round 5. `P7-T3` swept the union of
`<FEATURE>/**` and `git status --porcelain`, which provably covers everything `P7-T4`
commits *except* `<FEATURE>/evidence/other/trx-sanitisation.<ts>.md`. Chasing the scope
one level deeper is an infinite regress; the plan already carried the right mitigation.

**How to apply:** When validating a sanitisation/redaction gate, enumerate the later
commit set against the sweep set and expect exactly one residual — the gate's own record.
Confirm the plan constrains that record's *content* rather than demanding it be swept.
Two mechanical checks that make the scope claim decidable:
- `git status --porcelain` collapses untracked directories, so a "no path *name* contains
the literal" check over that half is blind to nested names. It is only safe when the
collapsed directories also fall under an independently file-enumerated half (here
`<FEATURE>/**`). Tracked-but-modified trees like `.claude/agent-memory/**` list per-file
and are not affected.
- Plan check-offs written after the sweep (e.g. the mandatory pre-commit `[x]` flip of the
final task) touch an already-swept file but add no identifier, so they are benign.

See [[project_trx_sanitisation_must_be_case_insensitive]] and
[[project_plan_checkoff_fixpoint_breaks_terminal_clean_tree_gate]].
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,25 @@ Verify with a strict parser (`xml.etree.ElementTree.parse`), not with `[xml]` in
confirm the decoded attribute value: `storage` should read `<repo-root>\...`, and the
`<UnitTestResult>` count should equal the run's test total.

### Catch the raw `<repo-root>` spelling at PREFLIGHT, not at execution

The escaping fix above is unusable once execution reaches the sanitisation task, because that task is
normally the second-to-last in the plan and the close-out task immediately after it forbids writing
anything to disk after the commit. An executor that reads this memory only when it reaches the
sanitisation task has already lost the chance to apply it without violating the clean-tree gate.

**Why:** on 2026-08-28 (feature 680, `[P7-T3]`) the plan text said "substitute ... the worktree-root
prefix -> `<repo-root>`" with the placeholder written raw. Following it literally produced five TRX
files that are no longer well-formed XML wherever a substituted path sat in an attribute value. The
task's own acceptance is three zero-hit greps plus a zero name-hit count, and all four passed, so
nothing in the task could detect it. The defect was noticed only after `[P7-T4]` had committed, at
which point amending would have dirtied the tree the close-out gate requires clean.

**How to apply:** during preflight, treat a sanitisation task that quotes a placeholder containing a
raw `<` or `>` and targets an XML-shaped artifact (TRX, coverage XML, `.csproj`) as a required plan
delta: the plan must say `&lt;repo-root&gt;`, or must state that the artifact is not required to
remain parseable. Raise it as a preflight revision, not as an execution-time judgment call.

## `/EnableCodeCoverage` drops a host-named binary INTO the evidence tree

A vstest run that combines `/EnableCodeCoverage` with an explicit `/ResultsDirectory:` pointing at
Expand Down
Loading
Loading