voyage/tests/fixtures/synthesis/exploration/dependency-tracer.md
Kjell Tore Guttormsen 6b30483304 feat(voyage): S12 — NW3 synthesis-agent built + measured → declined per measurement [skip-docs]
NW3 (CC-26 §6 PoC): delegate trekplan Phase 7 synthesis to a synthesis-agent,
adopt only if Δ main-context ≥30% with no quality loss. Operator chose the
deterministic-proof path (live ≥3-run bake-off was env-blocked: no API key;
installed plugin is a cache copy so a new agent is invisible to `claude -p`).

Decisive structural finding: trekplan Phase 5 runs the swarm FOREGROUND, so its
outputs are already resident in main before Phase 7. Delegating only Phase 7
evicts nothing → Δ_faithful = 0% (BASE-independent). The ≥30% saving needs an
out-of-scope Phase-5 redesign (swarm-writes-to-disk / nested orchestrator).
VERDICT: DECLINED per measurement.

- agents/synthesis-agent.md — dormant, schema-conformant deliverable (NOT wired)
- lib/plan/synthesis-digest-schema.mjs — digest output contract (+ tests)
- scripts/synthesis-measure.mjs — deterministic Δ-accounting core (+ tests)
- tests/fixtures/synthesis/ — 7 exploration outputs + representative digest
- docs/T1-synthesis-poc-results.md — measurement + verdict (reproducible)
- CLAUDE.md — agent table row (doc-consistency: 24 agents)

Tests 670 → 695 (693 pass / 2 skip / 0 fail). `claude plugin validate` clean
(only the pre-existing root-CLAUDE.md warning). commands/trekplan.md untouched.

[skip-docs] rationale: no user-facing feature ships (NW3 declined; agent dormant
and unwired). The substantive doc is docs/T1-synthesis-poc-results.md; the
README/CHANGELOG roll-up for NW1–NW3 is the S13 coordinated release per
docs/W1-narrow-wins-plan.md §S13.

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

76 lines
3.4 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.

# Dependency & Data-Flow Report — output of dependency-tracer
Task: Add a per-wave concurrency cap to trekexecute headless launches.
## Import / call chain relevant to the task
```
commands/trekexecute.md (Phase 2.6 prose)
└─ generates → templates/headless-launch-template.md (Bash here-doc)
├─ reads SHARED_CONTEXT_FILE (append-system-prompt-file)
├─ spawns claude -p ×N (one per wave member, backgrounded with &)
└─ waits via `wait` on collected PIDs
└─ consumes → .session-state.local.json (Handover 7; session graph)
```
## Data flow
1. session-decomposer emits a plan with wave groupings + a dependency graph.
2. trekexecute Phase 2.6 turns each independent wave into a launch batch.
3. The template loops over batch members and backgrounds each `claude -p`,
collecting PIDs into a Bash array, then `wait`s for the whole batch.
4. There is **no slot-limiting** between "background member" and "wait" — the
degree of parallelism equals the batch size.
## Side effects
- Each subprocess does `git` work under `GIT_OPTIONAL_LOCKS=0`; high concurrency
raises the chance of index-lock contention (mitigated, not eliminated).
- `--max-budget-usd` is per-subprocess; total spend scales with batch size, so a
concurrency cap also indirectly bounds burst spend.
## What a cap touches
- **Pure-addable:** a `maxParallel` resolver in `lib/` (reads plan/profile/flag,
returns an integer ≥ 1). No existing module imports would change.
- **Wire-in:** the template's loop must consume slots (e.g. a counting semaphore
in Bash, or `xargs -P <n>`). This is the only behavioral edit.
## No hidden dependents
Grepped for other call sites of the launch template — only trekexecute Phase 2.6
and the headless-launch-template test reference it. A cap is local in blast
radius.
## Resolver input provenance (what the cap reads)
The resolved integer must be derived from, in lookup order:
1. **CLI flag** `--max-parallel <n>` — parsed by `lib/parsers/arg-parser.mjs`;
highest precedence (operator override).
2. **Brief signal**`phase_signals` already carries per-phase orchestration
shape; a `max_parallel` hint here is honoured if no flag.
3. **Profile**`lib/profiles/` resolves `--profile economy|balanced|premium`;
each profile can carry a `max_parallel` default. This is the same lookup
order `phase_models` uses, so the resolver should *reuse* profile-resolver,
not re-implement precedence.
4. **Hard default**`batchSize` (i.e. no cap / current behavior), so the change
is a strict no-op until someone opts in.
## Downstream of the cap
- **Budget:** total burst spend = `min(cap, batchSize) × per-member --max-budget-usd`.
A cap therefore tightens the worst-case spend envelope — worth noting in the
plan's risk/observability section.
- **Git contention:** fewer concurrent `git`-touching subprocesses → fewer
`index.lock` races. `GIT_OPTIONAL_LOCKS=0` reduces lock acquisition but does
not serialize ref updates; the cap is the structural mitigation.
- **Classifier exposure:** a smaller concurrent fan-out under `auto`/`bypass`
lowers the surface the proliferation classifier (S7 F4) scrutinises.
## Data-flow invariant to preserve
`SHARED_CONTEXT_FILE` is built once per wave and read by every member; the cap
must not cause it to be rebuilt per-slot (would defeat the cache prefix). Slot
limiting happens at spawn time only; the context file is wave-scoped, not
slot-scoped.