peaks-loop 4.0.0-beta.2 → 4.0.0-beta.4

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.
Files changed (72) hide show
  1. package/CHANGELOG.md +81 -0
  2. package/README-en.md +16 -3
  3. package/README.md +16 -3
  4. package/dist/src/cli/commands/asset-commands.d.ts +45 -0
  5. package/dist/src/cli/commands/asset-commands.js +404 -0
  6. package/dist/src/cli/commands/bee-commands.d.ts +26 -0
  7. package/dist/src/cli/commands/bee-commands.js +169 -0
  8. package/dist/src/cli/commands/evolution-commands.d.ts +27 -0
  9. package/dist/src/cli/commands/evolution-commands.js +393 -0
  10. package/dist/src/cli/commands/loop-commands.d.ts +19 -13
  11. package/dist/src/cli/commands/loop-commands.js +147 -13
  12. package/dist/src/cli/commands/sediment-commands.js +9 -0
  13. package/dist/src/cli/commands/skill-loop-engineering-readiness-commands.d.ts +67 -0
  14. package/dist/src/cli/commands/skill-loop-engineering-readiness-commands.js +173 -0
  15. package/dist/src/cli/program.js +17 -0
  16. package/dist/src/services/crystallization/crystallization-service.d.ts +239 -0
  17. package/dist/src/services/crystallization/crystallization-service.js +397 -0
  18. package/dist/src/services/crystallization/crystallization-store.d.ts +75 -0
  19. package/dist/src/services/crystallization/crystallization-store.js +193 -0
  20. package/dist/src/services/crystallization/crystallization-types.d.ts +313 -0
  21. package/dist/src/services/crystallization/crystallization-types.js +299 -0
  22. package/dist/src/services/crystallization/evidence-brief-builder.d.ts +237 -0
  23. package/dist/src/services/crystallization/evidence-brief-builder.js +240 -0
  24. package/dist/src/services/evolution/evolution-service.d.ts +137 -0
  25. package/dist/src/services/evolution/evolution-service.js +281 -0
  26. package/dist/src/services/evolution/evolution-store.d.ts +57 -0
  27. package/dist/src/services/evolution/evolution-store.js +232 -0
  28. package/dist/src/services/evolution/evolution-types.d.ts +706 -0
  29. package/dist/src/services/evolution/evolution-types.js +286 -0
  30. package/dist/src/services/evolution/independent-evaluator-runner.d.ts +90 -0
  31. package/dist/src/services/evolution/independent-evaluator-runner.js +106 -0
  32. package/dist/src/services/evolution/regression-skeptic-runner.d.ts +64 -0
  33. package/dist/src/services/evolution/regression-skeptic-runner.js +113 -0
  34. package/dist/src/services/loop/loop-bee-relation-service.d.ts +107 -0
  35. package/dist/src/services/loop/loop-bee-relation-service.js +211 -0
  36. package/dist/src/services/loop/loop-bee-relation-store.d.ts +53 -0
  37. package/dist/src/services/loop/loop-bee-relation-store.js +130 -0
  38. package/dist/src/services/loop/loop-bee-relation-types.d.ts +118 -0
  39. package/dist/src/services/loop/loop-bee-relation-types.js +114 -0
  40. package/dist/src/services/loop/loop-release-service.d.ts +46 -0
  41. package/dist/src/services/loop/loop-release-service.js +66 -0
  42. package/dist/src/services/loop/loop-release-store.d.ts +55 -0
  43. package/dist/src/services/loop/loop-release-store.js +134 -0
  44. package/dist/src/services/loop/loop-release-types.d.ts +250 -0
  45. package/dist/src/services/loop/loop-release-types.js +162 -0
  46. package/dist/src/services/share/bundle-reader.d.ts +100 -0
  47. package/dist/src/services/share/bundle-reader.js +434 -0
  48. package/dist/src/services/share/bundle-types.d.ts +392 -0
  49. package/dist/src/services/share/bundle-types.js +318 -0
  50. package/dist/src/services/share/bundle-writer.d.ts +97 -0
  51. package/dist/src/services/share/bundle-writer.js +429 -0
  52. package/dist/src/services/share/run-state-contract.d.ts +133 -0
  53. package/dist/src/services/share/run-state-contract.js +138 -0
  54. package/dist/src/services/skillhub/release-import.js +7 -2
  55. package/dist/src/services/skillhub/release-retain.js +6 -1
  56. package/dist/src/services/skillhub/sqlite-store.js +17 -1
  57. package/dist/src/services/skillhub/types.d.ts +10 -0
  58. package/dist/src/services/standards/loop-engineering-lint.d.ts +38 -0
  59. package/dist/src/services/standards/loop-engineering-lint.js +101 -0
  60. package/dist/src/services/standards/loop-engineering-readiness-lint.d.ts +111 -0
  61. package/dist/src/services/standards/loop-engineering-readiness-lint.js +248 -0
  62. package/dist/src/shared/version.d.ts +1 -1
  63. package/dist/src/shared/version.js +1 -1
  64. package/examples/video-demo/README.md +57 -0
  65. package/examples/video-demo/out/en-closing-960.png +0 -0
  66. package/examples/video-demo/out/zh-closing-960.png +0 -0
  67. package/examples/video-demo/preview/peaks-loop-demo-en.mp4 +0 -0
  68. package/examples/video-demo/preview/peaks-loop-demo.mp4 +0 -0
  69. package/package.json +6 -2
  70. package/skills/peaks-code/SKILL.md +13 -0
  71. package/skills/peaks-content/SKILL.md +272 -0
  72. 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
+ };