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
96 lines
4.7 KiB
Markdown
96 lines
4.7 KiB
Markdown
# Architecture Report — output of architecture-mapper
|
|
|
|
Task being planned: Add a per-wave concurrency cap to trekexecute headless launches.
|
|
|
|
## Summary
|
|
|
|
Voyage is a contract-driven Claude Code plugin (Node ESM, zero runtime deps).
|
|
The pipeline is six commands (`commands/*.md`) backed by a `lib/` of pure,
|
|
unit-tested validators/parsers and a thin `scripts/` layer of measurement and
|
|
codegen harnesses. trekexecute is the disciplined plan/session-spec executor;
|
|
its headless path (Phase 2.6) fans out parallel "waves" of `claude -p`
|
|
subprocesses driven by a Bash launcher template.
|
|
|
|
## Tech stack
|
|
|
|
| Layer | Choice | Evidence |
|
|
|-------|--------|----------|
|
|
| Language | JavaScript (ESM, `.mjs`) | `lib/**/*.mjs`, `"type":"module"` in package.json |
|
|
| Tests | `node:test` + `node:assert/strict` | every `tests/**/*.test.mjs` |
|
|
| Validation | hand-rolled validators returning `{valid,errors,warnings}` | `lib/util/result.mjs` |
|
|
| Orchestration substrate | command prose + Bash + Agent/Task tool | `commands/trekexecute.md` |
|
|
| Headless launch | Bash here-doc template, backgrounded subprocesses | `templates/headless-launch-template.md` |
|
|
|
|
## Key patterns
|
|
|
|
- **3-layer module pattern** — Content validator → raw-text wrapper → CLI shim
|
|
(`if (import.meta.url === \`file://${process.argv[1]}\`)`), repeated across
|
|
`lib/validators`, `lib/parsers`, `lib/review`. Any new lib must follow it.
|
|
- **Structured Result type** — `issue(code,message,hint,location)` + `fail()` /
|
|
`ok()` from `lib/util/result.mjs`. Stable error codes are the contract.
|
|
- **Prose-as-orchestrator** — commands carry the control flow in markdown; the
|
|
harness executes it. Schema-drift defenses are *inlined* into command prose so
|
|
they survive even when agent docs are not implicitly loaded.
|
|
|
|
## Anti-patterns / debt near the task
|
|
|
|
- The headless launcher backgrounds **all** wave members at once with no upper
|
|
bound on concurrent `claude -p` processes; concurrency is implicit in how many
|
|
steps a wave contains. No central place caps it.
|
|
- Wave composition (which steps go in which wave) is computed by
|
|
session-decomposer, but the *launch* fan-out is template Bash, so a cap would
|
|
straddle a JS (decomposer) / Bash (launcher) boundary.
|
|
|
|
## Module map (task-relevant)
|
|
|
|
```
|
|
commands/trekexecute.md # Phase 2.6 parallel-wave orchestration prose
|
|
templates/headless-launch-template.md # the Bash fan-out site
|
|
lib/util/result.mjs # error shape any new guard returns
|
|
agents/session-decomposer.md # produces the wave/dependency graph
|
|
```
|
|
|
|
## Boundaries
|
|
|
|
The cap is a launch-time concern (Bash template + the Phase 2.6 prose that
|
|
generates it). It does not belong in the pure `lib/` validators unless we add a
|
|
small "max parallelism" resolver that the prose reads. Recommend a lib resolver
|
|
(testable) + a template wire-in (the actual `xargs -P` / job-slot mechanism).
|
|
|
|
## How Phase 2.6 assembles a wave (detail)
|
|
|
|
The executor reads the plan's `## Step N` blocks and the dependency edges
|
|
session-decomposer emitted (`depends_on:` frontmatter). Steps with no unmet
|
|
dependency at the current frontier form a wave. For each wave the prose:
|
|
|
|
1. builds a `SHARED_CONTEXT_FILE` (brief + plan + relevant exploration digest)
|
|
passed to every member via `--append-system-prompt-file` (cache-prefix
|
|
material — see q3 experiment);
|
|
2. emits one `claude -p … &` invocation per member from the here-doc, each with
|
|
`--max-turns`, `--max-budget-usd`, `GIT_OPTIONAL_LOCKS=0`, and the GH#36071
|
|
push-before-cleanup workaround;
|
|
3. collects the backgrounded PIDs and `wait`s for the batch to drain before
|
|
advancing the frontier.
|
|
|
|
The cap belongs strictly between (2) and (3): bound how many of the emitted
|
|
members run concurrently, leaving wave *composition* (1) untouched.
|
|
|
|
## Layering verdict
|
|
|
|
Three layers, in increasing blast radius: (a) a pure resolver in `lib/`
|
|
(arithmetic only — trivially testable, follows the 3-layer module pattern);
|
|
(b) Phase 2.6 prose passing the resolved integer + a `--max-parallel` flag into
|
|
the template; (c) the template's fan-out mechanism. Keep (a) the single source
|
|
of the number; (c) should only consume it. This matches every prior launcher
|
|
hardening, which added one bounded externality (budget, locks, turns) at a time
|
|
without reshaping wave composition.
|
|
|
|
## Cross-cutting observations
|
|
|
|
- The launcher is the most operationally sensitive file in the repo (it spends
|
|
money and mutates git). Every edit here is co-reviewed with its
|
|
doc-consistency needle list — treat the needle test as part of the contract,
|
|
not an afterthought.
|
|
- Nothing in `lib/` currently imports anything launcher-related; the resolver
|
|
will be a leaf module. Good — it can be tested and shipped independently of the
|
|
template wire-in, enabling a TDD-first slice.
|