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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -69,3 +69,4 @@ CLAUDE.md

# Added by ggshield
.cache_ggshield
specs/*/review-transcript.jsonl
10 changes: 9 additions & 1 deletion AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -233,7 +233,7 @@ complex. **No conversational filler.**

These rules **counter agent harness defaults** that would otherwise silently win at runtime (e.g. a CLI whose default appends `Co-Authored-By` to commits). They are re-affirmed here because a default not explicitly overridden is the default that ships. Canonical source: `00_meta/patterns/pattern-git-workflow.md` §6–§9. *(Generated by the HARNESS engine via `scripts/compile-harness.sh` — edit the vault pattern, then re-run setup. Do NOT edit between the markers.)*

<!-- BEGIN HARNESS GENERATED (sha256:9bbc453bc3f4cd17) — SSOT: vault 00_meta/patterns; edit there + re-run setup, do NOT edit between markers -->
<!-- BEGIN HARNESS GENERATED (sha256:05033446ee458324) — SSOT: vault 00_meta/patterns; edit there + re-run setup, do NOT edit between markers -->
- **No AI attribution** in git history or GitHub messages (commits, PRs, issues).
- No `Co-Authored-By` trailers referencing AI agents.
- No bot-style emojis or "Generated with" footers.
Expand All @@ -257,6 +257,14 @@ Working code is not a finished change. Before saying done, each of these is true
5. **Evidence** — no completion claim without the command output that proves it, produced in this session.

Any of the five may be skipped, but only as a stated decision naming which one and why. Silence is not a skip.

> Injected verbatim into every agent's instructions (harness `enforced` id `pr-stewardship`). It elaborates Definition of Done §4 — "an open PR is not finished work" — into what that item leaves implicit: what you still owe a PR after you push it, and what does not count as having been reviewed.

**What binds is the disposition, not the waiting.** Before the change is called done, the PR's checks and its reviewer output are dispositioned — each one applied, ticketed, or declined with a reason. *How* you learn they arrived is not prescribed: a project that already tells you when to look back — the human notifies, a hook fires — has met this, and its instruction wins. Absent such a signal the default mechanism is to stay: the window closes at the first of an actionable reviewer comment or ten minutes after the checks settle, and pushing a fix reopens it, because the reviewer re-reviews. Leaving with nothing dispositioned hands the next session a change nobody read.

**A comment is not a review, and green checks are not the end of one.** Both halves have been observed failing here. On one PR every check went green and the reviewer then posted four Major findings. On another, checks went green and the reviewer posted *"review limit reached — we couldn't start this review"*: a comment arrived, and nobody looked. **A notice that no review ran leaves the PR unreviewed.** Tell the two apart by content, never by author — a review names files, lines, or claims; a notice talks about the review itself. Proceeding on an unreviewed PR is allowed; proceeding silently is not. "Merged unreviewed, reviewer quota exhausted" is a disclosure; saying nothing is a claim of review that never happened.

**A change that closes a spec gets an independent adversarial review before it archives.** The trigger is the archive gate and nothing wider — not every PR that touches a spec folder. It names an obligation that already binds mechanically, so the only question is whether you meet it deliberately or discover it as a refusal: the spec gate declines to merge a PR closing a spec's issue without archiving it, `spec archive` declines without a passing review, and the reviewer pool declines one signed by the wrong model. The reviewer must not be the implementer; that independence is the entire value.
<!-- END HARNESS GENERATED -->

### Interaction Discipline
Expand Down
10 changes: 9 additions & 1 deletion ai/claude/CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ If session start context reports memory files needing archive (>60 days cold):
## Claude Code Tooling Notes

* **Overrides of harness defaults (generated).** Sourced from the vault via `scripts/compile-harness.sh` — edit the vault pattern + re-run setup, not here:
<!-- BEGIN HARNESS GENERATED (sha256:9bbc453bc3f4cd17) — SSOT: vault 00_meta/patterns; edit there + re-run setup, do NOT edit between markers -->
<!-- BEGIN HARNESS GENERATED (sha256:05033446ee458324) — SSOT: vault 00_meta/patterns; edit there + re-run setup, do NOT edit between markers -->
- **No AI attribution** in git history or GitHub messages (commits, PRs, issues).
- No `Co-Authored-By` trailers referencing AI agents.
- No bot-style emojis or "Generated with" footers.
Expand All @@ -52,6 +52,14 @@ Working code is not a finished change. Before saying done, each of these is true
5. **Evidence** — no completion claim without the command output that proves it, produced in this session.

Any of the five may be skipped, but only as a stated decision naming which one and why. Silence is not a skip.

> Injected verbatim into every agent's instructions (harness `enforced` id `pr-stewardship`). It elaborates Definition of Done §4 — "an open PR is not finished work" — into what that item leaves implicit: what you still owe a PR after you push it, and what does not count as having been reviewed.

**What binds is the disposition, not the waiting.** Before the change is called done, the PR's checks and its reviewer output are dispositioned — each one applied, ticketed, or declined with a reason. *How* you learn they arrived is not prescribed: a project that already tells you when to look back — the human notifies, a hook fires — has met this, and its instruction wins. Absent such a signal the default mechanism is to stay: the window closes at the first of an actionable reviewer comment or ten minutes after the checks settle, and pushing a fix reopens it, because the reviewer re-reviews. Leaving with nothing dispositioned hands the next session a change nobody read.

**A comment is not a review, and green checks are not the end of one.** Both halves have been observed failing here. On one PR every check went green and the reviewer then posted four Major findings. On another, checks went green and the reviewer posted *"review limit reached — we couldn't start this review"*: a comment arrived, and nobody looked. **A notice that no review ran leaves the PR unreviewed.** Tell the two apart by content, never by author — a review names files, lines, or claims; a notice talks about the review itself. Proceeding on an unreviewed PR is allowed; proceeding silently is not. "Merged unreviewed, reviewer quota exhausted" is a disclosure; saying nothing is a claim of review that never happened.

**A change that closes a spec gets an independent adversarial review before it archives.** The trigger is the archive gate and nothing wider — not every PR that touches a spec folder. It names an obligation that already binds mechanically, so the only question is whether you meet it deliberately or discover it as a refusal: the spec gate declines to merge a PR closing a spec's issue without archiving it, `spec archive` declines without a passing review, and the reviewer pool declines one signed by the wrong model. The reviewer must not be the implementer; that independence is the entire value.
<!-- END HARNESS GENERATED -->
* **Skills.** `~/.claude/skills/<skill>/SKILL.md` auto-load via slash commands. Skill auto-loading is a Claude Code feature, not portable. Skill **content** is portable: the harness render path (`harness/skills/<name>/` with `targets[]`, deployed offline by `compile-harness.sh --deploy` — ADR-021) emits each skill as an OpenCode command at `~/.config/opencode/commands/<name>.md`. (AI-012 shipped the original transform in PR #43; the standalone `skills-to-opencode.sh` was since retired.)
* **TaskCreate / TaskUpdate / TaskList.** Use for non-trivial multi-step work (≥3 distinct steps). Mark `in_progress` BEFORE starting; mark `completed` immediately on finish. Don't batch updates.
Expand Down
13 changes: 13 additions & 0 deletions docs/lessons.md
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,8 @@ awk '/^## Entries$/,0' docs/lessons.md | grep '^### \[' | sed -E 's/^### \[([0-9
- [2026-08-14] A dormant declared field must be validated on the same schedule it's written, not the schedule it activates on
- [2026-08-14] An agent that cannot reach the repo still writes a confident review
- [2026-08-14] Widening a shared return type is a change to every consumer, and Go's zero values hide the ones you missed
- [2026-08-15] A check whose precondition the architecture forbids reports SKIP forever, and SKIP reads as nothing-to-check
- [2026-08-15] A check that cannot fail the way you cite it

---

Expand Down Expand Up @@ -2388,3 +2390,14 @@ The blast radius was also wider than the one function: because `compile-harness.
**Rule**: when an architecture change removes a *precondition* that existing checks depend on, the checks do not fail — they go quiet, in the branch that was written to mean "this is fine". Grep for consumers of what you removed (an env var, a file, a daemon, a login step) and ask of each: on a correctly configured machine after this change, which branch does it take? A check that can only take its no-op branch is not a weakened check, it is a deleted one that still prints. Two tells worth trusting: a remediation string naming a command that no longer exists is a dead check with a timestamp on it — grep the repo for the command before believing the message — and a health section that has never once complained is a claim about the section, not about the system.

**Tags**: `verification`, `secrets`, `doctor`, `architecture-migration`, `observability`
### [2026-08-15] A check that cannot fail the way you cite it

**Context**: HARNESS-072 (#963) adds an `enforced` harness region — text injected verbatim into every agent's instructions across every repo. The spec's own Risks section named the obvious failure: *"a region added to `enforced` but missing from a target's `inject` list silently misses that surface"* — the producer-updated / consumer-forgotten class that BUG-077 had been. It named the mitigation in the same breath: `compile-harness.sh --check` is the test, not a hand count. The acceptance criterion was written on that basis.

**Problem**: `--check` cannot detect that failure and never could. `do_check` builds the expected side of its diff from the target's *own* inject list — `mapfile -t ids < <(target_inject "$file")` — so an id missing from that list is missing from **both** sides of the comparison. The diff is clean, the target prints `[check] OK`, and the surface that never received the rule is indistinguishable from one that did. It is a consistency check (does the injected text match its record?) being cited as a coverage check (did the region reach the surfaces it should?). Running the new assertion against the tree as it stood produced two immediate hits on `pr-sizing`, doctrine-only by a decision argued at length in #830 and recorded nowhere a machine could read — a real exclusion that had survived on institutional memory alone.

**Solution**: a separate `check_coverage` pass over every enforced id × every surface: injected, or an `opt_out` entry naming that surface **with a reason** — an empty reason is still a gap. The decisive test asserts both halves on one run: the region diff reports `OK -> TARGET2.md` while coverage reports `GAP` on that same file. That also picks the shape — an orphan check ("is this id used anywhere?") would pass the partial case, and the partial case is the likelier mistake. Found by a second session reading this worktree from the outside, and verified against the source before being acted on.

**Rule**: when a spec names a command as the mitigation for a risk, open the command and find the line that would fail. A check earns its citation by the question it actually asks, and the question is usually narrower than its name suggests — `--check` also cannot see a committed record trailing its vault source, because it is offline by design (ADR-013), which is how six stale records sat clean until someone ran `--refresh`. This is the `pattern-verification-fails-toward-unproven` family in its cheapest form: not a check that ran and lied, but a check that was never capable of the answer and was trusted for it anyway. The tell is a mitigation you can state but not demonstrate red.

**Tags**: `harness`, `verification`, `spec-driven-development`, `ci`
3 changes: 2 additions & 1 deletion harness/agents/curator/AGENT.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
---
generated: true
generated_from: 00_meta/agents/definitions/curator/AGENT.md
generated_sha: 94a6cfb6a212d027
generated_sha: 669ffa7acb345ea6
id: agent-curator
type: agent
status: active
Expand All @@ -12,6 +12,7 @@ kind: invocable
model: top
capabilities: [read, search, edit, shell]
skills: [vault-doctor, crystallize, insights, genre-picker, context-refresh, handoff, place-knowledge, dispose-proposals]
owner: manu
---

# Curator
Expand Down
8 changes: 8 additions & 0 deletions harness/enforced/pr-stewardship.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@

> Injected verbatim into every agent's instructions (harness `enforced` id `pr-stewardship`). It elaborates Definition of Done §4 — "an open PR is not finished work" — into what that item leaves implicit: what you still owe a PR after you push it, and what does not count as having been reviewed.

**What binds is the disposition, not the waiting.** Before the change is called done, the PR's checks and its reviewer output are dispositioned — each one applied, ticketed, or declined with a reason. *How* you learn they arrived is not prescribed: a project that already tells you when to look back — the human notifies, a hook fires — has met this, and its instruction wins. Absent such a signal the default mechanism is to stay: the window closes at the first of an actionable reviewer comment or ten minutes after the checks settle, and pushing a fix reopens it, because the reviewer re-reviews. Leaving with nothing dispositioned hands the next session a change nobody read.

**A comment is not a review, and green checks are not the end of one.** Both halves have been observed failing here. On one PR every check went green and the reviewer then posted four Major findings. On another, checks went green and the reviewer posted *"review limit reached — we couldn't start this review"*: a comment arrived, and nobody looked. **A notice that no review ran leaves the PR unreviewed.** Tell the two apart by content, never by author — a review names files, lines, or claims; a notice talks about the review itself. Proceeding on an unreviewed PR is allowed; proceeding silently is not. "Merged unreviewed, reviewer quota exhausted" is a disclosure; saying nothing is a claim of review that never happened.

**A change that closes a spec gets an independent adversarial review before it archives.** The trigger is the archive gate and nothing wider — not every PR that touches a spec folder. It names an obligation that already binds mechanically, so the only question is whether you meet it deliberately or discover it as a refusal: the spec gate declines to merge a PR closing a spec's issue without archiving it, `spec archive` declines without a passing review, and the reviewer pool declines one signed by the wrong model. The reviewer must not be the implementer; that independence is the entire value.
16 changes: 12 additions & 4 deletions harness/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,20 +7,28 @@
{ "id": "no-phase-references", "source": "pattern-git-workflow.md#7-message-content-policy" },
{ "id": "no-auto-merge", "source": "pattern-git-workflow.md#9-merge-policy" },
{ "id": "definition-of-done", "source": "pattern-change-lifecycle.md#definition-of-done" },
{ "id": "pr-sizing", "source": "pattern-git-workflow.md#10-pr-sizing-policy" }
{ "id": "pr-stewardship", "source": "pattern-change-lifecycle.md#pr-stewardship" },
{
"id": "pr-sizing",
"source": "pattern-git-workflow.md#10-pr-sizing-policy",
"opt_out": {
"AGENTS.md": "the targets region counters harness defaults only; a precedence rule between two of our own rules overrides none, and #824 already states this policy in this file's hand-written prose (#830)",
"ai/claude/CLAUDE.md": "same as AGENTS.md — the compact doctrine payload substitutes for the constitution agy and codex never receive, and this file's reader already gets the policy from AGENTS.md (#830)"
}
}
],
"targets": [
{
"agent": "agents",
"kind": "native",
"file": "AGENTS.md",
"inject": ["no-attribution", "english-only", "no-phase-references", "no-auto-merge", "definition-of-done"]
"inject": ["no-attribution", "english-only", "no-phase-references", "no-auto-merge", "definition-of-done", "pr-stewardship"]
},
{
"agent": "claude",
"kind": "pointer",
"file": "ai/claude/CLAUDE.md",
"inject": ["no-attribution", "english-only", "no-phase-references", "no-auto-merge", "definition-of-done"]
"inject": ["no-attribution", "english-only", "no-phase-references", "no-auto-merge", "definition-of-done", "pr-stewardship"]
}
],
"skills": {
Expand All @@ -38,7 +46,7 @@
"catalog": { "agent": "copilot", "file": ".copilot/copilot-instructions.md" }
},
"doctrine": {
"inject": ["no-attribution", "english-only", "no-phase-references", "no-auto-merge", "definition-of-done", "pr-sizing"],
"inject": ["no-attribution", "english-only", "no-phase-references", "no-auto-merge", "definition-of-done", "pr-stewardship", "pr-sizing"],
"deploy": [
{
"agent": "agy",
Expand Down
16 changes: 14 additions & 2 deletions harness/skills/dispatching-parallel-agents/SKILL.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
---
generated: true
generated_from: 00_meta/skills/dispatching-parallel-agents/SKILL.md
generated_sha: a716db8d40dd96ce
generated_sha: 4ef93031ee74f9c8
id: dispatching-parallel-agents-skill
type: skill
status: active
Expand Down Expand Up @@ -81,9 +81,21 @@ Your task:
3. Fix the issue
4. Do NOT change unrelated code

Return: Summary of root cause and changes made.
Return: Summary of root cause and changes made, ending with the mandatory reconciliation block:

```yaml:reconciliation
agent_verdict: SUCCESS # SUCCESS | FAILURE | PARTIAL
files_modified:
- path/to/file1
tickets_created: []
unresolved_blockers: []
summary: "Brief 1-2 sentence human summary"
```

## Mandatory Structured Handoff

Every dispatched subagent MUST conclude with the `yaml:reconciliation` block so the orchestrator can mechanically verify changes against `git status` without ambiguous parsing.

## Common Mistakes

| Mistake | Fix |
Expand Down
4 changes: 2 additions & 2 deletions harness/skills/pr-review-triage/SKILL.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
---
generated: true
generated_from: 00_meta/skills/pr-review-triage/SKILL.md
generated_sha: 97df7c925532c797
generated_sha: fc4a81aaec806760
id: pr-review-triage-skill
type: skill
status: active
created: "2026-08-08"
owner: manu
name: pr-review-triage
description: Triage an open pull request after its checks and reviewers have run — read the CI result, read every review comment, and give each one a disposition (apply / skip / defer) with a one-line reason. Triggers on /pr-review-triage, "triage the PR", "review the review", "what did the reviewer say", "revisa los comentarios de la PR", "check CI and the bot comments", and by default once a PR you opened has finished its checks. Never applies a change or merges without explicit human confirmation.
description: Triage an open pull request after its checks and reviewers have run — read the CI result, read every review comment, and give each one a disposition (apply / skip / defer) with a one-line reason. Triggers on /pr-review-triage, "triage the PR", "review the review", "what did the reviewer say", "revisa los comentarios de la PR", "check CI and the bot comments", and by default once a PR you opened has come back — from its checks and from its reviewers, whichever lands later, because checks finishing is not the end of the window. Never applies a change or merges without explicit human confirmation.
allowed-tools: [Bash, Read, Grep]
---

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ id: "condition-based-waiting"
type: reference
status: active
tags: []
owner: manu
created: "2026-06-10"
---

# Condition-Based Waiting
Expand Down
2 changes: 2 additions & 0 deletions harness/skills/systematic-debugging/defense-in-depth.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ id: "defense-in-depth"
type: reference
status: active
tags: []
owner: manu
created: "2026-06-10"
---

# Defense-in-Depth Validation
Expand Down
2 changes: 2 additions & 0 deletions harness/skills/systematic-debugging/root-cause-tracing.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ id: "root-cause-tracing"
type: reference
status: active
tags: []
owner: manu
created: "2026-06-10"
---

# Root Cause Tracing
Expand Down
Loading
Loading