Skip to content

Commit 48715df

Browse files
V48 Gate 3 (specification-implementation): propagate synthesis mode to the SDIVF phases so deposit runs deposit agents (F20)
A /deposit run ("SynthesizeAssetPacks (deposit mode)") was executing the READ-lens agents — ReadFitsFindingSynthesisReadComprehensionAgent (read-comprehension step), ReadFitsFindingSynthesisAssetPackSynthesisAgent — and ending with "Pipeline yielded no admissible options; falling back to bounded deposit synthesis." The agent pills are each agent's real config.name, so the read agents genuinely ran (it was not just mislabeled telemetry). Cause: factorySDIVFExecutorPipeline composes the phases with `sequential`, which runs preprocess and each phase on ISOLATED sibling child executions (execution.child('seq-N')). factoryPreprocess stored the resolved mode on its own child (seq-0); the phases run on seq-1/seq-2 and resolve the mode via synthesizeAssetPacksModeFromExecution, which only walks ANCESTORS — never sideways to seq-0. So every phase resolved null -> 'read', took the read branch, and resolved the init-registered read agents. The agents registry is already shared up the tree (the read implementation agent is registered by the phase and resolves), so the only gap was the mode. Fix (index.ts): the factorySynthesizeAssetPacksPipeline wrapper now resolves the mode and stores it on the shared outer execution (the parent of all seq-N phase children) before running the SDIVF executor, so every phase resolves it via the upward walk. Once the phases see 'deposit', their mode-conditional registrations (setup comprehension override, deposit Discovery agents, deposit Implementation/Validation) take effect on the shared registry and the deposit-lens agents run — which also makes the telemetry verbiage deposit-correct at the root. Read mode unchanged (default was already read). Added a mode-propagation regression test (reproduces sibling isolation; shared-parent storage resolves on the phase children). Spec records the shared-execution requirement; QA ledger records F20. asset-pack tsc 0; asset-pack suite 210 tests green; spec checker green. Needs a live deposit run to confirm end-to-end. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
1 parent 4d8134a commit 48715df

4 files changed

Lines changed: 71 additions & 4 deletions

File tree

BITCODE_SPEC_V48_NOTES.md

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -149,10 +149,16 @@ Accepted V48 architecture law (decided 2026-06-25):
149149
**SDIVF** pipeline (Setup -> Discovery -> Implementation -> Validation ->
150150
Finish, with the Discovery/Implementation/Validation loop iterating up to a
151151
bounded maxIterations) executed in one of two **modes**: deposit or read.
152-
The mode is resolved once in preprocess and stored on the execution; all
153-
variance is carried by **conditional runtime registries** — each phase
154-
registers and resolves the mode-appropriate agents, tools, and prompts under
155-
the same phase keys. Renamed SynthesizeAssetPacks for parity with the future
152+
The mode is resolved once and stored on the **shared pipeline execution** (the
153+
parent of all phase children), NOT on a phase sibling — `sequential` runs
154+
preprocess and each phase on isolated sibling child executions
155+
(`execution.child('seq-N')`) and mode resolution only walks ancestors, so a
156+
mode stored inside preprocess is invisible to the phases (QA F20: they default
157+
to read and run the read-lens agents during a deposit run). All variance is
158+
carried by **conditional runtime registries** — each phase registers and
159+
resolves the mode-appropriate agents, tools, and prompts under the same phase
160+
keys (the registry is shared up the execution tree, so a phase's registrations
161+
are visible to its agent resolution). Renamed SynthesizeAssetPacks for parity with the future
156162
Gate-6 **SettleAssetPacks** pipeline; it subsumes the legacy, poorly-named
157163
"Develop" gate (which remains a thin alias so its `develop.*` observability
158164
is unchanged).

BITCODE_V48_QA.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,13 @@ Track 3-4 scripts (BTD ledger, settlement, pack journaling) get added when those
202202
- `usePipelineExecution.ts` (the second half — fragments persisted live) — the live SSE tail re-parsed each frame through `parseStreamChunk`, which flattened the structured onStore event into a namespace-less `{type:'status', status:{message}}` shape; the activity-builder classifier keys off `namespace` to suppress fragments, so namespace-stripped live events leaked every store as a row (the history path, which relays raw `event_data`, was already correct). The tail now relays raw `event_data` verbatim — identical in shape to history — so the contract holds during streaming, not just on reload.
203203
- Verified: uapi tsc 0; F19 activity-builder contract test + a `usePipelineExecution` test asserting the live tail preserves `namespace`/`key`/`executionState` + 10-suite telemetry/terminal/deposit regression batch — all green.
204204

205+
### F20 — Deposit synthesis runs the READ-lens agents (mode never reaches the phases)
206+
207+
- Severity: high (the deposit pipeline isn't actually depositing). Surfaced as "Read" verbiage in a deposit run, but the cause is that the read agents execute.
208+
- Observed (2026-06-26): a `/deposit` run ("SynthesizeAssetPacks (deposit mode)") rendered read-lens agents in telemetry — `ReadFitsFindingSynthesisReadComprehensionAgent` with a `read-comprehension` step, `ReadFitsFindingSynthesisAssetPackSynthesisAgent` with a `synthesis` step — and ended with "Pipeline yielded no admissible options; falling back to bounded deposit synthesis." The agent pills are each agent's real `config.name`, so the read agents were genuinely running.
209+
- Cause: `factorySDIVFExecutorPipeline` composes the phases with `sequential`, which runs preprocess and every phase on ISOLATED sibling child executions (`execution.child('seq-N')`). `factoryPreprocess` stored the resolved mode on its own child (`seq-0`); the phases run on `seq-1`/`seq-2` and resolve the mode with `synthesizeAssetPacksModeFromExecution`, which only walks ANCESTORS — never sideways to `seq-0`. So every phase resolved `null → 'read'`, took the read branch, and resolved the init-registered read agents. The agents registry is already shared (the read implementation agent is registered by the phase and resolves), so the only gap was the mode.
210+
- Repair (2026-06-26, `index.ts`): the `factorySynthesizeAssetPacksPipeline` wrapper now resolves the mode and stores it on the shared outer execution (the parent of all `seq-N` phase children) before running the SDIVF executor, so every phase resolves it via the upward walk. Once the phases see `deposit`, their mode-conditional registrations (setup comprehension override, deposit Discovery agents, deposit Implementation/Validation) take effect on the shared registry and the deposit-lens agents run — which also makes the telemetry verbiage deposit-correct at the root. Read mode is unchanged (default was already read). Regression test added (sibling isolation reproduced; shared-parent storage resolves). Needs a live deposit run to confirm end-to-end.
211+
205212
## Track 1 — Identity / Authentication / Auxillaries — COMPLETE 2026-06-12 (email deferred by decision; F2/F9 and legacy eradication queued for gates)
206213

207214
- [x] Sign up / sign in via Connect Wallet (nav CTA → SignUpWindow → wallet signature on testnet4 → `custom:bitcode-bitcoin` session → `/tps/supabase/callback`) — verified 2026-06-12 after F5 fix; lands on `/packs`. Re-verified from fully nuked state (purged user + cleared site data): created 19:29:21 → session 19:29:25 → binding auto-written 19:29:29 by the bridge on `/packs` mount with no Auxillaries visit; UI consistent across nav, Wallet, and Profile panes.
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
import { Execution } from '@bitcode/execution-generics';
2+
import {
3+
storeSynthesizeAssetPacksMode,
4+
synthesizeAssetPacksModeFromExecution,
5+
} from '../synthesize-asset-packs';
6+
7+
/**
8+
* QA F20 — deposit-mode propagation. `factorySDIVFExecutorPipeline` composes the
9+
* phases with `sequential`, which runs preprocess and every phase on ISOLATED
10+
* sibling child executions (`execution.child('seq-N')`). The mode must therefore
11+
* be stored on the SHARED parent so the phase children resolve it via the upward
12+
* walk; storing it on a sibling (the old behavior) leaves it unreachable and the
13+
* phases default to read, running the read-lens agents during a deposit run.
14+
*/
15+
describe('synthesize-asset-packs mode propagation (F20)', () => {
16+
it('resolves the mode on sibling phase children when stored on the shared parent', () => {
17+
const shared = new Execution('pipeline-root');
18+
storeSynthesizeAssetPacksMode(shared, 'deposit');
19+
20+
// sequential() gives preprocess and each phase their own sibling child.
21+
const preprocessExec = shared.child('seq-0');
22+
const setupExec = shared.child('seq-1');
23+
const divExec = shared.child('seq-2');
24+
25+
// Every phase child reaches the shared parent's mode via the upward walk.
26+
expect(synthesizeAssetPacksModeFromExecution(preprocessExec)).toBe('deposit');
27+
expect(synthesizeAssetPacksModeFromExecution(setupExec)).toBe('deposit');
28+
expect(synthesizeAssetPacksModeFromExecution(divExec)).toBe('deposit');
29+
// And deeper (the phase's own sequential children) still resolve it.
30+
expect(synthesizeAssetPacksModeFromExecution(divExec.child('seq-0'))).toBe('deposit');
31+
});
32+
33+
it('does NOT leak the mode across siblings (reproduces the F20 bug)', () => {
34+
const shared = new Execution('pipeline-root');
35+
// The pre-fix behavior: preprocess stored the mode on its own sibling child.
36+
const preprocessExec = shared.child('seq-0');
37+
storeSynthesizeAssetPacksMode(preprocessExec, 'deposit');
38+
39+
// A phase sibling cannot see a value stored on another sibling.
40+
const setupExec = shared.child('seq-1');
41+
expect(synthesizeAssetPacksModeFromExecution(setupExec)).toBeNull();
42+
});
43+
});

packages/pipelines/asset-pack/src/index.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -449,6 +449,17 @@ function factorySynthesizeAssetPacksPipeline(
449449

450450
return async (input, execution) => {
451451
await initializeAssetPackPipeline(execution as any);
452+
// Resolve + store the synthesis mode on THIS (shared) execution so every
453+
// SDIVF phase can read it. factorySDIVFExecutorPipeline composes the phases
454+
// with `sequential`, which runs preprocess and each phase on ISOLATED sibling
455+
// child executions (`execution.child('seq-N')`). Storing the mode only inside
456+
// preprocess (itself a sibling) left it unreachable from the phase children —
457+
// synthesizeAssetPacksModeFromExecution only walks ancestors — so every phase
458+
// defaulted to `read` and ran the read-lens agents during deposit runs (QA
459+
// F20). Storing it here, on the parent of all phase children, makes the
460+
// upward resolution find it; the shared agents registry then receives each
461+
// phase's mode-conditional (deposit) registrations.
462+
storeSynthesizeAssetPacksMode(execution, resolveSynthesizeAssetPacksMode(input, execution));
452463
return developExecutor(input, execution);
453464
};
454465
}

0 commit comments

Comments
 (0)