@mgiles/perk 3.1.0 → 3.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -0
- package/extension/authoring/gist/draft.ts +198 -0
- package/extension/authoring/gist/prose.ts +46 -0
- package/extension/authoring/gist/review.ts +133 -0
- package/extension/authoring/gist/save.ts +118 -0
- package/extension/authoring/objective/draft.ts +345 -0
- package/extension/{factories/objectiveDreamReport.ts → authoring/objective/dreamReportGate.ts} +74 -131
- package/extension/authoring/objective/planning.ts +124 -0
- package/extension/authoring/objective/prose.ts +103 -0
- package/extension/authoring/objective/review.ts +128 -0
- package/extension/authoring/objective/save.ts +224 -0
- package/extension/authoring/plan/draft.ts +84 -0
- package/extension/authoring/plan/prose.ts +41 -0
- package/extension/authoring/plan/review.ts +269 -0
- package/extension/authoring/plan/save.ts +256 -0
- package/extension/authoring/plan/source.ts +82 -0
- package/extension/authoring/refinement/context.ts +468 -0
- package/extension/authoring/refinement/draft.ts +261 -0
- package/extension/authoring/refinement/prose.ts +79 -0
- package/extension/authoring/refinement/review.ts +111 -0
- package/extension/authoring/refinement/save.ts +119 -0
- package/extension/authoring/review/approvalGate.ts +34 -0
- package/extension/authoring/review/draftContext.ts +68 -0
- package/extension/codeReview/automated.ts +352 -0
- package/extension/codeReview/submission.ts +229 -0
- package/extension/delivery/address.ts +295 -0
- package/extension/delivery/ci.ts +355 -0
- package/extension/delivery/commitCompact.ts +93 -0
- package/extension/delivery/conflictResolution.ts +247 -0
- package/extension/delivery/ready.ts +193 -0
- package/extension/delivery/stackConflict.ts +361 -0
- package/extension/delivery/stackObjective.ts +16 -0
- package/extension/delivery/stackReconcile.ts +165 -0
- package/extension/delivery/submit.ts +171 -0
- package/extension/index.ts +369 -359
- package/extension/learning/analystWave.ts +324 -0
- package/extension/learning/audit.ts +667 -0
- package/extension/learning/capture.ts +92 -0
- package/extension/learning/containment.ts +104 -0
- package/extension/{waves/dreamWave.ts → learning/dream.ts} +112 -94
- package/extension/learning/dreamAnalysis.ts +435 -0
- package/extension/{waves/dreamReducerWave.ts → learning/dreamReducer.ts} +46 -41
- package/extension/{waves → learning}/dreamReport.ts +35 -31
- package/extension/learning/harvest.ts +491 -0
- package/extension/learning/prose.ts +66 -0
- package/extension/learning/routing.ts +79 -0
- package/extension/pi/v1/bashScanTimeout.ts +64 -0
- package/extension/{doors/prReview.ts → pi/v1/codeReview/automated.ts} +215 -310
- package/extension/{doors/prReviewBrowser.ts → pi/v1/codeReview/browser.ts} +125 -57
- package/extension/{doors/hunkHandoff.ts → pi/v1/codeReview/checkout.ts} +12 -8
- package/extension/{doors/reviewWaveTools.ts → pi/v1/codeReview/reviewWave.ts} +169 -116
- package/extension/pi/v1/codeReview/stack.ts +606 -0
- package/extension/pi/v1/codeReview/submit.ts +354 -0
- package/extension/{doors/prReviewTerminal.ts → pi/v1/codeReview/terminal.ts} +32 -27
- package/extension/pi/v1/contextEvidence.ts +80 -0
- package/extension/pi/v1/contextInjection.ts +207 -0
- package/extension/{doors → pi/v1/delivery}/address.ts +163 -265
- package/extension/pi/v1/delivery/ci.ts +570 -0
- package/extension/pi/v1/delivery/commitCompact.ts +201 -0
- package/extension/pi/v1/delivery/conflictResolverEngine.ts +425 -0
- package/extension/{doors → pi/v1/delivery}/land.ts +128 -60
- package/extension/pi/v1/delivery/ready.ts +322 -0
- package/extension/pi/v1/delivery/stackConflictResolver.ts +172 -0
- package/extension/pi/v1/delivery/stackDrive.ts +120 -0
- package/extension/pi/v1/delivery/stackLand.ts +223 -0
- package/extension/pi/v1/delivery/stackRecover.ts +265 -0
- package/extension/pi/v1/delivery/stackStatus.ts +237 -0
- package/extension/pi/v1/delivery/stackSync.ts +658 -0
- package/extension/pi/v1/delivery/submit.ts +389 -0
- package/extension/pi/v1/delivery/submitConflict.ts +186 -0
- package/extension/pi/v1/draftReview.ts +431 -0
- package/extension/{doors → pi/v1}/draftReviewWaveTools.ts +141 -151
- package/extension/pi/v1/gist.ts +794 -0
- package/extension/pi/v1/learning/audit.ts +186 -0
- package/extension/pi/v1/learning/dream.ts +207 -0
- package/extension/{doors/learnFactory.ts → pi/v1/learning/factory.ts} +18 -65
- package/extension/{doors/harvestWaveTools.ts → pi/v1/learning/harvest.ts} +46 -100
- package/extension/pi/v1/learning/learn.ts +585 -0
- package/extension/{doors → pi/v1}/lifecycleGates.ts +14 -59
- package/extension/{factories → pi/v1}/objective.ts +53 -33
- package/extension/pi/v1/objectiveAuthoring.ts +672 -0
- package/extension/pi/v1/objectiveDreamGate.ts +160 -0
- package/extension/pi/v1/objectivePlanning.ts +776 -0
- package/extension/pi/v1/objectiveRefinement.ts +1320 -0
- package/extension/pi/v1/objectiveReview.ts +451 -0
- package/extension/{doors → pi/v1}/objectiveReviewBrowser.ts +259 -172
- package/extension/pi/v1/plan.ts +812 -0
- package/extension/pi/v1/planReview.ts +820 -0
- package/extension/{doors → pi/v1}/planReviewBrowser.ts +228 -152
- package/extension/{doors/annotationPush.ts → pi/v1/providers/annotations.ts} +158 -89
- package/extension/pi/v1/providers/plannotator.ts +487 -0
- package/extension/{doors → pi/v1/providers}/plannotatorHandoff.ts +152 -34
- package/extension/pi/v1/providers/selection.ts +43 -0
- package/extension/{adapters/planAdapterTombell.ts → pi/v1/providers/tombell.ts} +43 -72
- package/extension/pi/v1/review.ts +538 -0
- package/extension/pi/v1/reviewOutcome.ts +9 -0
- package/extension/pi/v1/scoutWave.ts +318 -0
- package/extension/{doors → pi/v1}/selfcheck.ts +4 -4
- package/extension/session/branchWorkflowSession.ts +60 -0
- package/extension/session/lifecycle.ts +644 -0
- package/extension/session/lifecycleGates.ts +64 -0
- package/extension/session/saveDestination.ts +87 -0
- package/extension/session/workflowSession.ts +971 -0
- package/extension/substrate/agentScratch.ts +27 -54
- package/extension/substrate/bashScanTimeout.ts +181 -0
- package/extension/substrate/bindingDelivery.ts +38 -30
- package/extension/substrate/bindings.ts +4 -5
- package/extension/substrate/cache.ts +64 -12
- package/extension/substrate/childRestrictions.ts +39 -0
- package/extension/substrate/coldDoor.ts +17 -1
- package/extension/substrate/config.ts +157 -19
- package/extension/substrate/git.ts +88 -6
- package/extension/substrate/modelVisible.ts +53 -0
- package/extension/substrate/paths.ts +2 -7
- package/extension/substrate/prompts.ts +22 -0
- package/extension/substrate/registry.ts +2 -0
- package/extension/substrate/resolverLease.ts +364 -0
- package/extension/substrate/sessionData.ts +85 -152
- package/extension/substrate/toolGating.ts +279 -84
- package/extension/substrate/unifiedDiff.ts +1 -1
- package/extension/substrate/workflowState.ts +191 -166
- package/extension/substrate/worktreeResolverLock.ts +261 -0
- package/extension/surfaces/surfaces.ts +79 -27
- package/extension/waves/adversarialReviewWave.ts +103 -48
- package/extension/waves/blockedReports.ts +59 -0
- package/extension/waves/draftReviewWave.ts +42 -42
- package/extension/waves/laneIdentity.ts +77 -0
- package/extension/waves/objectiveExplorerWave.ts +24 -24
- package/extension/waves/prReviewWave.ts +89 -77
- package/extension/waves/reportWave.ts +438 -578
- package/extension/waves/reviewClassifierWave.ts +22 -22
- package/extension/waves/rpcAdapter.ts +100 -15
- package/extension/waves/scoutWave.ts +192 -0
- package/extension/waves/transport.ts +480 -0
- package/extension/worker/sdkAdapter.ts +494 -0
- package/extension/worker/stageExecution.ts +679 -0
- package/extension/workerMain.ts +18 -19
- package/package.json +6 -4
- package/prompts/_fixtures/live.yaml +98 -10
- package/prompts/contexts/adapters/plannotator-gist.md +6 -0
- package/prompts/contexts/adapters/plannotator-objective.md +6 -0
- package/prompts/contexts/adapters/plannotator-plan.md +8 -1
- package/prompts/contexts/adapters/plannotator-refinement.md +22 -0
- package/prompts/contexts/adapters/tombell-plan.md +4 -0
- package/prompts/contexts/objective-refinement.md +17 -0
- package/prompts/contexts/plan-authoring.md +6 -5
- package/prompts/contexts/read-only.md +1 -1
- package/prompts/stages/conflict-resolution-continuation.md +9 -0
- package/prompts/stages/conflict-resolution.md +4 -4
- package/prompts/stages/objective-author/adopt.md +1 -1
- package/prompts/stages/objective-author/file.md +1 -1
- package/prompts/stages/objective-author/seed.md +1 -1
- package/prompts/stages/objective-plan/guidance.md +2 -2
- package/prompts/stages/objective-plan/seed.md +9 -1
- package/prompts/stages/objective-reconcile-ready.md +7 -0
- package/prompts/stages/objective-reconcile.md +1 -1
- package/prompts/stages/objective-refine/seed.md +18 -0
- package/prompts/stages/objective-review-browser.md +4 -4
- package/prompts/stages/objective-sync.md +1 -1
- package/prompts/stages/plan-review-browser.md +4 -4
- package/prompts/stages/pr-review-browser/active.md +3 -4
- package/prompts/stages/pr-review-browser/foreign.md +3 -4
- package/prompts/stages/pr-review-terminal/active.md +3 -3
- package/prompts/stages/pr-review-terminal/foreign.md +3 -3
- package/prompts/stages/pr-review.md +3 -3
- package/prompts/stages/stack-review/cold.md +1 -0
- package/prompts/stages/stack-review-browser/stack.md +22 -0
- package/shared/README.md +8 -3
- package/shared/bindings.yaml +6 -3
- package/shared/contracts.md +4499 -2147
- package/shared/fixtures/issues-table.json +130 -0
- package/shared/registry.yaml +29 -1
- package/shared/schemas/outputs/objective-node-engagement.schema.json +318 -0
- package/shared/schemas/outputs/objective-stack-status.schema.json +178 -2
- package/shared/schemas/outputs/pr-ready.schema.json +110 -2
- package/shared/schemas/outputs/pr-review-context.schema.json +54 -9
- package/shared/schemas/outputs/pr-review-stack-context.schema.json +196 -0
- package/extension/adapters/planAdapterPlannotator.ts +0 -362
- package/extension/doors/auditWaveTools.ts +0 -352
- package/extension/doors/ciExecutor.ts +0 -756
- package/extension/doors/commitCompact.ts +0 -251
- package/extension/doors/dreamWaveTools.ts +0 -475
- package/extension/doors/learn.ts +0 -655
- package/extension/doors/objectiveStack.ts +0 -1143
- package/extension/doors/prReviewDynamic.ts +0 -276
- package/extension/doors/ready.ts +0 -87
- package/extension/doors/submit.ts +0 -347
- package/extension/doors/submitPrReview.ts +0 -408
- package/extension/factories/gistAuthor.ts +0 -94
- package/extension/factories/gistDraft.ts +0 -265
- package/extension/factories/gistSave.ts +0 -251
- package/extension/factories/implementHere.ts +0 -116
- package/extension/factories/objectiveAuthor.ts +0 -98
- package/extension/factories/objectiveDraft.ts +0 -466
- package/extension/factories/objectivePlan.ts +0 -975
- package/extension/factories/objectiveSave.ts +0 -363
- package/extension/factories/planDraft.ts +0 -140
- package/extension/factories/planMode.ts +0 -205
- package/extension/factories/planReview.ts +0 -1237
- package/extension/factories/planSave.ts +0 -604
- package/extension/factories/planTitle.ts +0 -141
- package/extension/substrate/structuredOutput.ts +0 -202
- package/extension/waves/auditWave.ts +0 -312
- package/extension/waves/harvestWave.ts +0 -399
- package/extension/waves/learnWave.ts +0 -155
- package/extension/waves/memoryAdapter.ts +0 -139
- package/extension/waves/prReviewDynamicWave.ts +0 -777
- package/extension/worker/readOnlySession.ts +0 -294
- package/extension/worker/worker.ts +0 -899
- package/prompts/stages/pr-review-dynamic.md +0 -7
- package/shared/contracts-history.md +0 -605
|
@@ -0,0 +1,435 @@
|
|
|
1
|
+
// The learn-dream analysis workflow as ONE typed feature operation — the two-level
|
|
2
|
+
// ordering/recovery POLICY sitting above the analyst tier (`dream.ts`) and the reducer tier
|
|
3
|
+
// (`dreamReducer.ts`). The sequence: the first-level analyst wave (strict) → the compact
|
|
4
|
+
// analyst bundle written under the enforced aggregate byte budget → the three fixed reducer
|
|
5
|
+
// lanes — reducers launch ONLY after a complete first wave and an in-budget write — then, only
|
|
6
|
+
// when BOTH waves completed, the revalidation bracket against the manifest's stamped
|
|
7
|
+
// `commit_sha` (drift skips the finalize AND the marker set — a drifted wave is structurally
|
|
8
|
+
// undraftable) and, bracket ok, the finalize-in-place rewrite of the same fixed name
|
|
9
|
+
// (`finalizeDreamBundle`, the added `reducers` section). Two writes of ONE name: the analyst
|
|
10
|
+
// write feeds the reducers; the finalize rewrite is what the dream-report recovery consumes.
|
|
11
|
+
// The `dream_bundle_digest` workflow-state marker is the recovery-side freshness authority:
|
|
12
|
+
// cleared unconditionally at entry BEFORE the stale-bundle removal attempt (the invalidation
|
|
13
|
+
// record — a failed cleanup leaves prior files behind, but recovery refuses them), set to the
|
|
14
|
+
// sha256 of the finalized bytes only after the finalize write succeeds.
|
|
15
|
+
//
|
|
16
|
+
// Pi-free by construction: the `ReportWave` seam and the function-shaped
|
|
17
|
+
// capabilities (`markBundleDigest`, `bracket`, `writeBundle`, `removeBundle`) are the only
|
|
18
|
+
// mechanism edges — the adapter constructs and threads them; artifact storage is never owned
|
|
19
|
+
// here. Analyst and reducer reports are untrusted DATA, re-decoded in code before they reach
|
|
20
|
+
// the caller. (contracts.md §8.61/§8.65)
|
|
21
|
+
|
|
22
|
+
import { dirname, join } from "node:path";
|
|
23
|
+
import type { ReportWave, ReportWaveAttemptReceipt } from "../waves/reportWave.ts";
|
|
24
|
+
import {
|
|
25
|
+
type DreamLaneAnalysis,
|
|
26
|
+
type DreamLaneFailure,
|
|
27
|
+
type DreamManifest,
|
|
28
|
+
runDreamAnalystWave,
|
|
29
|
+
} from "./dream.ts";
|
|
30
|
+
import {
|
|
31
|
+
composeDreamBundle,
|
|
32
|
+
DREAM_ANALYSES_FILENAME,
|
|
33
|
+
DREAM_BUNDLE_BUDGET_BYTES,
|
|
34
|
+
type DreamReducerAnalysis,
|
|
35
|
+
type DreamReducerFailure,
|
|
36
|
+
finalizeDreamBundle,
|
|
37
|
+
nonKeepProposals,
|
|
38
|
+
runDreamReducerWave,
|
|
39
|
+
} from "./dreamReducer.ts";
|
|
40
|
+
|
|
41
|
+
/** The first-level analysis section every aggregate arm carries. */
|
|
42
|
+
interface AnalysisSection<C extends boolean> {
|
|
43
|
+
complete: C;
|
|
44
|
+
analyses: DreamLaneAnalysis[];
|
|
45
|
+
failures: DreamLaneFailure[];
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/** The reducer section on the two pre-launch skip arms. */
|
|
49
|
+
interface SkippedReducers<R extends "incomplete-analysis" | "budget-exceeded"> {
|
|
50
|
+
launched: false;
|
|
51
|
+
skip_reason: R;
|
|
52
|
+
complete: false;
|
|
53
|
+
reports: [];
|
|
54
|
+
failures: [];
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/** The reducer section after a launch (failures only when the wave stayed incomplete — plus
|
|
58
|
+
* the synthetic `digest-marker` entry on the failed-marker-set arm). */
|
|
59
|
+
interface LaunchedReducers<C extends boolean, F extends DreamReducerFailure[] | []> {
|
|
60
|
+
launched: true;
|
|
61
|
+
skip_reason: null;
|
|
62
|
+
complete: C;
|
|
63
|
+
reports: DreamReducerAnalysis[];
|
|
64
|
+
failures: F;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/** The written-bundle accounting (the happy write: in budget, `overflow_bytes` pinned 0). */
|
|
68
|
+
interface WrittenBundle {
|
|
69
|
+
path: string;
|
|
70
|
+
written: true;
|
|
71
|
+
bytes: number;
|
|
72
|
+
budget_bytes: number;
|
|
73
|
+
overflow_bytes: 0;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* The typed normalized aggregate — a discriminated union of the real post-launch arms over the
|
|
78
|
+
* exact wire fields (`complete`, `bundle` null/`written`, `bracket` null/`ok`, the
|
|
79
|
+
* `reducers.skip_reason` literals), each arm constructed at exactly one policy site, so
|
|
80
|
+
* contradictory combinations (e.g. `complete: true` with `bracket: null`) are unrepresentable
|
|
81
|
+
* while the serialized JSON stays byte-identical to the flat aggregate shape. Arms in policy
|
|
82
|
+
* order: incomplete first wave (no bundle, no bracket, no reducers) · over-budget (explicit
|
|
83
|
+
* accounting, nothing written — the loud corpus-growth tripwire, never truncation) ·
|
|
84
|
+
* incomplete reducer wave (the analyses-only bundle stays behind with a cleared marker) ·
|
|
85
|
+
* bracket drift (both waves done; finalize + marker set skipped — structurally undraftable) ·
|
|
86
|
+
* failed marker set (finalize landed; the unverified append is the synthetic `digest-marker`
|
|
87
|
+
* failure — honestly incomplete) · complete.
|
|
88
|
+
*/
|
|
89
|
+
export type DreamAnalysisAggregate = { attempts: ReportWaveAttemptReceipt[] } & (
|
|
90
|
+
| {
|
|
91
|
+
complete: false;
|
|
92
|
+
analysis: AnalysisSection<false>;
|
|
93
|
+
bracket: null;
|
|
94
|
+
bundle: null;
|
|
95
|
+
reducers: SkippedReducers<"incomplete-analysis">;
|
|
96
|
+
}
|
|
97
|
+
| {
|
|
98
|
+
complete: false;
|
|
99
|
+
analysis: AnalysisSection<true>;
|
|
100
|
+
bracket: null;
|
|
101
|
+
bundle: {
|
|
102
|
+
path: string;
|
|
103
|
+
written: false;
|
|
104
|
+
bytes: number;
|
|
105
|
+
budget_bytes: number;
|
|
106
|
+
overflow_bytes: number;
|
|
107
|
+
};
|
|
108
|
+
reducers: SkippedReducers<"budget-exceeded">;
|
|
109
|
+
}
|
|
110
|
+
| {
|
|
111
|
+
complete: false;
|
|
112
|
+
analysis: AnalysisSection<true>;
|
|
113
|
+
bracket: null;
|
|
114
|
+
bundle: WrittenBundle;
|
|
115
|
+
reducers: LaunchedReducers<false, DreamReducerFailure[]>;
|
|
116
|
+
}
|
|
117
|
+
| {
|
|
118
|
+
complete: false;
|
|
119
|
+
analysis: AnalysisSection<true>;
|
|
120
|
+
bracket: { ok: false; detail: string | null };
|
|
121
|
+
bundle: WrittenBundle;
|
|
122
|
+
reducers: LaunchedReducers<true, []>;
|
|
123
|
+
}
|
|
124
|
+
| {
|
|
125
|
+
complete: false;
|
|
126
|
+
analysis: AnalysisSection<true>;
|
|
127
|
+
bracket: { ok: true; detail: string | null };
|
|
128
|
+
bundle: WrittenBundle;
|
|
129
|
+
reducers: LaunchedReducers<true, DreamReducerFailure[]>;
|
|
130
|
+
}
|
|
131
|
+
| {
|
|
132
|
+
complete: true;
|
|
133
|
+
analysis: AnalysisSection<true>;
|
|
134
|
+
bracket: { ok: true; detail: string | null };
|
|
135
|
+
bundle: WrittenBundle;
|
|
136
|
+
reducers: LaunchedReducers<true, []>;
|
|
137
|
+
}
|
|
138
|
+
);
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* The typed dream-analysis outcome: ONE `io_failed` arm for every io site — the unverified
|
|
142
|
+
* marker clear, a failed stale-bundle removal, a bundle-write throw, a finalize-write throw —
|
|
143
|
+
* retaining the analyst analyses AND every already-recorded attempt receipt (empty arrays
|
|
144
|
+
* pre-launch); or the post-launch `aggregate`.
|
|
145
|
+
*/
|
|
146
|
+
export type DreamAnalysisOutcome =
|
|
147
|
+
| {
|
|
148
|
+
kind: "io_failed";
|
|
149
|
+
detail: string;
|
|
150
|
+
analyses: DreamLaneAnalysis[];
|
|
151
|
+
attempts: ReportWaveAttemptReceipt[];
|
|
152
|
+
}
|
|
153
|
+
| { kind: "aggregate"; details: DreamAnalysisAggregate };
|
|
154
|
+
|
|
155
|
+
/**
|
|
156
|
+
* The one dream-analysis entry op — the two-level ordering/recovery policy with every
|
|
157
|
+
* capability REQUIRED (the compiler walks every call site to an explicit choice; the adapter
|
|
158
|
+
* wires production seams, tests inject fakes). Caller preconditions: the manifest came from
|
|
159
|
+
* `decodeDreamManifest` and `verifyDocContainment` was run (the registered tool's pre-spawn
|
|
160
|
+
* ladder). The ordered sequence and each step's invariant are commented at their policy sites
|
|
161
|
+
* below: verified marker clear → entry-time bundle removal → the strict analyst wave → the
|
|
162
|
+
* budget check before reducer composition → the analyst-bundle write → the reducer wave → the
|
|
163
|
+
* §8.65 bracket (only after BOTH waves) → the finalize-in-place rewrite → the marker set.
|
|
164
|
+
*/
|
|
165
|
+
export async function analyzeDream(
|
|
166
|
+
wave: ReportWave,
|
|
167
|
+
opts: {
|
|
168
|
+
manifest: DreamManifest;
|
|
169
|
+
/** The `sha256:<hex>` digest of the manifest BYTES the caller read + decoded — bound into
|
|
170
|
+
* the finalized bundle so recovery authenticates the manifest too. */
|
|
171
|
+
manifestDigest: string;
|
|
172
|
+
/** The one function-shaped `dream_bundle_digest` marker capability: `null` is the
|
|
173
|
+
* invalidation clear; a string is the FINALIZED BUNDLE BYTES, digested by the capability
|
|
174
|
+
* owner (the digest convention lives with the adapter, not the feature); the boolean is
|
|
175
|
+
* the verified append+read-back result. The adapter wires the production
|
|
176
|
+
* `appendWorkflowState` closure; tests inject fakes. */
|
|
177
|
+
markBundleDigest: (finalized: string | null) => boolean;
|
|
178
|
+
/** The post-wave revalidation bracket (contracts.md §8.65) — REQUIRED on purpose: every
|
|
179
|
+
* call site (production and tests) makes an explicit choice; production wires
|
|
180
|
+
* `revalidationBracket(ctx.cwd, manifest.commit_sha)`. */
|
|
181
|
+
bracket: () => { ok: boolean; detail: string | null };
|
|
182
|
+
writeBundle: (path: string, content: string) => void;
|
|
183
|
+
removeBundle: (path: string) => void;
|
|
184
|
+
analystModel?: string;
|
|
185
|
+
reducerModel?: string;
|
|
186
|
+
signal?: AbortSignal;
|
|
187
|
+
},
|
|
188
|
+
): Promise<DreamAnalysisOutcome> {
|
|
189
|
+
// The invalidation record FIRST: any new attempt clears the digest marker before the removal
|
|
190
|
+
// attempt below, so a failed cleanup leaves prior files behind that recovery refuses. An
|
|
191
|
+
// UNVERIFIED clear refuses outright — with the old digest possibly still live, a failed
|
|
192
|
+
// removal below would leave the prior bundle+digest pair recoverable as fresh.
|
|
193
|
+
if (!opts.markBundleDigest(null)) {
|
|
194
|
+
return {
|
|
195
|
+
kind: "io_failed",
|
|
196
|
+
detail:
|
|
197
|
+
"dream_bundle_digest invalidation could not be verified — refusing to run the wave " +
|
|
198
|
+
"over possibly-recoverable prior finalized state",
|
|
199
|
+
analyses: [],
|
|
200
|
+
attempts: [],
|
|
201
|
+
};
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
// One path authority: the bundle lives beside the decode-time-bound manifest path — no
|
|
205
|
+
// second runScratchDir derivation inside this op. A failed removal refuses BEFORE any
|
|
206
|
+
// spawn (a typed io_failed, never an uncaught throw): launching over an irremovable stale
|
|
207
|
+
// bundle would break the current-attempt-only invariant.
|
|
208
|
+
const bundlePath = join(dirname(opts.manifest.manifestPath), DREAM_ANALYSES_FILENAME);
|
|
209
|
+
try {
|
|
210
|
+
opts.removeBundle(bundlePath);
|
|
211
|
+
} catch (error) {
|
|
212
|
+
const detail = error instanceof Error ? error.message : String(error);
|
|
213
|
+
return {
|
|
214
|
+
kind: "io_failed",
|
|
215
|
+
detail: `stale dream bundle removal failed at '${bundlePath}': ${detail}`,
|
|
216
|
+
analyses: [],
|
|
217
|
+
attempts: [],
|
|
218
|
+
};
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
const analysis = await runDreamAnalystWave(
|
|
222
|
+
wave,
|
|
223
|
+
{
|
|
224
|
+
manifest: opts.manifest,
|
|
225
|
+
...(opts.analystModel !== undefined ? { model: opts.analystModel } : {}),
|
|
226
|
+
},
|
|
227
|
+
opts.signal,
|
|
228
|
+
);
|
|
229
|
+
const attempts = [analysis.attempt];
|
|
230
|
+
|
|
231
|
+
if (!analysis.complete) {
|
|
232
|
+
// STRICT: no bundle write, no reducer launch after an incomplete first wave.
|
|
233
|
+
return {
|
|
234
|
+
kind: "aggregate",
|
|
235
|
+
details: {
|
|
236
|
+
complete: false,
|
|
237
|
+
analysis: { complete: false, analyses: analysis.analyses, failures: analysis.failures },
|
|
238
|
+
bracket: null,
|
|
239
|
+
bundle: null,
|
|
240
|
+
reducers: {
|
|
241
|
+
launched: false,
|
|
242
|
+
skip_reason: "incomplete-analysis",
|
|
243
|
+
complete: false,
|
|
244
|
+
reports: [],
|
|
245
|
+
failures: [],
|
|
246
|
+
},
|
|
247
|
+
attempts,
|
|
248
|
+
},
|
|
249
|
+
};
|
|
250
|
+
}
|
|
251
|
+
const analysisDetails = {
|
|
252
|
+
complete: true as const,
|
|
253
|
+
analyses: analysis.analyses,
|
|
254
|
+
failures: analysis.failures,
|
|
255
|
+
};
|
|
256
|
+
|
|
257
|
+
const { content, bytes } = composeDreamBundle(opts.manifest, analysis.analyses);
|
|
258
|
+
if (bytes > DREAM_BUNDLE_BUDGET_BYTES) {
|
|
259
|
+
// The loud corpus-growth tripwire: explicit accounting, nothing written, no reducers —
|
|
260
|
+
// never truncation (enforced BEFORE reducer task composition).
|
|
261
|
+
return {
|
|
262
|
+
kind: "aggregate",
|
|
263
|
+
details: {
|
|
264
|
+
complete: false,
|
|
265
|
+
analysis: analysisDetails,
|
|
266
|
+
bracket: null,
|
|
267
|
+
bundle: {
|
|
268
|
+
path: bundlePath,
|
|
269
|
+
written: false,
|
|
270
|
+
bytes,
|
|
271
|
+
budget_bytes: DREAM_BUNDLE_BUDGET_BYTES,
|
|
272
|
+
overflow_bytes: bytes - DREAM_BUNDLE_BUDGET_BYTES,
|
|
273
|
+
},
|
|
274
|
+
reducers: {
|
|
275
|
+
launched: false,
|
|
276
|
+
skip_reason: "budget-exceeded",
|
|
277
|
+
complete: false,
|
|
278
|
+
reports: [],
|
|
279
|
+
failures: [],
|
|
280
|
+
},
|
|
281
|
+
attempts,
|
|
282
|
+
},
|
|
283
|
+
};
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
try {
|
|
287
|
+
opts.writeBundle(bundlePath, content);
|
|
288
|
+
} catch (error) {
|
|
289
|
+
const detail = error instanceof Error ? error.message : String(error);
|
|
290
|
+
return {
|
|
291
|
+
kind: "io_failed",
|
|
292
|
+
detail: `dream bundle write failed: ${detail}`,
|
|
293
|
+
analyses: analysis.analyses,
|
|
294
|
+
attempts,
|
|
295
|
+
};
|
|
296
|
+
}
|
|
297
|
+
const bundleDetails: WrittenBundle = {
|
|
298
|
+
path: bundlePath,
|
|
299
|
+
written: true,
|
|
300
|
+
bytes,
|
|
301
|
+
budget_bytes: DREAM_BUNDLE_BUDGET_BYTES,
|
|
302
|
+
overflow_bytes: 0,
|
|
303
|
+
};
|
|
304
|
+
|
|
305
|
+
const reducers = await runDreamReducerWave(
|
|
306
|
+
wave,
|
|
307
|
+
{
|
|
308
|
+
manifestPath: opts.manifest.manifestPath,
|
|
309
|
+
bundlePath,
|
|
310
|
+
proposals: nonKeepProposals(analysis.analyses),
|
|
311
|
+
...(opts.reducerModel !== undefined ? { model: opts.reducerModel } : {}),
|
|
312
|
+
},
|
|
313
|
+
opts.signal,
|
|
314
|
+
);
|
|
315
|
+
attempts.push(reducers.attempt);
|
|
316
|
+
|
|
317
|
+
if (!reducers.complete) {
|
|
318
|
+
// An incomplete reducer wave leaves the analyses-only bundle and a cleared marker (the
|
|
319
|
+
// finalized decode refuses it); the bracket is never evaluated on an earlier arm.
|
|
320
|
+
return {
|
|
321
|
+
kind: "aggregate",
|
|
322
|
+
details: {
|
|
323
|
+
complete: false,
|
|
324
|
+
analysis: analysisDetails,
|
|
325
|
+
bracket: null,
|
|
326
|
+
bundle: bundleDetails,
|
|
327
|
+
reducers: {
|
|
328
|
+
launched: true,
|
|
329
|
+
skip_reason: null,
|
|
330
|
+
complete: false,
|
|
331
|
+
reports: reducers.reports,
|
|
332
|
+
failures: reducers.failures,
|
|
333
|
+
},
|
|
334
|
+
attempts,
|
|
335
|
+
},
|
|
336
|
+
};
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
// The post-wave revalidation bracket (§8.65): evaluated only after BOTH waves completed,
|
|
340
|
+
// BEFORE the finalize write. Drift skips the finalize AND the marker set — the entry
|
|
341
|
+
// clear stands, so recovery refuses the analyses-only bundle left behind (a drifted wave
|
|
342
|
+
// is structurally undraftable); the analyses + reducer reports stay in the aggregate for
|
|
343
|
+
// honest coverage reporting.
|
|
344
|
+
const bracket = opts.bracket();
|
|
345
|
+
if (!bracket.ok) {
|
|
346
|
+
return {
|
|
347
|
+
kind: "aggregate",
|
|
348
|
+
details: {
|
|
349
|
+
complete: false,
|
|
350
|
+
analysis: analysisDetails,
|
|
351
|
+
bracket: { ok: false, detail: bracket.detail },
|
|
352
|
+
bundle: bundleDetails,
|
|
353
|
+
reducers: {
|
|
354
|
+
launched: true,
|
|
355
|
+
skip_reason: null,
|
|
356
|
+
complete: true,
|
|
357
|
+
reports: reducers.reports,
|
|
358
|
+
failures: [],
|
|
359
|
+
},
|
|
360
|
+
attempts,
|
|
361
|
+
},
|
|
362
|
+
};
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
// Finalize in place — the SAME fixed name gains the reducers section (never a second
|
|
366
|
+
// file), then the digest marker publishes the finalized bytes for the recovery consumer.
|
|
367
|
+
// An incomplete reducer wave never reaches here: the analyses-only shape stays behind with
|
|
368
|
+
// a cleared marker, and the finalized decode refuses it.
|
|
369
|
+
const finalized = finalizeDreamBundle(
|
|
370
|
+
opts.manifest,
|
|
371
|
+
analysis.analyses,
|
|
372
|
+
reducers.reports,
|
|
373
|
+
opts.manifestDigest,
|
|
374
|
+
);
|
|
375
|
+
try {
|
|
376
|
+
opts.writeBundle(bundlePath, finalized);
|
|
377
|
+
} catch (error) {
|
|
378
|
+
const detail = error instanceof Error ? error.message : String(error);
|
|
379
|
+
return {
|
|
380
|
+
kind: "io_failed",
|
|
381
|
+
detail: `dream bundle finalize write failed: ${detail}`,
|
|
382
|
+
analyses: analysis.analyses,
|
|
383
|
+
attempts,
|
|
384
|
+
};
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
// A failed marker append (an unverified read-back) leaves the marker cleared by the
|
|
388
|
+
// entry clear — recovery refuses (fail-closed) — and the aggregate reports the outcome
|
|
389
|
+
// as honestly incomplete; re-running the wave repairs it.
|
|
390
|
+
if (!opts.markBundleDigest(finalized)) {
|
|
391
|
+
return {
|
|
392
|
+
kind: "aggregate",
|
|
393
|
+
details: {
|
|
394
|
+
complete: false,
|
|
395
|
+
analysis: analysisDetails,
|
|
396
|
+
bracket: { ok: true, detail: bracket.detail },
|
|
397
|
+
bundle: bundleDetails,
|
|
398
|
+
reducers: {
|
|
399
|
+
launched: true,
|
|
400
|
+
skip_reason: null,
|
|
401
|
+
complete: true,
|
|
402
|
+
reports: reducers.reports,
|
|
403
|
+
failures: [
|
|
404
|
+
{
|
|
405
|
+
angle: "digest-marker",
|
|
406
|
+
reason: "run-failed",
|
|
407
|
+
detail:
|
|
408
|
+
"dream_bundle_digest marker append failed its read-back — the marker stays " +
|
|
409
|
+
"cleared, so recovery refuses this bundle; re-run perk learn dream",
|
|
410
|
+
},
|
|
411
|
+
],
|
|
412
|
+
},
|
|
413
|
+
attempts,
|
|
414
|
+
},
|
|
415
|
+
};
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
return {
|
|
419
|
+
kind: "aggregate",
|
|
420
|
+
details: {
|
|
421
|
+
complete: true,
|
|
422
|
+
analysis: analysisDetails,
|
|
423
|
+
bracket: { ok: true, detail: bracket.detail },
|
|
424
|
+
bundle: bundleDetails,
|
|
425
|
+
reducers: {
|
|
426
|
+
launched: true,
|
|
427
|
+
skip_reason: null,
|
|
428
|
+
complete: true,
|
|
429
|
+
reports: reducers.reports,
|
|
430
|
+
failures: [],
|
|
431
|
+
},
|
|
432
|
+
attempts,
|
|
433
|
+
},
|
|
434
|
+
};
|
|
435
|
+
}
|
|
@@ -1,20 +1,27 @@
|
|
|
1
|
-
// The learn-dream reducer
|
|
2
|
-
//
|
|
1
|
+
// The learn-dream reducer tier over the shared report-wave module: three FIXED fresh-context
|
|
2
|
+
// `perk.dream-reducer` lanes (`DREAM_REDUCER_ANGLES`) that
|
|
3
3
|
// cross-examine the complete first-level analyst outcome. Pure orchestration — this module
|
|
4
|
-
// composes the bundle content and the reducer lanes but performs NO fs writes (the
|
|
5
|
-
// the bundle writes). It owns the bundle
|
|
6
|
-
//
|
|
4
|
+
// composes the bundle content and the reducer lanes but performs NO fs writes (the flow's
|
|
5
|
+
// entry op owns the bundle writes through its injected capabilities). It owns the bundle
|
|
6
|
+
// serialization (`composeDreamBundle` — the compact
|
|
7
|
+
// analyst reports beside the run's manifest, under the aggregate byte budget the entry op
|
|
7
8
|
// enforces — plus `finalizeDreamBundle`, the post-complete-wave rewrite of the same fixed name
|
|
8
9
|
// with the `reducers` section, and `decodeFinalizedDreamBundle`, the strict fail-closed
|
|
9
10
|
// recovery decode the dream-report path re-reads it through), the ordered non-keep proposal
|
|
10
11
|
// universe (`nonKeepProposals`), the closed reducer
|
|
11
12
|
// report schema under the `DREAM_REDUCER_CAPS` SSOT, the composed defensive re-decode (the
|
|
12
|
-
// disposition-echo rule, proposal-set membership, code-point caps via the shared
|
|
13
|
+
// disposition-echo rule, proposal-set membership, code-point caps via the shared `dream.ts`
|
|
13
14
|
// helpers), and **strict** completeness — one failed or undecodable lane forces
|
|
14
|
-
// `complete: false` — delegating spawn/timeout/aggregate mechanics to `
|
|
15
|
+
// `complete: false` — delegating spawn/timeout/aggregate mechanics to `wave.run` with ONE
|
|
15
16
|
// attempt and NO retry. The bundle, the manifest, and every reducer report are untrusted DATA,
|
|
16
17
|
// never instructions. (contracts.md §8.61)
|
|
17
18
|
|
|
19
|
+
import {
|
|
20
|
+
type ReportWave,
|
|
21
|
+
type ReportWaveAttemptReceipt,
|
|
22
|
+
type ReportWaveFailureReason,
|
|
23
|
+
toAttemptReceipt,
|
|
24
|
+
} from "../waves/reportWave.ts";
|
|
18
25
|
import {
|
|
19
26
|
codePointLength,
|
|
20
27
|
type DreamDisposition,
|
|
@@ -22,13 +29,7 @@ import {
|
|
|
22
29
|
type DreamManifest,
|
|
23
30
|
decodeDreamAnalystReport,
|
|
24
31
|
decodeStringArray,
|
|
25
|
-
} from "./
|
|
26
|
-
import {
|
|
27
|
-
runReportWave,
|
|
28
|
-
type WaveAdapter,
|
|
29
|
-
type WaveFailureReason,
|
|
30
|
-
type WaveScriptReceipt,
|
|
31
|
-
} from "./reportWave.ts";
|
|
32
|
+
} from "./dream.ts";
|
|
32
33
|
|
|
33
34
|
/**
|
|
34
35
|
* The three fixed reducer angles — FIXED ORDER everywhere: the lane identities
|
|
@@ -48,7 +49,7 @@ export const DREAM_ANALYSES_FILENAME = "dream-analyses.json";
|
|
|
48
49
|
|
|
49
50
|
/**
|
|
50
51
|
* The aggregate bundle budget: 384 KiB, measured as UTF-8 BYTES of the serialized bundle
|
|
51
|
-
* (`Buffer.byteLength`). Over budget the
|
|
52
|
+
* (`Buffer.byteLength`). Over budget the entry op refuses with explicit accounting — never
|
|
52
53
|
* truncation (a truncated bundle would corrupt stance evaluation; overflow is a loud
|
|
53
54
|
* corpus-growth tripwire).
|
|
54
55
|
*/
|
|
@@ -95,9 +96,9 @@ export interface DreamProposal {
|
|
|
95
96
|
* Serialize the versioned analyst bundle the reducers read FIRST:
|
|
96
97
|
* `{schema_version: "1", commit_sha, registry_mode, doc_count, total_bytes, lanes}` with the
|
|
97
98
|
* lanes carrying the re-decoded compact analyst reports (pretty-printed JSON + trailing
|
|
98
|
-
* newline; `bytes` = UTF-8 `Buffer.byteLength`). Caller preconditions (discharged by the
|
|
99
|
-
* and NOT re-checked here): the first wave was COMPLETE, so `analyses` covers the manifest's
|
|
100
|
-
* lanes exactly and is already in manifest lane order — the runner normalizes to `spec.
|
|
99
|
+
* newline; `bytes` = UTF-8 `Buffer.byteLength`). Caller preconditions (discharged by the entry
|
|
100
|
+
* op and NOT re-checked here): the first wave was COMPLETE, so `analyses` covers the manifest's
|
|
101
|
+
* lanes exactly and is already in manifest lane order — the runner normalizes to `spec.assignments`
|
|
101
102
|
* order, `buildDreamLanes` plans in manifest order, and `decodeDreamAnalystReport` normalizes
|
|
102
103
|
* each report's docs to manifest lane-doc order, so no re-sort layer exists here.
|
|
103
104
|
*/
|
|
@@ -122,7 +123,8 @@ export function composeDreamBundle(
|
|
|
122
123
|
* two-level wave (contracts.md §8.61): the `composeDreamBundle` wrapper fields unchanged
|
|
123
124
|
* (`schema_version` stays `"1"`) plus `manifest_digest` — the `sha256:<hex>` digest of the
|
|
124
125
|
* on-disk manifest BYTES this wave decoded (`analyses`/`reducers` must be in manifest lane /
|
|
125
|
-
* fixed `DREAM_REDUCER_ANGLES` order — guaranteed by the wave outcome shapes the
|
|
126
|
+
* fixed `DREAM_REDUCER_ANGLES` order — guaranteed by the wave outcome shapes the entry op
|
|
127
|
+
* passes) —
|
|
126
128
|
* binding the manifest into the authenticated chain (the `dream_bundle_digest` marker
|
|
127
129
|
* authenticates these bundle bytes; this field extends that authority to the manifest, so an
|
|
128
130
|
* at-rest manifest edit that preserves the echoed identity fields still refuses at recovery) —
|
|
@@ -255,23 +257,23 @@ export interface DreamReducerAnalysis {
|
|
|
255
257
|
/**
|
|
256
258
|
* One reducer failure — the `DreamLaneFailure` shape with ANGLE identity (a thin
|
|
257
259
|
* dream-specific remap so the aggregate's failure vocabulary stays angle-named, never
|
|
258
|
-
*
|
|
260
|
+
* wave-key-named): `angle` is the assigned angle slug, or `null` for wave-level failures.
|
|
259
261
|
*/
|
|
260
262
|
export interface DreamReducerFailure {
|
|
261
263
|
angle: string | null;
|
|
262
|
-
reason:
|
|
264
|
+
reason: ReportWaveFailureReason;
|
|
263
265
|
detail: string;
|
|
264
266
|
}
|
|
265
267
|
|
|
266
|
-
/** The typed reducer outcome: strict completeness with reports RETAINED even when incomplete.
|
|
268
|
+
/** The typed reducer outcome: strict completeness with reports RETAINED even when incomplete.
|
|
269
|
+
* `attempt` is the launch's flow-attributed output-free receipt (observability only), composed
|
|
270
|
+
* at the seam — its `requestedKeys` are the code-owned orchestration keys in launch order (=
|
|
271
|
+
* the angle slugs), receipt-correlation telemetry only (the `DreamWaveOutcome.attempt` twin). */
|
|
267
272
|
export interface DreamReducerOutcome {
|
|
268
273
|
complete: boolean;
|
|
269
274
|
reports: DreamReducerAnalysis[];
|
|
270
275
|
failures: DreamReducerFailure[];
|
|
271
|
-
|
|
272
|
-
/** The code-owned orchestration keys in launch order (= the angle slugs) —
|
|
273
|
-
* receipt-correlation telemetry only (the `DreamWaveOutcome.requestedKeys` twin). */
|
|
274
|
-
requestedKeys: string[];
|
|
276
|
+
attempt: ReportWaveAttemptReceipt;
|
|
275
277
|
}
|
|
276
278
|
|
|
277
279
|
function isRecord(value: unknown): value is Record<string, unknown> {
|
|
@@ -296,8 +298,11 @@ function nonNegativeInteger(value: unknown): value is number {
|
|
|
296
298
|
* - stances normalized to the `proposals` order (deterministic downstream);
|
|
297
299
|
* - EMPTY `stances` is valid — the re-decode never requires stance coverage: silence counts
|
|
298
300
|
* as non-endorsement downstream (the dream-report node's evidence bar, not this decode).
|
|
301
|
+
*
|
|
302
|
+
* Module-private: both callers (`runDreamReducerWave`, `decodeFinalizedDreamBundle`) live
|
|
303
|
+
* here — its refusal matrix is exercised through them.
|
|
299
304
|
*/
|
|
300
|
-
|
|
305
|
+
function decodeDreamReducerReport(
|
|
301
306
|
report: unknown,
|
|
302
307
|
angle: string,
|
|
303
308
|
proposals: readonly DreamProposal[],
|
|
@@ -605,7 +610,7 @@ export function decodeFinalizedDreamBundle(
|
|
|
605
610
|
|
|
606
611
|
/**
|
|
607
612
|
* Compose one reducer lane's task text IN CODE (short — the judgment rubric lives in the agent
|
|
608
|
-
* def, the `
|
|
613
|
+
* def, the `dream.ts` `laneTask` posture): the assigned angle, the bundle path (read
|
|
609
614
|
* FIRST), and the manifest path (doc identity, cluster rollups, findings).
|
|
610
615
|
*/
|
|
611
616
|
function reducerTask(angle: string, bundlePath: string, manifestPath: string): string {
|
|
@@ -623,19 +628,19 @@ function reducerTask(angle: string, bundlePath: string, manifestPath: string): s
|
|
|
623
628
|
* Run the dream reducer wave: three fixed fresh-context `perk.dream-reducer` lanes — key =
|
|
624
629
|
* label = the angle slug (code-owned, run-key-safe by construction) — under **strict**
|
|
625
630
|
* completeness, ONE attempt, NO retry, module-default timeout, the caller's `model?` as the
|
|
626
|
-
* workflow-level default (`[models.subagents] dream-reducer`, resolved by the
|
|
627
|
-
* time). Every schema-valid report is defensively re-decoded (`decodeDreamReducerReport`)
|
|
631
|
+
* workflow-level default (`[models.subagents] dream-reducer`, resolved by the adapter at
|
|
632
|
+
* execute time). Every schema-valid report is defensively re-decoded (`decodeDreamReducerReport`)
|
|
628
633
|
* against its assigned angle and the ordered non-keep proposal universe — a decode miss is a
|
|
629
|
-
* `malformed-report` failure carrying the angle identity; `complete` = the
|
|
634
|
+
* `malformed-report` failure carrying the angle identity; `complete` = the wave's
|
|
630
635
|
* completeness AND zero decode failures, with decoded reports retained even when incomplete
|
|
631
636
|
* and normalized to `DREAM_REDUCER_ANGLES` order.
|
|
632
637
|
*
|
|
633
|
-
* Caller preconditions (discharged by the launching
|
|
634
|
-
* COMPLETE, the bundle at `bundlePath` was written by the current call, and `proposals` is
|
|
638
|
+
* Caller preconditions (discharged by the launching entry op): the first-level analyst wave
|
|
639
|
+
* was COMPLETE, the bundle at `bundlePath` was written by the current call, and `proposals` is
|
|
635
640
|
* `nonKeepProposals` over the complete analyses.
|
|
636
641
|
*/
|
|
637
642
|
export async function runDreamReducerWave(
|
|
638
|
-
|
|
643
|
+
wave: ReportWave,
|
|
639
644
|
opts: {
|
|
640
645
|
manifestPath: string;
|
|
641
646
|
bundlePath: string;
|
|
@@ -645,11 +650,10 @@ export async function runDreamReducerWave(
|
|
|
645
650
|
signal?: AbortSignal,
|
|
646
651
|
): Promise<DreamReducerOutcome> {
|
|
647
652
|
const requestedKeys = [...DREAM_REDUCER_ANGLES];
|
|
648
|
-
const result = await
|
|
649
|
-
adapter,
|
|
653
|
+
const result = await wave.run(
|
|
650
654
|
{
|
|
651
655
|
flow: "dream-reducer",
|
|
652
|
-
|
|
656
|
+
assignments: DREAM_REDUCER_ANGLES.map((angle) => ({
|
|
653
657
|
key: angle,
|
|
654
658
|
label: angle,
|
|
655
659
|
agent: "perk.dream-reducer",
|
|
@@ -660,10 +664,10 @@ export async function runDreamReducerWave(
|
|
|
660
664
|
completeness: "strict",
|
|
661
665
|
...(opts.model !== undefined ? { model: opts.model } : {}),
|
|
662
666
|
},
|
|
663
|
-
signal,
|
|
667
|
+
{ signal },
|
|
664
668
|
);
|
|
665
669
|
|
|
666
|
-
// The lane keys ARE the angle slugs (code-owned, fixed), and the
|
|
670
|
+
// The lane keys ARE the angle slugs (code-owned, fixed), and the wave normalizes strictly
|
|
667
671
|
// against them — a keyed report/failure carries an angle by construction; wave-level failures
|
|
668
672
|
// carry `angle: null`.
|
|
669
673
|
const failures: DreamReducerFailure[] = result.failures.map((failure) => ({
|
|
@@ -694,7 +698,8 @@ export async function runDreamReducerWave(
|
|
|
694
698
|
complete: result.complete && decodeFailures === 0,
|
|
695
699
|
reports,
|
|
696
700
|
failures,
|
|
697
|
-
receipt:
|
|
698
|
-
|
|
701
|
+
// The transport receipt converts at this seam: ONE attempt, the fixed angle slugs as the
|
|
702
|
+
// pre-launch assignment manifest.
|
|
703
|
+
attempt: toAttemptReceipt("dream-reducer", 1, requestedKeys, result.receipt),
|
|
699
704
|
};
|
|
700
705
|
}
|