fix(docs): the deep-research merge and engine condition are stated and the research prose is pinned exactly

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

View file

@ -823,7 +823,7 @@ flowchart TB
BR --> RES --> PL --> EX --> RV BR --> RES --> PL --> EX --> RV
``` ```
`* = conditional`: convention-scanner / test-strategist on medium+ codebases (50+ files); research-scout for unknown external tech; contrarian-researcher, when selected, runs in wave 2 after wave 1 returns, with the leading answer of wave 1's external findings to attack (with `--engine deep-research`, after the engine returns, from the leading answer of its report), always at `effort=high`; brief-conformance-reviewer skipped under `--quick`. `* = conditional`: convention-scanner / test-strategist on medium+ codebases (50+ files); research-scout for unknown external tech; contrarian-researcher, when selected, runs in wave 2 after wave 1 returns, with the leading answer of wave 1's external findings to attack (with `--engine deep-research`, when the engine is active, after the engine returns, from the leading answer of its report), always at `effort=high`; brief-conformance-reviewer skipped under `--quick`.
> **Which Claude Code primitive each phase uses — and the alternatives considered (Workflow substrate, delegated orchestrator, dormant synthesis-agent)** → see [docs/architecture.md §Primitives per step](docs/architecture.md#primitives-per-step-decision-matrix). > **Which Claude Code primitive each phase uses — and the alternatives considered (Workflow substrate, delegated orchestrator, dormant synthesis-agent)** → see [docs/architecture.md §Primitives per step](docs/architecture.md#primitives-per-step-decision-matrix).

View file

@ -762,7 +762,10 @@ raw report. Specifically:
- Reduce the report to ≥ 1 `### {Dimension} -- Confidence: {high|medium|low|contradictory}` - Reduce the report to ≥ 1 `### {Dimension} -- Confidence: {high|medium|low|contradictory}`
entry, each carrying **External findings** bullets with per-claim source URLs. entry, each carrying **External findings** bullets with per-claim source URLs.
Local findings still come from the local agents (Phase 4) and are merged in per Local findings still come from the local agents (Phase 4) and are merged in per
dimension as usual. dimension as usual. Wave 2's `contrarian-researcher` findings (Launch rules)
are not part of the report: they are merged in per dimension as **External
findings**, cited by URL like the report's, and where one disputes the
report's leading answer, the dimension's **Contradictions** gives both sides.
- Emit a numeric `confidence ∈ [0,1]` in frontmatter and a 3-sentence - Emit a numeric `confidence ∈ [0,1]` in frontmatter and a 3-sentence
`## Executive Summary` (answer, confidence, key caveat). `## Executive Summary` (answer, confidence, key caveat).
- Populate `## Sources` from the report's citations. - Populate `## Sources` from the report's citations.

View file

@ -106,4 +106,48 @@ run_tagged "$TMP/base.jsonl" --test-timeout=300000 --test-force-exit $PATS`,
}, },
], ],
}, },
{
key: 'E17a',
id: 'E17a',
what: 'the two wave 2 sentences on outbound queries are deleted from /trekresearch',
spans: [
{
file: 'commands/trekresearch.md',
find: `It searches with the words it is given, so no
local file name or project term may be in them. `,
replace: '',
},
{
file: 'commands/trekresearch.md',
find: `When wave 1's external
findings hold no leading answer, say so and give it the research question
alone, stripped the same way. `,
replace: '',
},
],
},
{
key: 'E18a',
id: 'E18a',
what: 'the summary-only triage row of /trekreview gains .claude/rules/**',
spans: [
{
file: 'commands/trekreview.md',
find: '| `summary-only` | `docs/**`, Markdown files at the repo root other than `CLAUDE.md` and `AGENTS.md` (README, CHANGELOG), `tests/fixtures/**`. |',
replace: '| `summary-only` | `docs/**`, Markdown files at the repo root other than `CLAUDE.md` and `AGENTS.md` (README, CHANGELOG), `tests/fixtures/**`, `.claude/rules/**`. |',
},
],
},
{
key: 'Db',
id: 'Db',
what: 'a security-researcher* star is added to the README agent list, outside the diagram line',
spans: [
{
file: 'README.md',
find: '4 external agents (docs-researcher, community-researcher, security-researcher, contrarian-researcher)',
replace: '4 external agents (docs-researcher, community-researcher, security-researcher*, contrarian-researcher)',
},
],
},
]; ];

View file

@ -20,7 +20,7 @@
| schema_id | fields | writer_path | line_ref | v4.1 additive | PII | | 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 | | 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:826-859 | 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:829-862 | 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 | | 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 (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 | | 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

@ -1414,7 +1414,7 @@ test('[#113] no conditional trigger is left, and high effort keeps contrarian-re
test('[#113] sibling: README.md', () => { test('[#113] sibling: README.md', () => {
const text = flat(read('README.md')); const text = flat(read('README.md'));
assert.doesNotMatch(text, /contrarian-researcher when a leading recommendation forms/); assert.doesNotMatch(text, /contrarian-researcher when a leading recommendation forms/);
assert.ok(text.includes('contrarian-researcher, when selected, runs in wave 2 after wave 1 returns, with the leading answer of wave 1\'s external findings to attack (with `--engine deep-research`, after the engine returns, from the leading answer of its report), always at `effort=high`;'), assert.ok(text.includes('contrarian-researcher, when selected, runs in wave 2 after wave 1 returns, with the leading answer of wave 1\'s external findings to attack (with `--engine deep-research`, when the engine is active, after the engine returns, from the leading answer of its report), always at `effort=high`;'),
'README.md does not describe wave 2'); 'README.md does not describe wave 2');
}); });
@ -1823,7 +1823,7 @@ test('found in execution: README.md lists security-researcher as no conditional
test('found in execution: README.md names the deep-research case of wave 2', () => { test('found in execution: README.md names the deep-research case of wave 2', () => {
const text = conditionalLine(); const text = conditionalLine();
assert.ok(text.includes('contrarian-researcher, when selected, runs in wave 2'), `the conditional line does not name wave 2: ${text}`); assert.ok(text.includes('contrarian-researcher, when selected, runs in wave 2'), `the conditional line does not name wave 2: ${text}`);
assert.ok(text.includes('contrarian-researcher, when selected, runs in wave 2 after wave 1 returns, with the leading answer of wave 1\'s external findings to attack (with `--engine deep-research`, after the engine returns, from the leading answer of its report), always at `effort=high`;'), `README.md does not name the deep-research case of wave 2: ${text}`); assert.ok(text.includes('contrarian-researcher, when selected, runs in wave 2 after wave 1 returns, with the leading answer of wave 1\'s external findings to attack (with `--engine deep-research`, when the engine is active, after the engine returns, from the leading answer of its report), always at `effort=high`;'), `README.md does not name the deep-research case of wave 2: ${text}`);
}); });
test('found in execution: README.md runs contrarian-researcher after wave 1 returns', () => { test('found in execution: README.md runs contrarian-researcher after wave 1 returns', () => {

View file

@ -33,6 +33,13 @@
// `auto_result: manual`. // `auto_result: manual`.
// K2 /trekbrief's Step 6a "Cancel — do manual" row runs Phase 7 with // K2 /trekbrief's Step 6a "Cancel — do manual" row runs Phase 7 with
// `auto_result: cancelled`, like the sentence after the table. // `auto_result: cancelled`, like the sentence after the table.
// E17a The two /trekresearch wave 2 sentences on outbound queries are pinned
// exactly (red under the E17a mutation).
// E17b The deep-research adapter says where wave 2's contrarian findings merge.
// Da The README deep-research parenthesis says "when the engine is active".
// E18a The F9 deep-review and summary-only rows are pinned exactly (red under
// the E18a mutation).
// Db No README line stars security-researcher (red under the Db mutation).
// No static import of a new export: the file must load at be0b631. // No static import of a new export: the file must load at be0b631.
// Fix the SOURCE a pin guards, not the pin. // Fix the SOURCE a pin guards, not the pin.
@ -349,3 +356,55 @@ test('[DJ2] the high-effort loop names the model for a turn that spawns', () =>
`the per-turn protocol does not say a turn that spawns passes model: phase_signal_result.model, else opus: ${hits.join(' | ')}`); `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"'); assert.doesNotMatch(loop, /model: "opus"/, 'the per-turn protocol pins a spawn to model: "opus"');
}); });
// --- E17a / E17b / Da / E18a / Db --------------------------------------------------
// E17a, E18a and Db are already right at be0b631; their tests are proven red
// under the E17a, E18a and Db entries of tests/fix-round-4-5b-mutations.mjs.
const LAUNCH = () => between('commands/trekresearch.md', '### Launch rules', '- Inject the resolved model at every spawn');
test('[E17a] the outbound-query sentence on local names is pinned', () => {
const hits = sentencesWith(LAUNCH(), 'It searches with the words it is given');
assert.deepEqual(hits, ['It searches with the words it is given, so no local file name or project term may be in them.'],
'the wave 2 rule no longer says the contrarian searches with the words it is given, so no local name may be in them');
});
test('[E17a] the no-leading-answer sentence is pinned', () => {
const hits = sentencesWith(LAUNCH(), 'no leading answer');
assert.deepEqual(hits, ['When wave 1\'s external findings hold no leading answer, say so and give it the research question alone, stripped the same way.'],
'the wave 2 rule no longer says what to give the contrarian when wave 1 holds no leading answer');
});
test('[E17b] the adapter says where wave 2\'s contrarian findings merge', () => {
const adapter = between('commands/trekresearch.md', '### Deep-research engine adapter (engine = deep-research only)', '### Output self-check');
const hits = sentencesWith(adapter, '`contrarian-researcher`');
assert.ok(hits.some((s) => /^Wave 2's `contrarian-researcher` findings\b/.test(s)
&& /\bmerged in per dimension as \*\*External findings\*\*/.test(s)
&& /\bthe dimension's \*\*Contradictions\*\* gives both sides\b/.test(s)),
`the deep-research adapter does not say wave 2's contrarian findings merge per dimension as External findings, with disputes under Contradictions: ${hits.join(' | ')}`);
});
test('[Da] the README parenthesis says when the engine is active', () => {
const text = oneLine('README.md', '`* = conditional`:', 'contrarian-researcher');
assert.ok(text.includes('(with `--engine deep-research`, when the engine is active, after the engine returns, from the leading answer of its report)'),
`the README deep-research parenthesis does not say "when the engine is active": ${text}`);
});
test('[E18a] the F9 deep row and summary-only row equal their text exactly', () => {
const p4 = between('commands/trekreview.md', '## Phase 4 — Triage gate', '## Phase 4.5 — ');
const row = (cell) => {
const rows = p4.split('\n').filter((l) => l.startsWith(`| ${cell} |`));
assert.equal(rows.length, 1, `Phase 4 must hold exactly one ${cell} row; found ${rows.length}`);
return rows[0];
};
assert.equal(row('`deep-review`'), '| `deep-review` | Default for every changed file not in the other two rows — code, tests, `commands/`, `agents/`, `skills/` Markdown, and the instruction files `CLAUDE.md`, `AGENTS.md` and `.claude/rules/**`. |',
'the deep-review triage row is not the F9 text');
assert.equal(row('`summary-only`'), '| `summary-only` | `docs/**`, Markdown files at the repo root other than `CLAUDE.md` and `AGENTS.md` (README, CHANGELOG), `tests/fixtures/**`. |',
'the summary-only triage row is not the F9 text');
});
test('[Db] the README stars security-researcher nowhere', () => {
const readme = read('README.md');
assert.match(readme, /security-researcher/, 'README.md names security-researcher nowhere');
assert.doesNotMatch(readme, /security-researcher\*/, 'a README line stars security-researcher as conditional');
});