fix(commands): the trekplan execute exits run Phase 12 and the research loop names its model

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Kjell Tore Guttormsen 2026-10-26 16:40:24 +01:00
commit 4b59ec7f16
Signed by: ktg
SSH key fingerprint: SHA256:JakMjO6FTBBzN0Bhfj9saOoEjaFxlSdYuZQQpM/lF9Q
5 changed files with 36 additions and 6 deletions

View file

@ -1295,14 +1295,14 @@ Confirm the plan and brief file locations and exit.
Do not implement in this session. Print the line the operator gives
`/trekexecute` — `/trekexecute --project {project_dir}`, or
`/trekexecute {plan_path}` without a project directory — and stop.
`/trekexecute {plan_path}` without a project directory — then run Phase 12 (`outcome: execute`).
`/trekexecute` is what checks the plan's approval (K2), locks the tests, runs
one step helper per step and the review.
### "execute with team" / "team"
There is no team path. Print the same `/trekexecute` line and stop; parallel
work is `--decompose` followed by `/trekexecute`'s session orders.
There is no team path. Print the same `/trekexecute` line, then run Phase 12
(`outcome: execute_team`); parallel work is `--decompose` followed by `/trekexecute`'s session orders.
## Phase 12 — Session tracking

View file

@ -648,6 +648,10 @@ reformulated, not forced through. A gate that *could not run* is neither — no
rewrite can clear it, so treat it as a hard stop and say so, rather than
rewriting a query that was never the problem.
A turn that spawns an agent passes `model: phase_signal_result.model`, else
`opus` — the agent may be one of Claude Code's built-in agents, which have no
Voyage frontmatter to fall back to; see Launch rules.
**Empty turns.** A turn that returns no findings, or findings without
citations, is marked `empty`. An empty turn is counted in `empty_turns` and
does NOT re-target the same dimension — re-asking the same question of the

View file

@ -20,7 +20,7 @@
| schema_id | fields | writer_path | line_ref | v4.1 additive | PII |
|-----------|--------|-------------|----------|---------------|-----|
| trekbrief-stats | ts, task, slug, mode, interview_turns, review_iterations, brief_quality, research_topics, auto_research, auto_result, intent_approved, project_dir, order_id, order_claimed_at, order_reason | commands/trekbrief.md (orchestrator-emit Phase 7; order_* added by lib/stats/stats-append.mjs) | trekbrief.md:1141-1165 | profile, phase_models, profile_source | none |
| trekresearch-stats | ts, question, mode, scope, engine, slug, project_dir, brief_path, dimensions, dimensions_baseline, dimensions_baseline_preserved, effort, conv_turns, empty_turns, unique_sources, agents_local, agents_external, gemini_used, confidence, contradictions, open_questions | lib/stats/stats-append.mjs (trekresearch.md Stats tracking) | trekresearch.md:822-855 | profile, phase_models, parallel_agents, external_research_enabled, profile_source | none |
| trekresearch-stats | ts, question, mode, scope, engine, slug, project_dir, brief_path, dimensions, dimensions_baseline, dimensions_baseline_preserved, effort, conv_turns, empty_turns, unique_sources, agents_local, agents_external, gemini_used, confidence, contradictions, open_questions | lib/stats/stats-append.mjs (trekresearch.md Stats tracking) | trekresearch.md:826-859 | profile, phase_models, parallel_agents, external_research_enabled, profile_source | none |
| trekplan-stats | ts, task, mode, slug, brief_path, project_dir, codebase_size, codebase_files, agents_deployed, deep_dives, research_briefs_used, research_scout_used, critic_verdict, guardian_verdict, outcome | lib/stats/stats-append.mjs (trekplan.md Phase 12) | trekplan.md:1307-1335 | profile, phase_models, parallel_agents, profile_source | none |
| trekexecute-stats (Phase 9 record) | ts, plan, plan_type, mode, result, steps_total, steps_passed, steps_failed, steps_skipped, failed_at_step | lib/stats/stats-append.mjs (trekexecute.md Phase 9) | trekexecute.md:2973-2995 | profile, phase_models, profile_source | none |
| trekexecute-stats (autonomy events) | ts, event, known_event, payload | lib/stats/event-emit.mjs `emit()` | event-emit.mjs:78-99 | payload.profile, payload.phase_models, payload.profile_source | none |

View file

@ -337,7 +337,7 @@ test('[#52] Phase 11 "execute": prints the /trekexecute line and stops, never im
neverImplementsHere(block, 'Phase 11 "execute"');
assert.match(block, /^### "execute" \/ "go" \/ "start" Do not implement in this session\./);
printsTrekexecuteLine(block, 'Phase 11 "execute"');
assert.match(block, /without a project directory — and stop\./);
assert.match(block, /without a project directory — then run Phase 12 \(`outcome: execute`\)\./);
assert.match(block, /`\/trekexecute` is what checks the plan's approval \(K2\), locks the tests, runs one step helper per step and the review\./);
});
@ -345,7 +345,7 @@ test('[#52] Phase 11 "team": no team path, the same /trekexecute line, then stop
const block = flat(section(read('commands/trekplan.md'), '### "execute with team" / "team"'));
neverImplementsHere(block, 'Phase 11 "team"');
assert.doesNotMatch(block, /proceed exactly as for "execute"/, 'Phase 11 "team": still proceeds as "execute" did');
assert.match(block, /There is no team path\. Print the same `\/trekexecute` line and stop; parallel work is `--decompose` followed by `\/trekexecute`'s session orders\./);
assert.match(block, /There is no team path\. Print the same `\/trekexecute` line, then run Phase 12 \(`outcome: execute_team`\); parallel work is `--decompose` followed by `\/trekexecute`'s session orders\./);
});
test('[#52] Phase 10 menu: "execute" is for the /trekexecute line, and a stopped gate withholds it', () => {

View file

@ -323,3 +323,29 @@ test('[K2] the 6a row names Phase 7 with auto_result cancelled', () => {
assert.match(flat(step6a), /If cancelled → fall back to manual path output, run Phase 7 \(`auto_result: cancelled`\) and stop\./,
'the sentence after the 6a table no longer names Phase 7 with auto_result cancelled');
});
// --- DJ1 / DJ2 ---------------------------------------------------------------------
const TREKPLAN = 'commands/trekplan.md';
test('[DJ1] the execute and team exits run Phase 12', () => {
const execute = flat(between(TREKPLAN, '### "execute" / "go" / "start"', '### "execute with team" / "team"'));
assert.match(execute, /`\/trekexecute \{plan_path\}` without a project directory — then run Phase 12 \(`outcome: execute`\)\./,
`the "execute" exit does not run Phase 12 with outcome execute: ${execute}`);
assert.doesNotMatch(execute, /\band stop\b/, `the "execute" exit still ends in a bare "and stop": ${execute}`);
const team = flat(between(TREKPLAN, '### "execute with team" / "team"', '## Phase 12 — Session tracking'));
assert.match(team, /There is no team path\. Print the same `\/trekexecute` line, then run Phase 12 \(`outcome: execute_team`\);/,
`the "team" exit does not run Phase 12 with outcome execute_team: ${team}`);
assert.doesNotMatch(team, /\band stop\b/, `the "team" exit still ends in a bare "and stop": ${team}`);
const p12 = between(TREKPLAN, '## Phase 12 — Session tracking', '## Profile');
assert.ok(p12.includes('"outcome": "{execute|execute_team|save|refine}"'),
'Phase 12 no longer holds the outcome enum the two exits name');
});
test('[DJ2] the high-effort loop names the model for a turn that spawns', () => {
const loop = between('commands/trekresearch.md', '### Per-turn protocol', '### Exits (all three, always one of them)');
const hits = sentencesWith(loop, 'spawns');
assert.ok(hits.some((s) => /^A turn that spawns an agent passes `model: phase_signal_result\.model`, else `opus`/.test(s)),
`the per-turn protocol does not say a turn that spawns passes model: phase_signal_result.model, else opus: ${hits.join(' | ')}`);
assert.doesNotMatch(loop, /model: "opus"/, 'the per-turn protocol pins a spawn to model: "opus"');
});