peaks-loop 4.0.0-beta → 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 (179) hide show
  1. package/CHANGELOG.md +105 -87
  2. package/README-en.md +17 -4
  3. package/README.md +17 -4
  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/{solo-commands.d.ts → code-commands.d.ts} +24 -24
  9. package/dist/src/cli/commands/{solo-commands.js → code-commands.js} +78 -78
  10. package/dist/src/cli/commands/core/skill-command.js +1 -1
  11. package/dist/src/cli/commands/dispatch-from-dag.js +1 -1
  12. package/dist/src/cli/commands/evolution-commands.d.ts +27 -0
  13. package/dist/src/cli/commands/evolution-commands.js +393 -0
  14. package/dist/src/cli/commands/hook-handle.js +7 -7
  15. package/dist/src/cli/commands/job-commands.js +2 -2
  16. package/dist/src/cli/commands/loop-commands.d.ts +19 -13
  17. package/dist/src/cli/commands/loop-commands.js +147 -13
  18. package/dist/src/cli/commands/sediment-commands.js +9 -0
  19. package/dist/src/cli/commands/session-auto-compact-hook-command.js +2 -2
  20. package/dist/src/cli/commands/skill-loop-engineering-readiness-commands.d.ts +67 -0
  21. package/dist/src/cli/commands/skill-loop-engineering-readiness-commands.js +173 -0
  22. package/dist/src/cli/commands/sub-agent-shared.d.ts +1 -1
  23. package/dist/src/cli/commands/user-touchpoint-commands.d.ts +4 -4
  24. package/dist/src/cli/commands/user-touchpoint-commands.js +14 -14
  25. package/dist/src/cli/commands/workflow-commands.js +22 -22
  26. package/dist/src/cli/program.js +23 -6
  27. package/dist/src/services/artifacts/repair-cycle-service.js +1 -1
  28. package/dist/src/services/audit/enforcers/active-skill-resolver.d.ts +1 -1
  29. package/dist/src/services/audit/enforcers/active-skill-resolver.js +1 -1
  30. package/dist/src/services/audit/enforcers/{solo-code-ban.d.ts → code-ban.d.ts} +6 -6
  31. package/dist/src/services/audit/enforcers/{solo-code-ban.js → code-ban.js} +6 -6
  32. package/dist/src/services/audit/red-line-catalog.d.ts +2 -2
  33. package/dist/src/services/audit/red-line-catalog.js +5 -5
  34. package/dist/src/services/audit/types.d.ts +2 -2
  35. package/dist/src/services/{solo → code}/auto-compact-orchestrator.d.ts +1 -1
  36. package/dist/src/services/{solo → code}/auto-compact-orchestrator.js +3 -3
  37. package/dist/src/services/{solo → code}/dag-orchestrator.d.ts +1 -1
  38. package/dist/src/services/{solo → code}/dag-orchestrator.js +1 -1
  39. package/dist/src/services/{solo → code}/emit-handoff.d.ts +1 -1
  40. package/dist/src/services/{solo → code}/emit-handoff.js +1 -1
  41. package/dist/src/services/{solo → code}/job-shape-decision.d.ts +1 -1
  42. package/dist/src/services/{solo → code}/job-shape-decision.js +5 -5
  43. package/dist/src/services/{solo → code}/mode-gate.d.ts +9 -9
  44. package/dist/src/services/{solo → code}/mode-gate.js +5 -5
  45. package/dist/src/services/{solo → code}/post-compact-detector.d.ts +3 -3
  46. package/dist/src/services/{solo → code}/post-compact-detector.js +4 -4
  47. package/dist/src/services/{solo → code}/step-08-gate.d.ts +4 -4
  48. package/dist/src/services/{solo → code}/step-08-gate.js +4 -4
  49. package/dist/src/services/{solo → code}/user-touchpoint-classifier.d.ts +1 -1
  50. package/dist/src/services/{solo → code}/user-touchpoint-classifier.js +1 -1
  51. package/dist/src/services/context/auto-compact-dispatcher.d.ts +2 -2
  52. package/dist/src/services/context/auto-compact-dispatcher.js +2 -2
  53. package/dist/src/services/context/auto-compact-types.d.ts +1 -1
  54. package/dist/src/services/crystallization/crystallization-service.d.ts +239 -0
  55. package/dist/src/services/crystallization/crystallization-service.js +397 -0
  56. package/dist/src/services/crystallization/crystallization-store.d.ts +75 -0
  57. package/dist/src/services/crystallization/crystallization-store.js +193 -0
  58. package/dist/src/services/crystallization/crystallization-types.d.ts +313 -0
  59. package/dist/src/services/crystallization/crystallization-types.js +299 -0
  60. package/dist/src/services/crystallization/evidence-brief-builder.d.ts +237 -0
  61. package/dist/src/services/crystallization/evidence-brief-builder.js +240 -0
  62. package/dist/src/services/dispatch/slice-dag.d.ts +2 -2
  63. package/dist/src/services/dispatch/test-tool-detection.d.ts +1 -1
  64. package/dist/src/services/dispatch/test-tool-detection.js +1 -1
  65. package/dist/src/services/evolution/evolution-service.d.ts +137 -0
  66. package/dist/src/services/evolution/evolution-service.js +281 -0
  67. package/dist/src/services/evolution/evolution-store.d.ts +57 -0
  68. package/dist/src/services/evolution/evolution-store.js +232 -0
  69. package/dist/src/services/evolution/evolution-types.d.ts +706 -0
  70. package/dist/src/services/evolution/evolution-types.js +286 -0
  71. package/dist/src/services/evolution/independent-evaluator-runner.d.ts +90 -0
  72. package/dist/src/services/evolution/independent-evaluator-runner.js +106 -0
  73. package/dist/src/services/evolution/regression-skeptic-runner.d.ts +64 -0
  74. package/dist/src/services/evolution/regression-skeptic-runner.js +113 -0
  75. package/dist/src/services/feedback/feedback-promotion-service.js +2 -2
  76. package/dist/src/services/job/job-progress-store.d.ts +1 -1
  77. package/dist/src/services/job/job-progress-store.js +1 -1
  78. package/dist/src/services/loop/loop-bee-relation-service.d.ts +107 -0
  79. package/dist/src/services/loop/loop-bee-relation-service.js +211 -0
  80. package/dist/src/services/loop/loop-bee-relation-store.d.ts +53 -0
  81. package/dist/src/services/loop/loop-bee-relation-store.js +130 -0
  82. package/dist/src/services/loop/loop-bee-relation-types.d.ts +118 -0
  83. package/dist/src/services/loop/loop-bee-relation-types.js +114 -0
  84. package/dist/src/services/loop/loop-release-service.d.ts +46 -0
  85. package/dist/src/services/loop/loop-release-service.js +66 -0
  86. package/dist/src/services/loop/loop-release-store.d.ts +55 -0
  87. package/dist/src/services/loop/loop-release-store.js +134 -0
  88. package/dist/src/services/loop/loop-release-types.d.ts +250 -0
  89. package/dist/src/services/loop/loop-release-types.js +162 -0
  90. package/dist/src/services/preferences/preferences-service.d.ts +1 -1
  91. package/dist/src/services/preferences/preferences-types.d.ts +1 -1
  92. package/dist/src/services/rd/standards-diagnostic.d.ts +1 -1
  93. package/dist/src/services/rd/standards-diagnostic.js +2 -2
  94. package/dist/src/services/recommendations/capability-seed-items.js +1 -1
  95. package/dist/src/services/recommendations/capability-seed-mappings.js +1 -1
  96. package/dist/src/services/recommendations/recommendation-service.js +1 -1
  97. package/dist/src/services/refactor/refactor-service.d.ts +1 -1
  98. package/dist/src/services/share/bundle-reader.d.ts +100 -0
  99. package/dist/src/services/share/bundle-reader.js +434 -0
  100. package/dist/src/services/share/bundle-types.d.ts +392 -0
  101. package/dist/src/services/share/bundle-types.js +318 -0
  102. package/dist/src/services/share/bundle-writer.d.ts +97 -0
  103. package/dist/src/services/share/bundle-writer.js +429 -0
  104. package/dist/src/services/share/run-state-contract.d.ts +133 -0
  105. package/dist/src/services/share/run-state-contract.js +138 -0
  106. package/dist/src/services/signal/cancel-handler.js +3 -3
  107. package/dist/src/services/skill/resume-detector.js +1 -1
  108. package/dist/src/services/skillhub/release-import.js +7 -2
  109. package/dist/src/services/skillhub/release-retain.js +6 -1
  110. package/dist/src/services/skillhub/sqlite-store.js +17 -1
  111. package/dist/src/services/skillhub/types.d.ts +10 -0
  112. package/dist/src/services/skills/skill-presence-service.d.ts +1 -1
  113. package/dist/src/services/standards/loop-engineering-lint.d.ts +38 -0
  114. package/dist/src/services/standards/loop-engineering-lint.js +101 -0
  115. package/dist/src/services/standards/loop-engineering-readiness-lint.d.ts +111 -0
  116. package/dist/src/services/standards/loop-engineering-readiness-lint.js +248 -0
  117. package/dist/src/services/upgrade/1x-detector-service.js +1 -1
  118. package/dist/src/services/workflow/pipeline-verify-service.d.ts +1 -1
  119. package/dist/src/services/workflow/pipeline-verify-service.js +3 -3
  120. package/dist/src/services/workflow/workflow-autonomous-service.d.ts +3 -3
  121. package/dist/src/services/workflow/workflow-autonomous-service.js +2 -2
  122. package/dist/src/services/workflow/workflow-router-service.d.ts +6 -6
  123. package/dist/src/services/workflow/workflow-router-service.js +33 -33
  124. package/dist/src/services/workspace/claude-settings-template.d.ts +1 -1
  125. package/dist/src/services/workspace/claude-settings-template.js +5 -5
  126. package/dist/src/shared/version.d.ts +1 -1
  127. package/dist/src/shared/version.js +1 -1
  128. package/examples/video-demo/README.md +57 -0
  129. package/examples/video-demo/out/en-closing-960.png +0 -0
  130. package/examples/video-demo/out/zh-closing-960.png +0 -0
  131. package/examples/video-demo/preview/peaks-loop-demo-en.mp4 +0 -0
  132. package/examples/video-demo/preview/peaks-loop-demo.mp4 +0 -0
  133. package/output-styles/peaks-skill-swarm.md +3 -3
  134. package/package.json +6 -2
  135. package/skills/bee/peaks-qa/SKILL.md +1 -1
  136. package/skills/bee/peaks-qa/references/artifact-per-request.md +3 -3
  137. package/skills/bee/peaks-qa/references/qa-sub-agent-dispatch.md +6 -6
  138. package/skills/bee/peaks-rd/references/rd-fanout-contracts.md +1 -1
  139. package/skills/bee/peaks-rd/references/rd-runbook.md +1 -1
  140. package/skills/bee/peaks-rd/references/rd-sub-agent-dispatch.md +11 -11
  141. package/skills/bee/peaks-rd/references/rd-transition-gates.md +1 -1
  142. package/skills/bee/peaks-sc/SKILL.md +1 -1
  143. package/skills/bee/peaks-txt/SKILL.md +3 -3
  144. package/skills/bee/peaks-ui/SKILL.md +8 -8
  145. package/skills/peaks-code/SKILL.md +34 -21
  146. package/skills/peaks-code/references/anchoring-and-session-info.md +2 -2
  147. package/skills/peaks-code/references/artifact-contracts.md +1 -1
  148. package/skills/peaks-code/references/boundaries.md +3 -3
  149. package/skills/peaks-code/references/codegraph-orchestration.md +1 -1
  150. package/skills/peaks-code/references/dag-orchestrator.md +7 -7
  151. package/skills/peaks-code/references/external-references.md +2 -2
  152. package/skills/peaks-code/references/fanout-mandatory.md +3 -3
  153. package/skills/peaks-code/references/fast-mode.md +2 -2
  154. package/skills/peaks-code/references/frontend-only-mode.md +9 -9
  155. package/skills/peaks-code/references/job-loop.md +1 -1
  156. package/skills/peaks-code/references/local-artifact-workspace.md +2 -2
  157. package/skills/peaks-code/references/micro-cycle.md +14 -14
  158. package/skills/peaks-code/references/mode-selection-with-stale-presence.md +5 -5
  159. package/skills/peaks-code/references/mode-selection.md +3 -3
  160. package/skills/peaks-code/references/openspec-workflow.md +16 -16
  161. package/skills/peaks-code/references/periodic-checkpoint.md +4 -4
  162. package/skills/peaks-code/references/quality-gate-cheatsheet.md +1 -1
  163. package/skills/peaks-code/references/refactor-mode.md +1 -1
  164. package/skills/peaks-code/references/runbook.md +15 -15
  165. package/skills/peaks-code/references/step-0-55-1x-detection.md +1 -1
  166. package/skills/peaks-code/references/step-0-8-gate.md +11 -11
  167. package/skills/peaks-code/references/sub-agent-dispatch.md +8 -8
  168. package/skills/peaks-code/references/swarm-dispatch-contract.md +17 -17
  169. package/skills/peaks-code/references/workflow-gates-and-types.md +2 -2
  170. package/skills/peaks-code/references/workflow.md +5 -5
  171. package/skills/peaks-content/SKILL.md +272 -0
  172. package/skills/peaks-issue-fix-orchestrator/SKILL.md +307 -0
  173. package/skills/peaks-resume/SKILL.md +2 -2
  174. package/skills/peaks-status/SKILL.md +2 -2
  175. package/skills/peaks-test/SKILL.md +2 -2
  176. /package/dist/src/services/{solo → code}/batch-heartbeat-poller.d.ts +0 -0
  177. /package/dist/src/services/{solo → code}/batch-heartbeat-poller.js +0 -0
  178. /package/dist/src/services/{solo → code}/status-line-renderer.d.ts +0 -0
  179. /package/dist/src/services/{solo → code}/status-line-renderer.js +0 -0
@@ -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
+ };
@@ -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
+ }