voyage/docs/T2-cc27-workflow-substrate.md
Kjell Tore Guttormsen b5f3d4a932 docs(voyage): S8 (W1/CC-27 gate) — T2 Workflow-substrate probe + measurement design
Second W1 gate, same staged execution as S7 (operator-chosen): cheap live
feasibility probe + design doc; the prose-vs-Workflow bake-off specified but
NOT run.

Probe (CC 2.1.181 interactive): a minimal trekreview-shaped Workflow —
parallel([reviewerA, reviewerB]) with a findings schema -> agent(coordinator)
with a verdict schema — ran end-to-end. F1 core ports natively; F2 structured
schemas retire the JSON-parse fragility at trekreview.md:202-204; F3 result
returns to main; F4 a small purposeful fan-out did NOT trip the S7 proliferation
classifier. 3 agents / 85461 tokens / 13.8s.

Reframe: 'substrate swap' is a false binary — a /trek* command is ~80%
non-orchestration glue, so Workflow can only replace the fan-out->synthesize
core (hybrid).

CC-27 recommendation (operator gates verdict): selective hybrid, NOT wholesale
swap. Tier 1 ship a prose schema contract (the F2 win, no Workflow dep); tier 2
port trekreview Phase 5-6 to a Workflow only if the designed bake-off shows
fidelity-equivalent output + acceptable control/cost; tier 3 wholesale swap
declined (portability floor 2.1.154+, opt-in UX, mid-flow visibility loss).
Open risk inherited from S7: classifier at large fan-out under auto/bypass
still unverified.

New: docs/T2-cc27-workflow-substrate.md (gate evidence F0-F4 + bake-off design
with thresholds + no-Workflow schema-contract PoC). Matrix: CC-27 row +
S8 resolutions + open-question/T2 pointers updated. Docs-only; no code/schema.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LqBYc8Ltrk7LipyJmGxXiB
2026-06-18 13:34:05 +02:00

240 lines
17 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# T2 — Workflow tool as orchestration substrate (CC-27 GATE)
**Status:** Gate evidence + measurement design + recommendation. The adopt/don't-adopt
verdict for CC-27 is **operator-gated** (mirrors S3/S6/S7).
**Date:** 2026-06-18 (S8)
**Resolves:** decision-matrix §W1 / **CC-27** ("does Voyage adopt the Workflow tool as its
execution substrate, or stay prose-orchestrated?") + Empirical test **T2**.
**Inputs:** `docs/cc-upgrade-2.1.181-decision-matrix.md` §W1 / CC-27, `commands/trekreview.md`
(Phases 56, the prototype target), `docs/T1-cc26-delegated-orchestration.md` §4 (the S7
proliferation-classifier handoff), the Workflow-tool reference (CC 2.1.154+).
**Method (this session, operator-chosen):** staged — cheap live feasibility probe + this design
doc; the expensive head-to-head bake-off is **specified but NOT run** (see §5), gated on the
recommendation below. Same shape as S7.
---
## 1. The question the gate actually decides
CC-27: Voyage **hand-rolls** its swarm / wave / pipeline orchestration in command prose — the main
session reads a `/trek*` command, interprets its phase prose, and spawns agents via the Agent tool
itself. The Workflow tool (2.1.154+) is a native primitive for exactly this: a JS-scripted
orchestrator with `parallel()` / `pipeline()` / `agent({schema})`, background execution, budget
control, and resume/journaling.
The decision is framed as the **biggest identity choice**: adopt Workflow as Voyage's execution
substrate, or stay prose-orchestrated for portability and fine-grained control? But that framing is
a trap — see §2.
## 2. Reframing: "substrate swap" is a false binary; the axis is selective hybrid
The decision-relevant axis is **not** "all-Workflow vs all-prose." It is **"does wrapping a
fan-out→synthesize *core* in a Workflow call earn its keep, against the portability / opt-in /
in-transcript-visibility costs?"** — measured per core, not per pipeline.
Why the binary is false, using `/trekreview` (the named prototype) as the worked example:
- A `/trek*` command is **~80% non-orchestration glue** and **~20% agent fan-out.** trekreview's
450 lines are: mode parsing (Phase 1), brief validation (Phase 2), SHA-range discovery (Phase 3),
a deterministic path-pattern triage classifier (Phase 4), the strict validator + repair-in-place
+ stats JSONL + HTML annotation (Phase 8), and validate-only mode (Phase 8.5). The Workflow tool
addresses **none** of that — it orchestrates *agents*, not bash calls, file writes, validators,
and operator-facing HTML.
- The part Workflow actually replaces is **Phase 5 (parallel reviewers) + Phase 6 (coordinator
synthesis)** — the clean fan-out→barrier→synthesize core. That is the 20%.
- So "adopt Workflow as substrate" can only ever mean **embed a Workflow call for the core, keep
prose for the glue** — i.e. a *hybrid*, not a substrate swap. The honest question is therefore
scoped: is the hybrid worth it for *this core*?
This mirrors the S7 reframing of CC-26 ("wall-time is not the gate metric; Δ main-context tokens
is"). For CC-27 the reframe is: **the gate metric is output-fidelity-preserving control/cost on a
single clean-barrier core, not a wholesale substrate identity.**
The trekreview core, for reference (the shape that gets ported):
```
Phase 5: [ brief-conformance-reviewer ∥ code-correctness-reviewer ] parallel fan-out
↓ merge findings arrays
Phase 6: review-coordinator (dedup → HubSpot Judge → Cloudflare reasonableness → verdict)
Phase 7: write review.md ← stays prose (file I/O, atomic write, frontmatter rules)
```
## 3. Feasibility probe (RUN — 2026-06-18, CC 2.1.181, interactive session)
**Goal:** isolate the *mechanism + semantics* (does the fan-out→synthesize shape execute and return
to main? do structured schemas remove the JSON-parse fragility? does the S7 proliferation classifier
bite a Workflow fan-out? is the tool even invocable here?) from the *workload* (real reviewers on a
real diff — deferred to §5). A minimal trekreview-shaped Workflow: `parallel([reviewerA, reviewerB])`
with a findings schema → `agent(coordinator)` with a verdict schema, run on a one-line synthetic
input, trivial agents, no file reads.
**Verbatim result (Workflow return value, surfaced to main via task-notification):**
```json
{
"reviewers_returned": 2,
"merged_findings_count": 2,
"sample_findings": [
{"file":"foo.js","line":10,"rule_key":"SC_UNTRACED","severity":"MAJOR"},
{"file":"foo.js","line":10,"rule_key":"ERR_UNGUARDED_PARSE","severity":"MAJOR"}
],
"verdict": {"verdict":"BLOCK","deduped_count":2,
"note":"Two distinct findings at foo.js:10 — rule_keys differ, so the dedup key
(file,line,rule_key) keeps both. … verdict BLOCK on the conservative
interpretation that one or more MAJOR findings remain unresolved."}
}
```
_Usage: 3 agents · 85 461 tokens · 13.8 s wall._
**Findings (measured):**
| # | Finding | Evidence | Decision impact |
|---|---------|----------|-----------------|
| F0 | **The Workflow tool is invocable here without a hard opt-in block.** | Launch returned a task ID; the operator's STATE directive (S8 = "reimplement the trekreview swarm as one Workflow") satisfied the opt-in gate. | The opt-in/billing gate is real but a command/operator directive **can** satisfy it. The general UX question (does every `/trekreview` invocation cleanly count as opt-in?) is unresolved — §4. |
| F1 | **The fan-out→barrier→synthesize core executes end-to-end.** Both parallel reviewers returned; the synthesizer ran on the merged result. | `reviewers_returned: 2`; the coordinator produced a verdict over both. | trekreview Phase 5→6 ports **natively** to `parallel()``agent()`. The shape is a 1:1 fit. |
| F2 | **Structured-output schemas remove the JSON-parse fragility.** Findings returned as typed, validated objects — no "collect trailing JSON block / `JSON.parse` / re-ask on error" dance. | `sample_findings` are schema-shaped `{file,line,rule_key,severity}`; no parse step in the script. | **The single most concrete win.** Directly retires the fragile contract at `commands/trekreview.md:202204`. Validation+retry happens at the tool layer. |
| F3 | **The finished artifact returns to main as structured JSON.** | The notification `<result>` carried the full return object; main received the digest, not a transcript to re-parse. | Main gets a clean handoff — but only the *final* object (see F4-control). |
| F4 | **A small purposeful fan-out did NOT trip the S7 proliferation classifier.** | 2-way fan-out + 1 synthesizer ran with zero denials; contrast S7's *purposeless recursive* chain, which the auto-mode classifier denied at L2→L3. | For trekreview specifically (23 agents) the classifier risk is **low**. The classifier's behavior at *large* Workflow fan-out (trekplan's 610-agent swarm) under `auto`/`bypass` remains **unverified** — same caveat shape as S7. |
> Verifiseringsplikt: F0F4 are *measured* from the probe above. The probe used trivial agents and a
> small (2-way) purposeful fan-out in an interactive session. It does **not** establish (a) classifier
> behavior for a large fan-out under auto/bypass, (b) output fidelity against a *real* diff, or (c)
> token cost at production context size — all deferred to §5. What it establishes is mechanism,
> schema-robustness, return-to-main, and small-scale classifier tolerance.
## 4. Decision-relevant analysis — the honest ledger
### 4.1 What the Workflow substrate demonstrably wins (measured / structural)
1. **Schema-validated reviewer contracts (F2)** — the one concrete, measured win. trekreview today
"collects each reviewer's trailing JSON block … on parse error, ask the agent to re-emit"
(`trekreview.md:202204`). `agent({schema})` makes that a tool-layer guarantee. *This win is
capturable even without the Workflow tool — see §6.*
2. **Deterministic control flow (F1/F3)** — fan-out, merge (`flatMap`), dedup-by-triplet can be
plain JS, not prose the model re-interprets each run. The Phase-6 dedup pass (`(file,line,
rule_key)`) is pure data manipulation that does not need an agent at all in a Workflow port;
only the *judgment* passes (HubSpot Judge, Cloudflare reasonableness) stay agent calls.
3. **Native pipelining / budget control**`pipeline()` (no-barrier streaming) and `budget.*`
exist. Minor for trekreview's single barrier; potentially relevant for trekplan's longer chain.
### 4.2 What the Workflow substrate costs (measured / structural)
1. **Loss of in-transcript operator visibility (F3, structural).** Workflow runs in the background;
intermediate reviewer findings appear in `/workflows`, not the main conversation. trekreview is
an **adversarial-review tool whose verdict the operator gates** — in-line visibility of each
finding as it lands, and the ability to interrupt mid-swarm, is a real property prose has and
Workflow trades away. (The final `review.md` artifact is still operator-gated, so this is a
degradation of *mid-flow* visibility, not of the gate itself.)
2. **Portability floor.** Workflow is CC **2.1.154+**. Voyage ships as a plugin; making a command
require the Workflow tool raises the consumer's CC floor. Prose commands run on any recent CC.
3. **Opt-in / billing semantics (F0).** Invocable here via the operator directive, but the Workflow
tool is explicitly gated on opt-in ("ONLY when the user has explicitly opted into multi-agent
orchestration"). A `/trekreview` invocation would have to *count as* that opt-in cleanly, or the
UX gains a second gate. Unresolved.
4. **Per-agent context floor is real but NOT a Workflow-specific tax.** 85k tokens for 3 trivial
agents (~28k/agent) is the fresh-context floor each spawned agent pays — but **prose
orchestration spawns the same 3 agents** (2 reviewers + coordinator) and pays the same floor.
So token cost is **roughly a wash** for equal agent count; it is *not* a strong differentiator
either way. (This corrects the instinct to count it as a Workflow con.)
5. **Loss of ad-hoc mid-flow model judgment.** Prose lets main *read* a malformed reviewer output
and decide to re-ask; a Workflow handles that via schema-retry (better for JSON) but cannot make
the unscripted judgment calls a prose-driven main session can.
### 4.3 The classifier handoff from S7 (resolved-partial)
S7's open item — "classifier behavior for a *purposeful* swarm under auto/bypass is unverified" —
is **partially closed**: a small purposeful Workflow fan-out is tolerated (F4). It remains open for
*large* fan-out (≥6 agents) under auto/bypass, which is trekplan's shape, not trekreview's. trekreview's
23-agent core is below the risk threshold; the bake-off (§5) must still measure it for the larger swarms.
## 5. Measurement design — the full prose-vs-Workflow bake-off (specified, ready to run)
If the operator greenlights a scoped port (§7), this resolves the *fidelity/control/cost* half of
CC-27. **Not run** in S8.
**Arms (same brief, same delivered diff, same model/effort; Phases 14 + 78 stay prose in both):**
- **Arm A — prose (baseline):** current `/trekreview` Phase 56 — main spawns the two reviewers in
parallel, collects + parses their JSON, spawns `review-coordinator`.
- **Arm B — Workflow:** Phase 56 reimplemented as one Workflow —
`parallel([conformance, correctness])` with a findings schema → `agent(coordinator)` with a
verdict schema; the dedup-by-triplet pass moved to plain JS; main receives the `review.md` body.
**Fixed inputs:** one representative delivered project (reuse an existing `.claude/projects/*/` with
a real diff + brief of medium size), `model: opus` / default effort, `--profile balanced`.
**Metrics (per arm, ≥3 runs for medians — q3 harness pattern for usage extraction):**
| Metric | Source | Role |
|--------|--------|------|
| **Output fidelity** — same verdict + equivalent finding set (IDs, severities, rule_keys) | diff the two `review.md` | **PRIMARY** — a substrate that changes the verdict/findings fails the gate |
| JSON-robustness — parse-error/re-ask events (Arm A) vs schema-retries (Arm B) | transcript/script logs | **the concrete win** — quantifies the fragility removed (F2) |
| Control / operator visibility | qualitative: intermediate findings in-transcript? interruptible mid-swarm? | **gate guard** — review is operator-gated (§4.2.1) |
| Classifier interference | count of denied/missing spawns (Arm B, repeat under `auto`/`bypass`) | feasibility guard (F4 / S7) |
| Total token cost (main + descendants) | summed stream-json `usage` | secondary — expected ≈ wash (§4.2.4) |
| Wall-time to `review.md` | timestamps | secondary |
**Decision thresholds (CC-27 verdict for *this core*):**
- **POSITIVE (adopt scoped hybrid):** output fidelity ≡ Arm A (same verdict; finding set within
tolerance) **AND** JSON-robustness strictly better **AND** zero classifier interference **AND**
token cost within +15% **AND** operator visibility judged acceptable (the `review.md` gate
survives).
- **NEGATIVE (keep prose):** verdict/findings diverge, **OR** any classifier interference drops a
reviewer, **OR** token cost > +30%, **OR** loss of mid-flow visibility judged unacceptable.
- **INCONCLUSIVE:** in-between → fall back to §6 (schema contract in prose, no Workflow) and re-measure.
**Harness note:** extend the `scripts/q3-cache-prefix-experiment.mjs` pattern (stream-json `usage`
extraction, median, threshold→verdict, always-write result file). The fidelity diff (review.md ↔
review.md) is new; the usage scaffold is reused.
## 6. Cheaper first step (preferred over the full bake-off) — schema contract without Workflow
The single concrete win (F2) is **capturable without adopting the Workflow tool at all.** The
reviewer-output fragility lives in prose ("collect trailing JSON block; on parse error, ask the
agent to re-emit"). The narrowest, zero-dependency fix is to **codify the reviewer findings JSON as
a validated schema contract in prose Phase 5** — main validates each reviewer's JSON against a
findings JSON-schema (Voyage already has `lib/validators/` + `lib/util/frontmatter.mjs` parsers) and
re-asks on schema failure, not just on parse failure.
This captures the robustness win with **no portability floor, no opt-in gate, no loss of
in-transcript visibility** — the substrate stays prose. It is the S8 analog of S7 §6's "narrow
synthesis-agent PoC preferred over the full bake-off": isolate the largest win with the smallest
blast radius. **Recommended as the first thing to ship if the operator wants the win without the
substrate commitment.**
## 7. CC-27 recommendation (operator gates the verdict)
**Three tiers, in increasing commitment:**
1. **Ship regardless (cheapest, no Workflow):** codify reviewer-output JSON as a schema-validated
contract in prose Phase 5 (§6). Captures the one measured win (F2 robustness) with zero new
dependency, zero opt-in friction, zero visibility loss. Low risk, high value.
2. **Scoped hybrid — a measured YES candidate, gated on the §5 bake-off:** port trekreview Phase 56
to a Workflow **if** the bake-off shows fidelity-equivalent output + acceptable control/cost.
trekreview's clean-barrier core is the **best-case first port**; trekplan's swarm is a later,
classifier-sensitive candidate (its larger fan-out under auto/bypass is the unverified risk).
3. **Wholesale substrate swap — NOT recommended.** Portability floor (2.1.154+), opt-in/billing UX
on every invocation, 80%-of-each-command is non-orchestration glue Workflow does not touch, and
loss of mid-flow operator visibility for tools whose verdict the operator gates. The identity
framing ("adopt Workflow as substrate") over-claims what the primitive can replace.
**Net:** CC-27 stays **EVALUATE**, resolving toward **selective hybrid, not substrate swap** — a
slightly more YES-leaning posture than S7's CC-26, because here both feasibility (F1) *and* a
concrete win (F2) are confirmed, where CC-26's only upside (main-context relief) was speculative and
counterweighted. The wholesale-substrate option is declined. The first action, if the operator wants
movement, is the §6 prose schema contract; the first Workflow port, if pursued, is trekreview
Phase 56 via the §5 bake-off. CC-26 (delegated orchestration, S7) and CC-27 are now both resolved
to "narrow/selective, operator-gated, not wholesale."
## 8. Open items
1. **Output fidelity unmeasured** — the probe used a synthetic input; a real-diff prose-vs-Workflow
`review.md` comparison (§5 PRIMARY metric) is designed but unrun.
2. **Classifier behavior at large fan-out under auto/bypass unverified** (F4) — trekreview's 23
agents are below threshold; trekplan's 610-agent swarm is not, and must be measured before any
Workflow port reaches a headless/auto path. Inherits directly from S7 §4.
3. **Opt-in UX for command-invoked Workflows unresolved** (F0) — whether a bare `/trekreview`
invocation cleanly satisfies the Workflow opt-in gate for an end user (not just via an operator
STATE directive) needs a real end-user test.
4. **§6 schema contract and §5 bake-off are both designed but unbuilt** — ready to run if CC-27 is
greenlit toward the schema contract (tier 1) and/or the scoped port (tier 2).