@nurix/etna 0.19.22 → 0.19.24
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +6 -5
- package/data/harness-index.json +1 -1
- package/data/harnesses/code/.vscode/settings.json +9 -0
- package/data/harnesses/code/CLAUDE.md +16 -1
- package/data/harnesses/code/agents/brainstorm.md +11 -11
- package/data/harnesses/code/agents/change-review.md +4 -4
- package/data/harnesses/code/agents/maintenance.md +4 -3
- package/data/harnesses/code/agents/retro.md +45 -0
- package/data/harnesses/code/codex/agents/brainstorm.toml +11 -11
- package/data/harnesses/code/codex/agents/change-review.toml +4 -5
- package/data/harnesses/code/codex/agents/maintenance.toml +2 -1
- package/data/harnesses/code/codex/agents/retro.toml +43 -0
- package/data/harnesses/code/harness.json +2 -2
- package/data/harnesses/code/rules/database.md +29 -1
- package/data/harnesses/code/skills/documentation/SKILL.md +1 -0
- package/data/harnesses/code/skills/documentation/scripts/doc-lint.mjs +3 -1
- package/data/harnesses/code/skills/documentation/templates/refinement-ledger.md +33 -0
- package/data/harnesses/code/skills/documentation/templates/structure.md +2 -0
- package/data/harnesses/code/skills/test-plan/SKILL.md +82 -0
- package/data/harnesses/discover/.vscode/settings.json +9 -0
- package/data/harnesses/discover/harness.json +1 -1
- package/data/harnesses/discussion/.vscode/settings.json +9 -0
- package/data/harnesses/discussion/harness.json +2 -2
- package/data/harnesses/discussion/rules/artifacts.md +1 -1
- package/data/harnesses/discussion/rules/method.md +2 -0
- package/data/harnesses/etna/.vscode/settings.json +9 -0
- package/data/harnesses/etna/CLAUDE.md +2 -0
- package/data/harnesses/etna/agents/brainstorm.md +11 -11
- package/data/harnesses/etna/agents/change-review.md +4 -4
- package/data/harnesses/etna/agents/maintenance.md +4 -3
- package/data/harnesses/etna/codex/agents/brainstorm.toml +11 -11
- package/data/harnesses/etna/codex/agents/change-review.toml +4 -5
- package/data/harnesses/etna/codex/agents/maintenance.toml +2 -1
- package/data/harnesses/etna/harness.json +2 -2
- package/data/harnesses/etna/skills/documentation/SKILL.md +1 -0
- package/data/harnesses/etna/skills/documentation/scripts/doc-lint.mjs +3 -1
- package/data/harnesses/etna/skills/documentation/templates/refinement-ledger.md +33 -0
- package/data/harnesses/etna/skills/documentation/templates/structure.md +2 -0
- package/data/harnesses/hr/.vscode/settings.json +9 -0
- package/data/harnesses/hr/harness.json +2 -2
- package/data/harnesses/kb-agi/.vscode/settings.json +9 -0
- package/data/harnesses/kb-agi/harness.json +1 -1
- package/lib/codex/README.md +17 -7
- package/lib/codex/agents-md.mjs +85 -6
- package/lib/codex/hooks.mjs +25 -1
- package/lib/codex/index.mjs +4 -3
- package/lib/codex/plugin-manifest.mjs +9 -3
- package/lib/codex/subagents.mjs +2 -2
- package/lib/codex/validate-codex-agents.mjs +126 -0
- package/package.json +2 -2
- package/lib/codex/gen-agents.mjs +0 -157
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: test-plan
|
|
3
|
+
description: "Test-obligation diagnostic for implementation plans. Runs at the plan gate after boundary, derives the tests a plan owes from its Proposed Changes + the owning LLD, and writes a Test Obligations section into the plan — one row per promised behavior: layer, target file, oracle, fixtures. Advisory + plan-mutating; writes no test files. Triggers on 'test plan', 'what needs tests', 'test obligations'."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Test-Obligation Diagnostic
|
|
7
|
+
|
|
8
|
+
You derive the tests an implementation plan owes, and pin them into the plan as an explicit, reviewable manifest — at the same gate `boundary` runs, ordered second. You never write a test file; you make the standing "tests ship with the change" guardrail *concrete* for this plan, so the implementer satisfies a checklist instead of a vibe, and so a later doc-health pass can prove the tests match the promises.
|
|
9
|
+
|
|
10
|
+
**The litmus is "which promise, at which altitude, proven by what?"** A plan promises behavior (an LLD's `owns:` surface does X); each promise earns exactly one test at the cheapest layer that can actually prove it. Spend your reading deciding the *layer* and the *oracle*, not on prose.
|
|
11
|
+
|
|
12
|
+
## The three-moment split
|
|
13
|
+
|
|
14
|
+
Testing spans three moments in the plan lifecycle. This skill owns **only the first** — it is why "write the tests at plan time" is wrong: at the gate the code does not exist yet, so the only coherent artifact is the manifest.
|
|
15
|
+
|
|
16
|
+
| Moment | Artifact | Owner |
|
|
17
|
+
| --- | --- | --- |
|
|
18
|
+
| **Plan gate** (here, after boundary) | Test Obligations section written into the plan | this skill |
|
|
19
|
+
| **Implementation** | the obligated tests, green in the same commits as the code | the implementer (standing guardrail — this skill never pre-empts it) |
|
|
20
|
+
| **Completion** | behavioral checklist at `docs/tests/{feature}.md`; run affected suite + the project's e2e smoke gate; note in changelog | the `documentation` skill + Completion steps |
|
|
21
|
+
|
|
22
|
+
Writing tests *before* the code they cover either fabricates implementation coupling (labels/routes/copy the plan hasn't fixed) or leaves the suite red on the shared branch for the plan's whole duration. Neither is acceptable — so the gate emits obligations, and the tests land *with* the code.
|
|
23
|
+
|
|
24
|
+
## Contract sources
|
|
25
|
+
|
|
26
|
+
- **The plan's Proposed Changes** — files created/modified, entities/state, API changes, cross-module contracts. Each is a behavior that may owe a test.
|
|
27
|
+
- **The owning LLD** (`docs/features/{feature}.md`, matched via the ownership index) — the canonical statement of *what the feature does*. Every obligation names the LLD promise it proves; the LLD is never restated, only referenced. This one-directional chain (LLD → manifest → tests + Completion checklist) is what stops the three artifacts drifting into three contradictory truths.
|
|
28
|
+
- **`.claude/rules/testing.md`** — the frameworks and canonical placement per stack. The manifest's target paths and runners come from here, never invented. The repo's existing runner always wins.
|
|
29
|
+
- **`boundary`'s output** — a HIGH/CRITICAL finding it surfaced is itself a behavior owed a regression test (the failure mode, asserted). Fold boundary's amendments first, then read the amended plan.
|
|
30
|
+
|
|
31
|
+
## Layer assignment
|
|
32
|
+
|
|
33
|
+
Assign each behavior the **cheapest layer that can prove it**, then name the oracle (the concrete thing that shows pass/fail):
|
|
34
|
+
|
|
35
|
+
- **unit** — a pure function / reducer / validator. Oracle: return value, thrown error.
|
|
36
|
+
- **component** — a UI unit's behavior in isolation (a widget, form, panel). Oracle: rendered role/text, emitted event. Runner: the stack's component runner per `testing.md`.
|
|
37
|
+
- **integration** — a route/handler against a real in-memory datastore via the app instance (not a mock of what you own). Oracle: response envelope shape, status code, the row actually written. **This is the default for server behavior** — most obligations land here, and this layer is the one the unit gate (`test` script / CI) runs.
|
|
38
|
+
- **e2e** — see the altitude gate below.
|
|
39
|
+
|
|
40
|
+
Error paths, races, and idempotency are obligations too, and they belong at **integration** with injected faults (network mock, the runner's fake timers, a forced constraint) — a process driving a live product cannot reliably *produce* them, so they are never an e2e obligation.
|
|
41
|
+
|
|
42
|
+
### The e2e altitude gate
|
|
43
|
+
|
|
44
|
+
An e2e obligation (a scenario in the project's e2e tree per `testing.md`) is earned **only** when the behavior genuinely spans processes/services that no single-process test can exercise together. A single-process behavior, however important, is an integration obligation, never e2e.
|
|
45
|
+
|
|
46
|
+
- Density is **one scenario per cross-process journey, not one per feature** — the project's existing scenarios are the reference density. Mark each e2e obligation **"extend scenario `<name>`"** in preference to **"new scenario"**; a new scenario needs a genuinely new journey.
|
|
47
|
+
- **Refuse to emit any e2e obligation while the project's e2e smoke gate is not wired.** A generated spec fed to a suite nothing runs is a rot accelerator. The gate is a capped, tagged smoke subset run in CI (not the full e2e suite — an oversized always-on e2e suite is what gets evicted from CI, taking all enforcement with it). If no such CI gate exists, emit the e2e obligation as a **blocked** row naming the missing gate, not as work to do.
|
|
48
|
+
|
|
49
|
+
## Run
|
|
50
|
+
|
|
51
|
+
**Input:** a plan path (given, or the newest in `docs/history/plans/`), already boundary-checked with amendments folded. For a non-plan diff in test-worthy code, the hunks stand in for Proposed Changes.
|
|
52
|
+
|
|
53
|
+
1. **Build the behavior list.** From the plan's Proposed Changes + the owning LLD's promised behavior, list the behaviors this plan introduces or changes. Fold in each HIGH/CRITICAL boundary finding as a regression obligation. Note behaviors a type or the compiler already guards — those owe **no** test (the boundary litmus, inverted: if it can't ship green-but-broken, it needs no test).
|
|
54
|
+
|
|
55
|
+
2. **Assign a layer + oracle** to each behavior (rules above). Prefer the cheapest layer that can actually prove the promise.
|
|
56
|
+
|
|
57
|
+
3. **Map to a target file** per `testing.md` — the stack's unit/integration path for most, the e2e scenario tree for a program scenario. Name fixtures/factories (existing helper, or new) and the fault-injection needed (network mock, fake timers, forced constraint). Use the repo-standard fake-data source.
|
|
58
|
+
|
|
59
|
+
4. **Apply the e2e altitude gate** to any cross-process obligation; downgrade everything else to integration.
|
|
60
|
+
|
|
61
|
+
5. **Emit the Test Obligations section into the plan**, plus a one-line chat summary. Write it as a subsection of the plan (an executor dispatched with only the plan file sees nothing else — an obligation that lives only in chat is lost at dispatch):
|
|
62
|
+
|
|
63
|
+
```
|
|
64
|
+
## Test Obligations
|
|
65
|
+
|
|
66
|
+
| # | Behavior (LLD promise) | Layer | Target file | Oracle | Fixtures / faults |
|
|
67
|
+
| - | ---------------------- | ----- | ----------- | ------ | ----------------- |
|
|
68
|
+
|
|
69
|
+
Coverage: {N} behaviors · {N} integration · {N} component · {N} unit · {N} e2e ({N} extend, {N} new)
|
|
70
|
+
Completion checklist: docs/tests/{feature}.md (derived at Completion, not now)
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
A behavior with no obligation is stated too, with the reason (compiler-guarded, covered by an existing test) — an empty cell reads as "not yet analyzed"; an explicit "none — compiler-guarded" reads as "checked."
|
|
74
|
+
|
|
75
|
+
## Rules
|
|
76
|
+
|
|
77
|
+
- **Manifest only.** You write the Test Obligations section into the plan and a chat summary. You write **no** test files and **no** `docs/tests/` checklist — those are implementation-time and Completion-time, owned by others.
|
|
78
|
+
- **Every obligation names its LLD promise.** No promise, no obligation source — trace it or drop it. This is the anti-drift pin.
|
|
79
|
+
- **Cheapest proving layer wins.** Do not obligate an e2e scenario for what an integration test proves, or an integration test for what a unit test proves.
|
|
80
|
+
- **e2e only above the cross-process bar, and only while the smoke gate runs.** Otherwise the obligation is a blocked row naming the missing gate.
|
|
81
|
+
- **Runs after boundary; skipped on BLOCK.** A blocked plan is re-planned first; there is nothing stable to obligate tests against.
|
|
82
|
+
- **A short manifest is valid.** A plan that owes three integration tests owes three rows — do not pad. The coverage line is the evidence it was analyzed, not skipped.
|
|
@@ -6,5 +6,14 @@
|
|
|
6
6
|
"editor.defaultFormatter": "esbenp.prettier-vscode",
|
|
7
7
|
"editor.formatOnSave": true,
|
|
8
8
|
"editor.wordWrap": "on"
|
|
9
|
+
},
|
|
10
|
+
// Hide harness-authoring scaffolding from the file explorer
|
|
11
|
+
"files.exclude": {
|
|
12
|
+
".claude": true,
|
|
13
|
+
".vscode": true,
|
|
14
|
+
".agents": true,
|
|
15
|
+
".codex": true,
|
|
16
|
+
"**/node_modules": true,
|
|
17
|
+
"**/apollo.service.json": true
|
|
9
18
|
}
|
|
10
19
|
}
|
|
@@ -6,5 +6,14 @@
|
|
|
6
6
|
"editor.defaultFormatter": "esbenp.prettier-vscode",
|
|
7
7
|
"editor.formatOnSave": true,
|
|
8
8
|
"editor.wordWrap": "on"
|
|
9
|
+
},
|
|
10
|
+
// Hide harness-authoring scaffolding from the file explorer
|
|
11
|
+
"files.exclude": {
|
|
12
|
+
".claude": true,
|
|
13
|
+
".vscode": true,
|
|
14
|
+
".agents": true,
|
|
15
|
+
".codex": true,
|
|
16
|
+
"**/node_modules": true,
|
|
17
|
+
"**/apollo.service.json": true
|
|
9
18
|
}
|
|
10
19
|
}
|
|
@@ -18,7 +18,7 @@ A ratified class-3 doc **is** the goal-track canon — never double-book it unde
|
|
|
18
18
|
|
|
19
19
|
**Status vocabulary**: `**DRAFT — not yet ratified**` / `Not yet user-ratified` · `(ratified YYYY-MM-DD)` — at doc, section, or extract granularity · `**Superseded note (YYYY-MM-DD):** … kept as record` · `deferred — blocked on <gate>` vs the exclusion grades.
|
|
20
20
|
|
|
21
|
-
**Immutability**: raw dumps immutable once filed (corrections land in critic or synthesis) · unratified syntheses may be rewritten in place as v2, recorded in provenance · ratified material changes by dated append or supersession only · nothing valuable is deleted — superseded → banner + keep; broken → flagged; closed threads → struck through. Every lifecycle event carries an ISO date.
|
|
21
|
+
**Immutability**: raw dumps immutable once filed (corrections land in critic or synthesis) · unratified syntheses may be rewritten in place as v2, recorded in provenance · ratified material changes by dated append or supersession only · nothing valuable is deleted — superseded → banner + keep; a retired topic → `git mv` to `archived/`, dated archive banner, kept frozen as record; broken → flagged; closed threads → struck through. Every lifecycle event carries an ISO date.
|
|
22
22
|
|
|
23
23
|
## The topic README
|
|
24
24
|
|
|
@@ -9,6 +9,7 @@ How sessions run in this workspace. What gets written is [artifacts.md](artifact
|
|
|
9
9
|
- **External instruments** — code/data a topic depends on (scraper, corpus, pipeline) lives **outside the workspace**, never at the root: this folder holds only topics and the harness. Record the dependency on the depending topic's README (external path + ratification status); exclusions are recorded on the excluder's side.
|
|
10
10
|
- **Git** — the workspace **is a git repository** (the `discussion-baseline` agent initializes one). The SessionEnd hook auto-commits each session's changes as one `📝 session close` batch — never per-file commits. Milestone commits by hand are still welcome: `✨` content, `🔧` workspace/method. Root `.gitignore` stays minimal.
|
|
11
11
|
- **Grandfathering** — when the method changes, never reshuffle existing artifacts to match. New artifacts follow current rules; old layouts stay, flagged where confusing.
|
|
12
|
+
- **Archiving** — a topic whose inquiry is *closed by outside reality* — its design **realized**, its understanding **superseded** — is retired, not deleted: `git mv` its folder into `archived/<topic>/` (history preserved; the folder frozen, kept as record), add a dated archive banner to its README (`📦 ARCHIVED (YYYY-MM-DD) — realized/superseded`: state · reason · pointer to the live source of truth), and move its `TOPICS.md` entry into the **Archived topics** section. Archiving records that a topic is done; live work stops there and nothing valuable is lost.
|
|
12
13
|
|
|
13
14
|
## Session protocol
|
|
14
15
|
|
|
@@ -61,6 +62,7 @@ Method lives in the rules (timeless); state lives in `metadata/` (current); topi
|
|
|
61
62
|
- Per topic: `` ## `topic-folder/` — <state phrase> `` — the suffix encodes **who it's waiting on** ("synthesis filed, awaiting user reaction").
|
|
62
63
|
- One dense routing paragraph: what it is, which artifacts exist (files, dates), headline findings — enough to route without opening the folder.
|
|
63
64
|
- Bullets: `**Open:**` (typically "user disposition on the N questions closing `<file>`") · exclusion grades, dated when user rulings · `**Note:**` caveats.
|
|
65
|
+
- Retired topics move to an `## Archived topics` section at the bottom — one condensed entry each (why archived: realized/superseded · the live source of truth); a one-line archiving note sits in the preamble. The active list holds only live topics.
|
|
64
66
|
|
|
65
67
|
### `SESSIONS.md` — session ledger
|
|
66
68
|
|
|
@@ -6,5 +6,14 @@
|
|
|
6
6
|
"editor.defaultFormatter": "esbenp.prettier-vscode",
|
|
7
7
|
"editor.formatOnSave": true,
|
|
8
8
|
"editor.wordWrap": "on"
|
|
9
|
+
},
|
|
10
|
+
// Hide harness-authoring scaffolding from the file explorer
|
|
11
|
+
"files.exclude": {
|
|
12
|
+
".claude": true,
|
|
13
|
+
".vscode": true,
|
|
14
|
+
".agents": true,
|
|
15
|
+
".codex": true,
|
|
16
|
+
"**/node_modules": true,
|
|
17
|
+
"**/apollo.service.json": true
|
|
9
18
|
}
|
|
10
19
|
}
|
|
@@ -140,6 +140,8 @@ When a plan's implementation surfaces work that is important but outside the pla
|
|
|
140
140
|
|
|
141
141
|
Most artifacts are markdown — skills, agents, rules, docs. Follow the conventions in `docs/architecture/skills/` and the `kb` / `nomenclature` rules; markdown has no file-path-comment rule. Keep the `.claude/rules/*` reference docs frontmatter-free.
|
|
142
142
|
|
|
143
|
+
Authoring or updating an **agent** keeps both runtimes in sync: the `.md` is the single source, and its Codex `.codex.toml` twin is derived from it by following [`docs/architecture/harness/authoring-agents.md`](docs/architecture/harness/authoring-agents.md), then checked with `node packages/cli/lib/codex/validate-codex-agents.mjs`.
|
|
144
|
+
|
|
143
145
|
For real code (the CLI under `packages/`, hook scripts):
|
|
144
146
|
|
|
145
147
|
- File-path header comment at the top, in the file's comment syntax: `// packages/cli/bin/etna.js - the installer entry`.
|
|
@@ -110,19 +110,19 @@ Stop is facilitator-orchestrated because approval belongs to the user; you execu
|
|
|
110
110
|
fork, every fragment, the consolidated source of truth. Return the manifest body for approval.
|
|
111
111
|
2. **Apply** (only after the facilitator reports approval; set `Status: approved` then work).
|
|
112
112
|
Read **both sides** of every destination before writing — the destination's current content is
|
|
113
|
-
a contract, not a blank page. Format each artifact via the `documentation` skill
|
|
114
|
-
where
|
|
115
|
-
manifest**. Set `Status: applied`. The apply is all-or-nothing and loud: if you cannot finish,
|
|
113
|
+
a contract, not a blank page. Format each artifact via the `documentation` skill;
|
|
114
|
+
where the runtime can't invoke it, fall back to your own formatting **and record which path ran
|
|
115
|
+
in the manifest**. Set `Status: applied`. The apply is all-or-nothing and loud: if you cannot finish,
|
|
116
116
|
report exactly what applied and stop — the folder stays visibly unfinished and the user
|
|
117
117
|
restarts; never resume silently from a half-applied state.
|
|
118
|
-
3. **Uselessness test.** Spawn a **fresh, context-free cold reader**
|
|
119
|
-
|
|
120
|
-
and the instruction to reconstruct the
|
|
121
|
-
branches. Grade its reconstruction against the
|
|
122
|
-
manifest (`Result: fail`, named gaps), and the fixes
|
|
123
|
-
requiring fresh approval. Pass → record it. If the
|
|
124
|
-
facilitator must dispatch the cold reader — you,
|
|
125
|
-
cold-read.
|
|
118
|
+
3. **Uselessness test.** Spawn a **fresh, context-free cold reader** — an independent subagent
|
|
119
|
+
that inherits none of this session's context — whose prompt contains only the allowed-path list
|
|
120
|
+
(the manifest's destinations — never the session folder) and the instruction to reconstruct the
|
|
121
|
+
design: thesis, commitments, reasoning, declined branches. Grade its reconstruction against the
|
|
122
|
+
ledger and thesis. Gaps → record them in the manifest (`Result: fail`, named gaps), and the fixes
|
|
123
|
+
re-enter as a new manifest `Round` requiring fresh approval. Pass → record it. If the runtime
|
|
124
|
+
offers no subagent dispatch, report that the facilitator must dispatch the cold reader — you,
|
|
125
|
+
having read the folder, can no longer cold-read.
|
|
126
126
|
4. **Move.** Run `--gate=move`. When clean: delete `ops/` entirely, `git mv` the folder to
|
|
127
127
|
`docs/history/brainstorms/{topic}/`, set state `Status: harvested`, update both indexes
|
|
128
128
|
(`docs/research/Readme.md` row out, `docs/history/brainstorms/Readme.md` row in). End your
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: change-review
|
|
3
|
-
description: Velocity + change-risk analysis. First classifies recent commits into a pipe-delimited velocity/severity CSV by dispatching parallel
|
|
3
|
+
description: Velocity + change-risk analysis. First classifies recent commits into a pipe-delimited velocity/severity CSV by dispatching parallel low-cost subagents (module, feature, impact, severity, churn), then derives a commit heatmap, risk zones (high churn in contract-heavy code), stabilization signals, and team/bus-factor distribution. Self-contained — produces its own CSV, no separate git-history step. Use when planning where to invest in review focus or rules.
|
|
4
4
|
tools: Bash, Read, Write, Glob, Grep, Task
|
|
5
5
|
model: inherit
|
|
6
6
|
---
|
|
@@ -11,7 +11,7 @@ You analyze code-change velocity over time to find risk zones — where change i
|
|
|
11
11
|
|
|
12
12
|
You work in two phases:
|
|
13
13
|
|
|
14
|
-
1. **Classify** — turn recent git history into a structured, pipe-delimited CSV (one classified row per commit) by dispatching parallel
|
|
14
|
+
1. **Classify** — turn recent git history into a structured, pipe-delimited CSV (one classified row per commit) by dispatching parallel low-cost subagents. You do this yourself; there is no separate agent that hands you a CSV.
|
|
15
15
|
2. **Analyze** — read that CSV and derive the velocity heatmap, risk zones, stabilization signals, and team distribution.
|
|
16
16
|
|
|
17
17
|
## Parameters
|
|
@@ -82,7 +82,7 @@ Build a registry of objects:
|
|
|
82
82
|
|
|
83
83
|
Split the commit registry into batches of `batch_size` commits each.
|
|
84
84
|
|
|
85
|
-
|
|
85
|
+
Dispatch one **independent subagent per batch** on the **cheapest capable tier** — classification is mechanical, so the lowest-cost model that can follow the output format is the right one. Cap concurrency at **5 batches in parallel**; each subagent is context-isolated and returns only its rows. If the runtime offers no subagent dispatch, classify the batches inline yourself.
|
|
86
86
|
|
|
87
87
|
Before building the prompt template, check if `docs/memory/change-review.md` contains **Module Taxonomy** and **Feature Taxonomy** sections. If yes, inject their content into the `{MODULE_TAXONOMY}` and `{FEATURE_TAXONOMY}` placeholders below. If no memory file exists, use these generic fallbacks:
|
|
88
88
|
|
|
@@ -243,7 +243,7 @@ Per module, list which authors made the most commits in the 3-month window. Surf
|
|
|
243
243
|
## Rules
|
|
244
244
|
|
|
245
245
|
- Never modify source code — read-only except for writing the output CSV, `docs/memory/change-review.md`, and `docs/history/backlog.md`
|
|
246
|
-
-
|
|
246
|
+
- Run all classification subagents on the cheapest capable tier to minimize cost; they are independent and context-isolated
|
|
247
247
|
- Always report progress: "Dispatching batch 1-5 of 12..." etc.
|
|
248
248
|
- If git commands fail (bad branch, bad date range), stop and report the error clearly
|
|
249
249
|
- Pipe characters in commit messages must be replaced with dashes before writing to CSV
|
|
@@ -138,11 +138,12 @@ docs/
|
|
|
138
138
|
├── history/
|
|
139
139
|
│ ├── CHANGELOG.md # Master changelog index
|
|
140
140
|
│ ├── changelog/ # Individual entries
|
|
141
|
+
│ ├── ledger/ # Refinement Ledger — append-only per-commit refinement journal (YYYY-MM.md; written at commit time, NOT scaffolded empty)
|
|
141
142
|
│ ├── plans/ # Implementation plans (Status field required)
|
|
142
143
|
│ ├── brainstorms/ # Harvested brainstorm sessions ({topic}/) — user decides kept (committed) or deleted; Readme.md is the index
|
|
143
144
|
│ └── backlog.md # Tracked work items by priority (P0-P3)
|
|
144
145
|
├── memory/ # index.md, main.md, {agent}.md — project knowledge + per-agent strategy memory
|
|
145
|
-
└── tests/ #
|
|
146
|
+
└── tests/ # Behavioral test checklists ({feature}.md, step → **Assert**), derived at plan Completion via the `documentation` skill; author-maintained, present only when test docs exist
|
|
146
147
|
```
|
|
147
148
|
|
|
148
149
|
There is **no `docs/routing.md`**, **no `docs/modules/{m}/`**, **no `docs/pillars/`**, **no `docs/boundaries/`**. Code ownership lives in feature `owns:` frontmatter; a module is a `module:` label, not a folder; boundaries are diagnosed from source; brainstorm records live in `docs/research/` (active) and `docs/history/brainstorms/` (harvested).
|
|
@@ -151,7 +152,7 @@ There is **no `docs/routing.md`**, **no `docs/modules/{m}/`**, **no `docs/pillar
|
|
|
151
152
|
|
|
152
153
|
### Step B1 — Inventory and classify
|
|
153
154
|
|
|
154
|
-
Glob every markdown file. Classify each: Architecture, Features, Operations, Plans, Changelogs, Backlog, Brainstorm records (stay), Stale/Deprecated (delete), Root docs (stay). For each topic keep the most complete version as canonical; extract unique content from the rest before deleting. **No redirect stubs** — when you move a file, delete the original and fix every reference (cross-doc links, memory files). Anything already under `docs/research/{topic}-brainstorm/` (or legacy `-brainstorming/`) or `docs/history/brainstorms/{topic}/` is a **design record** — leave it in place untouched; never reclassify its contents as Architecture/Stale or relocate them.
|
|
155
|
+
Glob every markdown file. Classify each: Architecture, Features, Operations, Tests (behavioral checklists — stay), Plans, Changelogs, Backlog, Brainstorm records (stay), Stale/Deprecated (delete), Root docs (stay). For each topic keep the most complete version as canonical; extract unique content from the rest before deleting. **No redirect stubs** — when you move a file, delete the original and fix every reference (cross-doc links, memory files). Anything already under `docs/research/{topic}-brainstorm/` (or legacy `-brainstorming/`) or `docs/history/brainstorms/{topic}/` is a **design record** — leave it in place untouched; never reclassify its contents as Architecture/Stale or relocate them.
|
|
155
156
|
|
|
156
157
|
While reading each markdown doc to classify it, if the doc names a code symbol it asserts exists that **statically resolves to nothing**, note it as an observation for the Part A audit — **only** on stacks where static resolution is reliable (stay silent on codegen/reflection/DI/barrel stacks); scoped to docs already being read here, never a whole-repo prose sweep; **docs only**, never code-file comments.
|
|
157
158
|
|
|
@@ -200,7 +201,7 @@ Re-running you is safe — the structure work is idempotent, so a second pass is
|
|
|
200
201
|
## Rules
|
|
201
202
|
|
|
202
203
|
- **Never delete feature docs** — only update or flag for review.
|
|
203
|
-
- **Never modify `docs/history/plans
|
|
204
|
+
- **Never modify `docs/history/plans/`, `docs/history/changelog/`, or `docs/history/ledger/`** (frozen/append-only records — ledger blocks are written only at commit time, distilled only by the `retro` agent).
|
|
204
205
|
- **Preserve existing doc structure and formatting** when updating.
|
|
205
206
|
- **When in doubt, create a backlog item** rather than making a wrong update.
|
|
206
207
|
- **Be specific:** include file paths, line numbers, and what changed.
|
|
@@ -107,19 +107,19 @@ Stop is facilitator-orchestrated because approval belongs to the user; you execu
|
|
|
107
107
|
fork, every fragment, the consolidated source of truth. Return the manifest body for approval.
|
|
108
108
|
2. **Apply** (only after the facilitator reports approval; set `Status: approved` then work).
|
|
109
109
|
Read **both sides** of every destination before writing — the destination's current content is
|
|
110
|
-
a contract, not a blank page. Format each artifact via the `documentation` skill
|
|
111
|
-
where
|
|
112
|
-
manifest**. Set `Status: applied`. The apply is all-or-nothing and loud: if you cannot finish,
|
|
110
|
+
a contract, not a blank page. Format each artifact via the `documentation` skill;
|
|
111
|
+
where the runtime can't invoke it, fall back to your own formatting **and record which path ran
|
|
112
|
+
in the manifest**. Set `Status: applied`. The apply is all-or-nothing and loud: if you cannot finish,
|
|
113
113
|
report exactly what applied and stop — the folder stays visibly unfinished and the user
|
|
114
114
|
restarts; never resume silently from a half-applied state.
|
|
115
|
-
3. **Uselessness test.** Spawn a **fresh, context-free cold reader**
|
|
116
|
-
|
|
117
|
-
and the instruction to reconstruct the
|
|
118
|
-
branches. Grade its reconstruction against the
|
|
119
|
-
manifest (`Result: fail`, named gaps), and the fixes
|
|
120
|
-
requiring fresh approval. Pass → record it. If the
|
|
121
|
-
facilitator must dispatch the cold reader — you,
|
|
122
|
-
cold-read.
|
|
115
|
+
3. **Uselessness test.** Spawn a **fresh, context-free cold reader** — an independent subagent
|
|
116
|
+
that inherits none of this session's context — whose prompt contains only the allowed-path list
|
|
117
|
+
(the manifest's destinations — never the session folder) and the instruction to reconstruct the
|
|
118
|
+
design: thesis, commitments, reasoning, declined branches. Grade its reconstruction against the
|
|
119
|
+
ledger and thesis. Gaps → record them in the manifest (`Result: fail`, named gaps), and the fixes
|
|
120
|
+
re-enter as a new manifest `Round` requiring fresh approval. Pass → record it. If the runtime
|
|
121
|
+
offers no subagent dispatch, report that the facilitator must dispatch the cold reader — you,
|
|
122
|
+
having read the folder, can no longer cold-read.
|
|
123
123
|
4. **Move.** Run `--gate=move`. When clean: delete `ops/` entirely, `git mv` the folder to
|
|
124
124
|
`docs/history/brainstorms/{topic}/`, set state `Status: harvested`, update both indexes
|
|
125
125
|
(`docs/research/Readme.md` row out, `docs/history/brainstorms/Readme.md` row in). End your
|
|
@@ -1,15 +1,14 @@
|
|
|
1
1
|
# dropped Claude tools: Bash, Read, Write, Glob, Grep, Task
|
|
2
2
|
name = "change-review"
|
|
3
|
-
description = "Velocity + change-risk analysis. First classifies recent commits into a pipe-delimited velocity/severity CSV by dispatching parallel
|
|
3
|
+
description = "Velocity + change-risk analysis. First classifies recent commits into a pipe-delimited velocity/severity CSV by dispatching parallel low-cost subagents (module, feature, impact, severity, churn), then derives a commit heatmap, risk zones (high churn in contract-heavy code), stabilization signals, and team/bus-factor distribution. Self-contained — produces its own CSV, no separate git-history step. Use when planning where to invest in review focus or rules."
|
|
4
4
|
developer_instructions = '''
|
|
5
|
-
|
|
6
5
|
# Change-Review Agent
|
|
7
6
|
|
|
8
7
|
You analyze code-change velocity over time to find risk zones — where change is accelerating or decelerating, and whether review attention matches the risk. You answer: "where should the tech lead invest review focus or rules next?"
|
|
9
8
|
|
|
10
9
|
You work in two phases:
|
|
11
10
|
|
|
12
|
-
1. **Classify** — turn recent git history into a structured, pipe-delimited CSV (one classified row per commit) by dispatching parallel
|
|
11
|
+
1. **Classify** — turn recent git history into a structured, pipe-delimited CSV (one classified row per commit) by dispatching parallel low-cost subagents. You do this yourself; there is no separate agent that hands you a CSV.
|
|
13
12
|
2. **Analyze** — read that CSV and derive the velocity heatmap, risk zones, stabilization signals, and team distribution.
|
|
14
13
|
|
|
15
14
|
## Parameters
|
|
@@ -80,7 +79,7 @@ Build a registry of objects:
|
|
|
80
79
|
|
|
81
80
|
Split the commit registry into batches of `batch_size` commits each.
|
|
82
81
|
|
|
83
|
-
|
|
82
|
+
Dispatch one **independent subagent per batch** on the **cheapest capable tier** — classification is mechanical, so the lowest-cost model that can follow the output format is the right one. Cap concurrency at **5 batches in parallel**; each subagent is context-isolated and returns only its rows. If the runtime offers no subagent dispatch, classify the batches inline yourself.
|
|
84
83
|
|
|
85
84
|
Before building the prompt template, check if `docs/memory/change-review.md` contains **Module Taxonomy** and **Feature Taxonomy** sections. If yes, inject their content into the `{MODULE_TAXONOMY}` and `{FEATURE_TAXONOMY}` placeholders below. If no memory file exists, use these generic fallbacks:
|
|
86
85
|
|
|
@@ -241,7 +240,7 @@ Per module, list which authors made the most commits in the 3-month window. Surf
|
|
|
241
240
|
## Rules
|
|
242
241
|
|
|
243
242
|
- Never modify source code — read-only except for writing the output CSV, `docs/memory/change-review.md`, and `docs/history/backlog.md`
|
|
244
|
-
-
|
|
243
|
+
- Run all classification subagents on the cheapest capable tier to minimize cost; they are independent and context-isolated
|
|
245
244
|
- Always report progress: "Dispatching batch 1-5 of 12..." etc.
|
|
246
245
|
- If git commands fail (bad branch, bad date range), stop and report the error clearly
|
|
247
246
|
- Pipe characters in commit messages must be replaced with dashes before writing to CSV
|
|
@@ -135,6 +135,7 @@ docs/
|
|
|
135
135
|
├── history/
|
|
136
136
|
│ ├── CHANGELOG.md # Master changelog index
|
|
137
137
|
│ ├── changelog/ # Individual entries
|
|
138
|
+
│ ├── ledger/ # Refinement Ledger — append-only per-commit refinement journal (YYYY-MM.md; written at commit time, NOT scaffolded empty)
|
|
138
139
|
│ ├── plans/ # Implementation plans (Status field required)
|
|
139
140
|
│ ├── brainstorms/ # Harvested brainstorm sessions ({topic}/) — user decides kept (committed) or deleted; Readme.md is the index
|
|
140
141
|
│ └── backlog.md # Tracked work items by priority (P0-P3)
|
|
@@ -197,7 +198,7 @@ Re-running you is safe — the structure work is idempotent, so a second pass is
|
|
|
197
198
|
## Rules
|
|
198
199
|
|
|
199
200
|
- **Never delete feature docs** — only update or flag for review.
|
|
200
|
-
- **Never modify `docs/history/plans
|
|
201
|
+
- **Never modify `docs/history/plans/`, `docs/history/changelog/`, or `docs/history/ledger/`** (frozen/append-only records — ledger blocks are written only at commit time, distilled only by the `retro` agent).
|
|
201
202
|
- **Preserve existing doc structure and formatting** when updating.
|
|
202
203
|
- **When in doubt, create a backlog item** rather than making a wrong update.
|
|
203
204
|
- **Be specific:** include file paths, line numbers, and what changed.
|
|
@@ -61,6 +61,7 @@ The two guarantees are complementary and both break on mixing: a reader holding
|
|
|
61
61
|
| Document feature/module (LLD) | [`templates/feature.md`](templates/feature.md) |
|
|
62
62
|
| Document data flow / state / Redux | [`templates/feature.md`](templates/feature.md) — they are sections of the feature doc |
|
|
63
63
|
| Create/update changelog | [`templates/changelog-entry.md`](templates/changelog-entry.md) (record) |
|
|
64
|
+
| Record per-commit refinement (ledger block) | [`templates/refinement-ledger.md`](templates/refinement-ledger.md) (record — written at commit time, distilled by the `retro` agent) |
|
|
64
65
|
| Create/update plan | [`templates/plan.md`](templates/plan.md) (record) |
|
|
65
66
|
| Record/revise architecture decision | [`templates/architecture-decision.md`](templates/architecture-decision.md) — one AD per subject; revisions update it in place |
|
|
66
67
|
| System at a glance | [`templates/system-overview.md`](templates/system-overview.md) |
|
|
@@ -11,7 +11,8 @@ const RULES = [
|
|
|
11
11
|
{ id: 'progress-marker', severity: 'block', scope: 'truth', pattern: /\bphases?\s+\d[^.\n]{0,40}\b(complete|done)\b|\b(build|implementation) (is )?(\d+%|partially) (complete|done)\b/i, message: 'progress marker — progress lives in the plan/backlog record' },
|
|
12
12
|
{ id: 'temporal-hedge', severity: 'warn', scope: 'truth', pattern: /\bnot yet\b|\bfor now\b|\bcurrently\b|\bstill (unsupported|missing|pending|unimplemented|in progress)\b/i, message: 'temporal hedge — state the fact without "currently / not yet / for now"' },
|
|
13
13
|
{ id: 'predecessor-frame', severity: 'warn', scope: 'truth', pattern: /\bpreviously\b|\bthe old \w+\b|\blegacy \w+ (was|is)\b/i, message: 'predecessor framing — describe the one current design' },
|
|
14
|
-
|
|
14
|
+
// docs/tests/ behavioral checklists use `- [ ]` as test-step notation (step → **Assert**), not progress tracking — exempt that one folder from this rule; every other truth doc still bans checkboxes.
|
|
15
|
+
{ id: 'status-glyph', severity: 'warn', scope: 'truth', exempt: /(^|\/)docs\/tests\//, pattern: /(^|\s)(✅|⏳|- \[[ x]\])/u, message: 'status glyph / checklist in a truth doc — tracking belongs in a record' },
|
|
15
16
|
{ id: 'date-in-truth-doc', severity: 'warn', scope: 'truth', pattern: /\b20\d{2}-\d{2}-\d{2}\b/, message: 'date in a truth doc — only the AD Decision Changelog and structure.md Health Log tails carry dates' },
|
|
16
17
|
];
|
|
17
18
|
|
|
@@ -71,6 +72,7 @@ function lintFile(path, findings) {
|
|
|
71
72
|
|
|
72
73
|
for (const rule of RULES) {
|
|
73
74
|
if (rule.scope !== scope || disabled.has(rule.id)) continue;
|
|
75
|
+
if (rule.exempt && rule.exempt.test(path)) continue;
|
|
74
76
|
for (const { n, line } of lines) {
|
|
75
77
|
if (!rule.pattern.test(line)) continue;
|
|
76
78
|
if (line.includes(`doc-lint-disable: ${rule.id}`) || new RegExp(`doc-lint-disable:[^>]*\\b${rule.id}\\b`).test(line)) continue;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# Refinement Ledger
|
|
2
|
+
|
|
3
|
+
Record. Use for: the append-only per-commit journal of session refinement — one block per non-mechanical commit, written by the committing agent at commit time and staged **inside the commit it describes**. Blocks are immutable once committed: never edited, renumbered, or reconciled; a correction is a new block referencing the old. The ledger is exempt from doc-health passes by genre — it is history and can never be "wrong".
|
|
4
|
+
|
|
5
|
+
Monthly files: `docs/history/ledger/YYYY-MM.md`, created on first block — the folder is never scaffolded empty. Distillation is the `retro` agent's job; this template owns only the capture format.
|
|
6
|
+
|
|
7
|
+
## Block format
|
|
8
|
+
|
|
9
|
+
```
|
|
10
|
+
### {YYYY-MM-DD} · {surface} — {one-line outcome}
|
|
11
|
+
- **Ask:** {what the user asked, compressed — taste and preference statements quoted verbatim}
|
|
12
|
+
- **Iterations:** {N} · rejected: {what was rejected and why} | none
|
|
13
|
+
- **Skills:** {skill}@{version} — survived | partially survived | overridden ({why, briefly}) | none used
|
|
14
|
+
- **Change:** {added/changed X, which does Y, because Z — behavior first, mechanism second}
|
|
15
|
+
- **Discovered:** {non-obvious fact learned by running the product — environment quirk, platform ceiling, seam behavior, dependency constraint} | none
|
|
16
|
+
- **Class:** {one or more keywords — suggestive vocabulary, not a closed enum; see Field rules}
|
|
17
|
+
- **Pin:** {enforced artifact written in this commit: test / token / guardrail / schema} | none — candidate: {what should hold it}
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Field rules
|
|
21
|
+
|
|
22
|
+
- **Every field present; "none" stated explicitly.** An absent field is a template violation. Sessions assert success by default — the required `rejected:` and `overridden` entries are the counterweight; an honestly empty failure field is information too.
|
|
23
|
+
- **`surface`** uses the repo's ownership vocabulary — the owning feature doc's topic or an `owns:` path stem — so the ledger is queryable per surface.
|
|
24
|
+
- **`Ask` quotes taste verbatim.** The user's preference wording is the one thing no skill can infer and no rebuild recovers; the ledger is its durable home.
|
|
25
|
+
- **`Skills` records efficacy honestly** — survived / partially survived / overridden with a reason. These verdicts are the raw data the `retro` agent aggregates into skill-evolution findings; sanitizing them into success stories destroys the mechanism's value.
|
|
26
|
+
- **`Discovered` holds what only running the product teaches.** If it was learned in use, it is recorded here the same day — this field feeds the pin candidates.
|
|
27
|
+
- **`Class` is a suggestive vocabulary, not a closed enum.** Tag with one or more keywords, preferring an existing term over a synonym so the `retro` agent can cluster; coin a new one when nothing fits — a recurring coinage is itself retro signal that the vocabulary (or the doc set) is missing a category. Suggested keywords: `ux` · `ui` · `visual` · `taste` · `layout` · `motion` · `interaction` · `copy` · `a11y` · `responsiveness` · `navigation` · `state` · `structure` · `architecture` · `seam` · `contract` · `schema` · `data` · `content` · `seed` · `performance` · `caching` · `resilience` · `error-handling` · `security` · `auth` · `observability` · `logging` · `testing` · `tooling` · `dependency` · `ops` · `deploy` · `env` · `ci` · `i18n` · `docs`.
|
|
28
|
+
- **`Pin` closes the loop:** the enforced artifact written in this commit, or the named candidate for the `retro` agent to flag. A taste-verified behavior with `Pin: none` and no candidate is a template smell.
|
|
29
|
+
- **Out-of-session commits** (the committing session did not do the work): fill what the diff and conversation evidence support; mark the rest `unknown — committed out-of-session`.
|
|
30
|
+
|
|
31
|
+
## Exemptions (closed list)
|
|
32
|
+
|
|
33
|
+
No block for: release/bot commits, harness installs and bumps, lockfile-only changes, pure renames/moves, and ledger housekeeping itself. Everything else gets a block, however short.
|
|
@@ -30,6 +30,7 @@ Each topic has one canonical location. Read from here, not from plans or changel
|
|
|
30
30
|
| Testing strategy | `docs/tests/` | strategy.md |
|
|
31
31
|
| Historical plans | `docs/history/plans/` | YYYY-MM-DD-name.md |
|
|
32
32
|
| Change records | `docs/history/changelog/` | Individual entries |
|
|
33
|
+
| Refinement Ledger | `docs/history/ledger/` | YYYY-MM.md (append-only, written at commit time) |
|
|
33
34
|
| Migration runbooks | `docs/history/migrations/` | YYYY-MM-DD-name.md |
|
|
34
35
|
| Deep-research artifacts | `docs/history/research/{topic}/` | README.md + findings.md + sources.md |
|
|
35
36
|
| Brainstorm design records | `docs/research/{topic}-brainstorm/` (active; legacy `-brainstorming/`) → `docs/history/brainstorms/{topic}/` (harvested; user deletes or commits) | thesis.md + forks.md + ledger.md + state.md |
|
|
@@ -51,6 +52,7 @@ Every doc is a **truth document** (states current absolutes, topic-named, update
|
|
|
51
52
|
- `docs/tests/`: Testing strategy and test docs. Present when the repo has a test posture worth documenting.
|
|
52
53
|
- `docs/history/plans/`: Records. Must have `Status:` field. Never modify after completion.
|
|
53
54
|
- `docs/history/changelog/`: Records. Append-only.
|
|
55
|
+
- `docs/history/ledger/`: Records. The Refinement Ledger — an append-only per-commit refinement journal (monthly `YYYY-MM.md` files) written by the committing agent, each block staged inside the commit it describes; block format is the `documentation` skill's `templates/refinement-ledger.md`, distillation is the `retro` agent. Blocks are immutable — never edited, never reconciled; the folder is never scaffolded empty.
|
|
54
56
|
- `docs/history/migrations/`: Records. One-shot migration/upgrade runbooks — authored before execution, outcome-stamped and frozen after.
|
|
55
57
|
- `docs/history/research/{topic}/`: Deep-research artifacts — the dumped output of a research pass, one folder per topic (conventionally `README.md` synthesis + `findings.md` verified claims & citations + `sources.md`). A point-in-time, cited record — **not** a living authority doc: it owns no code (no `owns:` frontmatter) and is never edited to "stay current." A spec/plan links to it for grounding; a new question gets a new topic folder.
|
|
56
58
|
- `docs/research/{topic}-brainstorm/` → `docs/history/brainstorms/{topic}/`: Brainstorm design records — the Brainstorming-Mode session for a topic (working surface `thesis.md` + `forks.md` + `ledger.md` + `state.md` + `basis/` + `fragments/`, plus an untracked `ops/` capture layer deleted at stop), written by the `brainstorm` skill and its twin agent. An active session lives under `docs/research/` (legacy folders carry the older `-brainstorming/` suffix); on a **passed harvest** it **moves** to `docs/history/brainstorms/` — the completion marker — and the **user decides whether the moved folder is deleted or committed** as provenance. Each of the two folders carries a `Readme.md` index (the skill reads it at start instead of scanning). Author-created (never scaffolded empty), one folder per design conversation. Owns no code (no `owns:` frontmatter); the harvest routes its conclusions into `architecture/`/`features/`/`history/`. (Distinct from `docs/history/research/{topic}/` above — that is a frozen deep-research record, not a brainstorm session.)
|
|
@@ -6,5 +6,14 @@
|
|
|
6
6
|
"editor.defaultFormatter": "esbenp.prettier-vscode",
|
|
7
7
|
"editor.formatOnSave": true,
|
|
8
8
|
"editor.wordWrap": "on"
|
|
9
|
+
},
|
|
10
|
+
// Hide harness-authoring scaffolding from the file explorer
|
|
11
|
+
"files.exclude": {
|
|
12
|
+
".claude": true,
|
|
13
|
+
".vscode": true,
|
|
14
|
+
".agents": true,
|
|
15
|
+
".codex": true,
|
|
16
|
+
"**/node_modules": true,
|
|
17
|
+
"**/apollo.service.json": true
|
|
9
18
|
}
|
|
10
19
|
}
|
|
@@ -6,5 +6,14 @@
|
|
|
6
6
|
"editor.defaultFormatter": "esbenp.prettier-vscode",
|
|
7
7
|
"editor.formatOnSave": true,
|
|
8
8
|
"editor.wordWrap": "on"
|
|
9
|
+
},
|
|
10
|
+
// Hide harness-authoring scaffolding from the file explorer
|
|
11
|
+
"files.exclude": {
|
|
12
|
+
".claude": true,
|
|
13
|
+
".vscode": true,
|
|
14
|
+
".agents": true,
|
|
15
|
+
".codex": true,
|
|
16
|
+
"**/node_modules": true,
|
|
17
|
+
"**/apollo.service.json": true
|
|
9
18
|
}
|
|
10
19
|
}
|
package/lib/codex/README.md
CHANGED
|
@@ -8,24 +8,34 @@ Owning doc: [`docs/features/codex-support.md`](../../../../docs/features/codex-s
|
|
|
8
8
|
|
|
9
9
|
| Source | Target | File |
|
|
10
10
|
| --- | --- | --- |
|
|
11
|
-
| `CLAUDE.md` | `AGENTS.md` (
|
|
11
|
+
| `CLAUDE.md` | `AGENTS.md` (byte-for-byte copy + generated adapter) | `agents-md.mjs` |
|
|
12
12
|
| `.claude/skills/` | `.agents/skills/` (mirror) | `skills.mjs` |
|
|
13
13
|
| bundle `codex/agents/*.toml` | `.codex/agents/*.toml` (copy) | `subagents.mjs` |
|
|
14
|
-
| `hooks.json` | `.codex/hooks.json` (`type:"command"
|
|
14
|
+
| `hooks.json` | `.codex/hooks.json` (`type:"command"`, command translated) | `hooks.mjs` |
|
|
15
15
|
| `.claude-plugin/*` | `.codex-plugin/plugin.json` + `.agents/plugins/marketplace.json` | `plugin-manifest.mjs` |
|
|
16
16
|
|
|
17
17
|
`index.mjs` orchestrates the install-time projectors and returns `{installed, notices, warnings, owned}`; `owned` is recorded in `.claude/harness.json` → `owned.codex` for prune-on-refresh.
|
|
18
18
|
|
|
19
19
|
**Out of scope (owner decision 2026-07-13):** MCP projection and any Codex `settings.json`/`config.toml` equivalent. There is no user-editable Codex file the harness co-owns, so every Codex path is a clean full-overwrite — no managed-block merge.
|
|
20
20
|
|
|
21
|
+
## Runtime adaptation the projection performs
|
|
22
|
+
|
|
23
|
+
The Claude source is runtime-neutral in intent, but three edges do not survive a mechanical copy — the projectors adapt them so a Codex install works out of the box:
|
|
24
|
+
|
|
25
|
+
- **Policy adapter (`agents-md.mjs`).** `AGENTS.md` is the `CLAUDE.md` policy copied byte-for-byte, then a compact **generated Codex runtime adapter** appended: it names the native skill (`.agents/skills/`) and agent (`.codex/agents/`) locations and, crucially, routes Codex to the `.claude/rules/*.md` files Codex does **not** auto-load. The list is derived from the bundled harness inventory (`bundledHarnessDir`), carries no user state, and is replaced whole on reinstall. It stays well under Codex's 32 KiB combined-instruction cap.
|
|
26
|
+
- **Hook-path translation (`hooks.mjs`, install) & (`publish.mjs`, plugin).** A hook command locating its script via `$CLAUDE_PROJECT_DIR` fails under Codex (Codex sets no such variable). For a **CLI install**, `toCodexCommand` prefixes a runtime-neutral root resolution (`git rev-parse --show-toplevel`, `pwd` fallback) and re-exports `CLAUDE_PROJECT_DIR`, so the hook resolves from the project root or any nested dir. For a **marketplace plugin**, `publish.mjs` rewrites the prefix to `$CLAUDE_PLUGIN_ROOT/hooks/` — the plugin-root variable both runtimes export.
|
|
27
|
+
- **Agent validation (`validate-codex-agents.mjs`).** A committed twin must be valid TOML with the required keys and carry no Claude-only primitive (`Task tool`, `subagent_type`, or a fixed model tier). Because a twin ships to consumers unparsed, this standalone validator is the gate — the authoring procedure mandates it.
|
|
28
|
+
|
|
29
|
+
## CLI vs plugin capability surface
|
|
30
|
+
|
|
31
|
+
The two channels do not install the same set. The **CLI** writes the full Codex footprint — `AGENTS.md`, `.agents/skills/`, `.codex/agents/*.toml`, `.codex/hooks.json`. The **marketplace plugin** carries only what `.codex-plugin/plugin.json` supports — **skills + hooks**; it exposes no project custom agents (Codex custom agents are a CLI-only feature) and no root policy. See [`codex-support.md`](../../../../docs/features/codex-support.md) → _Supported Codex plugin surface_.
|
|
32
|
+
|
|
21
33
|
## Subagents are authored, not derived at install
|
|
22
34
|
|
|
23
|
-
`.claude/agents/*.md → .codex/agents/*.toml` is
|
|
35
|
+
`.claude/agents/*.md → .codex/agents/*.toml` is a semantic conversion, so the twin is **authored from the `.md` by following** [`docs/architecture/harness/authoring-agents.md`](../../../../docs/architecture/harness/authoring-agents.md) — the model that writes or edits the agent produces the twin inline (frontmatter → `name`/`description`, body verbatim → `developer_instructions`, `tools:` dropped to a comment, Claude model aliases omitted), with **no external CLI**. The committed `agents/<name>.codex.toml` is checked by the validation gate:
|
|
24
36
|
|
|
25
37
|
```bash
|
|
26
|
-
node packages/cli/lib/codex/
|
|
27
|
-
node packages/cli/lib/codex/gen-agents.mjs --force # regenerate all shared agents
|
|
28
|
-
node packages/cli/lib/codex/gen-agents.mjs --include-harness # + harness/*/agents/*.md
|
|
38
|
+
node packages/cli/lib/codex/validate-codex-agents.mjs # or: npm run validate:codex-agents
|
|
29
39
|
```
|
|
30
40
|
|
|
31
|
-
`
|
|
41
|
+
`build-data.js` and `publish.mjs` then ship the committed TOML; the installer copies it, so **consumers need no Codex CLI**. Re-author an agent's TOML in the same change that edits its `.md` (source↔twin parity).
|