docs(intent): M3 + M7 — the header says only what is true
M3: the header claimed "reflowing a paragraph keeps the approval"; joining
lines gives STALE (PM probe iii-c). It now says what keeps the approval
(indentation, in-line spacing, blank lines, CRLF) and that joining or
splitting lines makes it stale — erring safe. Also states the one-section
and code-block/comment rules from M1.
M7: the trekreview exemption is read from the brief's own frontmatter, so a
relabelled brief walks past the gate — the same trust class as self-stamping.
Now said in the module header, HANDOVER-CONTRACTS and /trekplan's gate prose.
HANDOVER-CONTRACTS also names both brief modes the --approve path reaches.
Red 097bae8 (M3, M7) → green. Suite 1224: 1222 pass / 0 fail / 2 skip.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
097bae8a02
commit
4592b40873
3 changed files with 15 additions and 6 deletions
|
|
@ -198,7 +198,10 @@ agent, write no plan. Print each error's `message` and `hint`, then stop:
|
||||||
If the command does not print the JSON report (module not found, node
|
If the command does not print the JSON report (module not found, node
|
||||||
missing, an unresolved `${CLAUDE_PLUGIN_ROOT}`), **halt** as well and show the
|
missing, an unresolved `${CLAUDE_PLUGIN_ROOT}`), **halt** as well and show the
|
||||||
raw error: an approval check that could not run is never a pass.
|
raw error: an approval check that could not run is never a pass.
|
||||||
`trekreview` briefs are exempt (the check returns exit 0 for them). What the
|
`trekreview` briefs are exempt (the check returns exit 0 for them). The
|
||||||
|
exemption is read from the brief's own frontmatter, so a brief relabelled
|
||||||
|
`type: trekreview` walks past this gate. That is
|
||||||
|
the same trust class as self-stamping. What the
|
||||||
marker does NOT prove — it is a trace that the approval step ran against this
|
marker does NOT prove — it is a trace that the approval step ran against this
|
||||||
text, not a signature: see the header of `lib/validators/intent-approval.mjs`.
|
text, not a signature: see the header of `lib/validators/intent-approval.mjs`.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -106,7 +106,7 @@ Optional but standard sections: `## Non-Goals`, `## Constraints`, `## Preference
|
||||||
|
|
||||||
**Pre-2.2 briefs receive zero framing enforcement (producer-elective defense).** The framing-alignment defense is gated at `brief_version ≥ 2.2`, so a brief declaring `2.0` or `2.1` gets **none** of it: `framing` is optional and a missing value is not an error, the `## TL;DR` section is not required, and the `brief-reviewer` memory-alignment dimension scores N/A. The backward-compatibility this buys is deliberate, but it also means the framing defense is **producer-elective**: any producer can sidestep the entire defense — deliberately or by shipping a legacy template — simply by declaring `brief_version: "2.1"`, and the pipeline raises no signal by default. This is a documented property of the contract, not a bug. Two remedies close it for a given consumer: (1) require upstream producers to emit `brief_version: "2.2"` (which forces `framing` + `## TL;DR`); or (2) pass the opt-in **`--min-brief-version <ver>`** flag to `/trekplan` or `/trekresearch` (forwarded to the validator as `--min-version`), which raises a `BRIEF_VERSION_BELOW_MINIMUM` **warning** — never a block — when a brief declares a version below the floor. The flag defaults to off, so the N-1 compatibility window for `2.0`/`2.1` briefs is preserved unless a consumer explicitly opts into the stricter floor.
|
**Pre-2.2 briefs receive zero framing enforcement (producer-elective defense).** The framing-alignment defense is gated at `brief_version ≥ 2.2`, so a brief declaring `2.0` or `2.1` gets **none** of it: `framing` is optional and a missing value is not an error, the `## TL;DR` section is not required, and the `brief-reviewer` memory-alignment dimension scores N/A. The backward-compatibility this buys is deliberate, but it also means the framing defense is **producer-elective**: any producer can sidestep the entire defense — deliberately or by shipping a legacy template — simply by declaring `brief_version: "2.1"`, and the pipeline raises no signal by default. This is a documented property of the contract, not a bug. Two remedies close it for a given consumer: (1) require upstream producers to emit `brief_version: "2.2"` (which forces `framing` + `## TL;DR`); or (2) pass the opt-in **`--min-brief-version <ver>`** flag to `/trekplan` or `/trekresearch` (forwarded to the validator as `--min-version`), which raises a `BRIEF_VERSION_BELOW_MINIMUM` **warning** — never a block — when a brief declares a version below the floor. The flag defaults to off, so the N-1 compatibility window for `2.0`/`2.1` briefs is preserved unless a consumer explicitly opts into the stricter floor.
|
||||||
|
|
||||||
**Intent approval gate (veikart steg 1) — additive schema, consumer-side requirement.** The two `intent_approved_*` fields are additive and optional in the schema: `brief-validator.mjs` does not require them, `/trekresearch` does not read them, and no `brief_version` bump is involved. The requirement lives in `/trekplan` Phase 1 (`### Read the brief`), which runs `intent-approval.mjs --check` and **halts** on `BRIEF_INTENT_NOT_APPROVED` (no marker), `BRIEF_INTENT_APPROVAL_STALE` (`## Intent` or `## Goal` changed after approval) or `BRIEF_INTENT_APPROVAL_INVALID` (malformed marker, or a section missing). It is version-independent, so a brief from ANY producer, of any `brief_version`, stops at `/trekplan` until approved. No producer has to emit anything new: the operator approves through `/trekbrief --approve <project-dir | brief-file>`, a Voyage-side step open to every producer's brief, so no producer is privileged. `trekreview` briefs are exempt. **What the marker does not prove:** same user, same machine. Any session can run `--stamp`. The marker is a trace that the approval step ran against this exact text, not a signature (see the header of `lib/validators/intent-approval.mjs`). `--stamp` also emits `brief-approved` to `trekexecute-stats.jsonl` under `CLAUDE_PLUGIN_DATA`, falling back to the plugin data dir the yardstick reads, on both the manual and the auto path.
|
**Intent approval gate (veikart steg 1) — additive schema, consumer-side requirement.** The two `intent_approved_*` fields are additive and optional in the schema: `brief-validator.mjs` does not require them, `/trekresearch` does not read them, and no `brief_version` bump is involved. The requirement lives in `/trekplan` Phase 1 (`### Read the brief`), which runs `intent-approval.mjs --check` and **halts** on `BRIEF_INTENT_NOT_APPROVED` (no marker), `BRIEF_INTENT_APPROVAL_STALE` (`## Intent` or `## Goal` changed after approval) or `BRIEF_INTENT_APPROVAL_INVALID` (malformed marker, or a section missing, empty or present more than once; a `## ` line inside a code block or HTML comment is not a heading). It is version-independent, so a brief from ANY producer, of any `brief_version`, stops at `/trekplan` until approved. No producer has to emit anything new: the operator approves through `/trekbrief --approve <project-dir | brief-file>`, a Voyage-side step open to every producer's brief, whether it is planned with `--project` (`<dir>/brief.md`) or `--brief <file>`, so no producer is privileged. `trekreview` briefs are exempt. The exemption is read from the brief's own frontmatter, so relabelling a brief `type: trekreview` walks past the gate, the same trust class as self-stamping. **What the marker does not prove:** same user, same machine. Any session can run `--stamp`. The marker is a trace that the approval step ran against this exact text, not a signature (see the header of `lib/validators/intent-approval.mjs`). `--stamp` also emits `brief-approved` to `trekexecute-stats.jsonl` under `CLAUDE_PLUGIN_DATA`, falling back to the plugin data dir the yardstick reads, on both the manual and the auto path.
|
||||||
|
|
||||||
**Failure modes:**
|
**Failure modes:**
|
||||||
- `BRIEF_INTENT_NOT_APPROVED` / `BRIEF_INTENT_APPROVAL_STALE` / `BRIEF_INTENT_APPROVAL_INVALID` → `/trekplan` halts (intent-approval gate, above); remedy `/trekbrief --approve <project-dir | brief-file>`
|
- `BRIEF_INTENT_NOT_APPROVED` / `BRIEF_INTENT_APPROVAL_STALE` / `BRIEF_INTENT_APPROVAL_INVALID` → `/trekplan` halts (intent-approval gate, above); remedy `/trekbrief --approve <project-dir | brief-file>`
|
||||||
|
|
|
||||||
|
|
@ -9,9 +9,12 @@
|
||||||
//
|
//
|
||||||
// The hash binds the approval to the EXACT intent text: each section is
|
// The hash binds the approval to the EXACT intent text: each section is
|
||||||
// normalized (lines trimmed, whitespace runs collapsed, blank lines dropped)
|
// normalized (lines trimmed, whitespace runs collapsed, blank lines dropped)
|
||||||
// and the pair is hashed. Reflowing a paragraph keeps the approval; changing
|
// and the pair is hashed. Indentation, spacing inside a line, blank lines and
|
||||||
// a word in ## Intent or ## Goal after approval makes it stale, and /trekplan
|
// CRLF keep the approval. Line breaks are part of the text:
|
||||||
// stops until the operator approves the new text.
|
// joining or splitting lines makes the approval stale, as does changing a
|
||||||
|
// word. That errs safe: /trekplan stops until the operator approves the new text.
|
||||||
|
// Each section must appear exactly once; a `## ` line inside a fenced code
|
||||||
|
// block or an HTML comment is text, not a heading.
|
||||||
//
|
//
|
||||||
// WHAT THE MARKER DOES NOT PROVE. Same user, same machine: any session with
|
// WHAT THE MARKER DOES NOT PROVE. Same user, same machine: any session with
|
||||||
// write access to the brief can run `--stamp` itself, or write the two fields
|
// write access to the brief can run `--stamp` itself, or write the two fields
|
||||||
|
|
@ -22,7 +25,10 @@
|
||||||
// operator's behalf.
|
// operator's behalf.
|
||||||
//
|
//
|
||||||
// trekreview briefs are exempt: they are produced from a review of an already
|
// trekreview briefs are exempt: they are produced from a review of an already
|
||||||
// planned brief and carry no ## Intent of their own.
|
// planned brief and carry no ## Intent of their own. The exemption is read
|
||||||
|
// from the brief's own frontmatter, so relabelling a brief `type: trekreview`
|
||||||
|
// walks past the gate. That is the same trust class as self-stamping: a
|
||||||
|
// session that can edit the brief can do either. Neither is caught here.
|
||||||
//
|
//
|
||||||
// CLI:
|
// CLI:
|
||||||
// node lib/validators/intent-approval.mjs --check [--json] <brief.md>
|
// node lib/validators/intent-approval.mjs --check [--json] <brief.md>
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue