agent-bios 0.12.0 → 0.13.0
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/claude/guides/coding-staged-workflow.md +1 -0
- package/claude/guides/review-defect-criteria.md +214 -0
- package/claude/guides/review-request.md +15 -1
- package/codex/guides/coding-staged-workflow.md +1 -0
- package/codex/guides/review-defect-criteria.md +214 -0
- package/codex/guides/review-request.md +15 -1
- package/compose/assemble.py +7 -0
- package/compose/domains.json +1 -0
- package/launch/agent-launch.py +953 -180
- package/package.json +2 -2
- package/provenance.json +1 -1
|
@@ -80,6 +80,7 @@ patching them one at a time is a queue that refills.
|
|
|
80
80
|
|
|
81
81
|
- At each stage, run review loops as appropriate: self review, subagent review when available, and structured multi-lens review when the repository or domain supports one (concrete tool: Environment Binding below).
|
|
82
82
|
- Iterate until material issues reach zero: review, identify material issues, fix them, and review again.
|
|
83
|
+
- "Material issues reach zero" is counted over the declared defect criterion's stop-relevant class; choosing and declaring that criterion is owned by `${CLAUDE_CONFIG_DIR:-$HOME/.claude}/guides/review-defect-criteria.md`.
|
|
83
84
|
- Use the severity contract for materiality — the canonical definition is the ladder below; external review tools map their levels onto it: blocker, high, and medium are material; low and info are non-material.
|
|
84
85
|
- Treat blocker as primary happy-path or core-contract failure.
|
|
85
86
|
- Treat high as supported user, environment, data, or execution path failure.
|
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
---
|
|
2
|
+
guide_id: review-defect-criteria
|
|
3
|
+
language: en
|
|
4
|
+
status: active
|
|
5
|
+
use_when:
|
|
6
|
+
- declaring what counts as a defect before dispatching any review
|
|
7
|
+
- choosing or writing the defect criterion for a system type × work goal
|
|
8
|
+
- a review loop plateaus, diverges, or its "material 0" stop never arrives
|
|
9
|
+
- a finding's class is contested at the boundary, or two lenses class it differently
|
|
10
|
+
core_rules:
|
|
11
|
+
- choose and declare the criterion before the review starts — undeclared, every reviewer substitutes its own
|
|
12
|
+
- the severity ladder answers how bad; the criterion answers whether it is a defect, of which class, and what "zero" is counted over
|
|
13
|
+
- a criterion with an empty cell is a hunch, not a criterion — do not start the review
|
|
14
|
+
- paste the goldens into the packet verbatim; a definition alone does not classify consistently at the boundary
|
|
15
|
+
- put the class enum on the accepting channel where one exists; on prose routes, run the fold procedure
|
|
16
|
+
- a mixed packet is split — never run two observers in one trajectory
|
|
17
|
+
verification_focus:
|
|
18
|
+
- every dispatched packet names its criterion and carries its goldens
|
|
19
|
+
- each round audits reported class against post-measurement class; repeated disagreement mints the next golden
|
|
20
|
+
- the stop condition is evaluated over the stop-relevant class only, never the whole finding count
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
# Review Defect Criteria
|
|
24
|
+
|
|
25
|
+
A defect criterion is chosen, not assumed. This guide is a scoped extension of
|
|
26
|
+
`${CLAUDE_CONFIG_DIR:-$HOME/.claude}/guides/review-request.md`: before that guide's
|
|
27
|
+
request composition starts, this one decides what the review is hunting. The
|
|
28
|
+
evidence: one codebase, two stop criteria, opposite trajectories.
|
|
29
|
+
|
|
30
|
+
| Rounds | Criterion | Trajectory |
|
|
31
|
+
|---|---|---|
|
|
32
|
+
| early | material = contract violation **or** unprotected contract sentence, small frozen surface | 10 → 4 → 1 → 0 |
|
|
33
|
+
| late | same, scoped to client-observable behavior | 17 → 19 → 21 → 23 → 19 — **plateau** |
|
|
34
|
+
| final | split classes: behavioral_defect / coverage_gap / doc_gap; stop = behavioral 0 | behavioral 10 → 5 — falling again |
|
|
35
|
+
|
|
36
|
+
The plateau was the criterion, not the code: counting "a contract sentence no test
|
|
37
|
+
protects" as a defect means every fix adds contract rows, each a potential defect
|
|
38
|
+
next round — a self-refilling criterion cannot reach zero while its surface grows.
|
|
39
|
+
Yet that same criterion is exactly right for a library, where an unprotected promise
|
|
40
|
+
is a first-class defect. Neither is wrong; starting without choosing is.
|
|
41
|
+
|
|
42
|
+
The **severity ladder** (in `${CLAUDE_CONFIG_DIR:-$HOME/.claude}/guides/coding-staged-workflow.md`)
|
|
43
|
+
answers *how bad* a finding is. The **criterion** answers *whether* it is a defect at
|
|
44
|
+
all, of which class, and what "zero" is counted over. The plateau happened entirely
|
|
45
|
+
inside "material" — no severity adjustment could have ended it. Ordering: system type
|
|
46
|
+
+ goal → defect criterion → classification → defect? → severity → materiality → stop.
|
|
47
|
+
|
|
48
|
+
## The criterion schema
|
|
49
|
+
|
|
50
|
+
One entry carries all of these. An empty cell makes it a hunch, not a criterion — do
|
|
51
|
+
not start the review on it.
|
|
52
|
+
|
|
53
|
+
| Field | Meaning |
|
|
54
|
+
|---|---|
|
|
55
|
+
| observer | whose eyes judge — client, caller, operator, a model reading the output |
|
|
56
|
+
| defect | what the observer must experience |
|
|
57
|
+
| classes | the enum, exactly ONE class stop-relevant; the others are relief valves that keep the stop class honest |
|
|
58
|
+
| evidence | what one finding must present |
|
|
59
|
+
| non-defects | defect-lookalikes excluded by this criterion — named explicitly |
|
|
60
|
+
| stop condition | what "0" means, counted over the stop class, and WHY it is reachable — how a growing surface is pinned |
|
|
61
|
+
| misclassification cost | which error is expensive — the direction to tell the reviewer to lean |
|
|
62
|
+
| goldens | ≥2 positive, ≥2 negative, ≥1 boundary; each with why, date, and provenance: `measured` (dated incident) or `constructed` (authored to pin a boundary) |
|
|
63
|
+
|
|
64
|
+
## The catalog
|
|
65
|
+
|
|
66
|
+
Four system types. A starting set, not a census.
|
|
67
|
+
|
|
68
|
+
### Web service / API surface (contract compliance)
|
|
69
|
+
|
|
70
|
+
- **Observer**: the HTTP client.
|
|
71
|
+
- **Defect**: a client today receives a response that differs from the contract — status code, envelope, stream terminal frames, the model actually run, isolation, resource caps.
|
|
72
|
+
- **Classes**: `behavioral_defect` (stop-relevant) · `coverage_gap` · `doc_gap`.
|
|
73
|
+
- **Evidence**: the concrete request and observed vs promised response.
|
|
74
|
+
- **Non-defects**: internal lifecycle (unless a request sequence shows two different responses), absence of a test, documentation wording.
|
|
75
|
+
- **Stop**: behavioral 0 — reachable: the code surface is finite and shrinks monotonically unless a fix creates a new behavioral defect.
|
|
76
|
+
- **Misclassification cost**: false negatives (a client actually breaks); but inflating coverage gaps into defects destroys the stop condition — audit category creep separately.
|
|
77
|
+
- **Goldens** (all `measured`, 2026-08-13–15):
|
|
78
|
+
- **+** `GET` on a nonexistent path returned 405, not 404 — an existing-method complaint attached to a path that does not exist.
|
|
79
|
+
- **+** a streaming endpoint's terminal delta carried only `output_tokens`, so cache/input token counts never reach a streaming client — non-streaming was correct, which is why nobody saw it.
|
|
80
|
+
- **−** "no test catches a one-line flip of this default": today's behavior is correct — `coverage_gap` here, a defect only under the library criterion.
|
|
81
|
+
- **−** child-process kill grace period — out of scope until a request sequence shows a client-visible difference; pins the observer to the client.
|
|
82
|
+
- **±** rejecting a documented-as-valid boundary value (compression 100, docs say "below 100 requires jpeg/webp") — the documentation is what makes it a defect; without that sentence it is taste.
|
|
83
|
+
|
|
84
|
+
### Library / SDK / contract-first system
|
|
85
|
+
|
|
86
|
+
- **Observer**: the caller **and** the future maintainer.
|
|
87
|
+
- **Defect**: a promise violated today, or a promise unprotected — a one-line change breaks it and nothing catches it. The API criterion's `coverage_gap` is first-class here.
|
|
88
|
+
- **Classes**: `contract_defect` (stop-relevant) · `style_note` · `internal_change`.
|
|
89
|
+
- **Evidence**: for a violation, as above; for an unprotected promise, the promise sentence + the one-line change that breaks it + the absence of any catching test.
|
|
90
|
+
- **Non-defects**: style, internal structure.
|
|
91
|
+
- **Stop**: caution — this criterion self-refills while the contract grows. Declare "0" only over a surface whose growth has stopped; on a growing surface, narrow the stop to "every promise this change added is protected."
|
|
92
|
+
- **Misclassification cost**: balanced — miss an unprotected promise and the next refactor breaks it silently; over-report and the loop never ends.
|
|
93
|
+
- **Goldens**:
|
|
94
|
+
- **+** a streaming-image event test matched only `.completed`, so an edit stream misnamed `image_generation.completed` still passed — mutation survival showed the promise unprotected. (`measured`, 2026-08-13–15)
|
|
95
|
+
- **+** the contract promised "storage serves a large image at least once"; the code evicted it on the next request — resolved by fixing the **contract**: the disagreement is the defect, whichever side moves. (`measured`, 2026-08-13–15)
|
|
96
|
+
- **−** renaming an internal helper no document promises — the observer holds the contract; undocumented internals carry no promise. (`measured`, 2026-08-13–15)
|
|
97
|
+
- **−** a caller breaking on undocumented iteration order — no promise existed; the rename boundary pinned from the caller's side. (`constructed`, 2026-08-19)
|
|
98
|
+
- **±** an inventory-listed test turns out vacuous — asserts nothing about its promise. "A test exists" is a claim about names until the assertion is read; hand the reviewer "check the assertion, not the name." (`measured`, 2026-08-13–15)
|
|
99
|
+
|
|
100
|
+
### AI workbench / harness (agent orchestration, review loops, verification pipelines)
|
|
101
|
+
|
|
102
|
+
- **Observer**: the operator, and any model consuming the harness's output.
|
|
103
|
+
- **Defect**: **a false signal that looks true** — a wrong PASS, a vacuous test, a silent fallback, a packet missing the call site, a wrong denominator. Being wrong is not the defect; being wrong while *looking right* is. Second form: a run claimed without provable dispatch — no receipt.
|
|
104
|
+
- **Classes**: `false_signal` (stop-relevant) · `detected_miss`. An unproven dispatch — a run or PASS claimed with no receipt — is classed `false_signal`, not given its own relief valve: a signal that cannot be shown true is counted false, or a round could declare completion while every dispatch stayed unproven.
|
|
105
|
+
- **Evidence**: the input on which the instrument gave a false verdict, plus the known correct answer. The standard probe: run the instrument against an input whose answer is known to be the opposite.
|
|
106
|
+
- **Non-defects**: one output's style; a false positive the harness itself **detected** — a caught error is the harness working.
|
|
107
|
+
- **Stop**: every PASS emitted this run survives a known-opposite check and evidences its own dispatch. The unit is "this run's signals are trustworthy," not a standing zero.
|
|
108
|
+
- **Misclassification cost**: false passes dominate. An instrument bug reporting failure dies in minutes because someone looks; one reporting success survives — a selection effect.
|
|
109
|
+
- **Goldens**:
|
|
110
|
+
- **+** a shell test runner received one nonexistent path (zsh does not word-split an unquoted variable), so every run exited 1 and every mutation reported KILLED — a green instrument that never ran its subject. (`measured`, 2026-08-13–15)
|
|
111
|
+
- **+** a test-inventory grep matched only `^test('...'` and missed every parameterized name; three reviewers judged a populated file empty — nothing tied the inventory's denominator to the source's own count. (`measured`, 2026-08-13–15)
|
|
112
|
+
- **+** a negative control kept passing after a faithful revert of the fix it was written against — a guard satisfied by an absence, a false PASS about the gate itself; found only by re-running reverts. (`measured`, 2026-08)
|
|
113
|
+
- **+** a review round returned "clean" with no receipt evidencing that the declared packet was dispatched on the exact seat — `false_signal` although nothing observed was wrong: what the stop refuses is absence of proof of dispatch, not proof of falsity. (`constructed`, 2026-08-19, pinned after a classification dispute at exactly this boundary)
|
|
114
|
+
- **−** one reviewer over-classed an item as material; another lens plus measurement filtered it — the harness caught it, so it worked: `detected_miss`, not a defect. (`measured`, 2026-08-13–15)
|
|
115
|
+
- **−** five review rounds returned 8 → 9 → 10 → 5 → 12 findings, refusing to converge — and every count was true. A truthful unpleasant signal is not a false signal; the defect lived in the undeclared criterion. (`measured`, 2026-08-16–17)
|
|
116
|
+
- **±** a surviving mutation proved equivalent — the platform already normalized what the mutated guard checked. Neither a harness defect nor a test gap; but a harness that auto-reads "survived = gap" has a defect in that rule. (`measured`, 2026-08-13–15)
|
|
117
|
+
|
|
118
|
+
### Decision ontology (an ontology a model decides from)
|
|
119
|
+
|
|
120
|
+
- **Observer**: a model or agent deciding from the ontology alone.
|
|
121
|
+
- **Defect**: a representation that produces a wrong decision or blocks a right one: overlapping concept boundaries, a missing distinction the decision needs, an instance contradicting reality, a wrong relation direction or cardinality, a name implying what the definition does not say.
|
|
122
|
+
- **Classes**: `decision_defect` (stop-relevant) · `representation_note` · `out_of_scope_gap`.
|
|
123
|
+
- **Evidence**: a **decision scenario** — "answered from the ontology alone, this question yields X; reality is Y" — with the question, the path taken, and the ground truth.
|
|
124
|
+
- **Non-defects**: representation format, completeness as such, a question the model would get wrong without the ontology too.
|
|
125
|
+
- **Stop**: zero wrong decisions over the agreed scenario set. The set is the scope — fix it first, or this criterion self-refills like the library one.
|
|
126
|
+
- **Misclassification cost**: situational — feeding a hard gate makes false negatives expensive; exploratory aid makes false positives expensive. Filling this cell is mandatory at declaration.
|
|
127
|
+
- **Goldens** (all `constructed`, 2026-08-19, authored to pin boundaries the source loop's decision-scenario framing left open):
|
|
128
|
+
- **+** `Customer` and `Account` both define "the paying party"; a refund-routing question resolves through both paths — overlap is a decision defect even when each definition is individually correct.
|
|
129
|
+
- **+** `Order —hasOne→ Payment` while split payments exist — cardinality is a claim, and a false claim misleads the deciding model.
|
|
130
|
+
- **−** a verbose concept description — no decision changes; form is outside this observer's sight.
|
|
131
|
+
- **−** a domain absent that no scenario in the agreed set needs — completeness is scoped by the set, not the world.
|
|
132
|
+
- **±** the distinction exists but the model cannot find it (name or link missing) — with the observer fixed as "a model seeing only the ontology," unreachable is a representation defect, not a search defect. The observer clause decides the class.
|
|
133
|
+
|
|
134
|
+
## Before any review
|
|
135
|
+
|
|
136
|
+
1. Write one sentence: the system type and this work's goal. ("API surface — make the responses clients receive today match the contract." / "Harness — make this run's PASS signals trustworthy.")
|
|
137
|
+
2. Pick a criterion from the catalog, or fill the schema fresh. A cell you cannot fill means the review does not start.
|
|
138
|
+
3. Paste the goldens into the packet verbatim. Never the definition alone.
|
|
139
|
+
4. Declare the stop condition and why it is reachable — or how the scope was pinned to make it so.
|
|
140
|
+
5. Put the classification on the accepting channel (next section).
|
|
141
|
+
6. Audit every round: reported class vs the class confirmed after measurement. A repeated disagreement is the next golden.
|
|
142
|
+
|
|
143
|
+
## Enforcing the enum, by channel
|
|
144
|
+
|
|
145
|
+
Ranked by how much the channel refuses for you:
|
|
146
|
+
|
|
147
|
+
1. **A route with a submit schema**: classification is a required enum field. The
|
|
148
|
+
measured precedent is anchors — 2,466 of 2,466 findings carried one, because the
|
|
149
|
+
schema refuses output without it. Where this channel exists, use it.
|
|
150
|
+
2. **Prose-packet routes** (the shipped deep-review methods): the packet header
|
|
151
|
+
declares `Criterion: <name>` with the goldens pasted verbatim, and the dispatching
|
|
152
|
+
agent runs this fold procedure on what comes back:
|
|
153
|
+
1. For each returned finding row, look up its class against the declared enum.
|
|
154
|
+
2. A row carrying a class from the enum enters the findings ledger under that class.
|
|
155
|
+
3. A row with no class, or a class outside the enum, is **not admitted**: send it
|
|
156
|
+
back once for classification, or record it as refused with the reason. Never
|
|
157
|
+
admit it unclassified, and never guess its class for it.
|
|
158
|
+
4. Count the stop condition over the stop-relevant class only.
|
|
159
|
+
5. Record the audit pair (reported class, confirmed class) for procedure step 6.
|
|
160
|
+
|
|
161
|
+
Stated honestly: on a prose route this is steering, not control — the fold is
|
|
162
|
+
performed by an agent following this guide, and nothing structural refuses a
|
|
163
|
+
class-less row for it. That is the known weaker result of a request-only rule.
|
|
164
|
+
3. **The launcher's criterion discipline** (agent-launch): a preset declaring
|
|
165
|
+
`criterion = true` renders one core-owned discipline clause into every review
|
|
166
|
+
method row — the criterion's content never enters the per-launch config; it rides
|
|
167
|
+
the packet as a `ReviewCriterion/v1:` record line beside the prose above.
|
|
168
|
+
`--compile-criterion` refuses a document failing the schema's decidable subset and
|
|
169
|
+
emits the canonical findings schema; where the host CLI's structured-output flag
|
|
170
|
+
probes present (`--check-schema-flag`), the dispatch passes that schema, and
|
|
171
|
+
receipt emission under `REVIEW_CRITERION_SCHEMA` refuses a class-less or
|
|
172
|
+
out-of-enum result — no receipt, and an unproven dispatch is already in the stop
|
|
173
|
+
class. `--verify-receipts --packet` recompiles the packet's record and refuses a
|
|
174
|
+
receipt whose schema digest was compiled from any other criterion. A route whose
|
|
175
|
+
flag probes absent runs rank 2 and is disclosed as prose discipline — never
|
|
176
|
+
credited as schema-enforced.
|
|
177
|
+
|
|
178
|
+
## Golden lifecycle
|
|
179
|
+
|
|
180
|
+
- **Admission**: only a golden that decides a boundary the definition leaves open,
|
|
181
|
+
evidenced by a recorded classification disagreement or an audited misclassification;
|
|
182
|
+
provenance labeled `measured` or `constructed`, each with its why and date.
|
|
183
|
+
- **Overturn**: only by a measured counterexample. Correct the golden in place — this
|
|
184
|
+
guide describes the present — plus a dated decision record, in whatever channel the
|
|
185
|
+
repo keeps decisions, naming the closed golden and the counterexample. Silent
|
|
186
|
+
deletion is forbidden: a wrong golden makes reviewers systematically wrong, and an
|
|
187
|
+
untracked fix hides that it ever did.
|
|
188
|
+
|
|
189
|
+
## Declaring, switching, and mixed packets
|
|
190
|
+
|
|
191
|
+
- Every dispatched packet names its criterion. A harness round declares `AI harness`;
|
|
192
|
+
a round whose system type has no catalog entry declares a **task-local criterion**,
|
|
193
|
+
written in the packet itself, conforming to the schema above and labeled task-local
|
|
194
|
+
— repeated use is what earns a catalog entry.
|
|
195
|
+
- A mixed packet is split into one packet per criterion. Two observers in one
|
|
196
|
+
trajectory produce findings no single stop condition can count.
|
|
197
|
+
- When a criterion changes mid-loop: re-classify only the findings still open; rounds
|
|
198
|
+
already recorded are dated history. Never splice pre- and post-switch counts into
|
|
199
|
+
one series — they count different things.
|
|
200
|
+
|
|
201
|
+
## Evidence base
|
|
202
|
+
|
|
203
|
+
Derived from a 39-round adversarial review loop (3 lenses × a frontier reviewer) on a
|
|
204
|
+
peer OAuth CLI-API adapter, 2026-08-13–15: the same codebase plateaued at
|
|
205
|
+
17→19→21→23→19 findings under a self-refilling criterion and resumed falling
|
|
206
|
+
(behavioral 10→5) the round the classes were split and the stop counted over
|
|
207
|
+
`behavioral_defect` alone. The boundary evidence is from the same loop: a packet
|
|
208
|
+
instruction saying "do not inflate coverage gaps" still left two lenses classing one
|
|
209
|
+
finding `doc_gap` and `behavioral_defect`, both defensibly — one golden would have
|
|
210
|
+
decided it. The non-convergence golden (8→9→10→5→12, every count true) is this
|
|
211
|
+
environment's own launcher-review loop, 2026-08-16–17, run under an undeclared
|
|
212
|
+
"material" criterion; the two series are two populations under two criteria and are
|
|
213
|
+
cited separately for exactly the reason the migration section gives. Re-derive when
|
|
214
|
+
the review routes or the bound models change.
|
|
@@ -26,7 +26,11 @@ verification_focus:
|
|
|
26
26
|
This guide is a scoped extension of the global Coding Guidelines. Use it when
|
|
27
27
|
composing what you ask a reviewer for — the request, the evidence bar, the
|
|
28
28
|
verdict shape. It does not cover when to review, how deep, or what counts as
|
|
29
|
-
material
|
|
29
|
+
material — that last question splits in two: the severity ladder and review loop in
|
|
30
|
+
`${CLAUDE_CONFIG_DIR:-$HOME/.claude}/guides/coding-staged-workflow.md` own *how bad*,
|
|
31
|
+
while whether something is a defect at all, of which class, and what "zero" is
|
|
32
|
+
counted over is the defect criterion, owned by
|
|
33
|
+
`${CLAUDE_CONFIG_DIR:-$HOME/.claude}/guides/review-defect-criteria.md`. Nor
|
|
30
34
|
which reviewer kind to route to — the convergence heuristic in
|
|
31
35
|
`${CLAUDE_CONFIG_DIR:-$HOME/.claude}/guides/verification-discipline.md` owns that. Phrasing a prompt for a specific model
|
|
32
36
|
family is out of scope here; where that guidance ships, the rule that needs it
|
|
@@ -38,6 +42,16 @@ is a per-model claim; these are the failures that persist regardless of who
|
|
|
38
42
|
reviews. Every rule names the evidence behind it, because a review guide that
|
|
39
43
|
asserts without evidence would fail its own bar.
|
|
40
44
|
|
|
45
|
+
## Declare the criterion
|
|
46
|
+
|
|
47
|
+
Before composing anything else, name the defect criterion the review runs under —
|
|
48
|
+
the per-system-type definition of what a defect is, its class enum, and what "zero"
|
|
49
|
+
is counted over. `${CLAUDE_CONFIG_DIR:-$HOME/.claude}/guides/review-defect-criteria.md`
|
|
50
|
+
owns choosing it; this guide assumes one is declared. Put `Criterion: <name>` at the
|
|
51
|
+
top of the packet with that criterion's goldens pasted verbatim — a definition
|
|
52
|
+
without goldens does not classify consistently at the boundary, and an undeclared
|
|
53
|
+
criterion means every reviewer substitutes its own.
|
|
54
|
+
|
|
41
55
|
## Demand a failure path, not a gap
|
|
42
56
|
|
|
43
57
|
The dominant reviewer failure is not hallucination. Across 372 rejected
|
|
@@ -80,6 +80,7 @@ patching them one at a time is a queue that refills.
|
|
|
80
80
|
|
|
81
81
|
- At each stage, run review loops as appropriate: self review, subagent review when available, and structured multi-lens review when the repository or domain supports one (concrete tool: Environment Binding below).
|
|
82
82
|
- Iterate until material issues reach zero: review, identify material issues, fix them, and review again.
|
|
83
|
+
- "Material issues reach zero" is counted over the declared defect criterion's stop-relevant class; choosing and declaring that criterion is owned by `${CODEX_HOME:-$HOME/.codex}/guides/review-defect-criteria.md`.
|
|
83
84
|
- Use the severity contract for materiality — the canonical definition is the ladder below; external review tools map their levels onto it: blocker, high, and medium are material; low and info are non-material.
|
|
84
85
|
- Treat blocker as primary happy-path or core-contract failure.
|
|
85
86
|
- Treat high as supported user, environment, data, or execution path failure.
|
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
---
|
|
2
|
+
guide_id: review-defect-criteria
|
|
3
|
+
language: en
|
|
4
|
+
status: active
|
|
5
|
+
use_when:
|
|
6
|
+
- declaring what counts as a defect before dispatching any review
|
|
7
|
+
- choosing or writing the defect criterion for a system type × work goal
|
|
8
|
+
- a review loop plateaus, diverges, or its "material 0" stop never arrives
|
|
9
|
+
- a finding's class is contested at the boundary, or two lenses class it differently
|
|
10
|
+
core_rules:
|
|
11
|
+
- choose and declare the criterion before the review starts — undeclared, every reviewer substitutes its own
|
|
12
|
+
- the severity ladder answers how bad; the criterion answers whether it is a defect, of which class, and what "zero" is counted over
|
|
13
|
+
- a criterion with an empty cell is a hunch, not a criterion — do not start the review
|
|
14
|
+
- paste the goldens into the packet verbatim; a definition alone does not classify consistently at the boundary
|
|
15
|
+
- put the class enum on the accepting channel where one exists; on prose routes, run the fold procedure
|
|
16
|
+
- a mixed packet is split — never run two observers in one trajectory
|
|
17
|
+
verification_focus:
|
|
18
|
+
- every dispatched packet names its criterion and carries its goldens
|
|
19
|
+
- each round audits reported class against post-measurement class; repeated disagreement mints the next golden
|
|
20
|
+
- the stop condition is evaluated over the stop-relevant class only, never the whole finding count
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
# Review Defect Criteria
|
|
24
|
+
|
|
25
|
+
A defect criterion is chosen, not assumed. This guide is a scoped extension of
|
|
26
|
+
`${CODEX_HOME:-$HOME/.codex}/guides/review-request.md`: before that guide's
|
|
27
|
+
request composition starts, this one decides what the review is hunting. The
|
|
28
|
+
evidence: one codebase, two stop criteria, opposite trajectories.
|
|
29
|
+
|
|
30
|
+
| Rounds | Criterion | Trajectory |
|
|
31
|
+
|---|---|---|
|
|
32
|
+
| early | material = contract violation **or** unprotected contract sentence, small frozen surface | 10 → 4 → 1 → 0 |
|
|
33
|
+
| late | same, scoped to client-observable behavior | 17 → 19 → 21 → 23 → 19 — **plateau** |
|
|
34
|
+
| final | split classes: behavioral_defect / coverage_gap / doc_gap; stop = behavioral 0 | behavioral 10 → 5 — falling again |
|
|
35
|
+
|
|
36
|
+
The plateau was the criterion, not the code: counting "a contract sentence no test
|
|
37
|
+
protects" as a defect means every fix adds contract rows, each a potential defect
|
|
38
|
+
next round — a self-refilling criterion cannot reach zero while its surface grows.
|
|
39
|
+
Yet that same criterion is exactly right for a library, where an unprotected promise
|
|
40
|
+
is a first-class defect. Neither is wrong; starting without choosing is.
|
|
41
|
+
|
|
42
|
+
The **severity ladder** (in `${CODEX_HOME:-$HOME/.codex}/guides/coding-staged-workflow.md`)
|
|
43
|
+
answers *how bad* a finding is. The **criterion** answers *whether* it is a defect at
|
|
44
|
+
all, of which class, and what "zero" is counted over. The plateau happened entirely
|
|
45
|
+
inside "material" — no severity adjustment could have ended it. Ordering: system type
|
|
46
|
+
+ goal → defect criterion → classification → defect? → severity → materiality → stop.
|
|
47
|
+
|
|
48
|
+
## The criterion schema
|
|
49
|
+
|
|
50
|
+
One entry carries all of these. An empty cell makes it a hunch, not a criterion — do
|
|
51
|
+
not start the review on it.
|
|
52
|
+
|
|
53
|
+
| Field | Meaning |
|
|
54
|
+
|---|---|
|
|
55
|
+
| observer | whose eyes judge — client, caller, operator, a model reading the output |
|
|
56
|
+
| defect | what the observer must experience |
|
|
57
|
+
| classes | the enum, exactly ONE class stop-relevant; the others are relief valves that keep the stop class honest |
|
|
58
|
+
| evidence | what one finding must present |
|
|
59
|
+
| non-defects | defect-lookalikes excluded by this criterion — named explicitly |
|
|
60
|
+
| stop condition | what "0" means, counted over the stop class, and WHY it is reachable — how a growing surface is pinned |
|
|
61
|
+
| misclassification cost | which error is expensive — the direction to tell the reviewer to lean |
|
|
62
|
+
| goldens | ≥2 positive, ≥2 negative, ≥1 boundary; each with why, date, and provenance: `measured` (dated incident) or `constructed` (authored to pin a boundary) |
|
|
63
|
+
|
|
64
|
+
## The catalog
|
|
65
|
+
|
|
66
|
+
Four system types. A starting set, not a census.
|
|
67
|
+
|
|
68
|
+
### Web service / API surface (contract compliance)
|
|
69
|
+
|
|
70
|
+
- **Observer**: the HTTP client.
|
|
71
|
+
- **Defect**: a client today receives a response that differs from the contract — status code, envelope, stream terminal frames, the model actually run, isolation, resource caps.
|
|
72
|
+
- **Classes**: `behavioral_defect` (stop-relevant) · `coverage_gap` · `doc_gap`.
|
|
73
|
+
- **Evidence**: the concrete request and observed vs promised response.
|
|
74
|
+
- **Non-defects**: internal lifecycle (unless a request sequence shows two different responses), absence of a test, documentation wording.
|
|
75
|
+
- **Stop**: behavioral 0 — reachable: the code surface is finite and shrinks monotonically unless a fix creates a new behavioral defect.
|
|
76
|
+
- **Misclassification cost**: false negatives (a client actually breaks); but inflating coverage gaps into defects destroys the stop condition — audit category creep separately.
|
|
77
|
+
- **Goldens** (all `measured`, 2026-08-13–15):
|
|
78
|
+
- **+** `GET` on a nonexistent path returned 405, not 404 — an existing-method complaint attached to a path that does not exist.
|
|
79
|
+
- **+** a streaming endpoint's terminal delta carried only `output_tokens`, so cache/input token counts never reach a streaming client — non-streaming was correct, which is why nobody saw it.
|
|
80
|
+
- **−** "no test catches a one-line flip of this default": today's behavior is correct — `coverage_gap` here, a defect only under the library criterion.
|
|
81
|
+
- **−** child-process kill grace period — out of scope until a request sequence shows a client-visible difference; pins the observer to the client.
|
|
82
|
+
- **±** rejecting a documented-as-valid boundary value (compression 100, docs say "below 100 requires jpeg/webp") — the documentation is what makes it a defect; without that sentence it is taste.
|
|
83
|
+
|
|
84
|
+
### Library / SDK / contract-first system
|
|
85
|
+
|
|
86
|
+
- **Observer**: the caller **and** the future maintainer.
|
|
87
|
+
- **Defect**: a promise violated today, or a promise unprotected — a one-line change breaks it and nothing catches it. The API criterion's `coverage_gap` is first-class here.
|
|
88
|
+
- **Classes**: `contract_defect` (stop-relevant) · `style_note` · `internal_change`.
|
|
89
|
+
- **Evidence**: for a violation, as above; for an unprotected promise, the promise sentence + the one-line change that breaks it + the absence of any catching test.
|
|
90
|
+
- **Non-defects**: style, internal structure.
|
|
91
|
+
- **Stop**: caution — this criterion self-refills while the contract grows. Declare "0" only over a surface whose growth has stopped; on a growing surface, narrow the stop to "every promise this change added is protected."
|
|
92
|
+
- **Misclassification cost**: balanced — miss an unprotected promise and the next refactor breaks it silently; over-report and the loop never ends.
|
|
93
|
+
- **Goldens**:
|
|
94
|
+
- **+** a streaming-image event test matched only `.completed`, so an edit stream misnamed `image_generation.completed` still passed — mutation survival showed the promise unprotected. (`measured`, 2026-08-13–15)
|
|
95
|
+
- **+** the contract promised "storage serves a large image at least once"; the code evicted it on the next request — resolved by fixing the **contract**: the disagreement is the defect, whichever side moves. (`measured`, 2026-08-13–15)
|
|
96
|
+
- **−** renaming an internal helper no document promises — the observer holds the contract; undocumented internals carry no promise. (`measured`, 2026-08-13–15)
|
|
97
|
+
- **−** a caller breaking on undocumented iteration order — no promise existed; the rename boundary pinned from the caller's side. (`constructed`, 2026-08-19)
|
|
98
|
+
- **±** an inventory-listed test turns out vacuous — asserts nothing about its promise. "A test exists" is a claim about names until the assertion is read; hand the reviewer "check the assertion, not the name." (`measured`, 2026-08-13–15)
|
|
99
|
+
|
|
100
|
+
### AI workbench / harness (agent orchestration, review loops, verification pipelines)
|
|
101
|
+
|
|
102
|
+
- **Observer**: the operator, and any model consuming the harness's output.
|
|
103
|
+
- **Defect**: **a false signal that looks true** — a wrong PASS, a vacuous test, a silent fallback, a packet missing the call site, a wrong denominator. Being wrong is not the defect; being wrong while *looking right* is. Second form: a run claimed without provable dispatch — no receipt.
|
|
104
|
+
- **Classes**: `false_signal` (stop-relevant) · `detected_miss`. An unproven dispatch — a run or PASS claimed with no receipt — is classed `false_signal`, not given its own relief valve: a signal that cannot be shown true is counted false, or a round could declare completion while every dispatch stayed unproven.
|
|
105
|
+
- **Evidence**: the input on which the instrument gave a false verdict, plus the known correct answer. The standard probe: run the instrument against an input whose answer is known to be the opposite.
|
|
106
|
+
- **Non-defects**: one output's style; a false positive the harness itself **detected** — a caught error is the harness working.
|
|
107
|
+
- **Stop**: every PASS emitted this run survives a known-opposite check and evidences its own dispatch. The unit is "this run's signals are trustworthy," not a standing zero.
|
|
108
|
+
- **Misclassification cost**: false passes dominate. An instrument bug reporting failure dies in minutes because someone looks; one reporting success survives — a selection effect.
|
|
109
|
+
- **Goldens**:
|
|
110
|
+
- **+** a shell test runner received one nonexistent path (zsh does not word-split an unquoted variable), so every run exited 1 and every mutation reported KILLED — a green instrument that never ran its subject. (`measured`, 2026-08-13–15)
|
|
111
|
+
- **+** a test-inventory grep matched only `^test('...'` and missed every parameterized name; three reviewers judged a populated file empty — nothing tied the inventory's denominator to the source's own count. (`measured`, 2026-08-13–15)
|
|
112
|
+
- **+** a negative control kept passing after a faithful revert of the fix it was written against — a guard satisfied by an absence, a false PASS about the gate itself; found only by re-running reverts. (`measured`, 2026-08)
|
|
113
|
+
- **+** a review round returned "clean" with no receipt evidencing that the declared packet was dispatched on the exact seat — `false_signal` although nothing observed was wrong: what the stop refuses is absence of proof of dispatch, not proof of falsity. (`constructed`, 2026-08-19, pinned after a classification dispute at exactly this boundary)
|
|
114
|
+
- **−** one reviewer over-classed an item as material; another lens plus measurement filtered it — the harness caught it, so it worked: `detected_miss`, not a defect. (`measured`, 2026-08-13–15)
|
|
115
|
+
- **−** five review rounds returned 8 → 9 → 10 → 5 → 12 findings, refusing to converge — and every count was true. A truthful unpleasant signal is not a false signal; the defect lived in the undeclared criterion. (`measured`, 2026-08-16–17)
|
|
116
|
+
- **±** a surviving mutation proved equivalent — the platform already normalized what the mutated guard checked. Neither a harness defect nor a test gap; but a harness that auto-reads "survived = gap" has a defect in that rule. (`measured`, 2026-08-13–15)
|
|
117
|
+
|
|
118
|
+
### Decision ontology (an ontology a model decides from)
|
|
119
|
+
|
|
120
|
+
- **Observer**: a model or agent deciding from the ontology alone.
|
|
121
|
+
- **Defect**: a representation that produces a wrong decision or blocks a right one: overlapping concept boundaries, a missing distinction the decision needs, an instance contradicting reality, a wrong relation direction or cardinality, a name implying what the definition does not say.
|
|
122
|
+
- **Classes**: `decision_defect` (stop-relevant) · `representation_note` · `out_of_scope_gap`.
|
|
123
|
+
- **Evidence**: a **decision scenario** — "answered from the ontology alone, this question yields X; reality is Y" — with the question, the path taken, and the ground truth.
|
|
124
|
+
- **Non-defects**: representation format, completeness as such, a question the model would get wrong without the ontology too.
|
|
125
|
+
- **Stop**: zero wrong decisions over the agreed scenario set. The set is the scope — fix it first, or this criterion self-refills like the library one.
|
|
126
|
+
- **Misclassification cost**: situational — feeding a hard gate makes false negatives expensive; exploratory aid makes false positives expensive. Filling this cell is mandatory at declaration.
|
|
127
|
+
- **Goldens** (all `constructed`, 2026-08-19, authored to pin boundaries the source loop's decision-scenario framing left open):
|
|
128
|
+
- **+** `Customer` and `Account` both define "the paying party"; a refund-routing question resolves through both paths — overlap is a decision defect even when each definition is individually correct.
|
|
129
|
+
- **+** `Order —hasOne→ Payment` while split payments exist — cardinality is a claim, and a false claim misleads the deciding model.
|
|
130
|
+
- **−** a verbose concept description — no decision changes; form is outside this observer's sight.
|
|
131
|
+
- **−** a domain absent that no scenario in the agreed set needs — completeness is scoped by the set, not the world.
|
|
132
|
+
- **±** the distinction exists but the model cannot find it (name or link missing) — with the observer fixed as "a model seeing only the ontology," unreachable is a representation defect, not a search defect. The observer clause decides the class.
|
|
133
|
+
|
|
134
|
+
## Before any review
|
|
135
|
+
|
|
136
|
+
1. Write one sentence: the system type and this work's goal. ("API surface — make the responses clients receive today match the contract." / "Harness — make this run's PASS signals trustworthy.")
|
|
137
|
+
2. Pick a criterion from the catalog, or fill the schema fresh. A cell you cannot fill means the review does not start.
|
|
138
|
+
3. Paste the goldens into the packet verbatim. Never the definition alone.
|
|
139
|
+
4. Declare the stop condition and why it is reachable — or how the scope was pinned to make it so.
|
|
140
|
+
5. Put the classification on the accepting channel (next section).
|
|
141
|
+
6. Audit every round: reported class vs the class confirmed after measurement. A repeated disagreement is the next golden.
|
|
142
|
+
|
|
143
|
+
## Enforcing the enum, by channel
|
|
144
|
+
|
|
145
|
+
Ranked by how much the channel refuses for you:
|
|
146
|
+
|
|
147
|
+
1. **A route with a submit schema**: classification is a required enum field. The
|
|
148
|
+
measured precedent is anchors — 2,466 of 2,466 findings carried one, because the
|
|
149
|
+
schema refuses output without it. Where this channel exists, use it.
|
|
150
|
+
2. **Prose-packet routes** (the shipped deep-review methods): the packet header
|
|
151
|
+
declares `Criterion: <name>` with the goldens pasted verbatim, and the dispatching
|
|
152
|
+
agent runs this fold procedure on what comes back:
|
|
153
|
+
1. For each returned finding row, look up its class against the declared enum.
|
|
154
|
+
2. A row carrying a class from the enum enters the findings ledger under that class.
|
|
155
|
+
3. A row with no class, or a class outside the enum, is **not admitted**: send it
|
|
156
|
+
back once for classification, or record it as refused with the reason. Never
|
|
157
|
+
admit it unclassified, and never guess its class for it.
|
|
158
|
+
4. Count the stop condition over the stop-relevant class only.
|
|
159
|
+
5. Record the audit pair (reported class, confirmed class) for procedure step 6.
|
|
160
|
+
|
|
161
|
+
Stated honestly: on a prose route this is steering, not control — the fold is
|
|
162
|
+
performed by an agent following this guide, and nothing structural refuses a
|
|
163
|
+
class-less row for it. That is the known weaker result of a request-only rule.
|
|
164
|
+
3. **The launcher's criterion discipline** (agent-launch): a preset declaring
|
|
165
|
+
`criterion = true` renders one core-owned discipline clause into every review
|
|
166
|
+
method row — the criterion's content never enters the per-launch config; it rides
|
|
167
|
+
the packet as a `ReviewCriterion/v1:` record line beside the prose above.
|
|
168
|
+
`--compile-criterion` refuses a document failing the schema's decidable subset and
|
|
169
|
+
emits the canonical findings schema; where the host CLI's structured-output flag
|
|
170
|
+
probes present (`--check-schema-flag`), the dispatch passes that schema, and
|
|
171
|
+
receipt emission under `REVIEW_CRITERION_SCHEMA` refuses a class-less or
|
|
172
|
+
out-of-enum result — no receipt, and an unproven dispatch is already in the stop
|
|
173
|
+
class. `--verify-receipts --packet` recompiles the packet's record and refuses a
|
|
174
|
+
receipt whose schema digest was compiled from any other criterion. A route whose
|
|
175
|
+
flag probes absent runs rank 2 and is disclosed as prose discipline — never
|
|
176
|
+
credited as schema-enforced.
|
|
177
|
+
|
|
178
|
+
## Golden lifecycle
|
|
179
|
+
|
|
180
|
+
- **Admission**: only a golden that decides a boundary the definition leaves open,
|
|
181
|
+
evidenced by a recorded classification disagreement or an audited misclassification;
|
|
182
|
+
provenance labeled `measured` or `constructed`, each with its why and date.
|
|
183
|
+
- **Overturn**: only by a measured counterexample. Correct the golden in place — this
|
|
184
|
+
guide describes the present — plus a dated decision record, in whatever channel the
|
|
185
|
+
repo keeps decisions, naming the closed golden and the counterexample. Silent
|
|
186
|
+
deletion is forbidden: a wrong golden makes reviewers systematically wrong, and an
|
|
187
|
+
untracked fix hides that it ever did.
|
|
188
|
+
|
|
189
|
+
## Declaring, switching, and mixed packets
|
|
190
|
+
|
|
191
|
+
- Every dispatched packet names its criterion. A harness round declares `AI harness`;
|
|
192
|
+
a round whose system type has no catalog entry declares a **task-local criterion**,
|
|
193
|
+
written in the packet itself, conforming to the schema above and labeled task-local
|
|
194
|
+
— repeated use is what earns a catalog entry.
|
|
195
|
+
- A mixed packet is split into one packet per criterion. Two observers in one
|
|
196
|
+
trajectory produce findings no single stop condition can count.
|
|
197
|
+
- When a criterion changes mid-loop: re-classify only the findings still open; rounds
|
|
198
|
+
already recorded are dated history. Never splice pre- and post-switch counts into
|
|
199
|
+
one series — they count different things.
|
|
200
|
+
|
|
201
|
+
## Evidence base
|
|
202
|
+
|
|
203
|
+
Derived from a 39-round adversarial review loop (3 lenses × a frontier reviewer) on a
|
|
204
|
+
peer OAuth CLI-API adapter, 2026-08-13–15: the same codebase plateaued at
|
|
205
|
+
17→19→21→23→19 findings under a self-refilling criterion and resumed falling
|
|
206
|
+
(behavioral 10→5) the round the classes were split and the stop counted over
|
|
207
|
+
`behavioral_defect` alone. The boundary evidence is from the same loop: a packet
|
|
208
|
+
instruction saying "do not inflate coverage gaps" still left two lenses classing one
|
|
209
|
+
finding `doc_gap` and `behavioral_defect`, both defensibly — one golden would have
|
|
210
|
+
decided it. The non-convergence golden (8→9→10→5→12, every count true) is this
|
|
211
|
+
environment's own launcher-review loop, 2026-08-16–17, run under an undeclared
|
|
212
|
+
"material" criterion; the two series are two populations under two criteria and are
|
|
213
|
+
cited separately for exactly the reason the migration section gives. Re-derive when
|
|
214
|
+
the review routes or the bound models change.
|
|
@@ -26,7 +26,11 @@ verification_focus:
|
|
|
26
26
|
This guide is a scoped extension of the global Coding Guidelines. Use it when
|
|
27
27
|
composing what you ask a reviewer for — the request, the evidence bar, the
|
|
28
28
|
verdict shape. It does not cover when to review, how deep, or what counts as
|
|
29
|
-
material
|
|
29
|
+
material — that last question splits in two: the severity ladder and review loop in
|
|
30
|
+
`${CODEX_HOME:-$HOME/.codex}/guides/coding-staged-workflow.md` own *how bad*,
|
|
31
|
+
while whether something is a defect at all, of which class, and what "zero" is
|
|
32
|
+
counted over is the defect criterion, owned by
|
|
33
|
+
`${CODEX_HOME:-$HOME/.codex}/guides/review-defect-criteria.md`. Nor
|
|
30
34
|
which reviewer kind to route to — the convergence heuristic in
|
|
31
35
|
`${CODEX_HOME:-$HOME/.codex}/guides/verification-discipline.md` owns that. Phrasing a prompt for a specific model
|
|
32
36
|
family is out of scope here; where that guidance ships, the rule that needs it
|
|
@@ -38,6 +42,16 @@ is a per-model claim; these are the failures that persist regardless of who
|
|
|
38
42
|
reviews. Every rule names the evidence behind it, because a review guide that
|
|
39
43
|
asserts without evidence would fail its own bar.
|
|
40
44
|
|
|
45
|
+
## Declare the criterion
|
|
46
|
+
|
|
47
|
+
Before composing anything else, name the defect criterion the review runs under —
|
|
48
|
+
the per-system-type definition of what a defect is, its class enum, and what "zero"
|
|
49
|
+
is counted over. `${CODEX_HOME:-$HOME/.codex}/guides/review-defect-criteria.md`
|
|
50
|
+
owns choosing it; this guide assumes one is declared. Put `Criterion: <name>` at the
|
|
51
|
+
top of the packet with that criterion's goldens pasted verbatim — a definition
|
|
52
|
+
without goldens does not classify consistently at the boundary, and an undeclared
|
|
53
|
+
criterion means every reviewer substitutes its own.
|
|
54
|
+
|
|
41
55
|
## Demand a failure path, not a gap
|
|
42
56
|
|
|
43
57
|
The dominant reviewer failure is not hallucination. Across 372 rejected
|
package/compose/assemble.py
CHANGED
|
@@ -272,11 +272,18 @@ def replace_atomically(path, text):
|
|
|
272
272
|
learn/migrate-learnings.py has had this discipline and states the reason; it now shares
|
|
273
273
|
this one implementation rather than keeping a second. The temp file is a sibling so the
|
|
274
274
|
replace stays on one filesystem, where os.replace is atomic.
|
|
275
|
+
|
|
276
|
+
An existing target's permission bits ride through the swap: the temp is born with
|
|
277
|
+
umask mode, so replacing a user-restricted file — a 0600 AGENTS.md — silently widened
|
|
278
|
+
it to world-readable. Ownership is not copied; this never runs with the privilege to
|
|
279
|
+
change it, and a same-owner rename keeps it anyway.
|
|
275
280
|
"""
|
|
276
281
|
path.parent.mkdir(parents=True, exist_ok=True)
|
|
277
282
|
tmp = path.with_name(path.name + ".tmp-agent-bios")
|
|
278
283
|
try:
|
|
279
284
|
tmp.write_text(text, encoding="utf-8")
|
|
285
|
+
if path.exists():
|
|
286
|
+
tmp.chmod(path.stat().st_mode & 0o777)
|
|
280
287
|
os.replace(tmp, path)
|
|
281
288
|
finally:
|
|
282
289
|
if tmp.exists():
|
package/compose/domains.json
CHANGED
|
@@ -100,6 +100,7 @@
|
|
|
100
100
|
"llm-capability-boundary-patterns.md": {"tier": "domain", "domains": ["llm-pipeline-dev"]},
|
|
101
101
|
"llm-capability-boundary.md": {"tier": "domain", "domains": ["llm-pipeline-dev"]},
|
|
102
102
|
"mock-realization-boundary.md": {"tier": "domain", "domains": ["builder-base"]},
|
|
103
|
+
"review-defect-criteria.md": {"tier": "domain", "domains": ["builder-base"]},
|
|
103
104
|
"review-request.md": {"tier": "domain", "domains": ["builder-base"]},
|
|
104
105
|
"session-distill-workflow.md": {"tier": "infra", "domains": []},
|
|
105
106
|
"learning-flow.md": {"tier": "infra", "domains": []},
|