docs(voyage): S24 — autonomy-gate truth-pass + guard pin (S21b doc/code drift)
operations.md:15 + command-modes.md described an autonomy surface that does
not exist in code. Truth-pass against lib/util/autonomy-gate.mjs (the source
of truth) closes three false claims found while auditing the autonomy surface
in S21 (devils-advocate-results.md S21b forward-pointer):
F1 (MAJOR) — fabricated state machine. operations.md claimed
`idle → approved → executing → merge-pending → main-merged`; only `idle`
exists. Real states: idle → gates_on|auto_running → paused_for_gate →
completed (events: start/phase_boundary/resume/finish).
F2 (MINOR) — event-emit.mjs does NOT "record each transition"; it emits 3
named lifecycle events (brief-approved, main-merge-gate, user_input) and
is decoupled from the pure, no-I/O autonomy-gate.
F3 — `--gates {open|closed|adaptive}` is false: the CLI shim + all 4 command
docs take a BOOLEAN `--gates {true|false}`. open/closed/adaptive is a
DERIVED gates_mode policy, /trekexecute-only, mapped from the brief effort
signal (low→open, standard→adaptive, high→closed; trekexecute.md:1562/74/75).
Operator-chosen fix (S24): boolean-true representation + a gates_mode policy
note, applied to BOTH operations.md and command-modes.md (4 rows) — same
false-claim class, fixed in one pass (fix-errors-found-in-scope).
TDD: doc-pin in doc-consistency.test.mjs imports STATES from autonomy-gate.mjs,
forbids the fabricated names + the flag-enum, requires the real states. Red
first (failed on "merge-pending"), green after the truth-pass.
Tests: 725 (723 pass / 2 skip / 0 fail). 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
b4edc12bec
commit
fe97f6172c
3 changed files with 63 additions and 11 deletions
|
|
@ -8,7 +8,7 @@ Per-command flag tables, imported from `CLAUDE.md` via pointer.
|
|||
|------|----------|
|
||||
| _(default)_ | Dynamic interview until quality gates pass → brief.md with research plan |
|
||||
| `--quick` | Compact start; still escalates if required sections are weak or the brief-review gate fails → brief.md with research plan |
|
||||
| `--gates {open\|closed\|adaptive}` | (v3.4.0) Autonomy-checkpoint policy. Default `adaptive` |
|
||||
| `--gates {true\|false}` | (v3.4.0) Boolean autonomy-gate flag; present → gating on. Policy (`gates_mode`) detailed under `## Autonomy mode` in `docs/operations.md`. |
|
||||
| `--profile <name>` | (v4.1.0) Model profile: `economy` / `balanced` / `premium` / `<custom>`. Sets `phase_models` for the brief phase. See `## Profile system` in `docs/operations.md`. |
|
||||
|
||||
Always interactive. Phase 3 is a section-driven completeness loop (no hard cap on question count); Phase 4 runs a `brief-reviewer` stop-gate with max 3 review iterations. After writing the brief, asks the user to choose manual (print commands) or auto (Claude runs research + plan in foreground).
|
||||
|
|
@ -23,7 +23,7 @@ Always interactive. Phase 3 is a section-driven completeness loop (no hard cap o
|
|||
| `--local` | Only codebase analysis agents (skip external + Gemini) |
|
||||
| `--external` | Only external research agents (skip codebase analysis) |
|
||||
| `--fg` | No-op alias (foreground is default since v2.4.0) |
|
||||
| `--gates {open\|closed\|adaptive}` | (v3.4.0) Autonomy-checkpoint policy. Default `adaptive` |
|
||||
| `--gates {true\|false}` | (v3.4.0) Boolean autonomy-gate flag; present → gating on. Policy (`gates_mode`) detailed under `## Autonomy mode` in `docs/operations.md`. |
|
||||
| `--min-brief-version <ver>` | (S18) Warn — never block — if an attached `--project` brief declares a version below `<ver>` (e.g. `2.2`), i.e. sidesteps framing enforcement |
|
||||
| `--profile <name>` | (v4.1.0) Model profile for the research phase. |
|
||||
|
||||
|
|
@ -41,7 +41,7 @@ Flags combine: `--project <dir> --local`, `--external --quick`.
|
|||
| `--min-brief-version <ver>` | (S18) Warn — never block — if the brief declares a version below `<ver>` (e.g. `2.2`), i.e. sidesteps framing enforcement |
|
||||
| `--export <pr\|issue\|markdown\|headless> <plan>` | Generate shareable output from existing plan |
|
||||
| `--decompose <plan>` | Split plan into self-contained headless sessions |
|
||||
| `--gates {open\|closed\|adaptive}` | (v3.4.0) Autonomy-checkpoint policy. Default `adaptive` |
|
||||
| `--gates {true\|false}` | (v3.4.0) Boolean autonomy-gate flag; present → gating on. Policy (`gates_mode`) detailed under `## Autonomy mode` in `docs/operations.md`. |
|
||||
| `--profile <name>` | (v4.1.0) Model profile for the plan phase (and others, since plan emits `profile:` to plan.md frontmatter). |
|
||||
|
||||
**Breaking change (v2.0):** one of `--brief` or `--project` is required. There is no interview inside `/trekplan`. The `--spec` flag has been removed — use `/trekbrief` to produce a brief instead.
|
||||
|
|
@ -60,7 +60,7 @@ If `{project_dir}/architecture/overview.md` exists (typically produced by an opt
|
|||
| `--step N` | Execute only step N |
|
||||
| `--fg` | Force foreground — run all steps sequentially, ignore Execution Strategy |
|
||||
| `--session N` | Execute only session N from plan's Execution Strategy |
|
||||
| `--gates {open\|closed\|adaptive}` | (v3.4.0) Autonomy-checkpoint policy. Default `adaptive` |
|
||||
| `--gates {true\|false}` | (v3.4.0) Boolean autonomy-gate flag; present → gating on. Policy (`gates_mode`) detailed under `## Autonomy mode` in `docs/operations.md`. |
|
||||
| `--profile <name>` | (v4.1.0) Model profile for the execute phase. Inherited from plan.md frontmatter `profile:` if present. |
|
||||
|
||||
## /trekreview modes
|
||||
|
|
|
|||
|
|
@ -4,15 +4,17 @@ Imported from `CLAUDE.md` via pointer.
|
|||
|
||||
## Autonomy mode (`--gates`, v3.4.0)
|
||||
|
||||
All four pipeline commands accept `--gates {open|closed|adaptive}`:
|
||||
All four pipeline commands accept a boolean `--gates {true|false}` flag. Presence (`--gates true`, or bare `--gates`) turns gating **on** — the run pauses at autonomy boundaries for operator confirmation. Absence (or `--gates false`, the default) runs phases continuously without pausing.
|
||||
|
||||
| Value | Behavior |
|
||||
|-------|----------|
|
||||
| `open` | Skip optional checkpoints; trust manifests + verify gates only |
|
||||
| `closed` | Stop at every autonomy boundary; operator confirms each transition |
|
||||
| `adaptive` (default) | Stop only at meaningful boundaries (manifest-audit FAIL, plan-critic BLOCKER, main-merge gate) |
|
||||
`/trekexecute` additionally refines *how strict* the gating is via a `gates_mode` policy derived from the brief's effort signal (an explicit operator `--gates` flag takes precedence over the brief signal — see `commands/trekexecute.md` § High-effort behavior (v5.1.1)):
|
||||
|
||||
Under the hood: `lib/util/autonomy-gate.mjs` runs the state machine `idle → approved → executing → merge-pending → main-merged`. `lib/stats/event-emit.mjs` records each transition to `${CLAUDE_PLUGIN_DATA}/trek*-stats.jsonl`. The main-merge gate is the final autonomy boundary before HEAD lands on `main`.
|
||||
| `gates_mode` | Derived from (effort) | Behavior |
|
||||
|--------------|-----------------------|----------|
|
||||
| `adaptive` | standard / absent (default) | Stop only at meaningful boundaries (manifest-audit FAIL, plan-critic BLOCKER, main-merge gate) |
|
||||
| `closed` | high | Stop at every autonomy boundary; operator confirms each transition |
|
||||
| `open` | low | Skip optional checkpoints; trust manifests + verify gates only |
|
||||
|
||||
Under the hood: `lib/util/autonomy-gate.mjs` runs the state machine `idle → gates_on | auto_running → paused_for_gate → completed`. `start` routes to `gates_on` when `--gates true`, else `auto_running`; a `phase_boundary` from `gates_on` pauses at `paused_for_gate` (awaiting `resume`); `finish` reaches the terminal `completed`. The module is pure data with no I/O. Separately, `lib/stats/event-emit.mjs` records named lifecycle events (`brief-approved`, `main-merge-gate`, `user_input`) to `${CLAUDE_PLUGIN_DATA}/trek*-stats.jsonl`. The main-merge gate is the final autonomy boundary before HEAD lands on `main`.
|
||||
|
||||
### Path A/B/C decision (v3.4.0; Path C closed 2026-05-05)
|
||||
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ import { join, dirname } from 'node:path';
|
|||
import { fileURLToPath } from 'node:url';
|
||||
import { parseDocument } from '../../lib/util/frontmatter.mjs';
|
||||
import { resolveProfile, loadProfile } from '../../lib/profiles/resolver.mjs';
|
||||
import { STATES } from '../../lib/util/autonomy-gate.mjs';
|
||||
|
||||
const HERE = dirname(fileURLToPath(import.meta.url));
|
||||
const ROOT = join(HERE, '..', '..');
|
||||
|
|
@ -375,6 +376,55 @@ test('operations.md custom-profile prose matches findProfilePath resolution orde
|
|||
);
|
||||
});
|
||||
|
||||
// --- S24 — anti-false-claim: operations.md + command-modes.md autonomy-gate truth-pass ---
|
||||
//
|
||||
// autonomy-gate.mjs is a BOOLEAN gate: --gates {true|false} → gates_on|auto_running.
|
||||
// State machine: idle → gates_on|auto_running → paused_for_gate → completed.
|
||||
// The old prose (operations.md:15 / command-modes.md gates rows) (1) fabricated a
|
||||
// state machine `idle → approved → executing → merge-pending → main-merged` — only
|
||||
// `idle` exists in autonomy-gate.mjs STATES; (2) claimed event-emit.mjs "records
|
||||
// each transition" — it emits 3 named lifecycle events and is decoupled from the
|
||||
// (pure, no-I/O) autonomy-gate; (3) advertised `--gates {open|closed|adaptive}` —
|
||||
// open/closed/adaptive is a DERIVED gates_mode policy in the command layer, not a
|
||||
// flag value (the CLI shim + all 4 command docs take boolean `--gates {true|false}`).
|
||||
test('operations.md + command-modes.md describe the real autonomy-gate, not a fabricated one [S24]', () => {
|
||||
const ops = read('docs/operations.md');
|
||||
const modes = read('docs/command-modes.md');
|
||||
|
||||
// F1 — fabricated state names (merge-pending/main-merged are unique to the false claim)
|
||||
for (const bad of ['merge-pending', 'main-merged']) {
|
||||
assert.ok(
|
||||
!ops.includes(bad),
|
||||
`docs/operations.md: fabricated autonomy state "${bad}" — autonomy-gate.mjs has no such state; fix the prose, not this test`,
|
||||
);
|
||||
}
|
||||
|
||||
// F1 — the real transient states (derived from autonomy-gate.mjs STATES) must be documented
|
||||
for (const real of [STATES.GATES_ON, STATES.AUTO_RUNNING, STATES.PAUSED_FOR_GATE]) {
|
||||
assert.ok(
|
||||
ops.includes(real),
|
||||
`docs/operations.md must name the real autonomy-gate state "${real}" (from autonomy-gate.mjs STATES)`,
|
||||
);
|
||||
}
|
||||
|
||||
// F2 — event-emit does NOT record each autonomy-gate transition
|
||||
assert.ok(
|
||||
!ops.includes('records each transition'),
|
||||
'docs/operations.md: event-emit records 3 named lifecycle events, not "each transition" of the (decoupled) autonomy-gate; fix the prose',
|
||||
);
|
||||
|
||||
// F3 — --gates is boolean; open/closed/adaptive is a derived gates_mode policy, not a flag enum
|
||||
const GATES_ENUM_FORMS = ['{open|closed|adaptive}', '{open\\|closed\\|adaptive}'];
|
||||
for (const [label, txt] of [['operations.md', ops], ['command-modes.md', modes]]) {
|
||||
for (const bad of GATES_ENUM_FORMS) {
|
||||
assert.ok(
|
||||
!txt.includes(bad),
|
||||
`docs/${label}: --gates flag enum "${bad}" is false — flag is boolean {true|false}; open/closed/adaptive is a derived gates_mode; fix the prose, not this test`,
|
||||
);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// --- v4.1 Step 21 — pin --profile + phase_models on the 6 commands ---
|
||||
//
|
||||
// CLAUDE.md / README.md pinning is deferred to Step 22 (post-write of
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue