@dogfood-lab/schemas 1.8.0 → 1.10.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.
@@ -175,7 +175,8 @@ export interface RecordOverallVerdict {
175
175
  * `verification.provenance_remediation` in dogfood-record.schema.json.
176
176
  */
177
177
  export interface ProvenanceRemediation {
178
- status?: 'stub_verified';
178
+ /** Schema-REQUIRED — `provenance_remediation.required` lists `status`. */
179
+ status: 'stub_verified';
179
180
  /** Schema maxLength: 500. */
180
181
  note?: string;
181
182
  remediated_at: string;
@@ -214,6 +215,13 @@ export interface Verification {
214
215
  policy_valid: boolean;
215
216
  /** Machine-readable rejection reasons. Empty/absent if accepted. */
216
217
  rejection_reasons?: string[];
218
+ /**
219
+ * Accepted-with-warning notes from warn-severity policy rules. A populated
220
+ * array does NOT imply rejection — the record was accepted. Optional and
221
+ * backward-compatible: records written before the accepted-with-warning
222
+ * channel existed have no warnings block. Mirrors the rejection_reasons shape.
223
+ */
224
+ warnings?: string[];
217
225
  provenance_remediation?: ProvenanceRemediation;
218
226
  }
219
227
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"payload-types.d.ts","sourceRoot":"","sources":["../src/payload-types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"payload-types.d.ts","sourceRoot":"","sources":["../src/payload-types.ts"],"names":[],"mappings":"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"}
@@ -124,8 +124,35 @@ const EXAMPLE_RECORD = {
124
124
  provenance_confirmed: true,
125
125
  schema_valid: true,
126
126
  policy_valid: true,
127
+ // Exercises the two verification fields the hand-authored mirror had drifted
128
+ // on (SCHEMA-A-002): the accepted-with-warning `warnings` channel and the
129
+ // stub_verified provenance_remediation block. Keying `warnings` here under
130
+ // `satisfies Record` also compile-pins its presence on Verification — an
131
+ // unknown key would be an excess-property error until the interface declares
132
+ // it. (status-required is pinned separately below.)
133
+ warnings: ['policy: [evidence-freshness] evidence older than the soft cap'],
134
+ provenance_remediation: {
135
+ status: 'stub_verified',
136
+ remediated_at: '2026-04-26T18:07:00Z',
137
+ note: 'Provenance API was unreachable; stub-verified per policy.',
138
+ },
127
139
  },
128
140
  };
141
+ // SCHEMA-A-002 compile-time pin — `verification.provenance_remediation.status`
142
+ // is REQUIRED by dogfood-record.schema.json (that sub-object's
143
+ // `required: ["status", "remediated_at"]`), so the mirror must type it
144
+ // non-optionally. Annotating the source AS the interface (not `satisfies`) makes
145
+ // `.status` reflect the INTERFACE's optionality rather than the literal's: if
146
+ // `status?` ever drifts back to optional, `.status` widens to
147
+ // `'stub_verified' | undefined` and this assignment to a non-optional target
148
+ // stops compiling under `strict`/strictNullChecks. Presence in EXAMPLE_RECORD
149
+ // alone cannot catch this — an optional field may still be supplied.
150
+ const _schemaA002Remediation = {
151
+ status: 'stub_verified',
152
+ remediated_at: '2026-04-26T18:07:00Z',
153
+ };
154
+ const _schemaA002StatusIsRequired = _schemaA002Remediation.status;
155
+ void _schemaA002StatusIsRequired;
129
156
  const EXAMPLE_FINDING = {
130
157
  schema_version: '1.0.0',
131
158
  finding_id: 'dfind-testing-os-schemas-payload-types',
@@ -1 +1 @@
1
- {"version":3,"file":"payload-types.js","sourceRoot":"","sources":["../src/payload-types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"payload-types.js","sourceRoot":"","sources":["../src/payload-types.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dogfood-lab/schemas",
3
- "version": "1.8.0",
3
+ "version": "1.10.0",
4
4
  "description": "JSON schemas for the testing-os contract spine — record, finding, pattern, recommendation, doctrine, policy, scenario, submission.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -14,7 +14,7 @@
14
14
  },
15
15
  "scripts": {
16
16
  "build": "tsc",
17
- "test": "vitest run --passWithNoTests"
17
+ "test": "vitest run"
18
18
  },
19
19
  "files": [
20
20
  "dist",
@@ -34,7 +34,7 @@
34
34
  },
35
35
  "devDependencies": {
36
36
  "@dogfood-lab/dogfood-swarm": "*",
37
- "@types/node": "^25.3.5",
37
+ "@types/node": "^26.1.0",
38
38
  "vitest": "^4.1.9"
39
39
  },
40
40
  "author": "mcp-tool-shop",
@@ -27,6 +27,11 @@
27
27
  "items": { "$ref": "#/$defs/finding" },
28
28
  "description": "Audit-pass findings. Required in audit outputs (Stages A–D)."
29
29
  },
30
+ "confirmed": {
31
+ "type": "array",
32
+ "items": { "type": "string", "minLength": 1 },
33
+ "description": "Audit-pass only: finding_ids from the brief's OPEN-findings confirmation queue that this agent explicitly checked and found gone. This is a positive-evidence declaration, and it is what closes a prior finding: classifyFindings marks an absent prior `fixed` only if its id is declared here, and `unverified` (still open) otherwise. Domain coverage cannot substitute — it proves the wave read the file, never that it looked for a given defect, which is exactly what a lens change breaks. Omit an id you did not actually verify; it costs nothing but another wave asking again."
34
+ },
30
35
  "features": {
31
36
  "type": "array",
32
37
  "items": { "$ref": "#/$defs/feature" },
@@ -0,0 +1,121 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://github.com/dogfood-lab/testing-os/packages/schemas/src/json/case-file.schema.json",
4
+ "title": "Jury Case-File (neutral verification briefing)",
5
+ "description": "The neutral briefing a planner-tier clerk (e.g. a Fable agent) assembles to PREPARE an external, family-different verification jury before it judges an artifact. It exists to fix under-abstention: a cold-dropped 'here are files, verify this' is under-specified, and an under-calibrated verifier hallucinates a confident verdict rather than abstaining. The case-file supplies the objective + falsifiable acceptance criteria + grounding evidence the jury judges AGAINST, so 'correct' is defined rather than guessed. Critically, the clerk renders NO verdict — this schema is SHAPE only, and carries no accept/reject/pass/fail/verdict field by construction (additionalProperties:false). The neutrality SEMANTICS the shape cannot express (no conclusion-words in a criterion; a grounding-extraction floor; no leaked producer reasoning) are enforced separately by the neutrality lint in packages/dogfood-swarm/lib/case-file/lint.js, exactly as policy.schema.json gates policy SHAPE while docs/policy-lint.md gates the data-independent semantics. This is a swarm-internal envelope (like agent-output.schema.json) resolved via the @dogfood-lab/schemas ./json/* subpath with a local Ajv — it is NOT one of the eight contract-spine payload schemas registered in validatePayload, and it carries no schema_version value gate.",
6
+ "type": "object",
7
+ "required": ["objective", "artifact_under_test", "acceptance_criteria"],
8
+ "additionalProperties": false,
9
+ "properties": {
10
+ "objective": {
11
+ "type": "string",
12
+ "minLength": 10,
13
+ "description": "What the artifact under test must accomplish — the intent the jury judges against, lifted from the ticket / spec / task. States the goal, never whether the artifact met it. A conclusion here ('correctly returns 401') is a neutrality violation the lint catches; the objective is 'the endpoint rejects expired tokens', a goal, not a grade."
14
+ },
15
+ "artifact_under_test": {
16
+ "type": "object",
17
+ "description": "The single artifact the jury renders a verdict on. Referenced by a stable handle; content is inlined when the jury cannot fetch it itself.",
18
+ "required": ["kind", "ref"],
19
+ "additionalProperties": false,
20
+ "properties": {
21
+ "kind": {
22
+ "type": "string",
23
+ "enum": ["diff", "file", "finding", "module", "answer", "citation"],
24
+ "description": "What kind of artifact is being judged. Governs how the jury reads it."
25
+ },
26
+ "ref": {
27
+ "type": "string",
28
+ "minLength": 1,
29
+ "description": "Stable pointer to the artifact — a file path, a finding id, a diff handle, a commit SHA. The jury and the deterministic floor resolve the same ref, so a verdict is anchored to a specific object."
30
+ },
31
+ "content": {
32
+ "type": "string",
33
+ "description": "Optional inline copy of the artifact the jury reads. Provided when the jury cannot resolve `ref` itself. MUST be free of the producer's reasoning trace (chain-of-thought, <thinking>/<reasoning>/<scratchpad>/<think> blocks, reasoning summaries) — the handoff refuses a case-file whose content leaks a producer trace, enforcing prism's reasoning-stripped boundary (Lock 2) at the briefing seam."
34
+ }
35
+ }
36
+ },
37
+ "acceptance_criteria": {
38
+ "type": "array",
39
+ "minItems": 1,
40
+ "description": "The falsifiable checks that define a pass. Each is a testable statement of expected behavior ('returns 401 on an expired token'), NOT a conclusion about the artifact ('correctly returns 401'). This is the rubric the jury judges against and the strongest form of grounding when the checks are extracted from the artifact's own test suite. A criterion the jury cannot evaluate from the case-file returns `insufficient_context` for that criterion — a first-class, non-penalized answer, not a failure.",
41
+ "items": {
42
+ "type": "object",
43
+ "required": ["id", "check"],
44
+ "additionalProperties": false,
45
+ "properties": {
46
+ "id": {
47
+ "type": "string",
48
+ "pattern": "^AC-[A-Za-z0-9][A-Za-z0-9-]*$",
49
+ "description": "Stable id for the criterion (AC-<slug>), so the jury's per-criterion verdict (including `insufficient_context`) maps back to a specific check."
50
+ },
51
+ "check": {
52
+ "type": "string",
53
+ "minLength": 3,
54
+ "description": "The falsifiable statement of expected behavior. Phrase as a check the jury can evaluate against the artifact + evidence, never as a verdict on the artifact. Lexical conclusion-words here are a neutrality violation the lint reports."
55
+ },
56
+ "source": {
57
+ "$ref": "#/$defs/provenance",
58
+ "description": "Where this criterion came from. `from-tests` (the check is an existing test assertion) is the strongest, most-grounded form; `fable-inference` marks a criterion the clerk synthesized, which the jury weights more skeptically and the grounding floor counts against."
59
+ }
60
+ }
61
+ }
62
+ },
63
+ "context": {
64
+ "type": "array",
65
+ "description": "The grounding evidence pack: factual claims about the artifact and its surroundings the jury needs to judge, each tagged with its provenance. Fed to the jury RAG-style (the way prism feeds the retrieved source to its Groundedness lens) rather than left to the verifier's parametric recall. Every claim is provenance-tagged; the neutrality lint enforces an extraction floor so the pack is assembled from checkable sources, not authored from the clerk's imagination.",
66
+ "items": {
67
+ "type": "object",
68
+ "required": ["claim", "source"],
69
+ "additionalProperties": false,
70
+ "properties": {
71
+ "claim": {
72
+ "type": "string",
73
+ "minLength": 3,
74
+ "description": "A factual, verdict-free statement of context ('this module is called by the payment path'; 'the expiry guard was added at auth.js:42'). States a fact, never a judgment of correctness — a conclusion here is a neutrality violation the lint catches."
75
+ },
76
+ "source": {
77
+ "$ref": "#/$defs/provenance",
78
+ "description": "Provenance of the claim. Everything except `fable-inference` is EXTRACTED (lifted from a checkable artifact); `fable-inference` is the clerk's own synthesis and is what the extraction floor bounds."
79
+ },
80
+ "ref": {
81
+ "type": "string",
82
+ "description": "Optional pointer to where the claim was extracted from (a file:line, a test id, a ticket url) so a reviewer can check the extraction."
83
+ },
84
+ "criterion_ids": {
85
+ "type": "array",
86
+ "items": { "type": "string" },
87
+ "description": "Optional. Names the acceptance_criteria[].id values this claim grounds. Absent is the default and means GLOBAL — the claim grounds every criterion exactly as it did before this field existed, so a case-file with no criterion_ids on any claim keeps validating and keeps behaving identically (backward-compatible). When present, the claim grounds ONLY the listed criteria and is omitted from every other criterion's evidence pack — this is what lets a capped verifier tier (e.g. --jury=prism, which budgets a fixed per-call character limit) spend that budget on claims relevant to the criterion being judged instead of every claim competing for one shared cap. Each entry SHOULD name an id that exists in this case-file's acceptance_criteria[], but that cross-field reference cannot be expressed in JSON Schema — a typo'd id is structurally valid here and would silently drop the claim from every criterion's brief with no schema-level symptom. The neutrality lint (packages/dogfood-swarm/lib/case-file/lint.js) is what actually enforces that every criterion_ids entry resolves to a real criterion id; this schema only shapes the field as an array of strings. Routing only — never itself forwarded to the jury as a judging input."
88
+ }
89
+ }
90
+ }
91
+ },
92
+ "out_of_scope": {
93
+ "type": "array",
94
+ "description": "What the jury should NOT flag — behavior, files, or concerns deliberately excluded from this verification. Bounds the judgment without asserting anything about the in-scope artifact. Note the rubric is a FLOOR, not a ceiling: the jury is licensed to flag out-of-brief defects it notices and mark them as not-in-brief, so an incomplete case-file does not make the clerk's blind spots the jury's.",
95
+ "items": {
96
+ "type": "string",
97
+ "minLength": 1
98
+ }
99
+ },
100
+ "prepared_by": {
101
+ "type": "string",
102
+ "description": "Optional handle of the clerk that assembled this case-file (e.g. a Fable agent id). Provenance only — carries no authority; the clerk renders no verdict."
103
+ },
104
+ "correlation_id": {
105
+ "type": "string",
106
+ "description": "Optional forensic anchor tying this case-file to the swarm wave / dispatch that produced it, in the coord-<base36-ts>-<4-hex> shape the coordination commands emit."
107
+ },
108
+ "notes": {
109
+ "type": "string",
110
+ "maxLength": 2000,
111
+ "description": "Optional neutral context for a human reviewer of the case-file itself. Not shown to the jury as a criterion; subject to the same no-verdict neutrality expectation as every other field."
112
+ }
113
+ },
114
+ "$defs": {
115
+ "provenance": {
116
+ "type": "string",
117
+ "enum": ["from-spec", "from-ticket", "from-tests", "from-code", "fable-inference"],
118
+ "description": "Where a claim or criterion originated. The four `from-*` values are EXTRACTED (lifted from an externally-authored, checkable artifact); `fable-inference` is the clerk's own synthesis. The extraction floor in the neutrality lint bounds how much of a case-file may be `fable-inference`, minimizing the clerk's authorial surface — the part that could be slanted."
119
+ }
120
+ }
121
+ }
@@ -221,7 +221,7 @@
221
221
  "doc",
222
222
  "rejection"
223
223
  ],
224
- "description": "Type of evidence supporting this finding."
224
+ "description": "Type of evidence supporting this finding. F-936c83f4 (wave 39, feature-pass integration finding): this is one of three structurally-similar-but-distinct 'how do we know this claim is true' enums in this repo, deliberately NOT unified — (1) HERE — what evidence backs a distilled cross-repo lesson; (2) packages/verify/validators/provenance.js's --provenance=stub|github (see that file's own cross-reference note) — whether a submitted CI run really happened; (3) the swarm control-plane's incoming verified_how (independent|self_attested|operator_evidence, docs/trajectory-and-closure.dispatch.md's C2 `swarm close` verb) — how a finding closure was verified. Each answers a genuinely different axis; this note exists so a reader of any of the three can find the other two without rediscovering the pattern from scratch."
225
225
  },
226
226
  "record_id": {
227
227
  "type": "string",
@@ -0,0 +1,281 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://github.com/dogfood-lab/testing-os/packages/schemas/src/json/dogfood-roadmap.schema.json",
4
+ "title": "Dogfood Roadmap (cross-run trajectory layer)",
5
+ "description": "F-fe05c6d7 (wave 39, Feature Pass T1): the canonical contract for the compiled artifact `swarm roadmap compile <run-id>` writes to dogfood/roadmap/<run-id>.json. Per docs/trajectory-and-closure.dispatch.md T1 ('The roadmap is compiled, never authored'), every section here is a QUERY result executed against the control-plane DB and git at compile time — never hand-edited prose, with the single exception of operator_notes (T3), the one human-authored section. This is a swarm-internal envelope, exactly like agent-output.schema.json and case-file.schema.json before it — NOT one of the eight contract-spine payload schemas registered in allSchemas / validatePayload / SUPPORTED_SCHEMA_VERSIONS (that registry gates the record/recordSubmission/finding/pattern/recommendation/doctrine/policy/scenario family). It resolves via this package's existing \"./json/*\": \"./src/json/*\" subpath export with a LOCAL Ajv instance in the consuming package, mirroring packages/dogfood-swarm/lib/templates.js:73's require.resolve('@dogfood-lab/schemas/json/agent-output.schema.json') precedent — no new export wiring, and no schema_version value gate. Every array/object section below is REQUIRED even when empty (an empty array or a zero-count object is valid) so an absent key can only ever mean 'the compiler did not run this query,' never 'ran it and found nothing' — a reader is never left guessing which. See $defs.latestPointer for the companion micro-shape of dogfood/roadmap/latest.json (T5), a separate file this same schema also shapes via $ref.",
6
+ "$comment": "WAVE-41 SEAM DECISIONS (F-c7b0f47b; coordinator's binding call for this wave: 'the schema is the contract' — core's lib-compiler and verbs' commands/roadmap.js conform their emitters to this document in their own worktrees this same wave, not the reverse). Four things changed HERE, deliberately, in response to the real committed artifact failing this schema with 16 Ajv errors: (1) `sections` stays UNBLESSED — additionalProperties:false already rejected it before this wave and continues to; what changed is that the rejection is now a stated decision, not an accident nobody had looked at. `sections` wholesale-duplicated compile.js's raw internal shape (findings-with-severity/category, a second, INCOMPATIBLE `attention.top[].factors` shape sitting alongside this schema's own `attention.items[].components`, a two-halves drain_queue with yet another shape) that the sections below already contract for in a considered form. Emitters MUST NOT write `sections` into a committed artifact; any richer per-item detail it carried belongs as optional enrichment of the fields below, never a parallel undifferentiated copy. (2) `notesPath` is now an explicit, OPTIONAL, repo-relative-only property (see its own entry below) — this key's mere presence was previously one of the 16 Ajv errors (a disallowed additionalProperty), and a real compile had already committed it as a machine-absolute Windows path, baking one operator's local checkout into version-controlled history (the finding's own first proven exhibit). (3) `compiled_at`'s description was rewritten for honesty about its DB-derived, not wall-clock, semantics; the field NAME is unchanged (see its own entry below). (4) `content_hash` stays OPTIONAL, not promoted to required, with its self-exclusion hashing semantics now specified (see its own entry below). NOT touched by this wave: open_summary / grandfathered_drain / recurrence_stats / attention / operator_notes / drain_queue keep their existing T1-T6 shapes; conforming emitters to THOSE is core's and verbs' materially larger burden, and out of this package's domain to make or verify — packages/dogfood-swarm's own pinned tests (F-1cd5de59, F-74ba2c79) currently assert a flatter, differently-shaped `drain`/`notes`/`expired` CLI surface than this schema's `drain_queue`/`operator_notes`, which core/verbs must reconcile (by conforming the emitter AND, if those tests are asserting a superseded shape, updating them) as part of landing this wave's fix — not something this package can resolve by editing files outside its own domain. WAVE-43 / AMENDMENT 3 SEAM DECISIONS (A3.2, F-471a06f1 + F-b785b581; docs/trajectory-and-closure.dispatch.md's Amendment 3, wave 42, recorded after one adversarial DO-NOT-SHIP skeptic round and a second SHIP-WITH-CHANGES pass). Amendment 3's own correction record first: the wave-42 claim that 'both implementations model DATES (revalidate_by)' — repeated in scripts/doc-drift-patterns.json's own comment prose, HANDOFF, and the wave-42 kickoff — was FALSE. lib/roadmap/drain.js#compileAuthoredDrainState is a shipped, F-1cd5de59-pinned RUNS-ORDINAL mechanism, not a dates mechanism, and it is DISTINCT from compileGrandfatheredManifestDrain (which reads the 36-entry scripts/regression-pin-allowlist.json, not the 256-entry scripts/grandfathered-pins.json this file's grandfathered_drain section now targets) — two wrong rulings shipped before this one, both caught by adversarial review, not by the author. Two things changed HERE in response: (1) T6's single $defs/drainEntry — never satisfied by any real producer, because no population actually has its {reason(required), added_at, cadence_runs, due_at_run} shape — is RETIRED, split into two per-population shapes matching each population's real authored data: $defs/drainQueueEntry (drain_queue, runs-ordinal, mirrors compileAuthoredDrainState's shipped {id,owner,cadence_runs,runs_since_review,overdue} return exactly) and $defs/grandfatheredManifestEntry (grandfathered_drain.outstanding, date-deadline, mirrors scripts/grandfathered-pins.json's real {owner,revalidate_by}-only per-entry shape — `reason` is optional on both new shapes and per-entry provenance is never invented to fill it; each section's shared rationale is documented at the section level instead, never repeated per entry). drain_queue itself changes shape from a bare array to an object, {entries[], overdue_ids[]}, preserving F-1cd5de59's distinct-listing assertion. (2) expired_notes joins the required (empty-allowed) sections, sharing the new $defs/operatorNote with operator_notes — T3's 'compile drops expired notes loudly... not silently omitted' now has an artifact-level home, settling the open question of whether that loud disclosure lives only in CLI stdout (gone the moment the process exits) or also in the cross-run-readable artifact: the artifact is the cross-run carrier (F-74ba2c79's fail-closed notes-validation pin is the live behavior this section assumes — see expired_notes' own description for why every entry there already satisfies operatorNote's invariant-conditional by construction). NOT touched by this wave, and deliberately so (A3.5 — named residuals, not silent drops, disclosed on the sections that would otherwise look like they should carry them): the allowlist-overdue output (scripts/regression-pin-allowlist.json's 36 entries, compileGrandfatheredManifestDrain's return) and compileUnroutableApprovedDrain's approved-but-unroutable findings surface only via `swarm roadmap show` + the digest, not this persisted artifact, this wave; compileDeferredFindingsDrain's waves-shape stays out of the artifact entirely because findings rows carry no owner column in this pass and an owner is never invented to populate one. Emitter wiring — compiler.js/commands/roadmap.js building grandfathered_drain from a NEW producer over grandfathered-pins.json, and drain_queue from compileAuthoredDrainState instead of the old compileDrainQueue composite — is core/verbs' cross-domain burden, unresolved as of this commit, same posture as the WAVE-41 paragraph above: this package states the contract, it does not and cannot conform the emitter that lives outside packages/schemas/**.",
7
+ "type": "object",
8
+ "required": [
9
+ "run_id",
10
+ "sequence",
11
+ "compiled_at",
12
+ "repo",
13
+ "compiled_from",
14
+ "open_summary",
15
+ "grandfathered_drain",
16
+ "recurrence_stats",
17
+ "attention",
18
+ "operator_notes",
19
+ "expired_notes",
20
+ "drain_queue"
21
+ ],
22
+ "additionalProperties": false,
23
+ "properties": {
24
+
25
+ "run_id": {
26
+ "type": "string",
27
+ "minLength": 1,
28
+ "pattern": "^[A-Za-z0-9_-]+$",
29
+ "description": "The swarm control-plane run id this roadmap was compiled from (e.g. swarm-1784091637-5127) — NOT a dogfood-record run_id, which names a different identifier namespace (a consumer's own CI run). Charset is constrained because run_id becomes a filesystem path segment (dogfood/roadmap/<run_id>.json), mirroring dogfood-record.schema.json's run_id field and its stated rationale exactly."
30
+ },
31
+
32
+ "sequence": {
33
+ "type": "integer",
34
+ "minimum": 1,
35
+ "description": "T5: increments on a same-run recompile; never edits a prior version. The first compile for a run is sequence 1. A recompile within the same run supersedes with a new sequence number — history is never rewritten. dogfood/roadmap/latest.json (see $defs.latestPointer) is the one mutable indirection that tracks which sequence is newest."
36
+ },
37
+
38
+ "compiled_at": {
39
+ "type": "string",
40
+ "format": "date-time",
41
+ "description": "WAVE-41 HONESTY FIX (F-c7b0f47b): this is deliberately NOT the wall-clock moment `swarm roadmap compile` was invoked — an earlier version of this description mischaracterized it as exactly that, which was false and has been corrected. The value is sourced from the compiled run's own DB row (`runs.created_at`), held fixed for that run's lifetime, so that two separate compile invocations against byte-identical DB state produce a byte-identical artifact — T1's determinism promise, proven cross-process by F-feeaef78 (see commands/roadmap.js's deterministicNow()). Two compiles of the SAME run, issued minutes or days apart, MUST carry the identical value here by construction; a future implementation that instead stamps a live clock read at invocation time is the regression F-feeaef78 exists to catch, not a more accurate timestamp. Distinct from any per-entry timestamp inside the sections below (e.g. grandfathered_drain.outstanding[].revalidate_by, or recurrence_stats.top_recurring[].first_seen/last_seen), which are independently DB- or file-sourced values, not derived from this run-creation stand-in. The GENUINE wall-clock moment this artifact VERSION was actually written is deliberately NOT this field either — it lives one layer outside this document, in the control-plane DB's `roadmap_artifacts.created_at` column (db/schema.js's v10 migration; queryable via lib/roadmap/artifacts.js#latestRoadmapArtifact), precisely so embedding it here would not defeat this field's own byte-identity promise for identical DB state (compile.js's own header names this split explicitly). WAVE-43 / AMENDMENT 3 (A3.3) disclosure: this field's byte-identity promise additionally depends on the compiling process parsing `runs.created_at` — a timezone-unmarked SQLite TEXT value — as UTC; a naive `new Date(...)` parse reads it as local time instead, silently offsetting the value by the host's UTC offset (F-5cfa163c, cross-routed to the verbs domain's commands/roadmap.js — this package cannot fix a call site outside its own globs, only record here that the promise this description makes is conditional on that fix landing)."
42
+ },
43
+
44
+ "repo": {
45
+ "type": "string",
46
+ "pattern": "^[a-zA-Z0-9_.-]+/[a-zA-Z0-9_.-]+$",
47
+ "description": "Full org/repo the roadmap was compiled for. Same pattern as dogfood-finding.schema.json's repo field."
48
+ },
49
+
50
+ "compiled_from": {
51
+ "type": "object",
52
+ "required": ["commit_sha"],
53
+ "additionalProperties": false,
54
+ "description": "The git state the compile queries ran against — the 'and git alone' half of T1's 'compiled from the control-plane DB and git alone.'",
55
+ "properties": {
56
+ "commit_sha": {
57
+ "type": "string",
58
+ "pattern": "^[0-9a-f]{40}$",
59
+ "description": "Full 40-hex commit SHA checked out at compile time. Same pattern as dogfood-record.schema.json's ref.commit_sha."
60
+ }
61
+ }
62
+ },
63
+
64
+ "open_summary": {
65
+ "type": "object",
66
+ "required": ["open", "deferred", "approved"],
67
+ "additionalProperties": false,
68
+ "description": "T1: 'Factual sections are queries executed at compile time: open/deferred/approved findings' — those three counts are the ones the pass contract names explicitly, and are required. The three optional siblings (fixed/rejected/recurring) round out the full finding-status vocabulary this build recognizes: packages/dogfood-swarm/lib/finding-status.js's CLOSED_FINDING_STATUSES = ['fixed','rejected','deferred'], with 'open'/'approved'/'recurring' all treated as still-open by that module's isOpenFinding(). additionalProperties:false because this is a closed, known status set, not an open-ended bag.",
69
+ "properties": {
70
+ "open": { "type": "integer", "minimum": 0, "description": "Findings with no disposition yet." },
71
+ "deferred": { "type": "integer", "minimum": 0, "description": "Findings consciously postponed — closed for gate purposes; the deferred ones with provenance/cadence are tracked in drain_queue below." },
72
+ "approved": { "type": "integer", "minimum": 0, "description": "Findings reviewed and greenlit for an amend wave — the DB-canonical work-order findings a run's lanes build against." },
73
+ "fixed": { "type": "integer", "minimum": 0, "description": "Findings resolved by an amend." },
74
+ "rejected": { "type": "integer", "minimum": 0, "description": "Findings triaged away as not-a-defect." },
75
+ "recurring": { "type": "integer", "minimum": 0, "description": "Findings reopened via the content-match regression-rediscovery path (a closed finding's fingerprint re-reported) or via C1's evidence-bearing operator reopen." }
76
+ }
77
+ },
78
+
79
+ "grandfathered_drain": {
80
+ "type": "object",
81
+ "required": ["frozen_total", "drained", "outstanding"],
82
+ "additionalProperties": false,
83
+ "description": "T6 drain state for the frozen grandfathered manifest — scripts/grandfathered-pins.json, the 256-entry migration-debt set frozen at commit 132dc18 (2026-07-16) when the declared-@pins-tag rewrite landed (docs/pin-matcher-rewrite.dispatch.md). WAVE-43 / AMENDMENT 3 (A3.2b) CORRECTION: an earlier revision of this section (and of scripts/doc-drift-patterns.json, HANDOFF, and the wave-42 kickoff) wrongly claimed this section shared a provenance shape with drain_queue below — false, caught by Amendment 3's own adversarial skeptic round. This section targets scripts/grandfathered-pins.json specifically, NOT scripts/regression-pin-allowlist.json (the 36-entry registry drain_queue's own section below is also not built from — see that section's description); the two suppression registries are distinct files with distinct shapes and must not be conflated a third time. frozen_total is the manifest's size at the moment it was frozen (a constant per manifest generation, not recomputed per compile — see that field's own description for why it must never be inferred from the current live count); drained counts entries removed from the manifest by a completed re-review since freeze; outstanding lists what remains, each an $defs/grandfatheredManifestEntry — a shape distinct from drain_queue.entries[] below as of this amendment, because the two are different populations over different files with different authored data, not one shape two sections risk drifting apart from (the pre-amendment framing this replaced was itself the bug: no producer ever satisfied a shared shape). The manifest's SHARED freeze rationale — every F-id the pin-matcher rewrite's own live heuristic classified as grandfathered at the freeze commit, migrating out only via a declared @pins tag, an allowlist entry, or removal as a still-undeclared orphan (scripts/grandfathered-pins.json's own header) — lives here, at the section level, rather than repeated on every entry: the manifest's real per-entry shape carries no individual reason (see $defs/grandfatheredManifestEntry's own `reason` field for why it is optional and never invented to fill it). No producer for this section is wired into the committed artifact as of this wave — A3.2b names it a NEW producer core's domain must build over the manifest file; this schema states the target contract, not the current reality.",
84
+ "properties": {
85
+ "frozen_total": { "type": "integer", "minimum": 0, "description": "Size of the grandfathered manifest at the moment it was frozen — display provenance for a human reader, NEVER an integrity guard (swarms/PROTOCOL.md's 'Fixing a class, not an instance' sub-law 5: 'a count is not integrity'). The real integrity guard is content-addressed (EXPECTED_GRANDFATHER_MANIFEST_HASH over the manifest file), independent of this field. Informational relationship, not schema-enforced (JSON Schema cannot cross-check arithmetic across sibling fields): drained = frozen_total minus the manifest's current live entry count." },
86
+ "drained": { "type": "integer", "minimum": 0, "description": "Entries removed from the manifest by a completed re-review since freeze — frozen_total minus the manifest's current live entry count in scripts/grandfathered-pins.json (informational relationship; see frozen_total's own description)." },
87
+ "outstanding": {
88
+ "type": "array",
89
+ "description": "Remaining grandfathered-manifest entries, one per still-frozen id in scripts/grandfathered-pins.json. Uses $defs/grandfatheredManifestEntry — a distinct shape from drain_queue.entries[] below as of WAVE-43/Amendment 3 (A3.2b).",
90
+ "items": { "$ref": "#/$defs/grandfatheredManifestEntry" }
91
+ }
92
+ }
93
+ },
94
+
95
+ "recurrence_stats": {
96
+ "type": "object",
97
+ "additionalProperties": true,
98
+ "description": "T1: 'recurrence stats (swarm trends internals)'. Deliberately left open (additionalProperties:true) rather than frozen here: the query layer this section reflects (packages/dogfood-swarm/lib/queries/cross-run-analytics.js's queryRecurringFindings and its siblings) is owned by the core/dogfood-swarm domain and evolves independently of this schemas-package registration. Freezing every field here would prematurely couple two domains this pass's own DECOMPOSE_BY_SECRETS scoring (docs/trajectory-and-closure.dispatch.md) deliberately keeps separate. The one field named below is grounded directly in that module's existing return shape as a documented-but-not-exhaustive convention, not a closed contract — an undisclosed gap would itself be the defect (swarms/CLAUDE.md, 'Honesty is a feature of the artifact, not a mood').",
99
+ "properties": {
100
+ "top_recurring": {
101
+ "type": "array",
102
+ "description": "Fingerprints observed across more than one run, most-recurring first. Mirrors queryRecurringFindings()'s actual return shape (packages/dogfood-swarm/lib/queries/cross-run-analytics.js) rather than redefining it independently.",
103
+ "items": {
104
+ "type": "object",
105
+ "additionalProperties": true,
106
+ "required": ["fingerprint", "run_count", "severity", "first_seen", "last_seen"],
107
+ "properties": {
108
+ "fingerprint": { "type": "string", "minLength": 1, "description": "Content-addressed finding fingerprint (packages/dogfood-swarm/lib/fingerprint.js)." },
109
+ "description": { "type": "string", "description": "A representative description from one of the recurring rows. Not fingerprint-folded — wording may vary run to run; this is a stable pick, not a canonical one." },
110
+ "run_count": { "type": "integer", "minimum": 2, "description": "Distinct runs this fingerprint was observed in. By construction always greater than 1 — that is what makes it 'recurring'." },
111
+ "severity": { "type": "string", "enum": ["CRITICAL", "HIGH", "MEDIUM", "LOW"], "description": "The most severe observation across runs (an explicit rank, not an alphabetical MAX — 'MEDIUM' must not beat 'CRITICAL')." },
112
+ "first_seen": { "type": "string", "format": "date-time", "description": "Earliest run this fingerprint was observed in." },
113
+ "last_seen": { "type": "string", "format": "date-time", "description": "Most recent run this fingerprint was observed in." }
114
+ }
115
+ }
116
+ }
117
+ }
118
+ },
119
+
120
+ "attention": {
121
+ "type": "object",
122
+ "required": ["advisory", "items"],
123
+ "additionalProperties": false,
124
+ "description": "T2: a ranked top-K per-file attention list, consumed ONLY as audit-brief context. `advisory` is a non-optional, const-true sibling of the ranked list — structurally inseparable, so a consumer can never read `items` without also validating the label that governs how it may be used.",
125
+ "$comment": "T2 is explicit: 'It is never a gate, never a predictor, never auto-blame' (Q3: Lewis et al. 2013, ICSE, research.google/pubs/pub41145 — Google's deployed bug predictor changed no developer behavior; only passive hotspot reports survived. Q3: SZZ-style blame misattributes against developer oracles, Rosa et al. 2021, arXiv:2102.03300). The schema cannot enforce HOW a consumer uses this section — only that the advisory label travels WITH the list and cannot be stripped from an instance without producing a schema violation.",
126
+ "properties": {
127
+ "advisory": {
128
+ "type": "boolean",
129
+ "const": true,
130
+ "description": "Always true by construction. A compiler cannot emit an attention section without this marker; a consumer cannot read `items` without also seeing this sibling is present and true (T2: 'never a gate, never a predictor, never auto-blame')."
131
+ },
132
+ "items": {
133
+ "type": "array",
134
+ "description": "Ranked top-K files by attention score. Empty is valid — no signal this compile.",
135
+ "items": {
136
+ "type": "object",
137
+ "required": ["file", "score", "components"],
138
+ "additionalProperties": false,
139
+ "properties": {
140
+ "file": { "type": "string", "minLength": 1, "description": "Repo-relative file path." },
141
+ "score": { "type": "number", "minimum": 0, "description": "Combined attention score — the product of the three normalized components below (T2)." },
142
+ "components": {
143
+ "type": "object",
144
+ "required": ["churn", "recency", "fragmentation"],
145
+ "additionalProperties": false,
146
+ "description": "The three factors T2 names explicitly, each independently sourced: churn relative to file size (Q3: Nagappan & Ball 2005, ICSE — relative, not absolute, churn discriminates); prior-finding recency/count (Q3: Rahman & Devanbu 2013, ICSE — process metrics beat static code metrics); lane-fragmentation, the count of distinct domains that touched the file (Q3: Bird et al. 2011, ESEC/FSE — ownership fragmentation predicts failures better than churn+complexity+coverage combined).",
147
+ "properties": {
148
+ "churn": { "type": "number", "minimum": 0, "description": "Recent churn normalized relative to file size." },
149
+ "recency": { "type": "number", "minimum": 0, "description": "Prior-finding recency/count signal for this file." },
150
+ "fragmentation": { "type": "number", "minimum": 0, "description": "Count (or normalized measure) of distinct domains/lanes that have touched this file." }
151
+ }
152
+ }
153
+ }
154
+ }
155
+ }
156
+ }
157
+ },
158
+
159
+ "operator_notes": {
160
+ "type": "array",
161
+ "maxItems": 7,
162
+ "description": "T3: the ONLY human-authored section — the ACCEPTED/active subset (lib/roadmap/notes.js#validateOperatorNotes' own `accepted` return). At most 7 entries (Q1: Shinn et al. 2023, Reflexion, arXiv:2303.11366 — bounded lesson buffers beat unbounded). See expired_notes below for the sibling bucket T3's loud-expiry rule feeds; both share $defs/operatorNote so the two buckets cannot drift into two different note shapes.",
163
+ "items": { "$ref": "#/$defs/operatorNote" }
164
+ },
165
+
166
+ "expired_notes": {
167
+ "type": "array",
168
+ "description": "WAVE-43 / AMENDMENT 3 (A3.4, F-74ba2c79): the operator notes T3 requires compile to drop LOUDLY rather than silently omit ('listed in output as EXPIRED, not silently omitted') — renamed from the notes-validation module's internal `expired` key (lib/roadmap/notes.js#validateOperatorNotes) to this artifact-level name. Settles T3's own 'output' ambiguity: the loud disclosure lives in the cross-run artifact itself, not only in a CLI stdout line a later run can no longer see — the artifact is the cross-run carrier (F-74ba2c79's fail-closed notes-validation pin is the live behavior this section assumes). REQUIRED, empty-allowed: absent would mean 'compile did not run this query', which is never true for this section — it is always computed in the same pass as operator_notes (this file's own top-level description states that convention for every section here). Every entry already satisfies $defs/operatorNote's own kind/text/enforced_by shape and invariant-conditional by construction: notes.js's control flow checks those BEFORE checking expiry, so a note only reaches this bucket after already passing them (an invariant note that FAILS the enforced_by check is dropped as invalid, not expired — this section is never where that failure surfaces). Unlike operator_notes, no maxItems cap here — deliberately: T3's 7-note bound polices what an operator may AUTHOR in one compile (validateOperatorNotes' own input, which happens to bound this bucket to at most 7 today as a side effect of that same check, not a rule this schema freezes), not how many historical expired notes a future reader might want visible; a compiler that someday carries forward multiple runs' expired history should not need a schema change to do it.",
169
+ "items": { "$ref": "#/$defs/operatorNote" }
170
+ },
171
+
172
+ "drain_queue": {
173
+ "type": "object",
174
+ "required": ["entries", "overdue_ids"],
175
+ "additionalProperties": false,
176
+ "description": "T6 drain state for the AUTHORED, runs-ordinal drain-state file — dogfood/roadmap-drain-state.json, a target-repo-local file an operator hand-maintains (F-1cd5de59 lineage; lib/roadmap/drain.js#compileAuthoredDrainState is the shipped, end-to-end-pinned reader). WAVE-43 / AMENDMENT 3 (A3.2a) CORRECTION: an earlier revision of this section (and of scripts/doc-drift-patterns.json, HANDOFF, and the wave-42 kickoff) wrongly claimed this section shared a provenance shape, and shared a 'both model DATES' character, with grandfathered_drain above — both false, caught by Amendment 3's own adversarial skeptic round. This section is RUNS-ORDINAL (cadence measured in runs on this repo, via a cross-run index over the `runs` table), not date-based, and it is a DIFFERENT population over a DIFFERENT file than either grandfathered_drain (scripts/grandfathered-pins.json) or the allowlist-overdue residual named below (scripts/regression-pin-allowlist.json) — three distinct suppression/drain files exist in this codebase and must not be conflated a fourth time. `entries` preserves F-1cd5de59's distinct-listing assertion; `overdue_ids` is compileAuthoredDrainState's own denormalized convenience subset. NAMED RESIDUALS, NOT SILENT DROPS (A3.5): this section does NOT surface the allowlist-overdue output (scripts/regression-pin-allowlist.json's 36 entries, compileGrandfatheredManifestDrain's return) or compileUnroutableApprovedDrain's approved-but-unroutable findings — both remain advisory-only via `swarm roadmap show` + the digest, not persisted here, this wave. compileDeferredFindingsDrain's waves-shape stays out of the artifact entirely: findings rows carry no owner column in this pass, and an owner is never invented to populate one (T6's own 'never anonymous' provenance discipline, mirrored by $defs/drainQueueEntry.owner below). No producer is wired into the committed artifact from THIS shape as of this wave (core/verbs' cross-domain burden, unresolved as of this commit) — this schema states the target contract; see this file's top-level $comment for the full seam-decision writeup.",
177
+ "properties": {
178
+ "entries": {
179
+ "type": "array",
180
+ "description": "One entry per id named in dogfood/roadmap-drain-state.json, mirroring compileAuthoredDrainState's shipped return shape exactly (lib/roadmap/drain.js). Uses $defs/drainQueueEntry — a distinct shape from grandfathered_drain.outstanding[] above as of WAVE-43/Amendment 3 (A3.2a).",
181
+ "items": { "$ref": "#/$defs/drainQueueEntry" }
182
+ },
183
+ "overdue_ids": {
184
+ "type": "array",
185
+ "description": "Subset of entries[].id where entries[].overdue===true — compileAuthoredDrainState's own denormalized convenience return, so a consumer wanting only the overdue set does not need to filter entries[] itself (T6: 'entries past cadence surface at the top of the next run's digest').",
186
+ "items": { "type": "string", "minLength": 1 }
187
+ }
188
+ }
189
+ },
190
+
191
+ "content_hash": {
192
+ "type": "string",
193
+ "minLength": 1,
194
+ "description": "OPTIONAL — WAVE-41 SEAM DECISION (F-c7b0f47b): stays optional, deliberately not promoted to required, even though this wave expects emitters to start populating it. Not part of the locked T1-T6 pass contract (docs/trajectory-and-closure.dispatch.md) — an integrity aid for T5's 'versions supersede, nothing rewrites' discipline, so a consumer can cheaply detect whether a previously-fetched dogfood/roadmap/<run-id>.json has changed, by comparing a freshly computed hash against one it cached earlier. HASHING SEMANTIC (newly specified this wave — the prior text left this undefined, which is why the field was computed by writeRoadmapArtifact but never actually reached the written bytes): if a producer includes this field, it MUST be a hash of the artifact's own serialized bytes computed WITH THIS FIELD ABSENT — hash-then-attach, never hash-including-self, which has no fixed point. Hash algorithm and length remain deliberately unconstrained here: choosing and documenting one is a compiler (core domain) decision, not a schemas-package one. Kept optional rather than required because this schema can only ever enforce the KEY's presence, never the VALUE's correctness — a wrong or stale hash is worse than an absent one, so a producer not yet confident in its self-exclusion computation should omit the field rather than ship a mismatched one. Promoting this to required is a reasonable follow-up once emitters are confirmed to populate it consistently."
195
+ },
196
+
197
+ "notesPath": {
198
+ "type": "string",
199
+ "minLength": 1,
200
+ "pattern": "^(?![/\\\\])(?![A-Za-z]:).+$",
201
+ "description": "OPTIONAL — WAVE-41 SEAM DECISION (F-c7b0f47b): records which local file compile read the operator-notes seed from. This is compile-ENVIRONMENT provenance, not one of the T1-T6 sections queried from the DB and git themselves — T3 is about note CONTENT, which lives in operator_notes above; this field only says which local file supplied it, and a producer with nothing meaningful to report (e.g. no seed file existed) may omit it entirely. MUST be repo-relative, resolved against the target repo root at read time, never a machine-absolute path baked into a committed artifact. The pattern mechanically enforces this: it rejects a leading `/` or `\\`, and a drive-letter prefix such as `C:` or `E:\\`. This closes the finding's own first proven exhibit — a real compile had committed this field as a machine-absolute Windows path, which resolves on no checkout but the one that produced it. Before this wave the key was not recognized at all (any value, relative or not, was rejected outright as a disallowed additionalProperty); now a relative value is accepted and only an absolute one is refused, and refused specifically for being absolute rather than merely unrecognized."
202
+ }
203
+ },
204
+
205
+ "$defs": {
206
+ "grandfatheredManifestEntry": {
207
+ "type": "object",
208
+ "required": ["id", "owner", "revalidate_by"],
209
+ "additionalProperties": false,
210
+ "description": "WAVE-43 / AMENDMENT 3 (A3.2b): grandfathered_drain.outstanding's per-entry shape, mirroring scripts/grandfathered-pins.json's real per-id shape exactly — {owner, revalidate_by}, keyed by finding id, no third field. Retired the pre-amendment shared $defs/drainEntry (required reason, added_at, cadence_runs, due_at_run), which no producer ever satisfied for this population: the manifest carries a DATE deadline, not a runs-ordinal cadence, and has never carried a per-entry reason or an added_at timestamp.",
211
+ "properties": {
212
+ "id": { "type": "string", "minLength": 1, "description": "A finding id (F-xxxxxxxx) — one of scripts/grandfathered-pins.json's own keys (e.g. 'F-002109-003'), the id the pin-matcher rewrite's live heuristic classified as grandfathered at the freeze commit. Contrast $defs/drainQueueEntry.id, which lives in a separate, arbitrary authored-file id namespace." },
213
+ "owner": { "type": "string", "minLength": 1, "description": "Named individual or role accountable for this entry's eventual re-review. Never anonymous — mirrors this repo's NAMED_COMPENSATORS discipline (.claude/rules/workflow-standards.md). Uniformly 'coordinator' in the real manifest today (freezing the list was a coordinator-level architectural decision, not a per-id domain judgment call — scripts/grandfathered-pins.json's own header) but not const-constrained here, since a future manifest generation could assign per-id owners." },
214
+ "revalidate_by": { "type": "string", "format": "date", "description": "ISO calendar date (YYYY-MM-DD) this entry is due for re-review — scripts/grandfathered-pins.json's own field of the same name, forwarded unchanged. INCLUSIVE boundary (lib/roadmap/drain.js#compileGrandfatheredManifestDrain, the allowlist's sibling reader): an entry whose date is today is already due, not due tomorrow — the opposite boundary convention from $defs/drainQueueEntry.overdue's exclusive one, deliberately, per F-1cd5de59's own pinned distinction between the two populations." },
215
+ "reason": { "type": "string", "minLength": 1, "description": "Why this specific entry is parked here. OPTIONAL and typically absent: scripts/grandfathered-pins.json's own per-entry shape is {owner, revalidate_by} only — per-entry provenance is never invented to populate this field. The manifest's SHARED rationale (why the whole set was frozen) lives in grandfathered_drain's own section description above, not repeated per entry." }
216
+ }
217
+ },
218
+
219
+ "drainQueueEntry": {
220
+ "type": "object",
221
+ "required": ["id", "owner", "cadence_runs", "runs_since_review", "overdue"],
222
+ "additionalProperties": false,
223
+ "description": "WAVE-43 / AMENDMENT 3 (A3.2a): drain_queue's per-entry shape, mirroring lib/roadmap/drain.js#compileAuthoredDrainState's shipped return exactly — {id, owner, cadence_runs, runs_since_review, overdue} + optional reason. Retired the pre-amendment shared $defs/drainEntry (added_at/due_at_run), which no producer ever satisfied: this population's real source (dogfood/roadmap-drain-state.json) carries a RUN-ORDINAL cadence, computed relative to a cross-run index, not an absolute due-at-run number or an added-at timestamp.",
224
+ "properties": {
225
+ "id": { "type": "string", "minLength": 1, "description": "The authored drain-state entry's own id (dogfood/roadmap-drain-state.json) — not necessarily a finding id; the authored file's own id namespace (F-1cd5de59). Contrast $defs/grandfatheredManifestEntry.id, which IS always a finding id." },
226
+ "owner": { "type": "string", "minLength": 1, "description": "Named individual or role accountable for this entry's eventual re-review. Never anonymous — mirrors this repo's NAMED_COMPENSATORS discipline (.claude/rules/workflow-standards.md) applied to drain entries instead of tool calls." },
227
+ "cadence_runs": { "type": "integer", "minimum": 1, "description": "Re-review cadence, in swarm runs on this repo — the authored source's own `cadence_runs` field, forwarded unchanged." },
228
+ "runs_since_review": { "type": "integer", "minimum": 0, "description": "Runs elapsed since this entry's last_reviewed_run_ordinal, computed against a cross-run ordinal index over `runs` rows sharing this entry's repo (compileAuthoredDrainState) — NOT a wave count, and not comparable to compileDeferredFindingsDrain's wave-scoped staleness (a residual excluded from this artifact this wave; see drain_queue's own section description)." },
229
+ "overdue": { "type": "boolean", "description": "True once runs_since_review strictly exceeds cadence_runs (exclusive boundary — an entry exactly AT cadence is not yet overdue; F-1cd5de59 pins this boundary verbatim). Compile surfaces overdue entries at the top of the next run's digest (T6; Q5's Chromium 'no forcing function is the failure' lesson)." },
230
+ "reason": { "type": "string", "minLength": 1, "description": "Why this entry is parked here. OPTIONAL: compileAuthoredDrainState's shipped shape does not populate this field today, and dogfood/roadmap-drain-state.json's own documented source shape has no reason property either (lib/roadmap/drain.js's own header) — kept optional for forward compatibility with a future authored-source enrichment. Per-entry provenance is never invented to satisfy this schema; omit rather than synthesize." }
231
+ }
232
+ },
233
+
234
+ "operatorNote": {
235
+ "type": "object",
236
+ "required": ["kind", "text", "expires"],
237
+ "additionalProperties": false,
238
+ "description": "T3's shared per-note shape, used by both operator_notes (active) and expired_notes (WAVE-43/Amendment 3 A3.4) above — the same shape, two buckets by lifecycle state, not two different note formats.",
239
+ "properties": {
240
+ "kind": { "type": "string", "enum": ["theme", "open-question", "invariant"], "description": "T3's three note kinds." },
241
+ "text": { "type": "string", "minLength": 1, "maxLength": 1000, "description": "The note's content." },
242
+ "expires": {
243
+ "description": "When this note stops being surfaced by compile. Either an integer horizon (expires after N further runs on this repo) or an ISO-8601 calendar date. Compile MUST drop expired notes LOUDLY — surfaced in expired_notes, never silently omitted (T3) — but that behavior belongs to the compiler (core domain); this schema only shapes the value, it cannot enforce the drop.",
244
+ "oneOf": [
245
+ { "type": "integer", "minimum": 1, "description": "Expires after this many further runs on this repo." },
246
+ { "type": "string", "format": "date", "description": "Expires on this calendar date (YYYY-MM-DD)." }
247
+ ]
248
+ },
249
+ "enforced_by": {
250
+ "type": "string",
251
+ "minLength": 1,
252
+ "description": "Path to the gate/test that mechanically enforces this note. Required by the conditional below whenever kind='invariant' — 'a lesson without a mechanical verifier is not persisted as a lesson' (Q1: Wang et al. 2023, Voyager, arXiv:2305.16291; Anthropic 2025, Project Vend, anthropic.com/research/project-vend-1 — a long-horizon agent's narrative correction did not hold across days). LIMITATION disclosed up front: this schema can only shape enforced_by as a non-empty string — it cannot verify the referenced gate/test file actually EXISTS on disk. That cross-file existence check belongs to the compiler (core domain), which per this repo's own Class #14 history (scripts/check-finding-regression-pins.mjs's AST-based rebuild after a prose-matching heuristic leaked 7 consecutive audits) should use a real structural check, never a string/regex scan, to confirm enforced_by resolves to something real."
253
+ }
254
+ },
255
+ "allOf": [
256
+ {
257
+ "$comment": "T3 invariant-requires-enforced_by conditional — the identical shape to dogfood-finding.schema.json's own proven H4 pattern ('if status===\"rejected\" then review.reject_reason required'), one file over in this same package. A note claiming kind='invariant' with no mechanical enforcement pointer is exactly the Project Vend failure mode (Q1): a narrative correction that does not hold, because nothing mechanical re-checks it. Shared by operator_notes and expired_notes (WAVE-43/Amendment 3 A3.4) via this $defs entry — an expired invariant note must have already satisfied this conditional to have been accepted long enough to expire (see notes.js's control-flow ordering, cited in expired_notes' own description), so this conditional is not redundant there, it is the reason expired_notes never needs a separate one.",
258
+ "if": {
259
+ "properties": { "kind": { "const": "invariant" } },
260
+ "required": ["kind"]
261
+ },
262
+ "then": {
263
+ "required": ["enforced_by"]
264
+ }
265
+ }
266
+ ]
267
+ },
268
+
269
+ "latestPointer": {
270
+ "type": "object",
271
+ "required": ["run_id", "sequence", "path"],
272
+ "additionalProperties": false,
273
+ "description": "T5 companion micro-shape for dogfood/roadmap/latest.json — the ONE mutable pointer to the newest compiled roadmap version for a run. This is a SEPARATE file's contract from the roadmap document above; a consumer validating latest.json directly references it as dogfood-roadmap.schema.json#/$defs/latestPointer, matching the way F-fe05c6d7's own recommendation named it a 'companion micro-shape' rather than a second top-level schema file.",
274
+ "properties": {
275
+ "run_id": { "type": "string", "minLength": 1, "pattern": "^[A-Za-z0-9_-]+$", "description": "Same run_id as the pointed-to roadmap document." },
276
+ "sequence": { "type": "integer", "minimum": 1, "description": "Same sequence as the pointed-to roadmap document — the newest compiled version for this run." },
277
+ "path": { "type": "string", "minLength": 1, "description": "Relative path to the versioned roadmap file this pointer resolves to, e.g. dogfood/roadmap/<run_id>.json." }
278
+ }
279
+ }
280
+ }
281
+ }
@@ -312,7 +312,7 @@
312
312
  "description": "Closed operator set. exists/not_exists are truthiness (not strict key-presence) and take no value."
313
313
  },
314
314
  "value": {
315
- "description": "Comparand. Omitted for exists/not_exists. An array for in/not_in. A scalar otherwise. Numeric for gt/gte/lt/lte (a non-numeric resolved field is an eval-time policy-config: fault)."
315
+ "description": "Comparand. Omitted for exists/not_exists. An array of scalars for in/not_in. A number for gt/gte/lt/lte. A scalar (string/number/boolean/null) for equals/not_equals/contains/not_contains. These type constraints are schema-enforced (F-3ed78d6f): the comparand lives in the policy file, so a mistyped one — e.g. the quoted-number YAML footgun value: \"95\" — is a data-independent fault caught structurally at author time, not a rule that silently never fires. A non-numeric resolved FIELD for a numeric op remains an eval-time policy-config: fault."
316
316
  }
317
317
  },
318
318
  "allOf": [
@@ -326,7 +326,15 @@
326
326
  },
327
327
  {
328
328
  "if": { "required": ["op"], "properties": { "op": { "enum": ["in", "not_in"] } } },
329
- "then": { "properties": { "value": { "type": "array" } } }
329
+ "then": { "properties": { "value": { "type": "array", "items": { "type": ["string", "number", "boolean", "null"] } } } }
330
+ },
331
+ {
332
+ "if": { "required": ["op"], "properties": { "op": { "enum": ["gt", "gte", "lt", "lte"] } } },
333
+ "then": { "properties": { "value": { "type": "number" } } }
334
+ },
335
+ {
336
+ "if": { "required": ["op"], "properties": { "op": { "enum": ["equals", "not_equals", "contains", "not_contains"] } } },
337
+ "then": { "properties": { "value": { "type": ["string", "number", "boolean", "null"] } } }
330
338
  }
331
339
  ]
332
340
  },