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.
Files changed (71) hide show
  1. package/README-en.md +16 -3
  2. package/README.md +16 -3
  3. package/dist/src/cli/commands/asset-commands.d.ts +45 -0
  4. package/dist/src/cli/commands/asset-commands.js +404 -0
  5. package/dist/src/cli/commands/bee-commands.d.ts +26 -0
  6. package/dist/src/cli/commands/bee-commands.js +169 -0
  7. package/dist/src/cli/commands/evolution-commands.d.ts +27 -0
  8. package/dist/src/cli/commands/evolution-commands.js +393 -0
  9. package/dist/src/cli/commands/loop-commands.d.ts +19 -13
  10. package/dist/src/cli/commands/loop-commands.js +147 -13
  11. package/dist/src/cli/commands/sediment-commands.js +9 -0
  12. package/dist/src/cli/commands/skill-loop-engineering-readiness-commands.d.ts +67 -0
  13. package/dist/src/cli/commands/skill-loop-engineering-readiness-commands.js +173 -0
  14. package/dist/src/cli/program.js +17 -0
  15. package/dist/src/services/crystallization/crystallization-service.d.ts +239 -0
  16. package/dist/src/services/crystallization/crystallization-service.js +397 -0
  17. package/dist/src/services/crystallization/crystallization-store.d.ts +75 -0
  18. package/dist/src/services/crystallization/crystallization-store.js +193 -0
  19. package/dist/src/services/crystallization/crystallization-types.d.ts +313 -0
  20. package/dist/src/services/crystallization/crystallization-types.js +299 -0
  21. package/dist/src/services/crystallization/evidence-brief-builder.d.ts +237 -0
  22. package/dist/src/services/crystallization/evidence-brief-builder.js +240 -0
  23. package/dist/src/services/evolution/evolution-service.d.ts +137 -0
  24. package/dist/src/services/evolution/evolution-service.js +281 -0
  25. package/dist/src/services/evolution/evolution-store.d.ts +57 -0
  26. package/dist/src/services/evolution/evolution-store.js +232 -0
  27. package/dist/src/services/evolution/evolution-types.d.ts +706 -0
  28. package/dist/src/services/evolution/evolution-types.js +286 -0
  29. package/dist/src/services/evolution/independent-evaluator-runner.d.ts +90 -0
  30. package/dist/src/services/evolution/independent-evaluator-runner.js +106 -0
  31. package/dist/src/services/evolution/regression-skeptic-runner.d.ts +64 -0
  32. package/dist/src/services/evolution/regression-skeptic-runner.js +113 -0
  33. package/dist/src/services/loop/loop-bee-relation-service.d.ts +107 -0
  34. package/dist/src/services/loop/loop-bee-relation-service.js +211 -0
  35. package/dist/src/services/loop/loop-bee-relation-store.d.ts +53 -0
  36. package/dist/src/services/loop/loop-bee-relation-store.js +130 -0
  37. package/dist/src/services/loop/loop-bee-relation-types.d.ts +118 -0
  38. package/dist/src/services/loop/loop-bee-relation-types.js +114 -0
  39. package/dist/src/services/loop/loop-release-service.d.ts +46 -0
  40. package/dist/src/services/loop/loop-release-service.js +66 -0
  41. package/dist/src/services/loop/loop-release-store.d.ts +55 -0
  42. package/dist/src/services/loop/loop-release-store.js +134 -0
  43. package/dist/src/services/loop/loop-release-types.d.ts +250 -0
  44. package/dist/src/services/loop/loop-release-types.js +162 -0
  45. package/dist/src/services/share/bundle-reader.d.ts +100 -0
  46. package/dist/src/services/share/bundle-reader.js +434 -0
  47. package/dist/src/services/share/bundle-types.d.ts +392 -0
  48. package/dist/src/services/share/bundle-types.js +318 -0
  49. package/dist/src/services/share/bundle-writer.d.ts +97 -0
  50. package/dist/src/services/share/bundle-writer.js +429 -0
  51. package/dist/src/services/share/run-state-contract.d.ts +133 -0
  52. package/dist/src/services/share/run-state-contract.js +138 -0
  53. package/dist/src/services/skillhub/release-import.js +7 -2
  54. package/dist/src/services/skillhub/release-retain.js +6 -1
  55. package/dist/src/services/skillhub/sqlite-store.js +17 -1
  56. package/dist/src/services/skillhub/types.d.ts +10 -0
  57. package/dist/src/services/standards/loop-engineering-lint.d.ts +38 -0
  58. package/dist/src/services/standards/loop-engineering-lint.js +101 -0
  59. package/dist/src/services/standards/loop-engineering-readiness-lint.d.ts +111 -0
  60. package/dist/src/services/standards/loop-engineering-readiness-lint.js +248 -0
  61. package/dist/src/shared/version.d.ts +1 -1
  62. package/dist/src/shared/version.js +1 -1
  63. package/examples/video-demo/README.md +57 -0
  64. package/examples/video-demo/out/en-closing-960.png +0 -0
  65. package/examples/video-demo/out/zh-closing-960.png +0 -0
  66. package/examples/video-demo/preview/peaks-loop-demo-en.mp4 +0 -0
  67. package/examples/video-demo/preview/peaks-loop-demo.mp4 +0 -0
  68. package/package.json +6 -2
  69. package/skills/peaks-code/SKILL.md +13 -0
  70. package/skills/peaks-content/SKILL.md +272 -0
  71. package/skills/peaks-issue-fix-orchestrator/SKILL.md +307 -0
@@ -0,0 +1,75 @@
1
+ import type Database from "better-sqlite3";
2
+ import { type CrystallizationEvent, type CrystallizationEventInput, type CrystallizationEventStatus } from "./crystallization-types.js";
3
+ /**
4
+ * Low-level SQLite access for the `crystallization_event` table.
5
+ * The migration is registered with the existing `openStateDb()`
6
+ * pipeline via
7
+ * `src/services/skillhub/migrations/006-crystallization-event.sql`
8
+ * and is applied in lexicographic order alongside the other
9
+ * skillhub migrations. The function `ensureCrystallizationEventTable`
10
+ * below is a belt-and-suspenders re-applier for callers that pass a
11
+ * database they built themselves (e.g. tests).
12
+ *
13
+ * Defense in depth:
14
+ * - All JSON columns are stored as TEXT and parsed at the
15
+ * boundary. No big JSON BLOB at the SQLite layer — the row
16
+ * stays small and queryable.
17
+ * - The migration is idempotent (CREATE TABLE IF NOT EXISTS,
18
+ * CREATE INDEX IF NOT EXISTS) so re-running it is safe.
19
+ * - The 4-section brief guard and any other business rule is
20
+ * enforced at the SERVICE layer (not the DB); the DB stores
21
+ * the persisted, validated row.
22
+ */
23
+ declare const SCHEMA_VERSION: "peaks.crystallization/1";
24
+ /**
25
+ * Re-apply the crystallization_event table migration against an
26
+ * already-open database. Used by tests that build their own DB
27
+ * without the openStateDb pipeline. Idempotent.
28
+ */
29
+ export declare function ensureCrystallizationEventTable(db: Database.Database): void;
30
+ /**
31
+ * Insert a CrystallizationEvent row. The row's `schema_version` is
32
+ * taken from the input (must equal `peaks.crystallization/1`);
33
+ * `id` and `created_at` are stamped here so callers cannot backdate
34
+ * a row.
35
+ *
36
+ * The Zod schema (parse boundary) re-asserts the 4-section brief
37
+ * guard: a missing-section event is rejected before the SQL INSERT.
38
+ *
39
+ * Returns the persisted row.
40
+ */
41
+ export declare function insertCrystallizationEvent(db: Database.Database, row: CrystallizationEventInput): CrystallizationEvent;
42
+ /** Read a single CrystallizationEvent row by id; returns undefined if absent. */
43
+ export declare function getCrystallizationEvent(db: Database.Database, id: string): CrystallizationEvent | undefined;
44
+ /**
45
+ * List CrystallizationEvent rows. Filter by `lifecycle_status` and/or
46
+ * any of the optional FK pointers. When ALL filters are omitted, lists
47
+ * every event (newest-first by `created_at`).
48
+ */
49
+ export declare function listCrystallizationEvents(db: Database.Database, opts?: {
50
+ lifecycle_status?: CrystallizationEventStatus;
51
+ created_loop_release_id?: string;
52
+ updated_loop_release_id?: string;
53
+ created_bee_release_id?: number;
54
+ updated_bee_release_id?: number;
55
+ }): CrystallizationEvent[];
56
+ /**
57
+ * Update the lifecycle_status of an existing CrystallizationEvent row.
58
+ * Returns the updated row, or undefined if absent.
59
+ *
60
+ * Lifecycle transitions are NOT validated here; the service layer
61
+ * decides whether `stable` requires a user_confirmation_pointer or
62
+ * other evidence (mirroring the evolution-store design).
63
+ */
64
+ export declare function updateCrystallizationEventStatus(db: Database.Database, id: string, next: CrystallizationEventStatus): CrystallizationEvent | undefined;
65
+ /**
66
+ * Test seam: produce a fresh id for a CrystallizationEvent row.
67
+ * Format: `crys-<hex>` (12 hex chars). Matches the Zod
68
+ * `^crys-[0-9a-f]{8,}$` pattern in CrystallizationEventSchema.
69
+ */
70
+ export declare function newCrystallizationId(): string;
71
+ /**
72
+ * Test seam: re-export the schema version so the service layer has a
73
+ * single source of truth.
74
+ */
75
+ export { SCHEMA_VERSION as CRYSTALLIZATION_SCHEMA_VERSION };
@@ -0,0 +1,193 @@
1
+ import { CrystallizationEventSchema, } from "./crystallization-types.js";
2
+ /**
3
+ * Low-level SQLite access for the `crystallization_event` table.
4
+ * The migration is registered with the existing `openStateDb()`
5
+ * pipeline via
6
+ * `src/services/skillhub/migrations/006-crystallization-event.sql`
7
+ * and is applied in lexicographic order alongside the other
8
+ * skillhub migrations. The function `ensureCrystallizationEventTable`
9
+ * below is a belt-and-suspenders re-applier for callers that pass a
10
+ * database they built themselves (e.g. tests).
11
+ *
12
+ * Defense in depth:
13
+ * - All JSON columns are stored as TEXT and parsed at the
14
+ * boundary. No big JSON BLOB at the SQLite layer — the row
15
+ * stays small and queryable.
16
+ * - The migration is idempotent (CREATE TABLE IF NOT EXISTS,
17
+ * CREATE INDEX IF NOT EXISTS) so re-running it is safe.
18
+ * - The 4-section brief guard and any other business rule is
19
+ * enforced at the SERVICE layer (not the DB); the DB stores
20
+ * the persisted, validated row.
21
+ */
22
+ const SCHEMA_VERSION = "peaks.crystallization/1";
23
+ /**
24
+ * Re-apply the crystallization_event table migration against an
25
+ * already-open database. Used by tests that build their own DB
26
+ * without the openStateDb pipeline. Idempotent.
27
+ */
28
+ export function ensureCrystallizationEventTable(db) {
29
+ db.exec(`
30
+ CREATE TABLE IF NOT EXISTS crystallization_event (
31
+ id TEXT PRIMARY KEY,
32
+ trigger TEXT NOT NULL CHECK (trigger IN (
33
+ 'user_explicit',
34
+ 'llm_suggested',
35
+ 'success_default_prompt',
36
+ 'similar_task_recurrence'
37
+ )),
38
+ evidence_brief_json TEXT NOT NULL,
39
+ evidence_bullets_json TEXT NOT NULL DEFAULT '[]',
40
+ source_trace_pointers_json TEXT NOT NULL DEFAULT '[]',
41
+ evaluator_summary TEXT NOT NULL DEFAULT '',
42
+ user_decision_summary TEXT NOT NULL DEFAULT '',
43
+ created_loop_release_id TEXT REFERENCES loop_release(id) ON DELETE SET NULL,
44
+ updated_loop_release_id TEXT REFERENCES loop_release(id) ON DELETE SET NULL,
45
+ created_bee_release_id INTEGER REFERENCES bee_release(id) ON DELETE SET NULL,
46
+ updated_bee_release_id INTEGER REFERENCES bee_release(id) ON DELETE SET NULL,
47
+ lifecycle_status TEXT NOT NULL DEFAULT 'candidate'
48
+ CHECK (lifecycle_status IN ('candidate','stable','retired')),
49
+ schema_version TEXT NOT NULL CHECK (schema_version = 'peaks.crystallization/1'),
50
+ created_at TEXT NOT NULL,
51
+ CHECK (length(id) > 0),
52
+ CHECK (length(evidence_brief_json) >= 2)
53
+ );
54
+ CREATE INDEX IF NOT EXISTS idx_crystallization_event_created_loop
55
+ ON crystallization_event(created_loop_release_id);
56
+ CREATE INDEX IF NOT EXISTS idx_crystallization_event_updated_loop
57
+ ON crystallization_event(updated_loop_release_id);
58
+ CREATE INDEX IF NOT EXISTS idx_crystallization_event_created_bee
59
+ ON crystallization_event(created_bee_release_id);
60
+ CREATE INDEX IF NOT EXISTS idx_crystallization_event_updated_bee
61
+ ON crystallization_event(updated_bee_release_id);
62
+ CREATE INDEX IF NOT EXISTS idx_crystallization_event_lifecycle
63
+ ON crystallization_event(lifecycle_status);
64
+ CREATE INDEX IF NOT EXISTS idx_crystallization_event_created_at
65
+ ON crystallization_event(created_at);
66
+ `);
67
+ }
68
+ function rowToCrystallizationEvent(row) {
69
+ return {
70
+ id: row.id,
71
+ trigger: row.trigger,
72
+ evidence_brief: JSON.parse(row.evidence_brief_json),
73
+ evidence_bullets: JSON.parse(row.evidence_bullets_json),
74
+ source_trace_pointers: JSON.parse(row.source_trace_pointers_json),
75
+ evaluator_summary: row.evaluator_summary,
76
+ user_decision_summary: row.user_decision_summary,
77
+ created_loop_release_id: row.created_loop_release_id ?? undefined,
78
+ updated_loop_release_id: row.updated_loop_release_id ?? undefined,
79
+ created_bee_release_id: row.created_bee_release_id ?? undefined,
80
+ updated_bee_release_id: row.updated_bee_release_id ?? undefined,
81
+ lifecycle_status: row.lifecycle_status,
82
+ schema_version: row.schema_version,
83
+ created_at: row.created_at,
84
+ };
85
+ }
86
+ /**
87
+ * Insert a CrystallizationEvent row. The row's `schema_version` is
88
+ * taken from the input (must equal `peaks.crystallization/1`);
89
+ * `id` and `created_at` are stamped here so callers cannot backdate
90
+ * a row.
91
+ *
92
+ * The Zod schema (parse boundary) re-asserts the 4-section brief
93
+ * guard: a missing-section event is rejected before the SQL INSERT.
94
+ *
95
+ * Returns the persisted row.
96
+ */
97
+ export function insertCrystallizationEvent(db, row) {
98
+ const id = newCrystallizationId();
99
+ const createdAt = new Date().toISOString();
100
+ // Build the persisted row first so the Zod refine guard (brief
101
+ // must have 4 sections) runs before any SQL side effects.
102
+ const persisted = CrystallizationEventSchema.parse({
103
+ ...row,
104
+ id,
105
+ schema_version: SCHEMA_VERSION,
106
+ created_at: createdAt,
107
+ });
108
+ const stmt = db.prepare(`INSERT INTO crystallization_event (
109
+ id, trigger, evidence_brief_json, evidence_bullets_json,
110
+ source_trace_pointers_json, evaluator_summary,
111
+ user_decision_summary,
112
+ created_loop_release_id, updated_loop_release_id,
113
+ created_bee_release_id, updated_bee_release_id,
114
+ lifecycle_status, schema_version, created_at
115
+ ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`);
116
+ stmt.run(persisted.id, persisted.trigger, JSON.stringify(persisted.evidence_brief), JSON.stringify(persisted.evidence_bullets), JSON.stringify(persisted.source_trace_pointers), persisted.evaluator_summary, persisted.user_decision_summary, persisted.created_loop_release_id ?? null, persisted.updated_loop_release_id ?? null, persisted.created_bee_release_id ?? null, persisted.updated_bee_release_id ?? null, persisted.lifecycle_status, persisted.schema_version, persisted.created_at);
117
+ return persisted;
118
+ }
119
+ /** Read a single CrystallizationEvent row by id; returns undefined if absent. */
120
+ export function getCrystallizationEvent(db, id) {
121
+ const row = db
122
+ .prepare("SELECT * FROM crystallization_event WHERE id = ?")
123
+ .get(id);
124
+ if (!row)
125
+ return undefined;
126
+ return rowToCrystallizationEvent(row);
127
+ }
128
+ /**
129
+ * List CrystallizationEvent rows. Filter by `lifecycle_status` and/or
130
+ * any of the optional FK pointers. When ALL filters are omitted, lists
131
+ * every event (newest-first by `created_at`).
132
+ */
133
+ export function listCrystallizationEvents(db, opts = {}) {
134
+ const wheres = [];
135
+ const params = [];
136
+ if (opts.lifecycle_status !== undefined) {
137
+ wheres.push("lifecycle_status = ?");
138
+ params.push(opts.lifecycle_status);
139
+ }
140
+ if (opts.created_loop_release_id !== undefined) {
141
+ wheres.push("created_loop_release_id = ?");
142
+ params.push(opts.created_loop_release_id);
143
+ }
144
+ if (opts.updated_loop_release_id !== undefined) {
145
+ wheres.push("updated_loop_release_id = ?");
146
+ params.push(opts.updated_loop_release_id);
147
+ }
148
+ if (opts.created_bee_release_id !== undefined) {
149
+ wheres.push("created_bee_release_id = ?");
150
+ params.push(opts.created_bee_release_id);
151
+ }
152
+ if (opts.updated_bee_release_id !== undefined) {
153
+ wheres.push("updated_bee_release_id = ?");
154
+ params.push(opts.updated_bee_release_id);
155
+ }
156
+ let sql = "SELECT * FROM crystallization_event";
157
+ if (wheres.length > 0)
158
+ sql += " WHERE " + wheres.join(" AND ");
159
+ sql += " ORDER BY created_at DESC, id ASC";
160
+ const rows = db.prepare(sql).all(...params);
161
+ return rows.map(rowToCrystallizationEvent);
162
+ }
163
+ /**
164
+ * Update the lifecycle_status of an existing CrystallizationEvent row.
165
+ * Returns the updated row, or undefined if absent.
166
+ *
167
+ * Lifecycle transitions are NOT validated here; the service layer
168
+ * decides whether `stable` requires a user_confirmation_pointer or
169
+ * other evidence (mirroring the evolution-store design).
170
+ */
171
+ export function updateCrystallizationEventStatus(db, id, next) {
172
+ const existing = getCrystallizationEvent(db, id);
173
+ if (!existing)
174
+ return undefined;
175
+ db.prepare("UPDATE crystallization_event SET lifecycle_status = ? WHERE id = ?").run(next, id);
176
+ return getCrystallizationEvent(db, id);
177
+ }
178
+ /**
179
+ * Test seam: produce a fresh id for a CrystallizationEvent row.
180
+ * Format: `crys-<hex>` (12 hex chars). Matches the Zod
181
+ * `^crys-[0-9a-f]{8,}$` pattern in CrystallizationEventSchema.
182
+ */
183
+ export function newCrystallizationId() {
184
+ const hex = Math.floor(Math.random() * 0x1_000_000_000_000)
185
+ .toString(16)
186
+ .padStart(12, "0");
187
+ return `crys-${hex}`;
188
+ }
189
+ /**
190
+ * Test seam: re-export the schema version so the service layer has a
191
+ * single source of truth.
192
+ */
193
+ export { SCHEMA_VERSION as CRYSTALLIZATION_SCHEMA_VERSION };
@@ -0,0 +1,313 @@
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
+ export declare const CrystallizationTriggerSchema: z.ZodEnum<["user_explicit", "llm_suggested", "success_default_prompt", "similar_task_recurrence"]>;
36
+ export type CrystallizationTrigger = z.infer<typeof CrystallizationTriggerSchema>;
37
+ export declare const CRYSTALLIZATION_TRIGGERS: readonly CrystallizationTrigger[];
38
+ export declare const CrystallizationEventStatusSchema: z.ZodEnum<["candidate", "stable", "retired"]>;
39
+ export type CrystallizationEventStatus = z.infer<typeof CrystallizationEventStatusSchema>;
40
+ /**
41
+ * EvidenceBrief — the 4-section brief (spec §4.7).
42
+ *
43
+ * Hard shape invariant: ALL FOUR KEYS must be present at parse
44
+ * time, with non-empty NL content. The `.refine(...)` guard is
45
+ * what makes a brief a "brief" — without it, the projection is
46
+ * not a brief and the recommendation MUST NOT be rendered
47
+ * (service layer enforces this; Zod makes it a parse-time
48
+ * guarantee).
49
+ *
50
+ * Field semantics:
51
+ * - what_happened — 1-2 sentence factual account of the run.
52
+ * - why_it_matters — 1-2 sentence explanation of why this is
53
+ * worth promoting.
54
+ * - what_learned — 1-2 sentence learning: failure modes
55
+ * encoded, preferences extracted.
56
+ * - what_action — 1-sentence recommended action with
57
+ * rationale.
58
+ */
59
+ export declare const EvidenceBriefSchema: z.ZodEffects<z.ZodObject<{
60
+ what_happened: z.ZodString;
61
+ why_it_matters: z.ZodString;
62
+ what_learned: z.ZodString;
63
+ what_action: z.ZodString;
64
+ }, "strict", z.ZodTypeAny, {
65
+ what_happened: string;
66
+ why_it_matters: string;
67
+ what_learned: string;
68
+ what_action: string;
69
+ }, {
70
+ what_happened: string;
71
+ why_it_matters: string;
72
+ what_learned: string;
73
+ what_action: string;
74
+ }>, {
75
+ what_happened: string;
76
+ why_it_matters: string;
77
+ what_learned: string;
78
+ what_action: string;
79
+ }, {
80
+ what_happened: string;
81
+ why_it_matters: string;
82
+ what_learned: string;
83
+ what_action: string;
84
+ }>;
85
+ export type EvidenceBrief = z.infer<typeof EvidenceBriefSchema>;
86
+ /**
87
+ * Helper for downstream code that needs to know whether a parsed
88
+ * brief satisfies the 4-section rule. Useful for the CLI when a
89
+ * payload arrived from the LLM and the brief-section guard has
90
+ * already passed — it returns the section count, always 4 here.
91
+ */
92
+ export declare function hasAllFourBriefSections(brief: EvidenceBrief): boolean;
93
+ /**
94
+ * Zod schema for the create payload (CrystallizationEventInput).
95
+ *
96
+ * Re-validates the evidence_brief inline; calling code may ALSO call
97
+ * `EvidenceBriefSchema.parse` separately if it builds the brief out
98
+ * of band. The CrystallizationEvent input schema wires the same
99
+ * guard so a brief cannot sneak through via a partial-input path.
100
+ */
101
+ export declare const CrystallizationEventInputSchema: z.ZodObject<{
102
+ trigger: z.ZodEnum<["user_explicit", "llm_suggested", "success_default_prompt", "similar_task_recurrence"]>;
103
+ evidence_brief: z.ZodEffects<z.ZodObject<{
104
+ what_happened: z.ZodString;
105
+ why_it_matters: z.ZodString;
106
+ what_learned: z.ZodString;
107
+ what_action: z.ZodString;
108
+ }, "strict", z.ZodTypeAny, {
109
+ what_happened: string;
110
+ why_it_matters: string;
111
+ what_learned: string;
112
+ what_action: string;
113
+ }, {
114
+ what_happened: string;
115
+ why_it_matters: string;
116
+ what_learned: string;
117
+ what_action: string;
118
+ }>, {
119
+ what_happened: string;
120
+ why_it_matters: string;
121
+ what_learned: string;
122
+ what_action: string;
123
+ }, {
124
+ what_happened: string;
125
+ why_it_matters: string;
126
+ what_learned: string;
127
+ what_action: string;
128
+ }>;
129
+ evidence_bullets: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
130
+ source_trace_pointers: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
131
+ evaluator_summary: z.ZodDefault<z.ZodString>;
132
+ user_decision_summary: z.ZodDefault<z.ZodString>;
133
+ created_loop_release_id: z.ZodOptional<z.ZodString>;
134
+ updated_loop_release_id: z.ZodOptional<z.ZodString>;
135
+ created_bee_release_id: z.ZodOptional<z.ZodNumber>;
136
+ updated_bee_release_id: z.ZodOptional<z.ZodNumber>;
137
+ lifecycle_status: z.ZodDefault<z.ZodEnum<["candidate", "stable", "retired"]>>;
138
+ }, "strip", z.ZodTypeAny, {
139
+ lifecycle_status: "candidate" | "stable" | "retired";
140
+ trigger: "user_explicit" | "llm_suggested" | "success_default_prompt" | "similar_task_recurrence";
141
+ evidence_brief: {
142
+ what_happened: string;
143
+ why_it_matters: string;
144
+ what_learned: string;
145
+ what_action: string;
146
+ };
147
+ evidence_bullets: string[];
148
+ source_trace_pointers: string[];
149
+ evaluator_summary: string;
150
+ user_decision_summary: string;
151
+ created_loop_release_id?: string | undefined;
152
+ updated_loop_release_id?: string | undefined;
153
+ created_bee_release_id?: number | undefined;
154
+ updated_bee_release_id?: number | undefined;
155
+ }, {
156
+ trigger: "user_explicit" | "llm_suggested" | "success_default_prompt" | "similar_task_recurrence";
157
+ evidence_brief: {
158
+ what_happened: string;
159
+ why_it_matters: string;
160
+ what_learned: string;
161
+ what_action: string;
162
+ };
163
+ lifecycle_status?: "candidate" | "stable" | "retired" | undefined;
164
+ evidence_bullets?: string[] | undefined;
165
+ source_trace_pointers?: string[] | undefined;
166
+ evaluator_summary?: string | undefined;
167
+ user_decision_summary?: string | undefined;
168
+ created_loop_release_id?: string | undefined;
169
+ updated_loop_release_id?: string | undefined;
170
+ created_bee_release_id?: number | undefined;
171
+ updated_bee_release_id?: number | undefined;
172
+ }>;
173
+ export type CrystallizationEventInput = z.input<typeof CrystallizationEventInputSchema>;
174
+ /**
175
+ * Full persisted row schema. Adds `id` (the event id) and stamps
176
+ * `schema_version` to the fixed literal `peaks.crystallization/1`.
177
+ *
178
+ * Brief section guard is INHERITED from `EvidenceBriefSchema.refine`
179
+ * because `EvidenceBriefSchema` is embedded; the service layer still
180
+ * re-asserts the guard so a hand-crafted row cannot bypass Zod at
181
+ * the store boundary.
182
+ */
183
+ export declare const CrystallizationEventSchema: z.ZodObject<{
184
+ trigger: z.ZodEnum<["user_explicit", "llm_suggested", "success_default_prompt", "similar_task_recurrence"]>;
185
+ evidence_brief: z.ZodEffects<z.ZodObject<{
186
+ what_happened: z.ZodString;
187
+ why_it_matters: z.ZodString;
188
+ what_learned: z.ZodString;
189
+ what_action: z.ZodString;
190
+ }, "strict", z.ZodTypeAny, {
191
+ what_happened: string;
192
+ why_it_matters: string;
193
+ what_learned: string;
194
+ what_action: string;
195
+ }, {
196
+ what_happened: string;
197
+ why_it_matters: string;
198
+ what_learned: string;
199
+ what_action: string;
200
+ }>, {
201
+ what_happened: string;
202
+ why_it_matters: string;
203
+ what_learned: string;
204
+ what_action: string;
205
+ }, {
206
+ what_happened: string;
207
+ why_it_matters: string;
208
+ what_learned: string;
209
+ what_action: string;
210
+ }>;
211
+ evidence_bullets: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
212
+ source_trace_pointers: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
213
+ evaluator_summary: z.ZodDefault<z.ZodString>;
214
+ user_decision_summary: z.ZodDefault<z.ZodString>;
215
+ created_loop_release_id: z.ZodOptional<z.ZodString>;
216
+ updated_loop_release_id: z.ZodOptional<z.ZodString>;
217
+ created_bee_release_id: z.ZodOptional<z.ZodNumber>;
218
+ updated_bee_release_id: z.ZodOptional<z.ZodNumber>;
219
+ lifecycle_status: z.ZodDefault<z.ZodEnum<["candidate", "stable", "retired"]>>;
220
+ } & {
221
+ id: z.ZodString;
222
+ schema_version: z.ZodDefault<z.ZodLiteral<"peaks.crystallization/1">>;
223
+ created_at: z.ZodString;
224
+ }, "strip", z.ZodTypeAny, {
225
+ schema_version: "peaks.crystallization/1";
226
+ id: string;
227
+ lifecycle_status: "candidate" | "stable" | "retired";
228
+ trigger: "user_explicit" | "llm_suggested" | "success_default_prompt" | "similar_task_recurrence";
229
+ evidence_brief: {
230
+ what_happened: string;
231
+ why_it_matters: string;
232
+ what_learned: string;
233
+ what_action: string;
234
+ };
235
+ evidence_bullets: string[];
236
+ source_trace_pointers: string[];
237
+ evaluator_summary: string;
238
+ user_decision_summary: string;
239
+ created_at: string;
240
+ created_loop_release_id?: string | undefined;
241
+ updated_loop_release_id?: string | undefined;
242
+ created_bee_release_id?: number | undefined;
243
+ updated_bee_release_id?: number | undefined;
244
+ }, {
245
+ id: string;
246
+ trigger: "user_explicit" | "llm_suggested" | "success_default_prompt" | "similar_task_recurrence";
247
+ evidence_brief: {
248
+ what_happened: string;
249
+ why_it_matters: string;
250
+ what_learned: string;
251
+ what_action: string;
252
+ };
253
+ created_at: string;
254
+ schema_version?: "peaks.crystallization/1" | undefined;
255
+ lifecycle_status?: "candidate" | "stable" | "retired" | undefined;
256
+ evidence_bullets?: string[] | undefined;
257
+ source_trace_pointers?: string[] | undefined;
258
+ evaluator_summary?: string | undefined;
259
+ user_decision_summary?: string | undefined;
260
+ created_loop_release_id?: string | undefined;
261
+ updated_loop_release_id?: string | undefined;
262
+ created_bee_release_id?: number | undefined;
263
+ updated_bee_release_id?: number | undefined;
264
+ }>;
265
+ export type CrystallizationEvent = z.infer<typeof CrystallizationEventSchema>;
266
+ /**
267
+ * Convenience: strict-parse an unknown payload into a
268
+ * CrystallizationEvent row. Throws ZodError on failure — including
269
+ * when the brief is missing a section (the `.refine` guard fires).
270
+ *
271
+ * Use this at every parse boundary (CLI input, store insertion).
272
+ */
273
+ export declare function parseCrystallizationEvent(input: unknown): CrystallizationEvent;
274
+ /**
275
+ * Convenience: strict-parse an unknown payload as a standalone
276
+ * EvidenceBrief. Throws ZodError on failure.
277
+ */
278
+ export declare function parseEvidenceBrief(input: unknown): EvidenceBrief;
279
+ /**
280
+ * Safe-parse twin of parseCrystallizationEvent. Returns a Result-like
281
+ * envelope so callers (CLI / tests) can render findings without
282
+ * try/catch noise. The `code` field is `MISSING_BRIEF_SECTION` when
283
+ * the brief refine guard trips OR when ANY brief-section key is
284
+ * missing (spec §10 RL-7) — distinguishes brief failures from
285
+ * generic validation errors.
286
+ */
287
+ export declare function safeParseCrystallizationEvent(input: unknown): {
288
+ ok: true;
289
+ row: CrystallizationEvent;
290
+ } | {
291
+ ok: false;
292
+ code?: "MISSING_BRIEF_SECTION";
293
+ findings: Array<{
294
+ path: string;
295
+ message: string;
296
+ }>;
297
+ };
298
+ /**
299
+ * Safe-parse twin of parseEvidenceBrief. Same Result-like envelope
300
+ * shape; same MISSING_BRIEF_SECTION code mapping (covers both
301
+ * refine-guard failures and per-section missing/empty failures).
302
+ */
303
+ export declare function safeParseEvidenceBrief(input: unknown): {
304
+ ok: true;
305
+ row: EvidenceBrief;
306
+ } | {
307
+ ok: false;
308
+ code?: "MISSING_BRIEF_SECTION";
309
+ findings: Array<{
310
+ path: string;
311
+ message: string;
312
+ }>;
313
+ };