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
8 changes: 7 additions & 1 deletion AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ plugins/dev-workflow/
CHANGELOG.md # every manifest version, newest first
skills/{intake,harden-finding}/SKILL.md
agents/finding-triage.md # read-only PR-comment checker (convention-loaded)
commands/{workflow-init,process-pr-review}.md
commands/{workflow-init,process-pr-review,claude-init}.md
hooks/{hooks.json,codex-gate.sh,codex-gate.test.sh}
hooks/fixtures/ # captured PostToolUse payloads the suite replays
examples/ # ships, but never scaffolded — one stack's answers
Expand Down Expand Up @@ -237,6 +237,12 @@ reader can judge whether it still holds.
its most frequent site. Before any rename or delete:
`grep -rn "<old name/anchor>"` across the repo *and* the inline templates. The same
applies to adding files: the layout tree above is part of the surface that drifts.
- **Never splice data into shell source a prompt tells the agent to run without bounding it.**
A value filled into a command or here-document — a directory name, a user's answer — is shell
text once it is there, and a quoted here-document delimiter stops expansion but not a line that
ends the document. State the rule the value must meet, the check, and what happens when it fails.
`claude-init`'s project name did not, and one containing a line break could run the rest of the
template as commands (PR #27). Nothing mechanical finds this; it is a reading check.
- **No dependency-freshness policy applies by ecosystem here** — this repo has no
package manager and no runtime dependencies. Invariant 5 (exact pinning) is its
equivalent, and it covers the tools CI installs.
Expand Down
20 changes: 20 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,26 @@ Before implementing:
- If a simpler approach exists, say so. Push back when warranted.
- If something is unclear, stop. Name what's confusing. Ask.

### Don't guess

Applies to factual claims in every answer, not only implementation. Confidence is not evidence.

**Leave gaps visible.** Do not invent missing or ambiguous facts. State what is unknown and why. In extraction
tasks, leave unsupported fields blank where the format permits; otherwise use the format's defined missing-value
handling.

**Separate evidence from inference.** Cite the relevant source for factual conclusions. Identify deductions and
assumptions as such, with their basis. For extraction tasks, label populated fields EXTRACTED or INFERRED and
explain each inference where the required output format permits. If neither annotations nor accompanying
explanations are permitted, preserve the required format. This does not permit inventing unsupported values.

**Keep decisions distinct from facts.** Make reasonable design and implementation choices within the authorized
scope, describing them as choices rather than source facts. Ask when missing information changes correctness or
scope.

**Verify before claiming.** Report a test or action as completed only when its result was observed. Preserve
required output formats; put explanations outside structured artifacts where permitted.

## 2. Simplicity First

**Minimum code that solves the problem. Nothing speculative.**
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ Why each of these, and how to adapt them: [`docs/coding-workflow.md`](docs/codin
| `/dev-workflow:process-pr-review` | command — validates PR bot comments against the code and your invariants, replies to each, fixes regressions, tracks pre-existing issues. |
| `dev-workflow:finding-triage` | agent — read-only, fresh context, judges whether one PR-bot claim is actually true of the code. Used by the PR processor; never counts as a review gate. |
| `/dev-workflow:workflow-init` | command — scaffolds the per-project files, then interviews you to write `AGENTS.md`. |
| `/dev-workflow:claude-init` | command — writes one `CLAUDE.md` of general working rules and nothing else: no review gates, no other files. An existing `CLAUDE.md` is never overwritten; you get a proposal instead. Creating the file needs an already-installed Python 3. |
| codex-gate hook | non-blocking reminders that count Gate A and Gate B passes, and verify a Gate-B review against a fingerprint of the effective index plus the included worktree content, as of the hook's invocation — a deliberate superset of any one commit's payload, so the gate errs toward firing. Always exits 0. |

## Setup
Expand Down
2 changes: 1 addition & 1 deletion docs/architecture.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ plugins/dev-workflow/
CHANGELOG.md # every manifest version, newest first
skills/{intake,harden-finding}/SKILL.md
agents/finding-triage.md
commands/{workflow-init,process-pr-review}.md
commands/{workflow-init,process-pr-review,claude-init}.md
hooks/{hooks.json,codex-gate.sh,codex-gate.test.sh}
hooks/fixtures/ # captured PostToolUse payloads the suite replays
examples/ # ships, but never scaffolded — one stack's answers
Expand Down
1 change: 1 addition & 0 deletions docs/hardening-log.md
Original file line number Diff line number Diff line change
Expand Up @@ -125,3 +125,4 @@ escape `\|`, one line), `source` (gate-a|gate-b|bot|manual),
| 2026-08-17 | prompt-vague-criteria | first row of this base class here: §5 named "clearly stuck" as the loop's terminal state and never said how to recognize one, so a plateauing artifact could burn passes with nobody entitled to call it — in the field one 2848-line spec ran 34 Gate-A spec passes, and over the 19 that were measured the count fell from 43 to an oscillation between 2 and 7 while Blockers fell from 8 to 0-1, i.e. the substance converged and the number never did | manual | major | P std | CLAUDE.md §5 loop paragraph + the same block in the workflow-init inline template. Guard: the recognition rule — after about six passes read the Blocker curve rather than the total, and Blockers at 0-1 with every remaining finding individually fixable IS the stuck state — plus the smaller-specs guidance that follows from the same measurement. Does NOT guard a size threshold (deliberately unmeasured and shipped as guidance), and does not say where a plateau begins. |
| 2026-09-02 | docs-drift | seventh occurrence: PR #26 (CodeRabbit) — the dark-factory vision document, sitting on the same branch, still said the kit "has a fixed 3-pass floor", listed the review-economics story as "in flight" twice, and made both claims about the very change the branch ships. Every sentence was true when written and false the moment the branch merged. NEW SUB-SHAPE, and it is why this row exists rather than a note: the standing lens was carried on this cycle and the falsified file is one the diff never touches — it is not in the changed-path set, so nothing scoped to the diff could reach it, and the lens's own recipe (grep for where each changed value is described elsewhere) was run against `CLAUDE.md`'s vocabulary and not against the branch's other documents | bot | major | 1 prose | The lens now names the branch, not the diff, as its search surface: a document added or edited **anywhere on the same branch** can be falsified by a change it does not contain, and a co-shipped design document describing the current state of the thing being changed is the likeliest instance. PRIOR ROW: 2026-08-16 docs-drift (1 prose), and 2026-08-04 (P std) whose guard asks what the diff changes the size, value or position of — this finding is INSIDE that guard and outside its reach at once: the value did change and was described elsewhere, but "elsewhere" was scoped to the changed paths by everyone who ran it, including me. Repaired at the same rung, not escalated. NO DETERMINISTIC RUNG EXISTS: nothing can tell that a design document's description of current state went stale, and widening the grep to the whole branch is a recipe a human runs. It raises the floor and does not close the class |
| 2026-09-02 | verification-masks-failure | fifth occurrence: PR #26 (CodeRabbit) — Plan C task 25's completion assert tested only that the provisional wording was ABSENT (`grep -c … -eq 0`). A replacement that deleted the provisional passage and wrote no closed record at all would have passed it, which is precisely the outcome the task exists to prevent. The task did run correctly this cycle, so the mask never fired; it was found by reading, not by failing | bot | major | 4 test | The assert gained a positive arm beside the negative one: the closed curves must be PRESENT, with a cardinality floor (`grep -cE '^Findings( +[0-9]+,?)+' … -ge 3`). PRIOR ROWS under this fingerprint all share one shape — a check whose only assertion is that something is gone. WHAT GENERALIZES: an absence assert is half a check whenever the edit it guards is a replacement rather than a deletion, and the missing half is always the same one. This row's remedy is specific to task 25; the general form belongs to the loop-rule consolidation story, which owns the plan-assert conventions |
| 2026-09-25 | missing-input-validation | first row of this base class here: PR #27 (Greptile P1, thread 4091660211) — `/dev-workflow:claude-init` filled an unconstrained project name into the create command's shell here-document; a name with a line break could put the fixed delimiter on its own line, end the document early and run the rest of the name and the template as shell. Confirmed as transport under sh and dash with a harmless marker, not as an end-to-end command run | bot | blocker | 1 prose | claude-init.md *Writing* step 2 now states the rule (one line, no Unicode `Cc` character, every name source, ask on failure, nothing sanitized) and gives a Python check for a directory-derived name; spec §2 carries it. AGENTS.md Don'ts gains the class-level rule: data spliced into shell source a prompt tells the agent to run must be bounded, with the rule, the check and the failure path stated. Does NOT guard: the rule is agent-followed — the create script does not validate the name, and a user-given name is checked by reading. NO DETERMINISTIC RUNG EXISTS: nothing mechanical can tell which prompt text becomes shell source; it is a reading check |
Loading