Operator runs Ghostty (also iTerm2, modern Terminal.app) — all support
cmd+click on file:// URLs. Producing commands (/trekbrief, /trekplan,
/trekreview) already emit both forms but the contract was implicit.
This commit makes it explicit:
1. CLAUDE.md gains an "Operator-UX guarantee" paragraph stating both
forms must always appear in the final report: (a) plain file://
URL with absolute path (for cmd+click), (b) copy-pasteable
`open file://` command (for terminals without cmd+click).
2. tests/lib/doc-consistency.test.mjs gains a pin asserting both
patterns appear in all three producing commands' final report
blocks. Drift catches at test time.
Non-functional change to the commands themselves — they already
emit both forms (verified at trekbrief.md L510/L519, trekplan.md
L798/L802, trekreview.md L299/L317).
Operator request 2026-05-13: "Noter ned i Voyage at jeg ALLTID får
en slik direkte file:// lenke."
v5.0.0 added a read-only HTML render. v5.0.1 deleted that and pointed at
/playground document-critique, which pre-generates Claude's suggestions
and asks the operator to approve/reject them. The operator asked for the
opposite — a surface where THEY drive every annotation. v5.0.2 lands it.
scripts/annotate.mjs (~430 lines, zero deps) takes any artifact .md and
writes a self-contained HTML next to it. The HTML renders the document
with line numbers, lets the operator click any line to add their own
note (inline textarea, save with Cmd+Enter or button), keeps a sidebar
of all notes (editable + deletable + persisted in localStorage per
artifact path), and exposes Copy Prompt to gather every note into one
structured prompt. Operator copies, pastes back, Claude revises the .md.
The three producing commands now run annotate.mjs at their last step and
print the file:// link with explicit "Click any line to add YOUR OWN note"
instructions. The v5.0.1 /playground document-critique line is gone.
npm test green: 516 tests, 514 pass, 0 fail, 2 skipped.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
The v5.0.0 stop-gap had /trekbrief, /trekplan, and /trekreview each render
a read-only {artifact}.html (via scripts/render-artifact.mjs) AND print a
vague "run the /playground plugin" instruction. In practice the read-only
HTML was redundant with what /playground produces and the instruction
wasn't copy-paste-ready — the operator had to guess the right invocation.
v5.0.1 deletes scripts/render-artifact.mjs + its test + npm run render,
and makes each producing command end with a single boxed, literal,
copy-paste-ready line:
/playground build a document-critique playground for {artifact_path}
One paste from the operator launches the official playground skill's
document-critique template, which builds an interactive HTML — artifact
on the left, per-line Approve/Reject/Comment cards on the right, Copy
Prompt button at the bottom. Mark suggestions, click Copy Prompt, paste
back, Claude revises the .md. Doc-consistency test pins the literal
invocation so the prose cannot soften back into vagueness.
npm test green: 503 tests, 501 pass, 0 fail, 2 skipped.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
The v4.2/v4.3 bespoke playground SPA (~388 KB), the /trekrevise command,
Handover 8 (annotation → revision), the supporting lib/ modules
(anchor-parser, annotation-digest, markdown-write, revision-guard), the
Playwright e2e suite, and the @playwright/test / @axe-core/playwright
devDeps are removed. A browser walkthrough found the playground borderline
unusable, and it duplicated the official /playground plugin's
document-critique / diff-review templates.
In their place: scripts/render-artifact.mjs — a small, zero-dependency
renderer that turns a brief/plan/review .md into a self-contained,
design-system-styled, zero-network .html (frontmatter folded into a
<details> block). /trekbrief, /trekplan, and /trekreview call it on their
last step and print the file:// link; to annotate, run /playground
(document-critique) on the .md and paste the generated prompt back.
Resolves the v4.3.1-deferred findings as moot (their target files are
deleted). npm test green: 509 tests, 507 pass, 0 fail, 2 skipped.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Step 21 of v4.1 — extend-in-place per Plan-critic Blocker 2 split:
commands-only assertions land here; CLAUDE.md / README.md pinning is
deferred to Step 22 (post-write).
Changes:
1. CLAUDE.md command coverage loop now spans all SIX pipeline commands
(added /trekcontinue — was 5 of 6 pre-v4.1 per HIGH risk-assessor).
2. New: every pipeline command-file (trekbrief/research/plan/execute/
review/continue.md) must document the --profile flag.
3. New: forbidden-alias check — no command-file may use the legacy
names model_per_phase / phase_to_model / profile_phase_models.
Canonical name is "phase_models" (locked in brief).
4. New: at least one command-file must mention "phase_models" by name
so the regression detects total removal of the canonical-name
reference.
Tests: 482 pass + 2 skipped (Docker not installed).
Step 3 av v4.1-execute (Wave 1, Session 1).
Legg ny eksportert const OPTIONAL_STRING_KEYS = ['profile_used'] parallel
til eksisterende OPTIONAL_KEYS. Utvid parseManifest med ny dispatch-loop
etter OPTIONAL_BOOLEAN_KEYS. Returnerer MANIFEST_OPTIONAL_TYPE hvis
profile_used finnes men ikke er string.
Forskjell fra OPTIONAL_BOOLEAN_KEYS: absence == not-present (NOT defaulted
til false, unlike boolean). Downstream-konsumenter kan dermed skille mellom
unset og empty-string.
Tester (5 nye, baseline 372 → 377):
- OPTIONAL_STRING_KEYS export drift-pin
- profile_used: economy parses successfully (SC #10 forward-compat)
- profile_used: numeric rejected
- absence: field NOT in parsed (string-key semantics)
- profile_used + skip_commit_check + memory_write co-existence
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Step 11 of v3.4.1 plan. Adds the lifecycle subsection to Handover 7
documenting:
- Producer/consumer arbeidsdeling (executor + helper write; ultracontinue
reads; pre-compact-flush refreshes only)
- Stale-file principle: status==='completed' state files SHOULD be
removed via /ultracontinue-local --cleanup --confirm (operator-invoked,
no auto-cleanup, no force flag)
- Frontmatter contract for NEXT-SESSION-PROMPT.local.md: producers MUST
write produced_by + produced_at (ISO-8601); files without frontmatter
are tolerated (warning, not error) for backwards compatibility
- Idempotency: --cleanup --confirm is safe to re-run; partial state
reported but never auto-recovered
Adds 3 doc-consistency pins:
- next-session-prompt-validator CLI shim
- Handover 7 § Lifecycle subsection present
- Handover 7 § Lifecycle names --cleanup + produced_by contract
358 -> 361 tests, all green.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Step 9 of v3.4.1 plan.
lib/util/cleanup.mjs (new):
- cleanupProject(projectDir, {dryRun, confirm}) reads
.session-state.local.json via validateSessionState; refuses unless the
parsed status is strictly equal to 'completed' (per risk-assessor
Critical 2 — no soft-match on similar statuses).
- Default dryRun: true; refuses dryRun: false without explicit
confirm: true (CLEANUP_REQUIRES_CONFIRM).
- Removes .session-state.local.json + NEXT-SESSION-PROMPT.local.md
candidates; ENOENT counts as "already absent" so the function is
idempotent.
- No CLI shim — invoked from /ultracontinue --cleanup via inline ESM
(Step 10 wires this in).
tests/lib/cleanup.test.mjs (new):
- 7 cases: dry-run lists candidates without deleting; confirm-mode
deletes both files; idempotent re-run signals CLEANUP_NO_STATE_FILE
after fully cleaned; refuses on status: in_progress
(CLEANUP_NOT_COMPLETED); refuses dryRun: false without confirm
(CLEANUP_REQUIRES_CONFIRM); defaults to dry-run; missing state file
returns CLEANUP_NO_STATE_FILE.
Internal scaffolding consumed by Step 10 (Phase 0.5 wire-up). User-facing
docs land with Step 14.
Tests 348 -> 355 (+7).
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Step 1 of v3.4.1 hot-fix plan (project 2026-05-04-v3.3.1-ultracontinue-fixes).
Adds ultracontinue entry to FLAG_SCHEMA covering boolean flags --help,
--cleanup, --confirm, --dry-run with no valued flags. The -h short form
is intentionally not aliased: it appears as positional[0] === '-h' and
the command prose dispatches usage on either condition.
7 new tests in tests/lib/arg-parser.test.mjs verify empty args, --help,
-h positional, --cleanup, --cleanup --confirm, project-dir positional,
and .md positional (parser-level accept; command-level reject).
Wire the main-merge-gate lifecycle event into commands/ultraexecute-local.md
Phase 8. Three event variants emitted via lib/stats/event-emit.mjs (S8):
- main-merge-gate fired at the gate boundary
- main-merge-approved fired on operator confirm
- main-merge-declined fired on operator decline (run recorded as partial)
The gate ALWAYS pauses regardless of gates_mode — it is the one always-on
boundary that --gates does not toggle. On decline, --resume re-enters at
the gate, and the wave session branches survive on the remote thanks to
Hard Rule 19's push-before-cleanup. Recovery surface is documented inline.
Pin in tests/lib/main-merge-gate.test.mjs locks the always-on prose, the
event names, and the recovery-surface contract.
Single autonomy-control surface (--gates) added to ultrabrief, ultraresearch,
ultraplan, and ultraexecute. When present, sets gates_mode = true and
re-enables approval pauses at every phase boundary + every wave for
high-stakes runs. When absent (default in auto), the chain runs continuously
to the main-merge gate (which always pauses regardless of --gates — that
boundary is the one always-on safety stop).
ultrabrief: pause after auto-mode confirmation; emit brief-approved event
ultraresearch: pause after each topic completes
ultraplan: pause after Phases 5, 7, 9
ultraexecute: pause after each wave's worktrees finish, before merge-back,
AND before the main-merge gate (MAIN_MERGE_GATE)
All four commands invoke the autonomy-gate state machine via the CLI shim
node lib/util/autonomy-gate.mjs (built in S8). Test pin in
tests/lib/gates-flag-coverage.test.mjs locks the contract.
Also wires the brief-approved stats emission into ultrabrief Phase 5 auto
path (was the SC4 wiring requirement from plan-v2 Step 11).
Bring the launch template (used by /ultraplan-local --decompose) into
contract-parity with the Phase 2.6 wave executor hardenings shipped in the
previous commit:
- GIT_OPTIONAL_LOCKS=0 exported once at the top
- MAX_TURNS / MAX_BUDGET_USD env-overridable (default 50 / 5)
- Absolute SHARED_CONTEXT_FILE built from brief + architecture
- SAFETY_PREAMBLE prepended to every per-session prompt (GH #36071 +
GH #52272 clarifications)
- Per-child --max-turns + --max-budget-usd + --append-system-prompt-file
- push-before-cleanup before merge AND in the cleanup_worktrees trap
- Three new template rules (16, 17, 18, 19) document the contract for
session-decomposer
Pin in tests/lib/doc-consistency.test.mjs locks all required substrings
against future regressions.
Strengthen single-message reinforcement for plan-critic + scope-guardian
parallel dispatch in commands/ultraplan-local.md Phase 9 and mirror in
agents/planning-orchestrator.md Phase 6. Reviewers now write structured JSON
to /tmp/{plan-critic,scope-guardian}-out.json which is merged via the
lib/review/plan-review-dedup.mjs CLI shim from S8.
The merged set lets us revise the plan once for duplicate findings instead
of twice. Source: research/05 R1 + R2.
Pin in tests/lib/doc-consistency.test.mjs locks both files against
single-message + dedup-helper regressions.
Inline STEP_HEADING_REGEX, FORBIDDEN_HEADING_REGEX, the canonical step+manifest
example, and the post-write plan-validator self-check directly into Phase 8 of
commands/ultraplan-local.md. This eliminates the dependency on Opus 4.7
implicitly loading agents/planning-orchestrator.md — the format contract now
travels with the command file itself.
Source: research/04 D5 + plan-v2 Step 7. Pin in tests/lib/doc-consistency.test.mjs
locks the substrings so future edits cannot silently regress the seal.
Pin the contract from plan-v2 Steps 1-3: every agents/*.md must declare
model: (opus|sonnet|haiku) AND (tools: or disallowedTools:). Orchestrators
(planning/research/review) must be opus and include the Agent tool;
non-orchestrators must not include Agent (no recursive swarming).
23 agents in scope; 5 pinning tests.
[skip-docs]
Three changes in one commit:
1. NEW lib/util/atomic-write.mjs — exports atomicWriteJson(path, obj),
the canonical tmp+rename pattern. Reused by pre-compact-flush.mjs and
(in subsequent steps) by the new session-state writer.
2. NEW tests/lib/atomic-write.test.mjs — 4 unit tests covering
round-trip, no-orphan-tmp, overwrite-atomic, pretty-print formatting.
3. REFACTOR hooks/scripts/pre-compact-flush.mjs — replace the inline
atomicWrite() with the imported atomicWriteJson(). Also fixes a
pre-existing syntax error (leading whitespace + stray --resume token
outside the comment block) that silently broke the hook from v3.1.0
onward — PreCompact runtime is fail-open and swallowed the error.
File reformatted with standard zero-indent JS.
163 → 167 tests, 0 fail.
Step 2 of /ultracontinue v3.3.0 (project 2026-05-01-ultracontinue).
Synthetic plan.md fixture with source_findings: block-style YAML list of 3
40-char hex IDs in frontmatter, plus minimal plan structure (Title +
Implementation Plan + 1 Step + Manifest). 3 tests verify:
1. plan-validator accepts a plan with source_findings (additive optional field)
2. frontmatter parser extracts source_findings as array of strings
3. each ID matches the 40-char lowercase hex format from finding-id.mjs
Closes the SC3(b) gap flagged by adversarial review (scope-guardian Gap 2).
LLM-level behavior (planner emitting source_findings) remains non-testable
without live invocation; this covers the structural contract.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
3 integration tests using the run-A/run-B fixtures:
- Jaccard(A, B) ≥ 0.70 (SC4 brief threshold)
- IDs match 40-char hex shape (lib/parsers/finding-id.mjs format)
- no duplicate IDs within a single run
Tests the Jaccard PIPELINE; real-LLM determinism deferred to v1.1.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Modify "all four pipeline commands" → "all five" (adds /ultrareview-local).
Add 3 new pins: Handover 6 section in HANDOVER-CONTRACTS.md,
review-validator CLI shim, rule-catalogue 12-key size invariant.
11/11 doc-consistency tests pass.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Step 1 of v2.0 plan. Hard cut from commands/ to skills/ per Anthropic
recommendation for new plugins. Frontmatter sets disable-model-invocation:
true and pins model: claude-sonnet-4-6. Docs (README, CLAUDE.md, root
README) deferred to Step 9 per plan.