peaks-loop 4.0.0-beta.2 → 4.0.0-beta.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README-en.md +16 -3
- package/README.md +16 -3
- package/dist/src/cli/commands/asset-commands.d.ts +45 -0
- package/dist/src/cli/commands/asset-commands.js +404 -0
- package/dist/src/cli/commands/bee-commands.d.ts +26 -0
- package/dist/src/cli/commands/bee-commands.js +169 -0
- package/dist/src/cli/commands/evolution-commands.d.ts +27 -0
- package/dist/src/cli/commands/evolution-commands.js +393 -0
- package/dist/src/cli/commands/loop-commands.d.ts +19 -13
- package/dist/src/cli/commands/loop-commands.js +147 -13
- package/dist/src/cli/commands/sediment-commands.js +9 -0
- package/dist/src/cli/commands/skill-loop-engineering-readiness-commands.d.ts +67 -0
- package/dist/src/cli/commands/skill-loop-engineering-readiness-commands.js +173 -0
- package/dist/src/cli/program.js +17 -0
- package/dist/src/services/crystallization/crystallization-service.d.ts +239 -0
- package/dist/src/services/crystallization/crystallization-service.js +397 -0
- package/dist/src/services/crystallization/crystallization-store.d.ts +75 -0
- package/dist/src/services/crystallization/crystallization-store.js +193 -0
- package/dist/src/services/crystallization/crystallization-types.d.ts +313 -0
- package/dist/src/services/crystallization/crystallization-types.js +299 -0
- package/dist/src/services/crystallization/evidence-brief-builder.d.ts +237 -0
- package/dist/src/services/crystallization/evidence-brief-builder.js +240 -0
- package/dist/src/services/evolution/evolution-service.d.ts +137 -0
- package/dist/src/services/evolution/evolution-service.js +281 -0
- package/dist/src/services/evolution/evolution-store.d.ts +57 -0
- package/dist/src/services/evolution/evolution-store.js +232 -0
- package/dist/src/services/evolution/evolution-types.d.ts +706 -0
- package/dist/src/services/evolution/evolution-types.js +286 -0
- package/dist/src/services/evolution/independent-evaluator-runner.d.ts +90 -0
- package/dist/src/services/evolution/independent-evaluator-runner.js +106 -0
- package/dist/src/services/evolution/regression-skeptic-runner.d.ts +64 -0
- package/dist/src/services/evolution/regression-skeptic-runner.js +113 -0
- package/dist/src/services/loop/loop-bee-relation-service.d.ts +107 -0
- package/dist/src/services/loop/loop-bee-relation-service.js +211 -0
- package/dist/src/services/loop/loop-bee-relation-store.d.ts +53 -0
- package/dist/src/services/loop/loop-bee-relation-store.js +130 -0
- package/dist/src/services/loop/loop-bee-relation-types.d.ts +118 -0
- package/dist/src/services/loop/loop-bee-relation-types.js +114 -0
- package/dist/src/services/loop/loop-release-service.d.ts +46 -0
- package/dist/src/services/loop/loop-release-service.js +66 -0
- package/dist/src/services/loop/loop-release-store.d.ts +55 -0
- package/dist/src/services/loop/loop-release-store.js +134 -0
- package/dist/src/services/loop/loop-release-types.d.ts +250 -0
- package/dist/src/services/loop/loop-release-types.js +162 -0
- package/dist/src/services/share/bundle-reader.d.ts +100 -0
- package/dist/src/services/share/bundle-reader.js +434 -0
- package/dist/src/services/share/bundle-types.d.ts +392 -0
- package/dist/src/services/share/bundle-types.js +318 -0
- package/dist/src/services/share/bundle-writer.d.ts +97 -0
- package/dist/src/services/share/bundle-writer.js +429 -0
- package/dist/src/services/share/run-state-contract.d.ts +133 -0
- package/dist/src/services/share/run-state-contract.js +138 -0
- package/dist/src/services/skillhub/release-import.js +7 -2
- package/dist/src/services/skillhub/release-retain.js +6 -1
- package/dist/src/services/skillhub/sqlite-store.js +17 -1
- package/dist/src/services/skillhub/types.d.ts +10 -0
- package/dist/src/services/standards/loop-engineering-lint.d.ts +38 -0
- package/dist/src/services/standards/loop-engineering-lint.js +101 -0
- package/dist/src/services/standards/loop-engineering-readiness-lint.d.ts +111 -0
- package/dist/src/services/standards/loop-engineering-readiness-lint.js +248 -0
- package/dist/src/shared/version.d.ts +1 -1
- package/dist/src/shared/version.js +1 -1
- package/examples/video-demo/README.md +57 -0
- package/examples/video-demo/out/en-closing-960.png +0 -0
- package/examples/video-demo/out/zh-closing-960.png +0 -0
- package/examples/video-demo/preview/peaks-loop-demo-en.mp4 +0 -0
- package/examples/video-demo/preview/peaks-loop-demo.mp4 +0 -0
- package/package.json +6 -2
- package/skills/peaks-code/SKILL.md +13 -0
- package/skills/peaks-content/SKILL.md +272 -0
- package/skills/peaks-issue-fix-orchestrator/SKILL.md +307 -0
|
@@ -0,0 +1,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
|
+
};
|