peaks-loop 4.0.0-beta.2 → 4.0.0-beta.3
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-en.md +16 -3
- package/README.md +16 -3
- package/dist/src/cli/commands/asset-commands.d.ts +45 -0
- package/dist/src/cli/commands/asset-commands.js +404 -0
- package/dist/src/cli/commands/bee-commands.d.ts +26 -0
- package/dist/src/cli/commands/bee-commands.js +169 -0
- package/dist/src/cli/commands/evolution-commands.d.ts +27 -0
- package/dist/src/cli/commands/evolution-commands.js +393 -0
- package/dist/src/cli/commands/loop-commands.d.ts +19 -13
- package/dist/src/cli/commands/loop-commands.js +147 -13
- package/dist/src/cli/commands/sediment-commands.js +9 -0
- package/dist/src/cli/commands/skill-loop-engineering-readiness-commands.d.ts +67 -0
- package/dist/src/cli/commands/skill-loop-engineering-readiness-commands.js +173 -0
- package/dist/src/cli/program.js +17 -0
- package/dist/src/services/crystallization/crystallization-service.d.ts +239 -0
- package/dist/src/services/crystallization/crystallization-service.js +397 -0
- package/dist/src/services/crystallization/crystallization-store.d.ts +75 -0
- package/dist/src/services/crystallization/crystallization-store.js +193 -0
- package/dist/src/services/crystallization/crystallization-types.d.ts +313 -0
- package/dist/src/services/crystallization/crystallization-types.js +299 -0
- package/dist/src/services/crystallization/evidence-brief-builder.d.ts +237 -0
- package/dist/src/services/crystallization/evidence-brief-builder.js +240 -0
- package/dist/src/services/evolution/evolution-service.d.ts +137 -0
- package/dist/src/services/evolution/evolution-service.js +281 -0
- package/dist/src/services/evolution/evolution-store.d.ts +57 -0
- package/dist/src/services/evolution/evolution-store.js +232 -0
- package/dist/src/services/evolution/evolution-types.d.ts +706 -0
- package/dist/src/services/evolution/evolution-types.js +286 -0
- package/dist/src/services/evolution/independent-evaluator-runner.d.ts +90 -0
- package/dist/src/services/evolution/independent-evaluator-runner.js +106 -0
- package/dist/src/services/evolution/regression-skeptic-runner.d.ts +64 -0
- package/dist/src/services/evolution/regression-skeptic-runner.js +113 -0
- package/dist/src/services/loop/loop-bee-relation-service.d.ts +107 -0
- package/dist/src/services/loop/loop-bee-relation-service.js +211 -0
- package/dist/src/services/loop/loop-bee-relation-store.d.ts +53 -0
- package/dist/src/services/loop/loop-bee-relation-store.js +130 -0
- package/dist/src/services/loop/loop-bee-relation-types.d.ts +118 -0
- package/dist/src/services/loop/loop-bee-relation-types.js +114 -0
- package/dist/src/services/loop/loop-release-service.d.ts +46 -0
- package/dist/src/services/loop/loop-release-service.js +66 -0
- package/dist/src/services/loop/loop-release-store.d.ts +55 -0
- package/dist/src/services/loop/loop-release-store.js +134 -0
- package/dist/src/services/loop/loop-release-types.d.ts +250 -0
- package/dist/src/services/loop/loop-release-types.js +162 -0
- package/dist/src/services/share/bundle-reader.d.ts +100 -0
- package/dist/src/services/share/bundle-reader.js +434 -0
- package/dist/src/services/share/bundle-types.d.ts +392 -0
- package/dist/src/services/share/bundle-types.js +318 -0
- package/dist/src/services/share/bundle-writer.d.ts +97 -0
- package/dist/src/services/share/bundle-writer.js +429 -0
- package/dist/src/services/share/run-state-contract.d.ts +133 -0
- package/dist/src/services/share/run-state-contract.js +138 -0
- package/dist/src/services/skillhub/release-import.js +7 -2
- package/dist/src/services/skillhub/release-retain.js +6 -1
- package/dist/src/services/skillhub/sqlite-store.js +17 -1
- package/dist/src/services/skillhub/types.d.ts +10 -0
- package/dist/src/services/standards/loop-engineering-lint.d.ts +38 -0
- package/dist/src/services/standards/loop-engineering-lint.js +101 -0
- package/dist/src/services/standards/loop-engineering-readiness-lint.d.ts +111 -0
- package/dist/src/services/standards/loop-engineering-readiness-lint.js +248 -0
- package/dist/src/shared/version.d.ts +1 -1
- package/dist/src/shared/version.js +1 -1
- package/examples/video-demo/README.md +57 -0
- package/examples/video-demo/out/en-closing-960.png +0 -0
- package/examples/video-demo/out/zh-closing-960.png +0 -0
- package/examples/video-demo/preview/peaks-loop-demo-en.mp4 +0 -0
- package/examples/video-demo/preview/peaks-loop-demo.mp4 +0 -0
- package/package.json +6 -2
- package/skills/peaks-code/SKILL.md +13 -0
- package/skills/peaks-content/SKILL.md +272 -0
- package/skills/peaks-issue-fix-orchestrator/SKILL.md +307 -0
|
@@ -0,0 +1,299 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
/**
|
|
3
|
+
* CrystallizationEvent — spec §4.5 / §4.7 / §5.
|
|
4
|
+
*
|
|
5
|
+
* M5 scope: the crystallization_event table + the 4-section
|
|
6
|
+
* evidence_brief projection (spec §4.7 / §10 RL-7). Every
|
|
7
|
+
* user-facing recommendation is gated on the brief being complete;
|
|
8
|
+
* the schema below enforces the 4-section shape at parse time.
|
|
9
|
+
*
|
|
10
|
+
* Hard rules enforced at the boundary (and re-asserted in the
|
|
11
|
+
* service layer):
|
|
12
|
+
*
|
|
13
|
+
* 1. The 4 brief sections (what_happened / why_it_matters /
|
|
14
|
+
* what_learned / what_action) are ALL required. A partial
|
|
15
|
+
* brief is a hard parse error (`MISSING_BRIEF_SECTION`),
|
|
16
|
+
* and `parseCrystallizationEvent` will throw.
|
|
17
|
+
* 2. The trigger enum mirrors spec §4.5 exactly:
|
|
18
|
+
* user_explicit | llm_suggested | success_default_prompt |
|
|
19
|
+
* similar_task_recurrence.
|
|
20
|
+
* 3. The event's own lifecycle_status is ORTHOGONAL to the
|
|
21
|
+
* created/updated loop_release.lifecycle_status — the same
|
|
22
|
+
* asset can have many crystallization events over its life.
|
|
23
|
+
* 4. source_trace_pointers are stable ids (the workflow trace
|
|
24
|
+
* id space), not path strings — the column is JSON-array of
|
|
25
|
+
* strings.
|
|
26
|
+
* 5. The brief section guard is implemented as a `.refine(...)`
|
|
27
|
+
* on the input schema — the canonical 4 keys must be present
|
|
28
|
+
* with non-empty values (the spec mandates 1-2 sentences per
|
|
29
|
+
* section; an empty string would be a degenerate brief).
|
|
30
|
+
*
|
|
31
|
+
* Out of scope (deferred to later slices):
|
|
32
|
+
* - cross-event aggregation (loop crystallized N times).
|
|
33
|
+
* - brief rewrite-on-update semantics (M8 dogfood).
|
|
34
|
+
*/
|
|
35
|
+
/* ---------------------------------------------------------------------- */
|
|
36
|
+
/* Trigger — §4.5 / §5.4 */
|
|
37
|
+
/* ---------------------------------------------------------------------- */
|
|
38
|
+
export const CrystallizationTriggerSchema = z.enum([
|
|
39
|
+
"user_explicit",
|
|
40
|
+
"llm_suggested",
|
|
41
|
+
"success_default_prompt",
|
|
42
|
+
"similar_task_recurrence",
|
|
43
|
+
]);
|
|
44
|
+
export const CRYSTALLIZATION_TRIGGERS = [
|
|
45
|
+
"user_explicit",
|
|
46
|
+
"llm_suggested",
|
|
47
|
+
"success_default_prompt",
|
|
48
|
+
"similar_task_recurrence",
|
|
49
|
+
];
|
|
50
|
+
/* ---------------------------------------------------------------------- */
|
|
51
|
+
/* Lifecycle status — §5.6 (event-scoped, not asset-scoped) */
|
|
52
|
+
/* ---------------------------------------------------------------------- */
|
|
53
|
+
export const CrystallizationEventStatusSchema = z.enum([
|
|
54
|
+
"candidate",
|
|
55
|
+
"stable",
|
|
56
|
+
"retired",
|
|
57
|
+
]);
|
|
58
|
+
/* ---------------------------------------------------------------------- */
|
|
59
|
+
/* EvidenceBrief — §4.7 / §10 RL-7. REQUIRED 4-section shape. */
|
|
60
|
+
/* ---------------------------------------------------------------------- */
|
|
61
|
+
/**
|
|
62
|
+
* The four brief sections. Spec §4.7 lists them as NL short
|
|
63
|
+
* sections; the service layer mandates 1-2 sentences (what_action
|
|
64
|
+
* is a single sentence per the spec). The Zod constraints below
|
|
65
|
+
* enforce NON-EMPTY strings. The brief-section guard (see
|
|
66
|
+
* `EvidenceBriefSchema.refine` below) rejects any payload missing
|
|
67
|
+
* one of the four keys, regardless of section content — it is
|
|
68
|
+
* the canonical hard gate per spec §10 RL-7.
|
|
69
|
+
*/
|
|
70
|
+
const BriefSectionSchema = z
|
|
71
|
+
.string()
|
|
72
|
+
.trim()
|
|
73
|
+
.min(1, "brief section must be non-empty natural language")
|
|
74
|
+
.max(4000);
|
|
75
|
+
/**
|
|
76
|
+
* EvidenceBrief — the 4-section brief (spec §4.7).
|
|
77
|
+
*
|
|
78
|
+
* Hard shape invariant: ALL FOUR KEYS must be present at parse
|
|
79
|
+
* time, with non-empty NL content. The `.refine(...)` guard is
|
|
80
|
+
* what makes a brief a "brief" — without it, the projection is
|
|
81
|
+
* not a brief and the recommendation MUST NOT be rendered
|
|
82
|
+
* (service layer enforces this; Zod makes it a parse-time
|
|
83
|
+
* guarantee).
|
|
84
|
+
*
|
|
85
|
+
* Field semantics:
|
|
86
|
+
* - what_happened — 1-2 sentence factual account of the run.
|
|
87
|
+
* - why_it_matters — 1-2 sentence explanation of why this is
|
|
88
|
+
* worth promoting.
|
|
89
|
+
* - what_learned — 1-2 sentence learning: failure modes
|
|
90
|
+
* encoded, preferences extracted.
|
|
91
|
+
* - what_action — 1-sentence recommended action with
|
|
92
|
+
* rationale.
|
|
93
|
+
*/
|
|
94
|
+
export const EvidenceBriefSchema = z
|
|
95
|
+
.object({
|
|
96
|
+
what_happened: BriefSectionSchema,
|
|
97
|
+
why_it_matters: BriefSectionSchema,
|
|
98
|
+
what_learned: BriefSectionSchema,
|
|
99
|
+
what_action: BriefSectionSchema,
|
|
100
|
+
})
|
|
101
|
+
.strict()
|
|
102
|
+
.refine((b) => typeof b.what_happened === "string" &&
|
|
103
|
+
b.what_happened.trim().length > 0 &&
|
|
104
|
+
typeof b.why_it_matters === "string" &&
|
|
105
|
+
b.why_it_matters.trim().length > 0 &&
|
|
106
|
+
typeof b.what_learned === "string" &&
|
|
107
|
+
b.what_learned.trim().length > 0 &&
|
|
108
|
+
typeof b.what_action === "string" &&
|
|
109
|
+
b.what_action.trim().length > 0, {
|
|
110
|
+
message: "evidence_brief must contain all 4 sections (what_happened, why_it_matters, what_learned, what_action) with non-empty content (spec §4.7 / RL-7)",
|
|
111
|
+
path: [],
|
|
112
|
+
});
|
|
113
|
+
/**
|
|
114
|
+
* Helper for downstream code that needs to know whether a parsed
|
|
115
|
+
* brief satisfies the 4-section rule. Useful for the CLI when a
|
|
116
|
+
* payload arrived from the LLM and the brief-section guard has
|
|
117
|
+
* already passed — it returns the section count, always 4 here.
|
|
118
|
+
*/
|
|
119
|
+
export function hasAllFourBriefSections(brief) {
|
|
120
|
+
return (typeof brief.what_happened === "string" &&
|
|
121
|
+
brief.what_happened.trim().length > 0 &&
|
|
122
|
+
typeof brief.why_it_matters === "string" &&
|
|
123
|
+
brief.why_it_matters.trim().length > 0 &&
|
|
124
|
+
typeof brief.what_learned === "string" &&
|
|
125
|
+
brief.what_learned.trim().length > 0 &&
|
|
126
|
+
typeof brief.what_action === "string" &&
|
|
127
|
+
brief.what_action.trim().length > 0);
|
|
128
|
+
}
|
|
129
|
+
/* ---------------------------------------------------------------------- */
|
|
130
|
+
/* CrystallizationEvent — §4.5 */
|
|
131
|
+
/* ---------------------------------------------------------------------- */
|
|
132
|
+
/**
|
|
133
|
+
* Structurally referenced columns: pointers to optional loop_release /
|
|
134
|
+
* bee_release rows. All four are optional — a crystallization event
|
|
135
|
+
* may exist for "trace only" / "discard" choices that touch no durable
|
|
136
|
+
* asset. Set is governed by the service layer's pre-run gate.
|
|
137
|
+
*/
|
|
138
|
+
const OptionalLoopId = z
|
|
139
|
+
.string()
|
|
140
|
+
.min(1)
|
|
141
|
+
.max(64)
|
|
142
|
+
.regex(/^[a-z][a-z0-9]*(-[a-z0-9]+)*$/, {
|
|
143
|
+
message: "loop_release_id must be kebab-case starting with a lowercase letter",
|
|
144
|
+
})
|
|
145
|
+
.optional();
|
|
146
|
+
const OptionalBeeId = z
|
|
147
|
+
.number()
|
|
148
|
+
.int()
|
|
149
|
+
.positive()
|
|
150
|
+
.max(2 ** 31 - 1, "bee_release_id out of 32-bit range")
|
|
151
|
+
.optional();
|
|
152
|
+
/**
|
|
153
|
+
* Zod schema for the create payload (CrystallizationEventInput).
|
|
154
|
+
*
|
|
155
|
+
* Re-validates the evidence_brief inline; calling code may ALSO call
|
|
156
|
+
* `EvidenceBriefSchema.parse` separately if it builds the brief out
|
|
157
|
+
* of band. The CrystallizationEvent input schema wires the same
|
|
158
|
+
* guard so a brief cannot sneak through via a partial-input path.
|
|
159
|
+
*/
|
|
160
|
+
export const CrystallizationEventInputSchema = z.object({
|
|
161
|
+
trigger: CrystallizationTriggerSchema,
|
|
162
|
+
evidence_brief: EvidenceBriefSchema,
|
|
163
|
+
evidence_bullets: z
|
|
164
|
+
.array(z.string().trim().min(1).max(1000))
|
|
165
|
+
.default([]),
|
|
166
|
+
source_trace_pointers: z
|
|
167
|
+
.array(z.string().trim().min(1).max(256))
|
|
168
|
+
.default([]),
|
|
169
|
+
evaluator_summary: z
|
|
170
|
+
.string()
|
|
171
|
+
.trim()
|
|
172
|
+
.max(4000)
|
|
173
|
+
.default(""),
|
|
174
|
+
user_decision_summary: z
|
|
175
|
+
.string()
|
|
176
|
+
.trim()
|
|
177
|
+
.max(4000)
|
|
178
|
+
.default(""),
|
|
179
|
+
created_loop_release_id: OptionalLoopId,
|
|
180
|
+
updated_loop_release_id: OptionalLoopId,
|
|
181
|
+
created_bee_release_id: OptionalBeeId,
|
|
182
|
+
updated_bee_release_id: OptionalBeeId,
|
|
183
|
+
lifecycle_status: CrystallizationEventStatusSchema.default("candidate"),
|
|
184
|
+
});
|
|
185
|
+
/**
|
|
186
|
+
* Full persisted row schema. Adds `id` (the event id) and stamps
|
|
187
|
+
* `schema_version` to the fixed literal `peaks.crystallization/1`.
|
|
188
|
+
*
|
|
189
|
+
* Brief section guard is INHERITED from `EvidenceBriefSchema.refine`
|
|
190
|
+
* because `EvidenceBriefSchema` is embedded; the service layer still
|
|
191
|
+
* re-asserts the guard so a hand-crafted row cannot bypass Zod at
|
|
192
|
+
* the store boundary.
|
|
193
|
+
*/
|
|
194
|
+
export const CrystallizationEventSchema = CrystallizationEventInputSchema.extend({
|
|
195
|
+
id: z
|
|
196
|
+
.string()
|
|
197
|
+
.min(1)
|
|
198
|
+
.max(128)
|
|
199
|
+
.regex(/^crys-[0-9a-f]{8,}$/, {
|
|
200
|
+
message: "id must start with 'crys-' followed by a hex suffix (spec §4.5)",
|
|
201
|
+
}),
|
|
202
|
+
schema_version: z
|
|
203
|
+
.literal("peaks.crystallization/1")
|
|
204
|
+
.default("peaks.crystallization/1"),
|
|
205
|
+
created_at: z.string().datetime(),
|
|
206
|
+
});
|
|
207
|
+
/**
|
|
208
|
+
* Convenience: strict-parse an unknown payload into a
|
|
209
|
+
* CrystallizationEvent row. Throws ZodError on failure — including
|
|
210
|
+
* when the brief is missing a section (the `.refine` guard fires).
|
|
211
|
+
*
|
|
212
|
+
* Use this at every parse boundary (CLI input, store insertion).
|
|
213
|
+
*/
|
|
214
|
+
export function parseCrystallizationEvent(input) {
|
|
215
|
+
return CrystallizationEventSchema.parse(input);
|
|
216
|
+
}
|
|
217
|
+
/**
|
|
218
|
+
* Convenience: strict-parse an unknown payload as a standalone
|
|
219
|
+
* EvidenceBrief. Throws ZodError on failure.
|
|
220
|
+
*/
|
|
221
|
+
export function parseEvidenceBrief(input) {
|
|
222
|
+
return EvidenceBriefSchema.parse(input);
|
|
223
|
+
}
|
|
224
|
+
/**
|
|
225
|
+
* Safe-parse twin of parseCrystallizationEvent. Returns a Result-like
|
|
226
|
+
* envelope so callers (CLI / tests) can render findings without
|
|
227
|
+
* try/catch noise. The `code` field is `MISSING_BRIEF_SECTION` when
|
|
228
|
+
* the brief refine guard trips OR when ANY brief-section key is
|
|
229
|
+
* missing (spec §10 RL-7) — distinguishes brief failures from
|
|
230
|
+
* generic validation errors.
|
|
231
|
+
*/
|
|
232
|
+
export function safeParseCrystallizationEvent(input) {
|
|
233
|
+
const r = CrystallizationEventSchema.safeParse(input);
|
|
234
|
+
if (r.success)
|
|
235
|
+
return { ok: true, row: r.data };
|
|
236
|
+
const findings = r.error.issues.map((i) => ({
|
|
237
|
+
path: i.path.join("."),
|
|
238
|
+
message: i.message,
|
|
239
|
+
}));
|
|
240
|
+
const isBrief = isBriefSectionFailure(r.error.issues);
|
|
241
|
+
return isBrief
|
|
242
|
+
? { ok: false, code: "MISSING_BRIEF_SECTION", findings }
|
|
243
|
+
: { ok: false, findings };
|
|
244
|
+
}
|
|
245
|
+
/**
|
|
246
|
+
* Safe-parse twin of parseEvidenceBrief. Same Result-like envelope
|
|
247
|
+
* shape; same MISSING_BRIEF_SECTION code mapping (covers both
|
|
248
|
+
* refine-guard failures and per-section missing/empty failures).
|
|
249
|
+
*/
|
|
250
|
+
export function safeParseEvidenceBrief(input) {
|
|
251
|
+
const r = EvidenceBriefSchema.safeParse(input);
|
|
252
|
+
if (r.success)
|
|
253
|
+
return { ok: true, row: r.data };
|
|
254
|
+
const findings = r.error.issues.map((i) => ({
|
|
255
|
+
path: i.path.join("."),
|
|
256
|
+
message: i.message,
|
|
257
|
+
}));
|
|
258
|
+
const isBrief = isBriefSectionFailure(r.error.issues);
|
|
259
|
+
return isBrief
|
|
260
|
+
? { ok: false, code: "MISSING_BRIEF_SECTION", findings }
|
|
261
|
+
: { ok: false, findings };
|
|
262
|
+
}
|
|
263
|
+
/**
|
|
264
|
+
* Decide whether a ZodIssue[] is a "brief section" failure: every
|
|
265
|
+
* issue points at one of the four required keys (the section is
|
|
266
|
+
* missing, or empty after trim), OR the explicit refine-guard issue
|
|
267
|
+
* is present. Used by both `safeParseCrystallizationEvent` and
|
|
268
|
+
* `safeParseEvidenceBrief` so callers see a single
|
|
269
|
+
* `MISSING_BRIEF_SECTION` code regardless of which Zod boundary
|
|
270
|
+
* caught the failure.
|
|
271
|
+
*/
|
|
272
|
+
function isBriefSectionFailure(issues) {
|
|
273
|
+
if (issues.length === 0)
|
|
274
|
+
return false;
|
|
275
|
+
// Explicit refine guard (EvidenceBriefSchema.refine message).
|
|
276
|
+
if (issues.some((i) => i.message.includes("evidence_brief must contain all 4 sections"))) {
|
|
277
|
+
return true;
|
|
278
|
+
}
|
|
279
|
+
// Per-section Zod failures (min(1) on each section key, or
|
|
280
|
+
// too_small, or invalid_type). Each issue's path will be either
|
|
281
|
+
// the section key (`what_happened`) OR the parent `evidence_brief`
|
|
282
|
+
// — Zod reports missing-key issues against the parent object.
|
|
283
|
+
return issues.every((i) => {
|
|
284
|
+
const path = i.path.join(".");
|
|
285
|
+
if (path === "evidence_brief")
|
|
286
|
+
return true;
|
|
287
|
+
if (i.path.length >= 2 && i.path[0] === "evidence_brief") {
|
|
288
|
+
const key = i.path[i.path.length - 1];
|
|
289
|
+
return (key === "what_happened" ||
|
|
290
|
+
key === "why_it_matters" ||
|
|
291
|
+
key === "what_learned" ||
|
|
292
|
+
key === "what_action");
|
|
293
|
+
}
|
|
294
|
+
return (path === "what_happened" ||
|
|
295
|
+
path === "why_it_matters" ||
|
|
296
|
+
path === "what_learned" ||
|
|
297
|
+
path === "what_action");
|
|
298
|
+
});
|
|
299
|
+
}
|
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { type EvidenceBrief } from "./crystallization-types.js";
|
|
3
|
+
/**
|
|
4
|
+
* EvidenceBriefBuilder — spec §4.7 / §10 RL-7.
|
|
5
|
+
*
|
|
6
|
+
* The brief is a 4-section natural-language projection that MUST
|
|
7
|
+
* accompany every user-facing recommendation. The shape guard is
|
|
8
|
+
* encoded in `EvidenceBriefSchema` (see crystallization-types.ts);
|
|
9
|
+
* this module is the LLM-side entry point that PRODUCES the brief
|
|
10
|
+
* from a finished trace + evaluator summary and the validator that
|
|
11
|
+
* REFUSES to render a recommendation payload without all 4 sections.
|
|
12
|
+
*
|
|
13
|
+
* Hard rules (mirrored from spec):
|
|
14
|
+
*
|
|
15
|
+
* 1. Every section must be a non-empty NL string (1-2 sentences
|
|
16
|
+
* for what_happened / why_it_matters / what_learned; 1
|
|
17
|
+
* sentence for what_action). An empty section is a hard
|
|
18
|
+
* `MISSING_BRIEF_SECTION` error.
|
|
19
|
+
*
|
|
20
|
+
* 2. The build path is lenient on raw prose and strict on the
|
|
21
|
+
* final shape — `buildEvidenceBrief` calls
|
|
22
|
+
* `EvidenceBriefSchema.parse(...)` so a partial brief throws
|
|
23
|
+
* before reaching the database.
|
|
24
|
+
*
|
|
25
|
+
* 3. `renderRecommendationPayload` refuses to return a
|
|
26
|
+
* recommendation envelope unless the brief passes the 4-section
|
|
27
|
+
* guard. This is the CLI's single source of truth for "may I
|
|
28
|
+
* show this to the user?".
|
|
29
|
+
*
|
|
30
|
+
* 4. The `evaluator_summary` is a separate field on the
|
|
31
|
+
* crystallization_event row (spec §4.5) and is NOT part of the
|
|
32
|
+
* brief. It feeds the broader recommendation envelope.
|
|
33
|
+
*
|
|
34
|
+
* Out of scope (deferred to later slices):
|
|
35
|
+
* - LLM-authored brief generation from live trace evidence (M8 dogfood).
|
|
36
|
+
* - brief rewrite-on-update semantics.
|
|
37
|
+
*/
|
|
38
|
+
/**
|
|
39
|
+
* The minimum viable trace shape that the builder needs to render
|
|
40
|
+
* a brief. The trace is the EVIDENCE; the builder is format-stable
|
|
41
|
+
* so a future slice can swap in a richer trace source without
|
|
42
|
+
* editing every caller.
|
|
43
|
+
*/
|
|
44
|
+
export declare const BriefTraceInputSchema: z.ZodObject<{
|
|
45
|
+
trace_id: z.ZodString;
|
|
46
|
+
/**
|
|
47
|
+
* The full NL recap of the run. Required for what_happened.
|
|
48
|
+
* 1-2 sentences is the spec guidance; the builder does not
|
|
49
|
+
* truncate, but tests passing multi-paragraph input will be
|
|
50
|
+
* warned at the Zod boundary (max 4000 chars per section).
|
|
51
|
+
*/
|
|
52
|
+
what_happened: z.ZodString;
|
|
53
|
+
/**
|
|
54
|
+
* The "why this matters" recap. Required for why_it_matters.
|
|
55
|
+
*/
|
|
56
|
+
why_it_matters: z.ZodString;
|
|
57
|
+
/**
|
|
58
|
+
* Failure-mode and preference-extraction recap. Required for
|
|
59
|
+
* what_learned.
|
|
60
|
+
*/
|
|
61
|
+
what_learned: z.ZodString;
|
|
62
|
+
/**
|
|
63
|
+
* The recommended action. Required for what_action (1
|
|
64
|
+
* sentence per spec).
|
|
65
|
+
*/
|
|
66
|
+
what_action: z.ZodString;
|
|
67
|
+
/**
|
|
68
|
+
* Optional structured bullets (e.g. "4 phases, 3 gates passed,
|
|
69
|
+
* 1 evaluator verdict"). Counts are allowed at this layer; the
|
|
70
|
+
* brief section is the NL primary (RL-7).
|
|
71
|
+
*/
|
|
72
|
+
bullets: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
|
|
73
|
+
/**
|
|
74
|
+
* Source trace ids backing the brief (the column on
|
|
75
|
+
* crystallization_event spec §4.5).
|
|
76
|
+
*/
|
|
77
|
+
source_trace_pointers: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
|
|
78
|
+
}, "strip", z.ZodTypeAny, {
|
|
79
|
+
source_trace_pointers: string[];
|
|
80
|
+
what_happened: string;
|
|
81
|
+
why_it_matters: string;
|
|
82
|
+
what_learned: string;
|
|
83
|
+
what_action: string;
|
|
84
|
+
trace_id: string;
|
|
85
|
+
bullets: string[];
|
|
86
|
+
}, {
|
|
87
|
+
what_happened: string;
|
|
88
|
+
why_it_matters: string;
|
|
89
|
+
what_learned: string;
|
|
90
|
+
what_action: string;
|
|
91
|
+
trace_id: string;
|
|
92
|
+
source_trace_pointers?: string[] | undefined;
|
|
93
|
+
bullets?: string[] | undefined;
|
|
94
|
+
}>;
|
|
95
|
+
export type BriefTraceInput = z.input<typeof BriefTraceInputSchema>;
|
|
96
|
+
/**
|
|
97
|
+
* The summary emitted by the independent evaluators (spec §4.5
|
|
98
|
+
* `evaluator_summary` field). Optional for the brief builder — the
|
|
99
|
+
* brief can be built without it, but a filled evaluator_summary
|
|
100
|
+
* flows into the recommendation envelope.
|
|
101
|
+
*/
|
|
102
|
+
export declare const EvaluatorSummarySchema: z.ZodObject<{
|
|
103
|
+
one_liner: z.ZodDefault<z.ZodString>;
|
|
104
|
+
risk_tags: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
|
|
105
|
+
}, "strip", z.ZodTypeAny, {
|
|
106
|
+
one_liner: string;
|
|
107
|
+
risk_tags: string[];
|
|
108
|
+
}, {
|
|
109
|
+
one_liner?: string | undefined;
|
|
110
|
+
risk_tags?: string[] | undefined;
|
|
111
|
+
}>;
|
|
112
|
+
export type EvaluatorSummary = z.input<typeof EvaluatorSummarySchema>;
|
|
113
|
+
export declare const RecommendationPayloadSchema: z.ZodObject<{
|
|
114
|
+
brief: z.ZodEffects<z.ZodObject<{
|
|
115
|
+
what_happened: z.ZodString;
|
|
116
|
+
why_it_matters: z.ZodString;
|
|
117
|
+
what_learned: z.ZodString;
|
|
118
|
+
what_action: z.ZodString;
|
|
119
|
+
}, "strict", z.ZodTypeAny, {
|
|
120
|
+
what_happened: string;
|
|
121
|
+
why_it_matters: string;
|
|
122
|
+
what_learned: string;
|
|
123
|
+
what_action: string;
|
|
124
|
+
}, {
|
|
125
|
+
what_happened: string;
|
|
126
|
+
why_it_matters: string;
|
|
127
|
+
what_learned: string;
|
|
128
|
+
what_action: string;
|
|
129
|
+
}>, {
|
|
130
|
+
what_happened: string;
|
|
131
|
+
why_it_matters: string;
|
|
132
|
+
what_learned: string;
|
|
133
|
+
what_action: string;
|
|
134
|
+
}, {
|
|
135
|
+
what_happened: string;
|
|
136
|
+
why_it_matters: string;
|
|
137
|
+
what_learned: string;
|
|
138
|
+
what_action: string;
|
|
139
|
+
}>;
|
|
140
|
+
bullets: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
|
|
141
|
+
source_trace_pointers: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
|
|
142
|
+
evaluator_summary: z.ZodDefault<z.ZodObject<{
|
|
143
|
+
one_liner: z.ZodDefault<z.ZodString>;
|
|
144
|
+
risk_tags: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
|
|
145
|
+
}, "strip", z.ZodTypeAny, {
|
|
146
|
+
one_liner: string;
|
|
147
|
+
risk_tags: string[];
|
|
148
|
+
}, {
|
|
149
|
+
one_liner?: string | undefined;
|
|
150
|
+
risk_tags?: string[] | undefined;
|
|
151
|
+
}>>;
|
|
152
|
+
}, "strip", z.ZodTypeAny, {
|
|
153
|
+
source_trace_pointers: string[];
|
|
154
|
+
evaluator_summary: {
|
|
155
|
+
one_liner: string;
|
|
156
|
+
risk_tags: string[];
|
|
157
|
+
};
|
|
158
|
+
bullets: string[];
|
|
159
|
+
brief: {
|
|
160
|
+
what_happened: string;
|
|
161
|
+
why_it_matters: string;
|
|
162
|
+
what_learned: string;
|
|
163
|
+
what_action: string;
|
|
164
|
+
};
|
|
165
|
+
}, {
|
|
166
|
+
brief: {
|
|
167
|
+
what_happened: string;
|
|
168
|
+
why_it_matters: string;
|
|
169
|
+
what_learned: string;
|
|
170
|
+
what_action: string;
|
|
171
|
+
};
|
|
172
|
+
source_trace_pointers?: string[] | undefined;
|
|
173
|
+
evaluator_summary?: {
|
|
174
|
+
one_liner?: string | undefined;
|
|
175
|
+
risk_tags?: string[] | undefined;
|
|
176
|
+
} | undefined;
|
|
177
|
+
bullets?: string[] | undefined;
|
|
178
|
+
}>;
|
|
179
|
+
export type RecommendationPayload = z.infer<typeof RecommendationPayloadSchema>;
|
|
180
|
+
export declare class BriefSectionError extends Error {
|
|
181
|
+
readonly code: "MISSING_BRIEF_SECTION";
|
|
182
|
+
readonly findings: ReadonlyArray<{
|
|
183
|
+
path: string;
|
|
184
|
+
message: string;
|
|
185
|
+
}>;
|
|
186
|
+
constructor(message: string, findings?: ReadonlyArray<{
|
|
187
|
+
path: string;
|
|
188
|
+
message: string;
|
|
189
|
+
}>);
|
|
190
|
+
}
|
|
191
|
+
/**
|
|
192
|
+
* Build a 4-section EvidenceBrief from a finished trace recap.
|
|
193
|
+
*
|
|
194
|
+
* The function is STRICT: it parses the input trace through
|
|
195
|
+
* `BriefTraceInputSchema`, then parses the assembled brief through
|
|
196
|
+
* `EvidenceBriefSchema`. Any missing section throws
|
|
197
|
+
* `BriefSectionError(MISSING_BRIEF_SECTION)` — the same code that
|
|
198
|
+
* `safeParseEvidenceBrief` returns — so a single error code is the
|
|
199
|
+
* user-facing signal for "brief incomplete, do not render".
|
|
200
|
+
*
|
|
201
|
+
* Brief-section related ZodErrors (e.g. `min(1)` on a section) are
|
|
202
|
+
* translated to `BriefSectionError` so callers only handle one
|
|
203
|
+
* shape of failure. Non-section ZodErrors (e.g. invalid `trace_id`)
|
|
204
|
+
* are re-raised unchanged.
|
|
205
|
+
*
|
|
206
|
+
* NOTE: callers who already have raw NL strings can also call
|
|
207
|
+
* `parseEvidenceBrief` directly; this function is the opinionated
|
|
208
|
+
* shape for trace -> brief.
|
|
209
|
+
*/
|
|
210
|
+
export declare function buildEvidenceBrief(trace: BriefTraceInput, evaluatorSummary?: EvaluatorSummary): EvidenceBrief;
|
|
211
|
+
/**
|
|
212
|
+
* Render the user-facing recommendation envelope (brief + bullets +
|
|
213
|
+
* trace pointers + evaluator summary). The function refuses to
|
|
214
|
+
* return a payload unless ALL 4 brief sections are present — this
|
|
215
|
+
* is the single CLI-facing gate per spec §10 RL-7.
|
|
216
|
+
*
|
|
217
|
+
* On success, returns the validated `RecommendationPayload`. On a
|
|
218
|
+
* missing-section brief, throws `BriefSectionError`.
|
|
219
|
+
*/
|
|
220
|
+
export declare function renderRecommendationPayload(trace: BriefTraceInput, evaluatorSummary?: EvaluatorSummary): RecommendationPayload;
|
|
221
|
+
/**
|
|
222
|
+
* Convenience: validate an arbitrary unknown payload AS IF it were a
|
|
223
|
+
* recommendation envelope. Returns a Result-like shape so the CLI can
|
|
224
|
+
* render a structured MISSING_BRIEF_SECTION error without try/catch
|
|
225
|
+
* noise.
|
|
226
|
+
*/
|
|
227
|
+
export declare function safeRenderRecommendationPayload(input: unknown): {
|
|
228
|
+
ok: true;
|
|
229
|
+
payload: RecommendationPayload;
|
|
230
|
+
} | {
|
|
231
|
+
ok: false;
|
|
232
|
+
code?: "MISSING_BRIEF_SECTION";
|
|
233
|
+
findings: Array<{
|
|
234
|
+
path: string;
|
|
235
|
+
message: string;
|
|
236
|
+
}>;
|
|
237
|
+
};
|