docs(voyage): S28 — locate plan_version in plan header line, not frontmatter
HANDOVER-CONTRACTS.md was the lone source that called plan_version a
frontmatter field. The plan template (templates/plan-template.md:21) emits it
ONLY in the prose "Generated by" header line; brief-generated plans carry no
frontmatter at all (the sole frontmatter block, source_findings, is
trekreview-only and additive). planning-orchestrator.md:228 ("metadata line
below the title"), the parser (lib/parsers/plan-schema.mjs, S26), and the
plan-schema.test.mjs comment all already say prose. The contract was the
outlier — the deferred doc-side closure the S26 commit named as scope to avoid
then ("a 3-file doc reconciliation").
Operator-chosen direction (Option A + A1): correct the contract to the
artifact, doc-only — NOT move the field to frontmatter (which would alter every
plan's shape and fight the trekreview-only frontmatter design). A1 keeps the
standardized "Frontmatter schema" heading, corrects the row, and notes the real
(optional, trekreview-only) source_findings frontmatter.
Three surgical spots in HANDOVER-CONTRACTS.md:
- versioning table: `plan_version` (frontmatter) → (plan header line)
- Handover 4 "Frontmatter schema": no-required-frontmatter note + Location
column locating plan_version in the "Generated by" header line + parser ref
- Handover 5 progress.json: "Mirrors plan's frontmatter" → "Mirrors the plan
header's plan_version"
TDD (red first): new doc-consistency pin asserts the contract no longer labels
plan_version a (frontmatter) field, drops "Mirrors plan's frontmatter", and
positively locates it in the plan header line. Red on the old wording (L15 +
L264), green after the edits.
Scope: only HANDOVER-CONTRACTS.md + the one pin. Template/orchestrator/parser/
examples untouched (already correct). Example-01's bare-line emission drift is
noted out-of-scope for a possible later item.
Tests: 729 (727 pass / 2 skip / 0 fail; live `node --test`, = 728 baseline +1).
plugin validate passes (1 accepted CLAUDE.md-at-root warning).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LqBYc8Ltrk7LipyJmGxXiB
This commit is contained in:
parent
1d638b2c7d
commit
8485ea1d36
2 changed files with 28 additions and 5 deletions
|
|
@ -12,7 +12,7 @@ Each artifact carries an explicit version field. Schema bumps are coordinated:
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
| `brief.md` | `brief_version` (frontmatter) | `2.2` |
|
| `brief.md` | `brief_version` (frontmatter) | `2.2` |
|
||||||
| `research/*.md` | (implicit; tracked via `type: trekresearch-brief`) | unversioned |
|
| `research/*.md` | (implicit; tracked via `type: trekresearch-brief`) | unversioned |
|
||||||
| `plan.md` | `plan_version` (frontmatter) | `1.7` |
|
| `plan.md` | `plan_version` (plan header line) | `1.7` |
|
||||||
| `progress.json` | `schema_version` (top-level) | `"1"` |
|
| `progress.json` | `schema_version` (top-level) | `"1"` |
|
||||||
| `review.md` | `review_version` (frontmatter) | `1.0` |
|
| `review.md` | `review_version` (frontmatter) | `1.0` |
|
||||||
| `.session-state.local.json` | `schema_version` (top-level) | `1` (number) |
|
| `.session-state.local.json` | `schema_version` (top-level) | `1` (number) |
|
||||||
|
|
@ -203,9 +203,18 @@ The validator (`lib/validators/architecture-discovery.mjs`) is intentionally min
|
||||||
|
|
||||||
**Frontmatter schema:**
|
**Frontmatter schema:**
|
||||||
|
|
||||||
| Field | Type | Required | Allowed |
|
`plan.md` has **no required frontmatter**. The only frontmatter block,
|
||||||
|---|---|---|---|
|
`source_findings` (optional), appears for `type: trekreview` plans — see
|
||||||
| `plan_version` | string | yes | `"1.7"` (current) |
|
Handover 6. Brief-generated plans carry no frontmatter at all.
|
||||||
|
|
||||||
|
| Field | Type | Required | Location | Allowed |
|
||||||
|
|---|---|---|---|---|
|
||||||
|
| `plan_version` | string | yes | plan header line, not frontmatter | `"1.7"` (current) |
|
||||||
|
|
||||||
|
`plan_version` is emitted in the plan's "Generated by" header metadata line
|
||||||
|
(`> Generated by … — `plan_version: 1.7``), parsed by `extractPlanVersion`
|
||||||
|
(`lib/parsers/plan-schema.mjs`) from either line-start or the backtick-wrapped
|
||||||
|
prose form (relaxed in S26 so the template's prose emission parses).
|
||||||
|
|
||||||
**Body invariants (strict, v1.7):**
|
**Body invariants (strict, v1.7):**
|
||||||
|
|
||||||
|
|
@ -261,7 +270,7 @@ The strongest validation in the entire pipeline. Phase 5.5 (planning-orchestrato
|
||||||
| `schema_version` | string | yes | `"1"` (current) |
|
| `schema_version` | string | yes | `"1"` (current) |
|
||||||
| `plan` | string | yes | Path to the plan being executed |
|
| `plan` | string | yes | Path to the plan being executed |
|
||||||
| `plan_type` | string | optional | `plan \| session-spec` |
|
| `plan_type` | string | optional | `plan \| session-spec` |
|
||||||
| `plan_version` | string | yes | Mirrors plan's frontmatter |
|
| `plan_version` | string | yes | Mirrors the plan header's plan_version |
|
||||||
| `started_at` | ISO string | yes | |
|
| `started_at` | ISO string | yes | |
|
||||||
| `updated_at` | ISO string | yes | Bumped on every write |
|
| `updated_at` | ISO string | yes | Bumped on every write |
|
||||||
| `completed_at` | ISO string | optional | Set when status flips to completed |
|
| `completed_at` | ISO string | optional | Set when status flips to completed |
|
||||||
|
|
|
||||||
|
|
@ -143,6 +143,20 @@ test('templates/plan-template.md declares plan_version: 1.7', () => {
|
||||||
assert.match(tpl, /plan_version:\s*['"]?1\.7['"]?/);
|
assert.match(tpl, /plan_version:\s*['"]?1\.7['"]?/);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('HANDOVER-CONTRACTS.md locates plan_version in the plan header line, not frontmatter (S28)', () => {
|
||||||
|
// The plan template emits plan_version only in the prose "Generated by"
|
||||||
|
// header line; brief-generated plans carry no frontmatter at all (the sole
|
||||||
|
// frontmatter block, `source_findings`, is trekreview-only and additive).
|
||||||
|
// The contract must therefore not label plan_version a frontmatter field.
|
||||||
|
const t = read('docs/HANDOVER-CONTRACTS.md');
|
||||||
|
assert.doesNotMatch(t, /`plan_version`\s*\(frontmatter\)/,
|
||||||
|
'HANDOVER-CONTRACTS.md must not call plan_version a (frontmatter) field — it lives in the plan header line');
|
||||||
|
assert.doesNotMatch(t, /Mirrors plan's frontmatter/,
|
||||||
|
"progress.json's plan_version mirrors the plan header line, not frontmatter");
|
||||||
|
assert.match(t, /`plan_version`\s*\(plan header line\)/,
|
||||||
|
'HANDOVER-CONTRACTS.md versioning table must locate plan_version in the plan header line');
|
||||||
|
});
|
||||||
|
|
||||||
// S19 prune (audit §Top changes #8): removed a tautological prose-pin —
|
// S19 prune (audit §Top changes #8): removed a tautological prose-pin —
|
||||||
// "commands/trekexecute.md still parses v1.7 plan schema" was an OR-chain
|
// "commands/trekexecute.md still parses v1.7 plan schema" was an OR-chain
|
||||||
// (`includes('plan_version') || includes('Step N:') || includes('### Step ')`)
|
// (`includes('plan_version') || includes('Step N:') || includes('### Step ')`)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue