# 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 `). 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 ` — 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.