Skip to content

chore: update the agent harness to copier template v0.6.0 - #3

Closed
egparedes wants to merge 3 commits into
mainfrom
ao/devmm-4/template-v0.6.0
Closed

egparedes wants to merge 3 commits into
mainfrom
ao/devmm-4/template-v0.6.0

Conversation

@egparedes

Copy link
Copy Markdown
Contributor

Feature

Harness maintenance, not a product feature — no development/work/ unit. The
template moved from v0.5.0 to v0.6.0 (4 upstream commits, 59 files) and this
reapplies it.

The headline is structural: the agent-facing docs, ADRs and per-feature work
units move out of docs/ and work/ into development/, leaving docs/ for
user documentation (docs/api.md) as the new convention reserves it.

Why the move is its own first commit

A bare copier update exits 0, reports no conflict, and deletes
docs/architecture.md, docs/style.md, docs/testing.md and
docs/tool-bootstrap.md, substituting the template scaffolds at the new path —
_skip_if_exists does not cover the delete side of a rename. Moving the tree
first, in ae0c46d, puts the files where _skip_if_exists can see them, so the
update preserves them. Verified both ways on throwaway clones before touching
this branch.

Line counts after the update, against 1beb326: architecture.md 78 → 78,
style.md 133 → 133, tool-bootstrap.md 122 → 122, testing.md 107 → 121
(the grafted section below).

Harness changes absorbed

  • report.md as a fifth work-unit artifact, written by the Developer as work
    happens and audited by the Reviewer for honesty.
  • DECISION-PENDING: escalation marker plus the decision register in
    development/adr/README.md, seeded with the two decisions already granted:
    the ADR 0003 GPU-suite waiver and the coverage thresholds.
  • development/glossary.md, the document-liveness table, and the
    architecture.md > spec.md > plan.md > tasks.md authority order.
  • Role playbook skills (product-owner, architect, developer, reviewer) over a
    shared design-principles core; each role subagent now reads its playbook.
  • PreToolUse hook fails closed when jq cannot parse the tool input.
  • ADR gate is now a three-criteria test (hard to reverse / surprising / real
    trade-off).

Two files _skip_if_exists shielded were hand-merged, since it is all-or-nothing
and upstream is strictly better in both: development/harness-usage.md
(262 → 308) and development/adr/README.md (29 → 74). Neither had
project-authored content. Upstream's new Reading gate output section was
grafted into our own development/testing.md.

One deliberate divergence

AGENTS.md keeps devmm's stricter rule that a required runtime dependency
needs an ADR, instead of the template's softer "check whether it clears the ADR
bar". The empty required-dependency set is a design invariant that
tests/test_packaging.py enforces, so the generic wording would understate it.

Definition of done

  • Gate green: make verify run locally, exit 0 — 900 passed, 75 skipped
  • Every success criterion has observable evidence — see the checks below
  • report.md written, deviations declared — n/a, no work unit; the
    deviation above is declared in this description
  • No test, tolerance, or assertion weakened; the 75 skips are the CUDA and
    ROCm suites off hardware (ADR 0003), unchanged from 1beb326. The
    tests/ diff is prose-only path references in docstrings and
    traceability.md
  • Every DECISION-PENDING: line added by this PR has a register row — none
    added; the register is seeded with two pre-existing accepted decisions
  • New structural decisions have an ADR — none; this adopts an upstream
    layout rather than deciding one

Also checked: every relative Markdown link in every tracked .md resolves;
.claude / .opencode symlinks intact; docs/api.md doctests still collected
and green (4 passed); AGENTS.md at 125 lines, under the 200 target.

Deviations & notes for the reviewer

Two problems that surfaced only in verification, both fixed here:

  • 65 broken links. The work units gained a directory level
    (work/p00/ → development/work/p00/), so their ../devmm-design.md targets
    needed ../../. The bulk rewrite corrected root-relative label text; these
    targets were already relative and needed a depth bump instead. A link checker
    over every tracked .md now passes.
  • A duplicated .gitignore entry. post_gen.py is incremental in v0.6.0,
    so it added development/work/*/scratch.md before the rewrite converted the
    existing work/*/scratch.md into the same line. The managed block is restored
    to upstream's exact ordering so future updates see it complete.

Worth knowing before the next feature, because the loop behaves differently:
/spec may ask up to five clarifying questions before writing anything, /plan
can hand back SPIKE-REQUEST: lines for the main agent to run (three rounds
max, as the architect cannot execute code), /verify ranks defects
MAJOR/MINOR/INFO with any MAJOR forcing NEEDS-WORK, and scratch.md is
redefined from the Developer's notepad to the feature's shared channel.

🤖 Generated with Claude Code

egparedes and others added 3 commits July 25, 2026 22:44
Adopts the template's development/ tree: the agent-facing docs, ADRs and
per-feature work units move out of docs/ and work/, leaving docs/ for user
documentation (docs/api.md) as the new convention reserves it.

The move is done as a pre-step so _skip_if_exists protects the
project-authored docs; a bare `copier update` deletes them and substitutes
the template scaffolds, because _skip_if_exists does not cover the delete
side of a rename.

Harness changes absorbed from v0.6.0:

- report.md as a fifth work-unit artifact, owned by the Developer and
  audited by the Reviewer for honesty.
- DECISION-PENDING: escalation marker plus the decision register in
  development/adr/README.md, seeded with the two decisions already granted
  (the ADR 0003 GPU-suite waiver and the coverage thresholds).
- development/glossary.md, the document-liveness table, and the
  architecture > spec > plan > tasks authority order.
- Role playbook skills (product-owner, architect, developer, reviewer) over
  a shared design-principles core.
- PreToolUse hook fails closed when jq cannot parse the tool input.
- .github/PULL_REQUEST_TEMPLATE.md with the definition-of-done checklist.

AGENTS.md keeps devmm's stricter rule that a required runtime dependency
needs an ADR, rather than the template's softer ADR-bar wording: the empty
required-dependency set is a design invariant tests/test_packaging.py
enforces.

Gate: make verify green — 900 passed, 75 skipped (GPU suites, off hardware).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
… contract

Review of #3 found the hardened PreToolUse guard bricks a session on any host
without jq: it fails closed, jq is not installed by the bootstrap, and the
denial covers the `apt-get install jq` that would fix it. Verified — with jq off
PATH, `make verify` returns exit 2. The pre-update wiring failed *open*
instead, allowing destructive commands through unchecked, so neither form was
right.

Keep fail-closed and make it self-explanatory:

- The guard checks for jq up front and names it as the reason, with the install
  command; the other two deny paths explain themselves too.
- block-destructive.sh reports which deny-list pattern matched, instead of a
  bare exit 2 that reads as an unexplained refusal and invites a reword-retry
  loop.
- ensure-toolchain.sh warns at SessionStart when jq is absent, so the problem
  surfaces before the first Bash call rather than as a mystery denial. Warning
  only — it must not abort the uv bootstrap.
- tool-bootstrap.md states jq is required, not merely standard.

The decision-register contract was self-defeating: it keyed on the literal
`DECISION-PENDING:` text, which this PR itself adds 15 times as documentation,
so `/verify` would have raised a dozen fabricated MAJOR defects while a real
escalation hid among the quotes. A marker is now defined by location — its own
line inside a development/work/*/report.md — with the scan command to match.
Also: register rows sourced from an ADR or a human grant are marker-less by
construction and no longer read as out-of-scope (both seeded rows are of that
kind); the Developer is named owner of the paired row, the only role that can
write it; and a PR with no work unit has the spec/plan/register axes marked n/a
rather than failed.

Remaining: gate-output rules now point at development/testing.md, which is
authoritative and records the sanctioned DEVMM_GPU skips; the Developer gets the
Architect's scratch.md clobber guard; development/README.md drops a
scaffold-marker section describing artifacts this repo no longer has and no
longer claims development/ is unpublished (the sdist ships it, the wheel does
not); README.md uses absolute links, as it is also the PyPI project page.

Gate: make verify green — 900 passed, 75 skipped, unchanged.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Comment thread .claude/settings.json
{
"type": "command",
"command": "S=\"${CLAUDE_PROJECT_DIR:-.}/.agents/hooks/block-destructive.sh\"; [ -r \"$S\" ] || exit 2; jq -r '.tool_input.command // empty' | sh \"$S\""
"command": "S=\"${CLAUDE_PROJECT_DIR:-.}/.agents/hooks/block-destructive.sh\"; [ -r \"$S\" ] || { echo \"PreToolUse: $S missing or unreadable — denying Bash.\" >&2; exit 2; }; command -v jq >/dev/null 2>&1 || { echo 'PreToolUse: jq not found, so the destructive-command guard cannot read the tool input — denying Bash. Install jq (apt-get install jq / brew install jq) from a shell outside the agent, then retry.' >&2; exit 2; }; c=$(jq -r '.tool_input.command // empty') || { echo 'PreToolUse: jq could not parse the hook payload — denying Bash.' >&2; exit 2; }; [ -n \"$c\" ] || { echo 'PreToolUse: hook payload carried no .tool_input.command — denying Bash.' >&2; exit 2; }; printf '%s' \"$c\" | sh \"$S\""

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[CONFIRMED] correctness — ✅ Fixed in e245a65

c=$(jq -r …) || exit 2 turns a missing or failing jq into a blanket denial of every Bash tool call, and jq is an assumed-present system tool that ensure-toolchain.sh does not install. [same root cause also at: .claude/settings.json:49, .claude/settings.json:49, .claude/settings.json:49, .claude/settings.json:49]

Failure scenario

On a minimal container / CI image / cloud sandbox without jq (documented in development/tool-bootstrap.md:23 only as "standard on dev machines", and not installed by the SessionStart bootstrap, which installs uv alone), the very first Bash call dies: verified exit=2, stderr='sh: 1: jq: not found'. The agent cannot run make verify, cannot run the test suite, and cannot even run apt-get install jq to self-recover, because the remedy is itself a Bash call. Every subsequent attempt fails the same way, so the session is unusable. The previous wiring degraded to allow-with-no-check instead.

Comment thread development/adr/README.md
**this register alone** records the outcome — to see what is still open, scan
the table for `pending` rows, not the reports. The reviewer checks the
contract per change: a marker added in the diff without a row here is a defect.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[CONFIRMED] correctness — ✅ Fixed in e245a65

The decision-register contract keys on the literal colon form DECISION-PENDING: while this PR introduces 14 colon-form prose mentions, so the marker is indistinguishable from documentation. [same root cause also at: .agents/subagents/reviewer.md:111, development/adr/README.md:57, development/adr/README.md:62]

Failure scenario

The register declares "The marker is the colon form, DECISION-PENDING:; mentions of the token without the colon are prose", and .agents/subagents/reviewer.md:125 makes "a DECISION-PENDING: line added without its register row" an automatic MAJOR/NEEDS-WORK. This diff adds 14 colon-form lines (AGENTS.md:60, .agents/subagents/developer.md, reviewer.md:64/111/125, .github/PULL_REQUEST_TEMPLATE.md:15, harness-usage.md:254/277, and README.md:52/57/61/62 itself) and zero register rows for them. Running /verify on this PR — or on any later PR that quotes the convention — produces a NEEDS-WORK verdict with a dozen fabricated MAJOR defects, and conversely a real escalation in a report.md is invisible among the prose hits, so a genuinely unauthorized decision merges unnoticed.

`report.md`, or the body of an existing ADR is an automatic MAJOR
defect unless the plan explicitly called for it. The two registers
have their own scope contracts instead: a decision-register row must
pair with an escalation marker in this diff *unless* its Source is an

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[CONFIRMED] correctness — ✅ Fixed in e245a65

The reviewer's scope rule requires every new decision-register row to pair with a DECISION-PENDING: line in the same diff, but the register explicitly admits rows for decisions a human granted with no marker — both existing rows are of that kind.

Failure scenario

A maintainer verbally grants a tolerance mid-feature; the developer appends the sanctioned register row (development/adr/README.md:52-53: "or that a human granted outside an ADR (a tolerance, a pin, a one-line operational fact)"). /verify finds a register row with no paired marker in the diff and, per this line, must rank it an out-of-scope MAJOR — automatic NEEDS-WORK. The loop cannot reach GO except by deleting the record the register was created to hold, or by fabricating a DECISION-PENDING: line in report.md for a decision that was never escalated. Both seeded rows (2026-07-p12.1, 2026-07-p12.2) have Source = an ADR / testing.md rather than a report, confirming marker-less rows are the intended norm.

and an undeclared deviation is a review defect.
- When a decision exceeds your authority — loosening a test tolerance
or assertion, adding a dependency, changing behaviour the spec froze —
write a `DECISION-PENDING:` line in `report.md` and stop. Do not

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[PLAUSIBLE] correctness — ✅ Fixed in e245a65

The DECISION-PENDING: escalation tells the Developer to write the marker in report.md and stop, but no role anywhere is assigned the paired decision-register row that development/adr/README.md:57 makes a same-PR contract and .agents/subagents/reviewer.md:111 makes an automatic MAJOR — the reviewer has write: deny, the architect/product-owner may not write outside the work dir, and .agents/commands/build.md:28-29 mentions only recording the marker.

Failure scenario

Developer hits a tolerance question, writes DECISION-PENDING: relax the pitch-alignment tolerance in report.md and stops; the user answers in chat and runs /verify; the reviewer applies its own rule ("a DECISION-PENDING: line in the diff without a row here is a defect") and returns an automatic MAJOR / NEEDS-WORK; /build re-invokes the developer, whose instructions still say only "write the line and stop. Do not resolve it locally", so the row is never added and the phase cannot leave NEEDS-WORK without the human noticing the missing owner.

Comment thread development/testing.md
- **Fast loop**: `make test` — must finish in <60s. Add slow suites under
`make test-all`.

## Reading gate output

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[CONFIRMED] cleanup — ✅ Fixed in e245a65

The gate-output reading policy is now restated in four places, and only this copy carries the ADR-0003 GPU-skip exception.

Failure scenario

The same rules (passed counts may only grow, no -x/-k/--ignore narrowing, no marker/assertion edits, new skips are findings) appear at development/testing.md:9-20, .agents/subagents/developer.md:65-70, .agents/subagents/reviewer.md:104-108, and .agents/skills/developer-playbook/SKILL.md, violating design-principles/SKILL.md:29 ("Every piece of knowledge — code, schema, doc, config — has one authoritative representation"). Only testing.md:19-20 carries the carve-out that the GPU suites "skip by design off hardware (development/adr/0003), so their skips are expected, not findings", so a reviewer or developer reading only its own role file treats the DEVMM_GPU skips as defects to explain, and any future change to the policy must be applied in four files or they drift. Fix: keep the rules in testing.md and have the role files link that section.

Comment thread .claude/settings.json
{
"type": "command",
"command": "S=\"${CLAUDE_PROJECT_DIR:-.}/.agents/hooks/block-destructive.sh\"; [ -r \"$S\" ] || exit 2; jq -r '.tool_input.command // empty' | sh \"$S\""
"command": "S=\"${CLAUDE_PROJECT_DIR:-.}/.agents/hooks/block-destructive.sh\"; [ -r \"$S\" ] || { echo \"PreToolUse: $S missing or unreadable — denying Bash.\" >&2; exit 2; }; command -v jq >/dev/null 2>&1 || { echo 'PreToolUse: jq not found, so the destructive-command guard cannot read the tool input — denying Bash. Install jq (apt-get install jq / brew install jq) from a shell outside the agent, then retry.' >&2; exit 2; }; c=$(jq -r '.tool_input.command // empty') || { echo 'PreToolUse: jq could not parse the hook payload — denying Bash.' >&2; exit 2; }; [ -n \"$c\" ] || { echo 'PreToolUse: hook payload carried no .tool_input.command — denying Bash.' >&2; exit 2; }; printf '%s' \"$c\" | sh \"$S\""

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[PLAUSIBLE] correctness — ✅ Fixed in e245a65

All three deny paths in the wrapper exit 2 with no stderr text, so the delegate's verdict and the wrapper's own failure reasons are indistinguishable to the caller. [same root cause also at: .claude/settings.json:49, .claude/settings.json:49]

Failure scenario

block-destructive.sh prints nothing before exit 2, and the two new guards (|| exit 2, [ -n "$c" ] || exit 2) print nothing either. A blocked call therefore surfaces to the agent as a bare "hook error ... No stderr output" (observed verbatim in this session when a review command contained rm -rf as text), giving no way to distinguish "your command matched the destructive deny-list" from "jq is missing" from "this tool has no command field". The agent's recovery is to reword and re-issue the same command repeatedly — burning turns and, in the jq/no-command cases, never succeeding — while the user sees unexplained refusals.

feature branch) before judging anything.
- Read `spec.md`, `plan.md`, the current `tasks.md`, `report.md` (if the
Developer has started it), and the diff (`git diff` against the
integration branch, plus `git log` for the feature branch) before

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[PLAUSIBLE] correctness — ⏭️ Not fixed here

If plan.md has a **Review checklist** section, it is part of your instructions grants an architect-authored, human-approved-at-plan-time document unbounded authority over the review, with none of the "never overrides the verdict rules" subordination clause that lines 46-49 and reviewer-playbook.md:63-65 apply to the playbook.

Failure scenario

A plan's Review checklist (template at architect.md:124-127) includes "the coverage thresholds and GPU-marker skips are out of scope for this phase — don't flag them"; the reviewer reads it as instructions, suppresses a genuine new skip that its own rules class as a defect ("any new skip is a defect to explain, not to ignore"), and returns GO — and the user who approved plan.md for its phases never realised they were also approving a narrower review.

Left for upstream: this is a gap in the template's role protocol rather than something this migration introduced, and fixing it here would deepen the divergence that every future copier update has to re-merge.

- When reading gate output, follow
[`development/testing.md`](../../development/testing.md#reading-gate-output) —
it is authoritative and names this project's sanctioned skips (the
`DEVMM_GPU` suites skip by design off hardware, so they are not

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[PLAUSIBLE] correctness — ✅ Fixed in e245a65

.agents/subagents/architect.md:77-80 adds an explicit "append with Edit, never replace with Write — it is gitignored, so what you clobber is gone" guard for the shared scratch.md, but the same guard is absent from the Developer, which holds both Write and Edit and is directed to leave notes in scratch.md in three places (lines 35-36, 75, 80) — as is .agents/commands/build.md:16, where the main agent drops an explorer summary into the same file.

Failure scenario

/plan leaves SPIKE-REQUEST:/SPIKE-FINDING: history in scratch.md, then /build starts; the developer discovers the plan is wrong and follows line 74-76 by writing its 2-3 sentence hand-back note with Write, truncating the file; the spike record is unrecoverable because .gitignore excludes development/work/*/scratch.md, and the re-invoked architect — told at architect.md:35-39 that scratch.md "holds the answer to the question you asked" — re-asks a question that was already answered and burns one of /plan's three spike rounds.

Comment thread .agents/commands/build.md
`DECISION-PENDING:` escalations are recorded when they happen.
- Run `make verify` at every phase boundary.
- Stop at the end of each phase and hand off to `/verify`
(Reviewer) before starting the next.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[PLAUSIBLE] correctness — ⏭️ Not fixed here

/build forwards only the developer subagent's "phase complete" hand-back; the developer's other documented stop (a scratch.md note requesting an explorer pass, developer.md:80) has no servicing step, unlike /plan's explicit SPIKE-REQUEST round-trip.

Failure scenario

The developer hits a search it cannot summarise inline, follows developer.md:78-81, writes "requesting an explorer pass" into scratch.md and stops mid-phase with tasks.md boxes unticked. build.md step 5 has exactly one branch — "When the developer reports a phase complete, stop and ask the user to run /verify" — so the parent reports the stop as a completed phase and routes the user to /verify. The reviewer then reviews half-implemented work and returns NEEDS-WORK (unticked tasks, missing tests), /build re-delegates to a fresh developer that hits the same wall, and the explorer request is never serviced: the phase ping-pongs between /build and /verify with no progress until the user reads scratch.md by hand.

Left for upstream: this is a gap in the template's role protocol rather than something this migration introduced, and fixing it here would deepen the divergence that every future copier update has to re-merge.

`report.md`, or the body of an existing ADR is an automatic MAJOR
defect unless the plan explicitly called for it. The two registers
have their own scope contracts instead: a decision-register row must
pair with an escalation marker in this diff *unless* its Source is an

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[PLAUSIBLE] correctness — ✅ Fixed in e245a65

The new scope-check rules (register row must pair with a marker; glossary entry must match a reviewed spec Glossary term) have no defined behaviour for a PR with no work unit, and this PR violates both. [same root cause also at: .agents/subagents/reviewer.md:61]

Failure scenario

.github/PULL_REQUEST_TEMPLATE.md:3 explicitly permits PRs that skip the four-phase loop, and this PR is one: it adds two decision-register rows (development/adr/README.md) with no DECISION-PENDING: line in any report, and a whole new development/glossary.md with no spec Glossary section anywhere in the repo. A reviewer following reviewer.md:57-68 literally reports both as MAJOR ("a glossary edit with no matching spec term … is out of scope (MAJOR)"), and its mandatory reads (spec.md, plan.md, tasks.md, report.md) do not exist, so /verify returns NEEDS-WORK on a correct change with defects the author cannot possibly clear.

decisions** block (with a one-line rationale and an "ADR needed:
<topic>" marker); the human or the Developer authors the ADR file
under `development/adr/` as a separate step.
- `scratch.md` belongs to every role, not to you: **append** to it with

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[PLAUSIBLE] cleanup — ✅ Fixed in e245a65

Architect is forbidden from ever using Write on scratch.md, but the spike protocol requires creating it when it does not yet exist.

Failure scenario

.agents/commands/spec.md:3-9 deliberately does not pre-create scratch.md ("whoever needs it first creates it"), so on a feature whose first hand-back is a spike, development/work/<slug>/scratch.md does not exist. Line 77-80 says "append to it with Edit, never replace it with Write", and Edit on a nonexistent file errors. The architect either loops on a failing Edit or violates its instructions, so the SPIKE-REQUEST: line the /plan loop reads back (plan.md:4, architect.md:139-141) is never recorded and the spike round-trip silently degrades into the architect guessing the assumption it was told never to guess. Fix: allow Write when the file is absent, forbid it when it exists.

the user, then re-invoke the product-owner subagent with the question
and the user's answer included in the prompt.* State it every time. Do
not assume the caller loaded `/spec` — the role is also reached by
description match, and then the slash command's instructions were never

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[PLAUSIBLE] cleanup — ⏭️ Not fixed here

Round caps for the question/spike loops live only in the slash commands, which both subagents state may never have been read.

Failure scenario

The five-round cap is only in .agents/commands/spec.md:28 and the three-round spike cap only in .agents/commands/plan.md:27, yet product-owner.md:110-113 and architect.md:148-150 both warn "Do not assume the caller loaded /spec|/plan — the role is also reached by description match, and then the slash command's instructions were never read." On the description-match path (e.g. a user saying "spec out feature X", which the playbook descriptions are written to trigger) the loop has no termination condition: the subagent asks one question and stops, the main agent relays and re-invokes, forever, burning a context window on ping-pong with no spec produced. Fix: restate the cap inside the subagent files, which are the only instructions guaranteed to load.

Left for upstream: this is a gap in the template's role protocol rather than something this migration introduced, and fixing it here would deepen the divergence that every future copier update has to re-merge.

Comment thread development/README.md
| [`harness-usage.md`](harness-usage.md) | how to drive the agent harness (Claude Code & OpenCode): phases, subagents, hooks, document liveness |
| [`architecture.md`](architecture.md) | orientation: system structure, boundaries, invariants |
| [`style.md`](style.md) | code style, comments, commit messages, changelog |
| [`glossary.md`](glossary.md) | the project's ubiquitous language: domain terms used in specs, code, and conversation |

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[CONFIRMED] cleanup — ✅ Fixed in e245a65

Scaffold-marker section describes template artifacts that do not exist anywhere in this repo.

Failure scenario

Lines 21-34 document _Fill in: …_ blocks, <placeholder> conventions, and "the example work/ unit" — but this brownfield repo has no example work unit (all 13 units are real, completed phases) and rg 'Fill in:' development/ returns only lines 24-25 of this file itself, i.e. the command it advertises for finding remaining scaffold matches nothing but its own documentation. An agent onboarding through this index spends context on 14 lines of instructions for markers it will never encounter, and may go looking for the nonexistent example unit. Fix: drop the section (or keep one line) until a scaffolded work unit actually exists.

Comment thread development/README.md

Everything agents and developers need to work on this repo: conventions,
decisions, and the per-feature work-document lifecycle. This tree is
**repo-internal**: it is never rendered to a documentation site and nothing

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[PLAUSIBLE] cleanup — ✅ Fixed in e245a65

"Never published" claim for development/ is contradicted by the packaging config and by README.md linking into it.

Failure scenario

Line 5 asserts the tree is "repo-internal — never published, never linked from a documentation site", but pyproject.toml declares no [tool.hatch.build.targets.sdist] section, so hatchling's default include ships all ~45 files of development/ (design doc, ADRs, 13 work units) inside every published sdist; and README.md:10 — the PyPI long description (readme = "README.md", pyproject.toml:5) — links development/devmm-design.md as "the authoritative design", a relative link that resolves to nothing on the PyPI project page. The invariant is stated in prose with nothing enforcing it, so pip download --no-binary :all: devmm hands users the agent process memory. Fix: add an sdist exclude for development/ (and tests/test_packaging.py coverage for it) or drop the claim.

Comment thread CHANGELOG.md

### Changed

- Repository layout: the agent-facing docs, ADRs and per-feature work units moved

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[PLAUSIBLE] cleanup — ✅ Fixed in e245a65

Single changelog bullet bundles five unrelated harness-internal changes, against the one-bullet-per-change rule.

Failure scenario

development/style.md:117-119 requires "one concise bullet per change" for "every user-facing change", yet lines 19-24 pack the docs/work -> development move, the template v0.6.0 bump, per-unit report.md, the decision register, the glossary, and the playbook skills into one six-line entry. None of these is user-facing for a library consumer reading the 0.1.x changelog, so the release notes now advertise agent-harness plumbing, and a reader scanning ### Changed for behaviour changes to devmm gets none of the separability the format exists to provide.

@egparedes

Copy link
Copy Markdown
Contributor Author

Filed the three skipped review findings upstream, where the fix belongs — each needs a change across several template role files, which would deepen the divergence every future copier update has to re-merge:

The other 12 findings are fixed in e245a65.

@egparedes

Copy link
Copy Markdown
Contributor Author

Superseded by #4, which carries these commits forward and lands on the template's v0.7.0 release tag.

Closing rather than merging: the template cut three releases while this was open, and two of them rewrote the same files this PR touches. Merging here and then immediately rewriting those files would leave a confusing pair of commits in main; #4 is the single reviewable end state.

Nothing here is lost. The migration commits are carried over intact, and the only patches dropped are the ones upstream has since superseded with better versions — the jq hook fix in particular (grAItools/harness-copier-template#31 → #32), where upstream correctly kept the deny decision on POSIX grep -qE; the grep -o extraction added here could fail open on binary-classified input.

The three findings this PR's review sent upstream are all fixed there and arrive via #4: harness-copier-template#28, #29 and #32.

CI here was 9/9 green at e245a65; #4 is 9/9 green at 4a2dab3.

@egparedes egparedes closed this Jul 28, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant