Skip to content

Commit 845dc71

Browse files
Gate 4: Reading pipeline observability (#23)
* Gate 4: project Reading pipeline observability Add contract-aware observability inventory and projection for ReadNeedComprehensionSynthesis and ReadFitsFindingSynthesis, stamp sandbox harness stream events with PTRR and ThricifiedGeneration metadata, and surface those fields through the Terminal execution stream UI. Update V29 spec, parity, docs, Gate 4 checker, CI wiring, and focused package/UAPI tests for the Reading telemetry closure criteria. * Gate 4: satisfy UAPI observability typecheck Normalize PTRR step-id parsing so the stricter UAPI TypeScript build receives a concrete string before checking Reading pipeline telemetry step names. Validation: pnpm -C uapi exec tsc --noEmit; pnpm run check:v29-gate4; pnpm --dir uapi exec jest --runTestsByPath tests/terminalPipelineHarnessClient.test.ts tests/pipelineExecutionLogHeader.test.tsx --runInBand; pnpm exec eslint packages/pipelines/asset-pack/src/reading-pipeline-observability.ts uapi/app/terminal/terminal-pipeline-harness-client.ts uapi/components/base/bitcode/execution/pipeline-execution-log-header.tsx uapi/components/base/bitcode/execution/pipeline-execution-log.tsx --ext .ts,.tsx; git diff --check
1 parent 94abf30 commit 845dc71

20 files changed

Lines changed: 1349 additions & 15 deletions

.github/workflows/bitcode-gate-quality.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ jobs:
4848
node scripts/check-v29-gate1-objectives-and-gating.mjs --skip-branch-check
4949
node scripts/check-v29-gate2-terminal-transaction-read-models.mjs --skip-branch-check
5050
node scripts/check-v29-gate3-wallet-signer-btc-operations.mjs --skip-branch-check
51+
node scripts/check-v29-gate4-reading-pipeline-observability.mjs --skip-branch-check
5152
5253
- name: Validate source casing and imports
5354
run: |
@@ -65,6 +66,7 @@ jobs:
6566
pnpm --filter @bitcode/btd test
6667
pnpm --filter @bitcode/btd test -- --runTestsByPath __tests__/btc-fee-operation.test.ts
6768
pnpm --filter @bitcode/pipeline-asset-pack exec jest --config jest.config.cjs --passWithNoTests --forceExit
69+
pnpm --filter @bitcode/pipeline-asset-pack exec jest --config jest.config.cjs --runTestsByPath src/__tests__/reading-pipeline-observability.test.ts src/__tests__/reading-pipeline-contract.test.ts --runInBand
6870
pnpm --filter @bitcode/pipeline-hosts exec jest --config jest.config.cjs --passWithNoTests --forceExit
6971
7072
- name: Test staged Reading route and Terminal harness contracts

BITCODE_SPEC_V29.md

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,40 @@ It may not expose protected AssetPack source, wallet secrets, provider tokens, o
247247
- Current validating commands and parity basis: pipeline contract tests, route tests, prompt rendering/audit checks, local live OpenAI validation, and V29 gate checks.
248248
- Current accepted boundaries: full-profile async push completion can deepen in V29 gates but cannot bypass source-safe preview or settlement boundaries.
249249

250+
#### V29 Reading pipeline observability canon
251+
252+
Reading pipeline observability is contract-projected, not ad hoc.
253+
The asset-pack package owns the inventory for `ReadNeedComprehensionSynthesis` and `ReadFitsFindingSynthesis`, and live harness events must project back to that inventory whenever they are emitted.
254+
255+
The observable contract levels are:
256+
257+
- execution;
258+
- phase;
259+
- PTRR agent;
260+
- PTRR step;
261+
- ThricifiedGeneration;
262+
- prompt;
263+
- tool;
264+
- raw output;
265+
- parsed output.
266+
267+
For every live Reading stream event that can be associated with a contract, Terminal-visible telemetry carries:
268+
269+
- pipeline name;
270+
- phase id;
271+
- PTRR agent id;
272+
- PTRR step id and step name;
273+
- ThricifiedGeneration id and failsafe;
274+
- prompt template id and generation prompt ids;
275+
- tool id, input type, and output type when the event is tool-backed;
276+
- declared return type and output schema;
277+
- prompt template/interpolated prompt presence;
278+
- reasoning, judgment, raw model response, and parsed typed output presence.
279+
280+
The Vercel Sandbox harness must export both the observability inventory and an observability coverage summary in its evidence artifact.
281+
Coverage readback is not a settlement proof by itself; it is the operational proof that Terminal can debug a live Reading run without relying on browser network logs.
282+
Failure to observe prompt, raw-output, parsed-output, or tool telemetry in a run that reaches those stages is a blocked-readiness signal for Gate 4+ QA.
283+
250284
### Fit, recall, ranking, and verification
251285

252286
- Current canonical objects and emitted artifacts: FindingFits query root, lexical search result, vector search result, fit deposit list, candidate score, ranking root, blocker list, and verification decision.

BITCODE_SPEC_V29_DELTA.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,15 @@ Closure acceptance:
113113

114114
Gate 4 owns deep Terminal visibility over `ReadNeedComprehensionSynthesis` and `ReadFitsFindingSynthesis`, including execution, phase, PTRR agent, PTRR step, ThricifiedGeneration, prompt, tool, output, and typed parse telemetry.
115115

116+
Closure acceptance:
117+
118+
- `@bitcode/pipeline-asset-pack` exposes a Reading pipeline observability inventory and `ReadingPipelineTelemetryProjection` over the existing Reading pipeline contracts.
119+
- The inventory accounts for both Reading pipelines, 11 phases, 12 PTRR agents, 48 PTRR steps, 144 ThricifiedGenerations, all registered prompt templates, all ThricifiedGeneration prompt ids, and the four Finding Fits tools.
120+
- The Vercel Sandbox harness annotates stream events with pipeline name, phase id, PTRR agent id, PTRR step id, ThricifiedGeneration id, prompt template id, generation prompt ids, tool id, output schema, return type, and prompt/raw/parsed/tool evidence posture.
121+
- Harness evidence includes Reading observability inventory and coverage readback so local/staging failures show exactly which telemetry levels were not observed.
122+
- Terminal converts harness SSE events into the shared execution log shape with contract-aware execution state, summary rows, and expandable metadata for prompt template, interpolated prompt, raw response, parsed typed output, tools, and output schema.
123+
- Gate-quality CI runs the Gate 4 checker plus focused asset-pack, pipeline-host, Terminal harness, and execution-log header tests.
124+
116125
### Gate 5: AssetPack Disclosure Rights And Preview Depth
117126

118127
Gate 5 owns AssetPack range detail, owner-read/licensed-read/denied-state flows, source-safe preview, disclosure policy review, paid unlock state, and protected-source leakage tests.

BITCODE_SPEC_V29_NOTES.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ For a simplified reading of V29:
6060

6161
4. **Gate 4: Reading Transaction Recovery And Pipeline Observability**
6262
- Make `ReadNeedComprehensionSynthesis` and `ReadFitsFindingSynthesis` execution telemetry fully readable in Terminal at execution, phase, PTRR agent, PTRR step, ThricifiedGeneration, prompt, tool, raw output, and parsed output levels.
63+
- Acceptance detail: the asset-pack package owns the observability inventory/projection; the sandbox harness stamps live stream events with contract identifiers and coverage; Terminal renders those identifiers in the shared execution stream header, row summary, and expandable metadata.
6364

6465
5. **Gate 5: AssetPack Disclosure Rights And Preview Depth**
6566
- Deepen source-safe preview, AssetPack range detail, owner-read/licensed-read/denied state, disclosure policy review, paid unlock, and source-leakage tests.
@@ -120,6 +121,19 @@ Accepted Gate 3 posture:
120121
- Terminal has a Wallet/BTC detail section so fee readiness is visible before raw ledger payload inspection.
121122
- Gate 3 does not implement settlement reconciliation repair; Gate 6 owns drift repair and ledger/database reconciliation action depth.
122123

124+
## Gate 4 working notes
125+
126+
Gate 4 makes Reading pipeline telemetry readable without changing the underlying execution primitive names.
127+
Execution remains the base primitive, Reading pipelines compose phases, each phase owns PTRR agents, each PTRR agent owns plan/try/refine/retry steps, and each step carries ThricifiedGeneration prompt/output evidence.
128+
129+
Accepted Gate 4 posture:
130+
131+
- `reading-pipeline-contract.ts` remains the source of pipeline, phase, PTRR agent, PTRR step, ThricifiedGeneration, prompt, tool, and return-type contracts.
132+
- `reading-pipeline-observability.ts` projects live stream events onto those contracts and reports observability coverage.
133+
- The sandbox harness records contract-aware telemetry events and stores coverage in exported evidence.
134+
- Terminal's live harness stream shows pipeline, phase id, PTRR agent, PTRR step, ThricifiedGeneration, prompt, tool, output schema, raw output posture, and parsed typed output posture through the shared execution log components.
135+
- Gate 4 does not implement disclosure-depth unlock, settlement repair, organization authority, or full browser proof; later gates own those slices.
136+
123137
## Later-version boundaries
124138

125139
- V30 remains reserved for Protocol/BTD hardening that is not necessary to close Terminal transaction depth.

BITCODE_SPEC_V29_PARITY_MATRIX.md

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ No `_legacy/` source is active source truth.
5151
| Workflow retargeting | Gate 1 | `.github/workflows/bitcode-gate-quality.yml`, `.github/workflows/bitcode-canon-quality.yml` | drafted | CI checks V28 active / V29 draft posture instead of stale V27/V28 posture. |
5252
| Terminal transaction read models | Gate 2 | `uapi/app/terminal/terminal-transaction-read-model.ts`, `uapi/app/terminal/terminal-transaction-query.ts`, `TerminalTransactionWorkspace.tsx`, `TerminalTransactionDetailSurface.tsx`, UAPI tests, Gate 2 checker | drafted | Terminal transaction state is URL-addressable, recoverable, typed, low-detail by default, and expandable without raw JSON as the ordinary operator contract. |
5353
| Wallet signer/BTC operations | Gate 3 | `packages/btd/src/btc-fee-operation.ts`, BTC fee route, Terminal Wallet/BTC detail section, BTD and UAPI tests, Gate 3 checker | drafted | Signer session, PSBT, broadcast/finality/reorg/replacement/failure states are ordinary Terminal states. |
54-
| Reading pipeline observability | Gate 4 | `packages/pipelines/asset-pack`, `packages/pipeline-hosts`, Terminal stream components | pending | Pipeline/phase/PTRR/ThricifiedGeneration/tool/prompt telemetry is complete and readable. |
54+
| Reading pipeline observability | Gate 4 | `packages/pipelines/asset-pack/src/reading-pipeline-observability.ts`, `packages/pipeline-hosts/src/asset-pack-harness.ts`, Terminal stream components, Gate 4 checker | drafted | Pipeline/phase/PTRR/ThricifiedGeneration/tool/prompt/raw-output/parsed-output telemetry is contract-projected, complete, and readable. |
5555
| AssetPack disclosure rights | Gate 5 | BTD access primitives, AssetPack preview UI, disclosure policy tests | pending | Source-safe preview and paid unlock are proven without source leakage. |
5656
| Settlement reconciliation repair | Gate 6 | BTD journal/reconciliation, Supabase readback, Terminal repair UI | pending | Ledger, database, and metaphysical state drift is visible and repairable. |
5757
| Organization permission authority | Gate 7 | access policy, org holdings, MCP/ChatGPT gates, Terminal permission UI | pending | Registry-derived roles, holdings, and read-license authority govern actions. |
@@ -69,6 +69,7 @@ No `_legacy/` source is active source truth.
6969
| Gate 1 script | `pnpm run check:v29-gate1` fails closed on stale posture or missing gates | drafted |
7070
| Gate 2 read model | `pnpm run check:v29-gate2` proves typed route-owned Terminal transaction reading | drafted |
7171
| Gate 3 wallet/BTC operation | `pnpm run check:v29-gate3` proves quote lifecycle, signer recovery, blocked readiness, API posture, and Terminal Wallet/BTC detail | drafted |
72+
| Gate 4 Reading observability | `pnpm run check:v29-gate4` proves contract-aware Reading stream telemetry and Terminal rendering | drafted |
7273
| Product implementation gates | Gates 3-9 close remaining Terminal transaction depth with tests and docs | pending |
7374
| Promotion gate | Gate 10 closes generated proof and promotion automation | pending |
7475

@@ -139,3 +140,26 @@ Gate 2 is complete when Terminal selected transaction state rewrites recoverable
139140
## Gate 3 completion condition
140141

141142
Gate 3 is complete when package primitives model BTC quotes, signer recovery, operation posture, and blocked readiness; API responses serialize operation posture; Terminal has a Wallet/BTC route-owned detail section; focused package and UAPI tests pass; `check:v29-gate3` passes; CI invokes the checker and tests; docs name the implemented source surfaces; and the gate branch is committed and pushed for review into `version/v29`.
143+
144+
## Gate 4 Parity
145+
146+
| Requirement | Source evidence | Current V29 judgment |
147+
| --- | --- | --- |
148+
| Reading pipeline contracts remain the source of truth | `reading-pipeline-contract.ts`, contract tests | drafted |
149+
| Observability inventory covers both Reading pipelines and all contract levels | `reading-pipeline-observability.ts`, observability tests | drafted |
150+
| Live sandbox harness stamps stream events with contract ids and output posture | `packages/pipeline-hosts/src/asset-pack-harness.ts`, harness tests | drafted |
151+
| Harness evidence exports inventory and coverage readback | `readingPipelineObservabilityInventory`, `readingPipelineObservabilityCoverage`, harness tests | drafted |
152+
| Terminal summaries and execution state expose pipeline, phase, PTRR, ThricifiedGeneration, prompt, tool, and schema fields | `terminal-pipeline-harness-client.ts`, Terminal harness tests | drafted |
153+
| Shared execution log header renders contract-aware identifiers without raw JSON first | `pipeline-execution-log-header.tsx`, header tests | drafted |
154+
| Gate 4 checker is wired to package scripts and CI | `scripts/check-v29-gate4-reading-pipeline-observability.mjs`, `package.json`, gate workflow | drafted |
155+
156+
## Gate 4 accepted boundaries
157+
158+
- Gate 4 does not add a new execution primitive; it projects existing execution, pipeline, PTRR, and ThricifiedGeneration primitives.
159+
- Gate 4 does not expose protected AssetPack source before settlement.
160+
- Gate 4 does not close disclosure-depth unlock, settlement repair, organization authority, or full browser proof.
161+
- Gate 4 does not add versioned API routes or source identifiers.
162+
163+
## Gate 4 completion condition
164+
165+
Gate 4 is complete when Reading pipeline observability is package-owned, stream events are contract-projected in the sandbox harness, Terminal renders the projection through shared execution components, focused package and UAPI tests pass, `check:v29-gate4` passes, CI invokes the checker and tests, docs name the implemented source surfaces, and the gate branch is committed and pushed for review into `version/v29`.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@
4747
"check:v29-gate1": "node scripts/check-v29-gate1-objectives-and-gating.mjs",
4848
"check:v29-gate2": "node scripts/check-v29-gate2-terminal-transaction-read-models.mjs",
4949
"check:v29-gate3": "node scripts/check-v29-gate3-wallet-signer-btc-operations.mjs",
50+
"check:v29-gate4": "node scripts/check-v29-gate4-reading-pipeline-observability.mjs",
5051
"check:spec-quality": "node scripts/run-bitcode-spec-quality.mjs --mode basic",
5152
"check:spec-quality:title": "node scripts/run-bitcode-spec-quality.mjs --mode strict-from-title",
5253
"check:spec-quality:v24": "node scripts/run-bitcode-spec-quality.mjs --mode strict-version --version V24",

packages/pipeline-hosts/src/__tests__/asset-pack-harness.test.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,14 @@ describe('asset-pack sandbox harness plan', () => {
187187
expect(source).toContain('rawModelResponsePresent');
188188
expect(source).toContain('parsedTypedOutputPresent');
189189
expect(source).toContain('inferenceAudit');
190+
expect(source).toContain('buildReadingPipelineObservabilityInventory');
191+
expect(source).toContain('resolveReadingPipelineTelemetryProjection');
192+
expect(source).toContain('summarizeReadingPipelineObservabilityCoverage');
193+
expect(source).toContain('readingPipelineTelemetry');
194+
expect(source).toContain('ptrrStepId');
195+
expect(source).toContain('thricifiedGenerationId');
196+
expect(source).toContain('outputSchema');
197+
expect(source).toContain('readingPipelineObservabilityCoverage');
190198
expect(source).toContain('Pipeline produced ');
191199
expect(source).toContain('sourceSafePreview,');
192200
expect(source).toContain('protectedSourceUnlock');

packages/pipeline-hosts/src/asset-pack-harness.ts

Lines changed: 51 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -392,6 +392,9 @@ let checkpointTimer = null;
392392
let heartbeatTimer = null;
393393
let checkpointInFlight = Promise.resolve();
394394
let lastCheckpointAt = 0;
395+
let readingPipelineObservabilityInventory = null;
396+
let resolveReadingPipelineTelemetryProjectionFn = null;
397+
let summarizeReadingPipelineObservabilityCoverageFn = null;
395398
396399
function normalizeResultState(candidate) {
397400
return ['worthy_fit', 'no_worthy_fit', 'blocked_readiness'].includes(candidate)
@@ -532,6 +535,15 @@ function summarizeStreamEvent(event) {
532535
parsedTypedOutput: summarizeInspectableValue(data.parsedTypedOutput ?? data.parsed ?? null),
533536
}
534537
: null;
538+
const readingPipelineTelemetry = resolveReadingPipelineTelemetryProjectionFn
539+
? resolveReadingPipelineTelemetryProjectionFn({
540+
...event,
541+
data: {
542+
...(data || {}),
543+
telemetryEvent: event,
544+
},
545+
})
546+
: null;
535547
return {
536548
type: 'pipeline-stream-event',
537549
stage: stageForStreamEvent(event),
@@ -558,6 +570,19 @@ function summarizeStreamEvent(event) {
558570
parsedTypedOutputPresent: Boolean(data?.parsedTypedOutput || data?.parsed),
559571
inferenceAudit: llmAudit,
560572
inspectable: summarizeLlmInspectable(event, event?.data ?? null),
573+
readingPipelineTelemetry,
574+
pipelineName: readingPipelineTelemetry?.pipelineName || null,
575+
phaseId: readingPipelineTelemetry?.phaseId || null,
576+
agentId: readingPipelineTelemetry?.agentId || null,
577+
ptrrStepId: readingPipelineTelemetry?.ptrrStepId || null,
578+
ptrrStepName: readingPipelineTelemetry?.ptrrStepName || null,
579+
thricifiedGenerationId: readingPipelineTelemetry?.thricifiedGenerationId || null,
580+
thricifiedFailsafe: readingPipelineTelemetry?.thricifiedFailsafe || null,
581+
promptTemplateId: readingPipelineTelemetry?.promptTemplateId || null,
582+
generationPromptIds: readingPipelineTelemetry?.generationPromptIds || null,
583+
toolId: readingPipelineTelemetry?.toolId || null,
584+
outputSchema: readingPipelineTelemetry?.outputSchema || null,
585+
returnType: readingPipelineTelemetry?.returnType || null,
561586
};
562587
}
563588
@@ -672,6 +697,10 @@ function checkpointEvidence(reason) {
672697
output,
673698
error,
674699
execution: execution ? summarizeExecution(execution) : null,
700+
readingPipelineObservabilityInventory,
701+
readingPipelineObservabilityCoverage: summarizeReadingPipelineObservabilityCoverageFn
702+
? summarizeReadingPipelineObservabilityCoverageFn(events)
703+
: null,
675704
events,
676705
startedAt,
677706
checkpointAt: new Date().toISOString(),
@@ -1523,14 +1552,26 @@ try {
15231552
manifestRoot = createHash('sha256').update(JSON.stringify(manifest)).digest('hex');
15241553
userId = process.env.BITCODE_PIPELINE_USER_ID || manifest.deposit?.userId || DEFAULT_USER_ID;
15251554
const [
1526-
{ assetPackPipeline, acceptReadNeed, buildAssetPackSourceSafePreview, isAcceptedReadNeed, synthesizeReadNeedForPipelineInput },
1555+
{
1556+
assetPackPipeline,
1557+
acceptReadNeed,
1558+
buildAssetPackSourceSafePreview,
1559+
buildReadingPipelineObservabilityInventory,
1560+
isAcceptedReadNeed,
1561+
resolveReadingPipelineTelemetryProjection,
1562+
summarizeReadingPipelineObservabilityCoverage,
1563+
synthesizeReadNeedForPipelineInput,
1564+
},
15271565
{ enablePipelineStreaming, factoryPipelineExecution },
15281566
{ applyAssetPackSettlementUnlockToPreview, buildAssetPackSettlementUnlock },
15291567
] = await Promise.all([
15301568
import('../../packages/pipelines/asset-pack/src/index'),
15311569
import('../../packages/pipelines-generics/src/index'),
15321570
import('../../packages/btd/src/settlement'),
15331571
]);
1572+
readingPipelineObservabilityInventory = buildReadingPipelineObservabilityInventory();
1573+
resolveReadingPipelineTelemetryProjectionFn = resolveReadingPipelineTelemetryProjection;
1574+
summarizeReadingPipelineObservabilityCoverageFn = summarizeReadingPipelineObservabilityCoverage;
15341575
execution = factoryPipelineExecution('asset_pack', undefined, {
15351576
pipelineName: 'asset_pack',
15361577
family: 'asset_pack',
@@ -1709,6 +1750,9 @@ try {
17091750
settlementAdmissible: ledgerSettlement.settlementAdmissible,
17101751
assetPackId: ledgerSettlement.assetPackId || null,
17111752
});
1753+
const readingPipelineObservabilityCoverage = summarizeReadingPipelineObservabilityCoverageFn
1754+
? summarizeReadingPipelineObservabilityCoverageFn(events)
1755+
: null;
17121756
17131757
const evidence = {
17141758
schema: 'bitcode.pipeline-harness.evidence',
@@ -1730,6 +1774,8 @@ try {
17301774
shippables: output?.shippables || null,
17311775
ledgerSettlement: output.ledgerSettlement,
17321776
execution: summarizeExecution(execution),
1777+
readingPipelineObservabilityInventory,
1778+
readingPipelineObservabilityCoverage,
17331779
events,
17341780
startedAt,
17351781
completedAt: new Date().toISOString(),
@@ -1774,6 +1820,10 @@ try {
17741820
output,
17751821
error,
17761822
execution: execution ? summarizeExecution(execution) : null,
1823+
readingPipelineObservabilityInventory,
1824+
readingPipelineObservabilityCoverage: summarizeReadingPipelineObservabilityCoverageFn
1825+
? summarizeReadingPipelineObservabilityCoverageFn(events)
1826+
: null,
17771827
events,
17781828
startedAt,
17791829
completedAt: new Date().toISOString(),

packages/pipelines/asset-pack/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
".": "./src/index.ts",
99
"./read-need": "./src/read-need.ts",
1010
"./reading-pipeline-contract": "./src/reading-pipeline-contract.ts",
11+
"./reading-pipeline-observability": "./src/reading-pipeline-observability.ts",
1112
"./depository-search": "./src/depository-search.ts"
1213
},
1314
"scripts": {

0 commit comments

Comments
 (0)