feat(trekbrief): add fable tier option to Phase 3.5 loop
This commit is contained in:
parent
5c37b95dfb
commit
dcc71d9577
3 changed files with 31 additions and 6 deletions
|
|
@ -367,13 +367,14 @@ in the question body so the operator sees why it was picked.
|
||||||
### The loop — 4 tier-coupled AskUserQuestion calls
|
### The loop — 4 tier-coupled AskUserQuestion calls
|
||||||
|
|
||||||
Loop over `[research, plan, execute, review]` in order. For each phase,
|
Loop over `[research, plan, execute, review]` in order. For each phase,
|
||||||
issue one `AskUserQuestion` with 3 options:
|
issue one `AskUserQuestion` with 4 options:
|
||||||
|
|
||||||
| Option | Maps to phase_signals entry |
|
| Option | Maps to phase_signals entry |
|
||||||
|--------|----------------------------|
|
|--------|----------------------------|
|
||||||
| **Low effort** | `{phase: <name>, effort: low, model: sonnet}` |
|
| **Low effort** | `{phase: <name>, effort: low, model: sonnet}` |
|
||||||
| **Standard (default)** | `{phase: <name>, effort: standard}` *(model omitted — composition falls through to profile)* |
|
| **Standard (default)** | `{phase: <name>, effort: standard}` *(model omitted — composition falls through to profile)* |
|
||||||
| **High effort** | `{phase: <name>, effort: high, model: opus}` |
|
| **High effort** | `{phase: <name>, effort: high, model: opus}` |
|
||||||
|
| **Fable (max quality)** | `{phase: <name>, effort: high, model: fable}` |
|
||||||
|
|
||||||
The proposed tier per phase (from the default-derivation heuristic) MUST be
|
The proposed tier per phase (from the default-derivation heuristic) MUST be
|
||||||
labelled `(default)` in the option list so the operator can one-click
|
labelled `(default)` in the option list so the operator can one-click
|
||||||
|
|
@ -384,6 +385,15 @@ The mapping table is canonical:
|
||||||
- `low → {effort: low, model: sonnet}` (force sonnet for the low-cost path)
|
- `low → {effort: low, model: sonnet}` (force sonnet for the low-cost path)
|
||||||
- `standard → {effort: standard}` (model omitted; composition rule resolves via profile)
|
- `standard → {effort: standard}` (model omitted; composition rule resolves via profile)
|
||||||
- `high → {effort: high, model: opus}` (force opus for the high-confidence path)
|
- `high → {effort: high, model: opus}` (force opus for the high-confidence path)
|
||||||
|
- `fable → {effort: high, model: fable}` (force Fable 5 for the max-quality path)
|
||||||
|
|
||||||
|
The fable tier reuses `effort: high` semantics — full swarm, contrarian +
|
||||||
|
gemini always-on; `EFFORT_LEVELS` is unchanged (Voyage effort is orchestration
|
||||||
|
shape, not model reasoning effort). Model reasoning effort is inherited from
|
||||||
|
the session: Fable 5's default effort is `high`, NOT xhigh. To run xhigh, the
|
||||||
|
operator sets it at session level via `/effort xhigh`, the `effortLevel`
|
||||||
|
setting, or `CLAUDE_CODE_EFFORT_LEVEL` — switching model resets effort to the
|
||||||
|
model default, so it does not follow the model.
|
||||||
|
|
||||||
### Force-stop handling
|
### Force-stop handling
|
||||||
|
|
||||||
|
|
@ -891,7 +901,7 @@ Never let stats failures block the workflow.
|
||||||
## Profile (v4.1)
|
## Profile (v4.1)
|
||||||
|
|
||||||
Accepts `--profile <name>` where `<name>` is one of `economy`, `balanced`,
|
Accepts `--profile <name>` where `<name>` is one of `economy`, `balanced`,
|
||||||
`premium`, or a custom profile under `voyage-profiles/`. Default: `premium`.
|
`premium`, `fable`, or a custom profile under `voyage-profiles/`. Default: `premium`.
|
||||||
|
|
||||||
Resolution order (per `lib/profiles/resolver.mjs`):
|
Resolution order (per `lib/profiles/resolver.mjs`):
|
||||||
1. `--profile` flag (source: `flag`)
|
1. `--profile` flag (source: `flag`)
|
||||||
|
|
|
||||||
|
|
@ -17,8 +17,9 @@ source: {interview | manual}
|
||||||
# plan polishing a wrong premise after a rejected iteration).
|
# plan polishing a wrong premise after a rejected iteration).
|
||||||
framing: {preserve | refine | replace | new-direction}
|
framing: {preserve | refine | replace | new-direction}
|
||||||
# v5.1 — per-phase effort + model signal (Phase 3.5).
|
# v5.1 — per-phase effort + model signal (Phase 3.5).
|
||||||
# `effort` ∈ {low, standard, high}. Omit `model:` for `standard` so composition
|
# `effort` ∈ {low, standard, high}; `model` ∈ {sonnet, opus, fable} (v5.9).
|
||||||
# falls through to profile resolver. Force-stop alternative is the commented
|
# Omit `model:` for `standard` so composition falls through to profile
|
||||||
|
# resolver. Force-stop alternative is the commented
|
||||||
# `phase_signals_partial: true` below (mutually exclusive with `phase_signals`).
|
# `phase_signals_partial: true` below (mutually exclusive with `phase_signals`).
|
||||||
phase_signals:
|
phase_signals:
|
||||||
- phase: research
|
- phase: research
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,7 @@ import { dirname, join } from 'node:path';
|
||||||
import { fileURLToPath } from 'node:url';
|
import { fileURLToPath } from 'node:url';
|
||||||
import { resolvePhaseSignal } from '../../lib/profiles/phase-signal-resolver.mjs';
|
import { resolvePhaseSignal } from '../../lib/profiles/phase-signal-resolver.mjs';
|
||||||
import { validateBriefContent, PHASE_SIGNAL_PHASES, EFFORT_LEVELS } from '../../lib/validators/brief-validator.mjs';
|
import { validateBriefContent, PHASE_SIGNAL_PHASES, EFFORT_LEVELS } from '../../lib/validators/brief-validator.mjs';
|
||||||
|
import { BASE_ALLOWED_MODELS } from '../../lib/validators/profile-validator.mjs';
|
||||||
import { parseDocument } from '../../lib/util/frontmatter.mjs';
|
import { parseDocument } from '../../lib/util/frontmatter.mjs';
|
||||||
|
|
||||||
const HERE = dirname(fileURLToPath(import.meta.url));
|
const HERE = dirname(fileURLToPath(import.meta.url));
|
||||||
|
|
@ -84,8 +85,8 @@ test('trekbrief — SC1: each of 4 phases has both effort AND model on full-sign
|
||||||
assert.ok(EFFORT_LEVELS.includes(r.effort),
|
assert.ok(EFFORT_LEVELS.includes(r.effort),
|
||||||
`phase=${phase}: effort "${r.effort}" not in EFFORT_LEVELS`);
|
`phase=${phase}: effort "${r.effort}" not in EFFORT_LEVELS`);
|
||||||
if ('model' in r) {
|
if ('model' in r) {
|
||||||
assert.ok(['sonnet', 'opus'].includes(r.model),
|
assert.ok(BASE_ALLOWED_MODELS.includes(r.model),
|
||||||
`phase=${phase}: model "${r.model}" not in [sonnet, opus]`);
|
`phase=${phase}: model "${r.model}" not in [${BASE_ALLOWED_MODELS.join(', ')}]`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
@ -99,6 +100,19 @@ test('trekbrief — SC1: missing phase_signals + brief_version 2.1 triggers BRIE
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// --- v5.9 — fable tier option in the Phase 3.5 loop ---
|
||||||
|
|
||||||
|
test('trekbrief — v5.9 Phase 3.5 canonical mapping contains the fable row and offers 4 options', () => {
|
||||||
|
const text = read();
|
||||||
|
const startIdx = text.indexOf('## Phase 3.5');
|
||||||
|
assert.ok(startIdx >= 0, 'Phase 3.5 not found');
|
||||||
|
const section = text.slice(startIdx, text.indexOf('## Phase 4', startIdx));
|
||||||
|
assert.ok(section.includes('fable → {effort: high, model: fable}'),
|
||||||
|
'Phase 3.5 canonical mapping must contain the fable tier row');
|
||||||
|
assert.ok(section.includes('with 4 options'),
|
||||||
|
'Phase 3.5 loop must offer 4 options (AskUserQuestion maxItems: 4)');
|
||||||
|
});
|
||||||
|
|
||||||
// --- v5.5 — framing enforcement + TL;DR + memory-alignment prose-pins ---
|
// --- v5.5 — framing enforcement + TL;DR + memory-alignment prose-pins ---
|
||||||
|
|
||||||
test('trekbrief — v5.5 Phase 2.5 framing declaration heading present', () => {
|
test('trekbrief — v5.5 Phase 2.5 framing declaration heading present', () => {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue