ultra-builder-pro-cli 0.23.0 → 0.24.0
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/.ultra-template/docs/research/README.md +4 -4
- package/CHANGELOG.md +45 -0
- package/README.md +21 -18
- package/adapters/_shared/codex-assets.cjs +121 -65
- package/adapters/_shared/interaction-contract.cjs +7 -1
- package/adapters/_shared/provenance.cjs +7 -2
- package/adapters/_shared/runtime-assets.cjs +3 -2
- package/adapters/_shared/runtime-native.cjs +132 -0
- package/adapters/claude.js +60 -30
- package/adapters/codex.js +178 -81
- package/adapters/grok.js +372 -0
- package/adapters/kimi.js +7 -3
- package/adapters/opencode.js +210 -32
- package/agents/code-reviewer.md +4 -2
- package/agents/debugger.md +4 -1
- package/agents/review-code.md +7 -3
- package/agents/review-comments.md +7 -4
- package/agents/review-coordinator.md +11 -7
- package/agents/review-design.md +8 -4
- package/agents/review-errors.md +8 -4
- package/agents/review-spec.md +8 -5
- package/agents/review-tests.md +7 -4
- package/agents/tdd-runner.md +5 -2
- package/bin/install.js +9 -4
- package/bin/orchestrator.js +4 -13
- package/docs/AGENT-CONTEXT.md +141 -229
- package/docs/ARCHITECTURE.md +203 -494
- package/docs/ARTIFACT-AUTHORITY.md +26 -22
- package/docs/PLUGIN-ISOLATION-CONTRACT.md +12 -9
- package/docs/ROADMAP.md +85 -110
- package/docs/RUNTIME-COMPAT-MATRIX.md +139 -175
- package/docs/SKILL-AUTHORING.md +3 -3
- package/docs/STATE-DB-ACCESS-POLICY.md +13 -8
- package/docs/WORKFLOW-LIFECYCLE.md +174 -448
- package/hooks/README.md +11 -8
- package/hooks/active_task_context.py +16 -16
- package/hooks/adapters/grok.py +134 -0
- package/hooks/{context_spine.py → context_envelope.py} +26 -22
- package/hooks/health_check.py +19 -29
- package/hooks/pre_stop_check.py +22 -12
- package/hooks/subagent_tracker.py +1 -1
- package/hooks/workflow_checkpoint.py +14 -13
- package/hooks/workflow_context.py +11 -12
- package/hooks/workflow_resume.py +14 -13
- package/mcp-server/{breadcrumb.cjs → hook-context.cjs} +7 -9
- package/mcp-server/lib/baseline-workflow.cjs +36 -38
- package/mcp-server/lib/canonical-json.cjs +19 -0
- package/mcp-server/lib/change-workflow.cjs +596 -44
- package/mcp-server/lib/context-envelope.cjs +508 -0
- package/mcp-server/lib/decision-records.cjs +337 -0
- package/mcp-server/lib/doctor.cjs +91 -33
- package/mcp-server/lib/init-project.cjs +78 -39
- package/mcp-server/lib/managed-file-write.cjs +116 -0
- package/mcp-server/lib/plan-checkpoint.cjs +177 -0
- package/mcp-server/lib/project-context.cjs +178 -0
- package/mcp-server/lib/stage-checkpoints.cjs +309 -0
- package/mcp-server/lib/state-db.cjs +155 -24
- package/mcp-server/lib/task-ledger.cjs +522 -13
- package/mcp-server/lib/ultra-facade.cjs +630 -442
- package/mcp-server/lib/worker-packet.cjs +358 -0
- package/mcp-server/server.cjs +200 -1103
- package/orchestrator/daemon.cjs +27 -9
- package/orchestrator/parallel-orchestrator.cjs +111 -76
- package/orchestrator/session-runner.cjs +135 -34
- package/package.json +10 -3
- package/skills/ultra-change/SKILL.md +9 -8
- package/skills/ultra-deliver/SKILL.md +3 -3
- package/skills/ultra-dev/SKILL.md +18 -11
- package/skills/ultra-doctor/SKILL.md +2 -2
- package/skills/ultra-init/SKILL.md +6 -5
- package/skills/ultra-init/references/brownfield-adoption.md +11 -8
- package/skills/ultra-plan/SKILL.md +10 -8
- package/skills/ultra-research/SKILL.md +12 -7
- package/skills/ultra-review/SKILL.md +9 -6
- package/skills/ultra-review/references/unified-schema.md +2 -0
- package/skills/ultra-review/scripts/review_wait.py +8 -0
- package/skills/ultra-status/SKILL.md +2 -2
- package/skills/ultra-test/SKILL.md +4 -2
- package/skills/ultra-think/SKILL.md +7 -7
- package/skills/ultra-think/references/interaction-boundary.md +56 -0
- package/spec/cli-protocol.md +80 -199
- package/spec/mcp-tools.yaml +37 -2804
- package/spec/schemas/state-db.sql +107 -4
- package/spec/schemas/{task-ledger.v1.schema.json → task-ledger.v2.schema.json} +70 -6
- package/ultra-tools/commands/status.cjs +369 -243
- package/mcp-server/lib/context-spine.cjs +0 -1208
- package/mcp-server/lib/decision-dialogue.cjs +0 -1128
- package/mcp-server/lib/project-breadcrumb.cjs +0 -173
- package/mcp-server/lib/spec-learning.cjs +0 -284
- package/mcp-server/lib/workflow-state.cjs +0 -3129
- package/skills/ultra-think/references/decision-dialogue.md +0 -155
|
@@ -0,0 +1,309 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const crypto = require('node:crypto');
|
|
4
|
+
|
|
5
|
+
const ops = require('./state-ops.cjs');
|
|
6
|
+
const canonical = require('./canonical-json.cjs');
|
|
7
|
+
|
|
8
|
+
const STAGES = new Set(['init', 'research', 'change', 'plan', 'dev', 'test', 'review', 'deliver']);
|
|
9
|
+
const SCOPE_KEYS = Object.freeze([
|
|
10
|
+
['task_id', 'task'],
|
|
11
|
+
['change_id', 'change'],
|
|
12
|
+
['baseline_id', 'baseline'],
|
|
13
|
+
['project_id', 'project'],
|
|
14
|
+
]);
|
|
15
|
+
|
|
16
|
+
class StageCheckpointError extends Error {
|
|
17
|
+
constructor(code, message, details) {
|
|
18
|
+
super(message);
|
|
19
|
+
this.name = 'StageCheckpointError';
|
|
20
|
+
this.code = code;
|
|
21
|
+
if (details) this.details = details;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function parseJson(value, fallback) {
|
|
26
|
+
try { return value == null ? fallback : JSON.parse(value); }
|
|
27
|
+
catch { return fallback; }
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function normalizeScope(scope = {}) {
|
|
31
|
+
const matches = SCOPE_KEYS.filter(([key]) => (
|
|
32
|
+
typeof scope[key] === 'string' && scope[key].trim()
|
|
33
|
+
));
|
|
34
|
+
if (matches.length !== 1) {
|
|
35
|
+
throw new StageCheckpointError(
|
|
36
|
+
'VALIDATION_ERROR',
|
|
37
|
+
'checkpoint scope must contain exactly one of project_id, baseline_id, change_id, or task_id',
|
|
38
|
+
);
|
|
39
|
+
}
|
|
40
|
+
const [key, type] = matches[0];
|
|
41
|
+
return { type, id: scope[key].trim() };
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function validateStage(stage) {
|
|
45
|
+
if (!STAGES.has(stage)) {
|
|
46
|
+
throw new StageCheckpointError('VALIDATION_ERROR', `unsupported checkpoint stage: ${stage}`);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function normalizeDiagnostics(value) {
|
|
51
|
+
if (!Array.isArray(value)) {
|
|
52
|
+
throw new StageCheckpointError('VALIDATION_ERROR', 'diagnostics must be an array');
|
|
53
|
+
}
|
|
54
|
+
return value.map((item, index) => {
|
|
55
|
+
if (!item || typeof item !== 'object' || Array.isArray(item)) {
|
|
56
|
+
throw new StageCheckpointError('VALIDATION_ERROR', `diagnostics[${index}] must be an object`);
|
|
57
|
+
}
|
|
58
|
+
const code = String(item.code || '').trim();
|
|
59
|
+
if (!code) {
|
|
60
|
+
throw new StageCheckpointError('VALIDATION_ERROR', `diagnostics[${index}].code is required`);
|
|
61
|
+
}
|
|
62
|
+
const severity = item.severity || 'needs_attention';
|
|
63
|
+
if (!['warning', 'needs_attention', 'hard_conflict'].includes(severity)) {
|
|
64
|
+
throw new StageCheckpointError(
|
|
65
|
+
'VALIDATION_ERROR',
|
|
66
|
+
`diagnostics[${index}].severity is invalid`,
|
|
67
|
+
);
|
|
68
|
+
}
|
|
69
|
+
return {
|
|
70
|
+
code,
|
|
71
|
+
severity,
|
|
72
|
+
...(item.message ? { message: String(item.message) } : {}),
|
|
73
|
+
...(item.details === undefined ? {} : { details: item.details }),
|
|
74
|
+
};
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
function checkpointDigest(value) {
|
|
79
|
+
return canonical.digest({
|
|
80
|
+
stage: value.stage,
|
|
81
|
+
scope_type: value.scope_type,
|
|
82
|
+
scope_id: value.scope_id,
|
|
83
|
+
revision: value.revision,
|
|
84
|
+
payload: value.payload,
|
|
85
|
+
evidence: value.evidence,
|
|
86
|
+
diagnostics: value.diagnostics,
|
|
87
|
+
context_envelope_id: value.context_envelope_id || null,
|
|
88
|
+
supersedes_id: value.supersedes_id || null,
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
function rowToCheckpoint(row) {
|
|
93
|
+
if (!row) return null;
|
|
94
|
+
const checkpoint = {
|
|
95
|
+
id: row.id,
|
|
96
|
+
stage: row.stage,
|
|
97
|
+
scope: { [`${row.scope_type}_id`]: row.scope_id },
|
|
98
|
+
scope_type: row.scope_type,
|
|
99
|
+
scope_id: row.scope_id,
|
|
100
|
+
revision: row.revision,
|
|
101
|
+
status: row.status,
|
|
102
|
+
payload: parseJson(row.payload_json, {}),
|
|
103
|
+
evidence: parseJson(row.evidence_json, []),
|
|
104
|
+
diagnostics: parseJson(row.diagnostics_json, []),
|
|
105
|
+
context_envelope_id: row.context_envelope_id,
|
|
106
|
+
digest: row.digest,
|
|
107
|
+
supersedes_id: row.supersedes_id,
|
|
108
|
+
idempotency_key: row.idempotency_key,
|
|
109
|
+
created_at: row.created_at,
|
|
110
|
+
updated_at: row.updated_at,
|
|
111
|
+
accepted_at: row.accepted_at,
|
|
112
|
+
};
|
|
113
|
+
const actual = checkpointDigest(checkpoint);
|
|
114
|
+
if (actual !== checkpoint.digest) {
|
|
115
|
+
throw new StageCheckpointError(
|
|
116
|
+
'CHECKPOINT_DIGEST_MISMATCH',
|
|
117
|
+
`Stage Checkpoint database authority is corrupt: ${checkpoint.id}`,
|
|
118
|
+
{ expected: checkpoint.digest, actual },
|
|
119
|
+
);
|
|
120
|
+
}
|
|
121
|
+
return checkpoint;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
function readCheckpoint(db, id) {
|
|
125
|
+
return rowToCheckpoint(db.prepare('SELECT * FROM stage_checkpoints WHERE id = ?').get(id));
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
function listCheckpoints(db, { stage, scope, status, limit = 100 } = {}) {
|
|
129
|
+
const clauses = [];
|
|
130
|
+
const params = [];
|
|
131
|
+
if (stage) { validateStage(stage); clauses.push('stage = ?'); params.push(stage); }
|
|
132
|
+
if (scope) {
|
|
133
|
+
const normalized = normalizeScope(scope);
|
|
134
|
+
clauses.push('scope_type = ?', 'scope_id = ?');
|
|
135
|
+
params.push(normalized.type, normalized.id);
|
|
136
|
+
}
|
|
137
|
+
if (status) { clauses.push('status = ?'); params.push(status); }
|
|
138
|
+
const bounded = Math.min(Math.max(Number(limit) || 100, 1), 500);
|
|
139
|
+
return db.prepare(
|
|
140
|
+
`SELECT * FROM stage_checkpoints
|
|
141
|
+
${clauses.length ? `WHERE ${clauses.join(' AND ')}` : ''}
|
|
142
|
+
ORDER BY stage, scope_type, scope_id, revision DESC
|
|
143
|
+
LIMIT ?`,
|
|
144
|
+
).all(...params, bounded).map(rowToCheckpoint);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
function existingByIdempotency(db, idempotencyKey) {
|
|
148
|
+
if (!idempotencyKey) return null;
|
|
149
|
+
return rowToCheckpoint(
|
|
150
|
+
db.prepare('SELECT * FROM stage_checkpoints WHERE idempotency_key = ?').get(idempotencyKey),
|
|
151
|
+
);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
function saveDraft(db, input = {}) {
|
|
155
|
+
validateStage(input.stage);
|
|
156
|
+
const scope = normalizeScope(input.scope);
|
|
157
|
+
const idempotencyKey = String(input.idempotency_key || '').trim();
|
|
158
|
+
if (!idempotencyKey) {
|
|
159
|
+
throw new StageCheckpointError('VALIDATION_ERROR', 'idempotency_key is required');
|
|
160
|
+
}
|
|
161
|
+
const existingRetry = existingByIdempotency(db, idempotencyKey);
|
|
162
|
+
if (existingRetry) return existingRetry;
|
|
163
|
+
const payload = input.payload && typeof input.payload === 'object' && !Array.isArray(input.payload)
|
|
164
|
+
? input.payload : {};
|
|
165
|
+
const evidence = Array.isArray(input.evidence) ? input.evidence : [];
|
|
166
|
+
const diagnostics = normalizeDiagnostics(input.diagnostics || []);
|
|
167
|
+
return ops.tx(db, () => {
|
|
168
|
+
const draft = db.prepare(
|
|
169
|
+
`SELECT * FROM stage_checkpoints
|
|
170
|
+
WHERE stage = ? AND scope_type = ? AND scope_id = ? AND status = 'draft'
|
|
171
|
+
ORDER BY revision DESC LIMIT 1`,
|
|
172
|
+
).get(input.stage, scope.type, scope.id);
|
|
173
|
+
if (draft) {
|
|
174
|
+
const value = {
|
|
175
|
+
stage: input.stage,
|
|
176
|
+
scope_type: scope.type,
|
|
177
|
+
scope_id: scope.id,
|
|
178
|
+
revision: draft.revision,
|
|
179
|
+
payload,
|
|
180
|
+
evidence,
|
|
181
|
+
diagnostics,
|
|
182
|
+
context_envelope_id: input.context_envelope_id || null,
|
|
183
|
+
supersedes_id: draft.supersedes_id,
|
|
184
|
+
};
|
|
185
|
+
const digest = checkpointDigest(value);
|
|
186
|
+
db.prepare(
|
|
187
|
+
`UPDATE stage_checkpoints
|
|
188
|
+
SET payload_json = ?, evidence_json = ?, diagnostics_json = ?,
|
|
189
|
+
context_envelope_id = ?, digest = ?, idempotency_key = ?,
|
|
190
|
+
updated_at = strftime('%Y-%m-%dT%H:%M:%fZ', 'now')
|
|
191
|
+
WHERE id = ?`,
|
|
192
|
+
).run(
|
|
193
|
+
JSON.stringify(payload),
|
|
194
|
+
JSON.stringify(evidence),
|
|
195
|
+
JSON.stringify(diagnostics),
|
|
196
|
+
input.context_envelope_id || null,
|
|
197
|
+
digest,
|
|
198
|
+
idempotencyKey,
|
|
199
|
+
draft.id,
|
|
200
|
+
);
|
|
201
|
+
return readCheckpoint(db, draft.id);
|
|
202
|
+
}
|
|
203
|
+
const accepted = db.prepare(
|
|
204
|
+
`SELECT id, revision FROM stage_checkpoints
|
|
205
|
+
WHERE stage = ? AND scope_type = ? AND scope_id = ? AND status = 'accepted'
|
|
206
|
+
ORDER BY revision DESC LIMIT 1`,
|
|
207
|
+
).get(input.stage, scope.type, scope.id);
|
|
208
|
+
const revision = (accepted?.revision || 0) + 1;
|
|
209
|
+
const id = `checkpoint-${crypto.randomUUID()}`;
|
|
210
|
+
const value = {
|
|
211
|
+
stage: input.stage,
|
|
212
|
+
scope_type: scope.type,
|
|
213
|
+
scope_id: scope.id,
|
|
214
|
+
revision,
|
|
215
|
+
payload,
|
|
216
|
+
evidence,
|
|
217
|
+
diagnostics,
|
|
218
|
+
context_envelope_id: input.context_envelope_id || null,
|
|
219
|
+
supersedes_id: accepted?.id || null,
|
|
220
|
+
};
|
|
221
|
+
db.prepare(
|
|
222
|
+
`INSERT INTO stage_checkpoints
|
|
223
|
+
(id, stage, scope_type, scope_id, revision, payload_json, evidence_json,
|
|
224
|
+
diagnostics_json, context_envelope_id, digest, supersedes_id, idempotency_key)
|
|
225
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
|
|
226
|
+
).run(
|
|
227
|
+
id,
|
|
228
|
+
input.stage,
|
|
229
|
+
scope.type,
|
|
230
|
+
scope.id,
|
|
231
|
+
revision,
|
|
232
|
+
JSON.stringify(payload),
|
|
233
|
+
JSON.stringify(evidence),
|
|
234
|
+
JSON.stringify(diagnostics),
|
|
235
|
+
input.context_envelope_id || null,
|
|
236
|
+
checkpointDigest(value),
|
|
237
|
+
accepted?.id || null,
|
|
238
|
+
idempotencyKey,
|
|
239
|
+
);
|
|
240
|
+
return readCheckpoint(db, id);
|
|
241
|
+
});
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
function acceptDraft(db, input = {}) {
|
|
245
|
+
const idempotencyKey = String(input.idempotency_key || '').trim();
|
|
246
|
+
if (!idempotencyKey) {
|
|
247
|
+
throw new StageCheckpointError('VALIDATION_ERROR', 'idempotency_key is required');
|
|
248
|
+
}
|
|
249
|
+
return ops.tx(db, () => {
|
|
250
|
+
const row = db.prepare('SELECT * FROM stage_checkpoints WHERE id = ?').get(input.id);
|
|
251
|
+
if (!row) throw new StageCheckpointError('CHECKPOINT_NOT_FOUND', `checkpoint not found: ${input.id}`);
|
|
252
|
+
if (row.status === 'accepted') return rowToCheckpoint(row);
|
|
253
|
+
if (row.status !== 'draft') {
|
|
254
|
+
throw new StageCheckpointError(
|
|
255
|
+
'CHECKPOINT_NOT_MUTABLE',
|
|
256
|
+
`checkpoint ${input.id} is ${row.status}`,
|
|
257
|
+
);
|
|
258
|
+
}
|
|
259
|
+
if (row.supersedes_id) {
|
|
260
|
+
db.prepare(
|
|
261
|
+
`UPDATE stage_checkpoints SET status = 'superseded',
|
|
262
|
+
updated_at = strftime('%Y-%m-%dT%H:%M:%fZ', 'now')
|
|
263
|
+
WHERE id = ? AND status = 'accepted'`,
|
|
264
|
+
).run(row.supersedes_id);
|
|
265
|
+
}
|
|
266
|
+
db.prepare(
|
|
267
|
+
`UPDATE stage_checkpoints
|
|
268
|
+
SET status = 'accepted', accepted_at = strftime('%Y-%m-%dT%H:%M:%fZ', 'now'),
|
|
269
|
+
updated_at = strftime('%Y-%m-%dT%H:%M:%fZ', 'now')
|
|
270
|
+
WHERE id = ?`,
|
|
271
|
+
).run(row.id);
|
|
272
|
+
const accepted = readCheckpoint(db, row.id);
|
|
273
|
+
ops.appendEventInTx(db, {
|
|
274
|
+
type: 'ultra_checkpoint_accepted',
|
|
275
|
+
change_id: accepted.scope_type === 'change' ? accepted.scope_id : null,
|
|
276
|
+
task_id: accepted.scope_type === 'task' ? accepted.scope_id : null,
|
|
277
|
+
payload: {
|
|
278
|
+
checkpoint_id: accepted.id,
|
|
279
|
+
stage: accepted.stage,
|
|
280
|
+
revision: accepted.revision,
|
|
281
|
+
digest: accepted.digest,
|
|
282
|
+
},
|
|
283
|
+
});
|
|
284
|
+
return accepted;
|
|
285
|
+
});
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
function currentCheckpoint(db, stage, scope, { includeDraft = true } = {}) {
|
|
289
|
+
validateStage(stage);
|
|
290
|
+
const normalized = normalizeScope(scope);
|
|
291
|
+
const statuses = includeDraft ? "('draft','accepted')" : "('accepted')";
|
|
292
|
+
return rowToCheckpoint(db.prepare(
|
|
293
|
+
`SELECT * FROM stage_checkpoints
|
|
294
|
+
WHERE stage = ? AND scope_type = ? AND scope_id = ? AND status IN ${statuses}
|
|
295
|
+
ORDER BY CASE status WHEN 'draft' THEN 0 ELSE 1 END, revision DESC LIMIT 1`,
|
|
296
|
+
).get(stage, normalized.type, normalized.id));
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
module.exports = {
|
|
300
|
+
StageCheckpointError,
|
|
301
|
+
STAGES,
|
|
302
|
+
normalizeScope,
|
|
303
|
+
readCheckpoint,
|
|
304
|
+
listCheckpoints,
|
|
305
|
+
saveDraft,
|
|
306
|
+
acceptDraft,
|
|
307
|
+
currentCheckpoint,
|
|
308
|
+
checkpointDigest,
|
|
309
|
+
};
|
|
@@ -9,7 +9,7 @@ const REPO_ROOT = process.env.UBP_RUNTIME_ROOT
|
|
|
9
9
|
? path.resolve(process.env.UBP_RUNTIME_ROOT)
|
|
10
10
|
: path.resolve(__dirname, '..', '..');
|
|
11
11
|
const SCHEMA_FILE = path.join(REPO_ROOT, 'spec', 'schemas', 'state-db.sql');
|
|
12
|
-
const EXPECTED_VERSION = '
|
|
12
|
+
const EXPECTED_VERSION = '22.0';
|
|
13
13
|
const KIMI_SCHEMA_VERSION = '9.1';
|
|
14
14
|
const CONTEXT_SCHEMA_VERSION = '10.0';
|
|
15
15
|
const BASELINE_SCHEMA_VERSION = '11.0';
|
|
@@ -22,6 +22,8 @@ const GIT_AUTHORITY_SCHEMA_VERSION = '17.0';
|
|
|
22
22
|
const ADAPTIVE_SCHEMA_VERSION = '18.0';
|
|
23
23
|
const DECISION_COMPLETION_SCHEMA_VERSION = '19.0';
|
|
24
24
|
const ARTIFACT_REGISTRY_SCHEMA_VERSION = '20.0';
|
|
25
|
+
const KERNEL_SCHEMA_VERSION = '21.0';
|
|
26
|
+
const CHECKPOINT_NATIVE_SCHEMA_VERSION = '22.0';
|
|
25
27
|
|
|
26
28
|
const MIGRATED_GAPS = Object.freeze([{
|
|
27
29
|
id: 'legacy-rebaseline-required',
|
|
@@ -56,6 +58,10 @@ const REQUIRED_TABLES = Object.freeze([
|
|
|
56
58
|
'workflow_steps',
|
|
57
59
|
'decision_threads',
|
|
58
60
|
'decision_items',
|
|
61
|
+
'stage_checkpoints',
|
|
62
|
+
'decision_records',
|
|
63
|
+
'context_envelopes',
|
|
64
|
+
'worker_packets',
|
|
59
65
|
]);
|
|
60
66
|
|
|
61
67
|
class ActiveSessionLeaseConflictError extends Error {
|
|
@@ -173,6 +179,7 @@ function applyBaselineUpgrade(db, { legacyState = false } = {}) {
|
|
|
173
179
|
classification_json TEXT NOT NULL DEFAULT '{}',
|
|
174
180
|
provider_refs_json TEXT NOT NULL DEFAULT '{}',
|
|
175
181
|
research_run_id TEXT,
|
|
182
|
+
research_checkpoint_id TEXT,
|
|
176
183
|
approved_by TEXT,
|
|
177
184
|
approval_note TEXT,
|
|
178
185
|
started_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ', 'now')),
|
|
@@ -226,6 +233,62 @@ function applyBaselineColumns(db) {
|
|
|
226
233
|
db, 'baselines', columns, 'classification_json', "TEXT NOT NULL DEFAULT '{}'",
|
|
227
234
|
) || changed;
|
|
228
235
|
changed = addColumnIfMissing(db, 'baselines', columns, 'research_run_id', 'TEXT') || changed;
|
|
236
|
+
changed = addColumnIfMissing(
|
|
237
|
+
db,
|
|
238
|
+
'baselines',
|
|
239
|
+
columns,
|
|
240
|
+
'research_checkpoint_id',
|
|
241
|
+
'TEXT',
|
|
242
|
+
) || changed;
|
|
243
|
+
if (columns.has('research_checkpoint_id')
|
|
244
|
+
&& tableNames(db).includes('stage_checkpoints')) {
|
|
245
|
+
const result = db.prepare(
|
|
246
|
+
`UPDATE baselines
|
|
247
|
+
SET research_checkpoint_id = research_run_id
|
|
248
|
+
WHERE research_checkpoint_id IS NULL
|
|
249
|
+
AND research_run_id IS NOT NULL
|
|
250
|
+
AND EXISTS (
|
|
251
|
+
SELECT 1 FROM stage_checkpoints
|
|
252
|
+
WHERE stage_checkpoints.id = baselines.research_run_id
|
|
253
|
+
AND stage_checkpoints.stage = 'research'
|
|
254
|
+
)`,
|
|
255
|
+
).run();
|
|
256
|
+
changed = result.changes > 0 || changed;
|
|
257
|
+
}
|
|
258
|
+
return changed;
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
function applyKernelIntegrityColumns(db) {
|
|
262
|
+
const tables = new Set(tableNames(db));
|
|
263
|
+
let changed = false;
|
|
264
|
+
if (tables.has('context_envelopes')) {
|
|
265
|
+
const columns = columnNames(db, 'context_envelopes');
|
|
266
|
+
changed = addColumnIfMissing(
|
|
267
|
+
db,
|
|
268
|
+
'context_envelopes',
|
|
269
|
+
columns,
|
|
270
|
+
'file_digest',
|
|
271
|
+
'TEXT',
|
|
272
|
+
) || changed;
|
|
273
|
+
}
|
|
274
|
+
if (tables.has('worker_packets')) {
|
|
275
|
+
const columns = columnNames(db, 'worker_packets');
|
|
276
|
+
for (const [name, definition] of [
|
|
277
|
+
['file_digest', 'TEXT'],
|
|
278
|
+
['status', "TEXT NOT NULL DEFAULT 'assigned' CHECK (status IN ('pending', 'assigned', 'abandoned'))"],
|
|
279
|
+
['assigned_at', 'TEXT'],
|
|
280
|
+
['abandoned_at', 'TEXT'],
|
|
281
|
+
['abandon_reason', 'TEXT'],
|
|
282
|
+
]) {
|
|
283
|
+
changed = addColumnIfMissing(
|
|
284
|
+
db,
|
|
285
|
+
'worker_packets',
|
|
286
|
+
columns,
|
|
287
|
+
name,
|
|
288
|
+
definition,
|
|
289
|
+
) || changed;
|
|
290
|
+
}
|
|
291
|
+
}
|
|
229
292
|
return changed;
|
|
230
293
|
}
|
|
231
294
|
|
|
@@ -422,7 +485,8 @@ function migrateAdaptiveWorkflowRuns(db, fromVersion = latestSchemaVersion(db))
|
|
|
422
485
|
).get();
|
|
423
486
|
if ([
|
|
424
487
|
ADAPTIVE_SCHEMA_VERSION, DECISION_COMPLETION_SCHEMA_VERSION,
|
|
425
|
-
ARTIFACT_REGISTRY_SCHEMA_VERSION,
|
|
488
|
+
ARTIFACT_REGISTRY_SCHEMA_VERSION, KERNEL_SCHEMA_VERSION,
|
|
489
|
+
CHECKPOINT_NATIVE_SCHEMA_VERSION,
|
|
426
490
|
].includes(fromVersion) || existing) {
|
|
427
491
|
return false;
|
|
428
492
|
}
|
|
@@ -538,11 +602,11 @@ function migrateAdaptiveWorkflowRuns(db, fromVersion = latestSchemaVersion(db))
|
|
|
538
602
|
return true;
|
|
539
603
|
}
|
|
540
604
|
|
|
541
|
-
function
|
|
605
|
+
function tableSupportsRuntime(db, table, runtime) {
|
|
542
606
|
const row = db.prepare(
|
|
543
607
|
"SELECT sql FROM sqlite_master WHERE type = 'table' AND name = ?",
|
|
544
608
|
).get(table);
|
|
545
|
-
return typeof row?.sql === 'string' && row.sql.includes(
|
|
609
|
+
return typeof row?.sql === 'string' && row.sql.includes(`'${runtime}'`);
|
|
546
610
|
}
|
|
547
611
|
|
|
548
612
|
function baselineSupportsUnbornGit(db) {
|
|
@@ -676,6 +740,7 @@ function upgradeBaselineWorktreeConstraint(db, fromVersion = latestSchemaVersion
|
|
|
676
740
|
classification_json TEXT NOT NULL DEFAULT '{}',
|
|
677
741
|
provider_refs_json TEXT NOT NULL DEFAULT '{}',
|
|
678
742
|
research_run_id TEXT,
|
|
743
|
+
research_checkpoint_id TEXT,
|
|
679
744
|
approved_by TEXT,
|
|
680
745
|
approval_note TEXT,
|
|
681
746
|
started_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ', 'now')),
|
|
@@ -687,7 +752,8 @@ function upgradeBaselineWorktreeConstraint(db, fromVersion = latestSchemaVersion
|
|
|
687
752
|
repository_revision, repository_branch, worktree_state, worktree_digest,
|
|
688
753
|
worktree_files_json, worktree_accepted, known_red_accepted, spec_refs_json,
|
|
689
754
|
evidence_json, verification_json, unknowns_json, gaps_json, classification_json,
|
|
690
|
-
provider_refs_json, research_run_id,
|
|
755
|
+
provider_refs_json, research_run_id, research_checkpoint_id,
|
|
756
|
+
approved_by, approval_note, started_at,
|
|
691
757
|
updated_at, converged_at
|
|
692
758
|
)
|
|
693
759
|
SELECT
|
|
@@ -695,7 +761,8 @@ function upgradeBaselineWorktreeConstraint(db, fromVersion = latestSchemaVersion
|
|
|
695
761
|
repository_revision, repository_branch, worktree_state, worktree_digest,
|
|
696
762
|
worktree_files_json, worktree_accepted, known_red_accepted, spec_refs_json,
|
|
697
763
|
evidence_json, verification_json, unknowns_json, gaps_json, classification_json,
|
|
698
|
-
provider_refs_json, research_run_id,
|
|
764
|
+
provider_refs_json, research_run_id, research_checkpoint_id,
|
|
765
|
+
approved_by, approval_note, started_at,
|
|
699
766
|
updated_at, converged_at
|
|
700
767
|
FROM baselines;
|
|
701
768
|
DROP TABLE baselines;
|
|
@@ -717,7 +784,11 @@ function upgradeBaselineWorktreeConstraint(db, fromVersion = latestSchemaVersion
|
|
|
717
784
|
|
|
718
785
|
function upgradeRuntimeConstraints(db, fromVersion = latestSchemaVersion(db)) {
|
|
719
786
|
assertNoDuplicateActiveSessionLeases(db);
|
|
720
|
-
|
|
787
|
+
const missingKimi = !tableSupportsRuntime(db, 'events', 'kimi')
|
|
788
|
+
|| !tableSupportsRuntime(db, 'sessions', 'kimi');
|
|
789
|
+
const missingGrok = !tableSupportsRuntime(db, 'events', 'grok')
|
|
790
|
+
|| !tableSupportsRuntime(db, 'sessions', 'grok');
|
|
791
|
+
if (!missingKimi && !missingGrok) return false;
|
|
721
792
|
const previousVersion = fromVersion || 'unknown';
|
|
722
793
|
const foreignKeys = db.pragma('foreign_keys', { simple: true });
|
|
723
794
|
db.pragma('foreign_keys = OFF');
|
|
@@ -732,7 +803,7 @@ function upgradeRuntimeConstraints(db, fromVersion = latestSchemaVersion(db)) {
|
|
|
732
803
|
task_id TEXT,
|
|
733
804
|
change_id TEXT,
|
|
734
805
|
session_id TEXT,
|
|
735
|
-
runtime TEXT CHECK (runtime IS NULL OR runtime IN ('claude', 'opencode', 'codex', 'kimi')),
|
|
806
|
+
runtime TEXT CHECK (runtime IS NULL OR runtime IN ('claude', 'opencode', 'codex', 'kimi', 'grok')),
|
|
736
807
|
payload_json TEXT
|
|
737
808
|
);
|
|
738
809
|
INSERT INTO events_runtime_upgrade
|
|
@@ -749,7 +820,7 @@ function upgradeRuntimeConstraints(db, fromVersion = latestSchemaVersion(db)) {
|
|
|
749
820
|
CREATE TABLE sessions_runtime_upgrade (
|
|
750
821
|
sid TEXT PRIMARY KEY,
|
|
751
822
|
task_id TEXT NOT NULL REFERENCES tasks(id),
|
|
752
|
-
runtime TEXT NOT NULL CHECK (runtime IN ('claude', 'opencode', 'codex', 'kimi')),
|
|
823
|
+
runtime TEXT NOT NULL CHECK (runtime IN ('claude', 'opencode', 'codex', 'kimi', 'grok')),
|
|
753
824
|
pid INTEGER,
|
|
754
825
|
worktree_path TEXT NOT NULL,
|
|
755
826
|
artifact_dir TEXT NOT NULL,
|
|
@@ -771,15 +842,28 @@ function upgradeRuntimeConstraints(db, fromVersion = latestSchemaVersion(db)) {
|
|
|
771
842
|
CREATE UNIQUE INDEX sessions_one_active_task
|
|
772
843
|
ON sessions(task_id) WHERE status = 'running';
|
|
773
844
|
`);
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
845
|
+
if (missingKimi) {
|
|
846
|
+
db.prepare(
|
|
847
|
+
`INSERT INTO migration_history
|
|
848
|
+
(from_version, to_version, direction, status, notes)
|
|
849
|
+
VALUES (?, ?, 'forward', 'success', ?)`,
|
|
850
|
+
).run(
|
|
851
|
+
previousVersion,
|
|
852
|
+
KIMI_SCHEMA_VERSION,
|
|
853
|
+
'Add Kimi to durable event and session runtime constraints',
|
|
854
|
+
);
|
|
855
|
+
}
|
|
856
|
+
if (missingGrok) {
|
|
857
|
+
db.prepare(
|
|
858
|
+
`INSERT INTO migration_history
|
|
859
|
+
(from_version, to_version, direction, status, notes)
|
|
860
|
+
VALUES (?, ?, 'forward', 'success', ?)`,
|
|
861
|
+
).run(
|
|
862
|
+
missingKimi ? KIMI_SCHEMA_VERSION : previousVersion,
|
|
863
|
+
KERNEL_SCHEMA_VERSION,
|
|
864
|
+
'Add Grok to durable event and session runtime constraints',
|
|
865
|
+
);
|
|
866
|
+
}
|
|
783
867
|
const violations = db.pragma('foreign_key_check');
|
|
784
868
|
if (violations.length > 0) {
|
|
785
869
|
throw new Error(`runtime constraint migration produced ${violations.length} foreign key violation(s)`);
|
|
@@ -935,6 +1019,7 @@ function applyCompatibleUpgrades(db, fromVersion = latestSchemaVersion(db), { le
|
|
|
935
1019
|
WORKFLOW_SCHEMA_VERSION, AUTHORITY_SCHEMA_VERSION, SEMANTIC_SCHEMA_VERSION,
|
|
936
1020
|
DIALOGUE_SCHEMA_VERSION, GIT_AUTHORITY_SCHEMA_VERSION, ADAPTIVE_SCHEMA_VERSION,
|
|
937
1021
|
DECISION_COMPLETION_SCHEMA_VERSION, ARTIFACT_REGISTRY_SCHEMA_VERSION,
|
|
1022
|
+
KERNEL_SCHEMA_VERSION, CHECKPOINT_NATIVE_SCHEMA_VERSION,
|
|
938
1023
|
].includes(fromVersion)
|
|
939
1024
|
&& !contextMigration,
|
|
940
1025
|
);
|
|
@@ -953,6 +1038,7 @@ function applyCompatibleUpgrades(db, fromVersion = latestSchemaVersion(db), { le
|
|
|
953
1038
|
applyBaselineColumns(db);
|
|
954
1039
|
applyChangeColumns(db);
|
|
955
1040
|
applySemanticAuthorityColumns(db);
|
|
1041
|
+
applyKernelIntegrityColumns(db);
|
|
956
1042
|
const artifactRegistryChanged = applyArtifactRegistryUpgrade(db);
|
|
957
1043
|
const baselineMigration = db.prepare(
|
|
958
1044
|
"SELECT 1 FROM migration_history WHERE to_version = '11.0' AND status = 'success' LIMIT 1",
|
|
@@ -962,6 +1048,7 @@ function applyCompatibleUpgrades(db, fromVersion = latestSchemaVersion(db), { le
|
|
|
962
1048
|
AUTHORITY_SCHEMA_VERSION, SEMANTIC_SCHEMA_VERSION, DIALOGUE_SCHEMA_VERSION,
|
|
963
1049
|
GIT_AUTHORITY_SCHEMA_VERSION, ADAPTIVE_SCHEMA_VERSION,
|
|
964
1050
|
DECISION_COMPLETION_SCHEMA_VERSION, ARTIFACT_REGISTRY_SCHEMA_VERSION,
|
|
1051
|
+
KERNEL_SCHEMA_VERSION, CHECKPOINT_NATIVE_SCHEMA_VERSION,
|
|
965
1052
|
].includes(fromVersion)
|
|
966
1053
|
&& !baselineMigration) {
|
|
967
1054
|
db.prepare(
|
|
@@ -993,7 +1080,8 @@ function applyCompatibleUpgrades(db, fromVersion = latestSchemaVersion(db), { le
|
|
|
993
1080
|
db.prepare(
|
|
994
1081
|
`UPDATE baselines SET mode = 'migrated', status = 'adopting',
|
|
995
1082
|
classification_json = ?, gaps_json = ?, approved_by = NULL, approval_note = ?,
|
|
996
|
-
converged_at = NULL, research_run_id = NULL,
|
|
1083
|
+
converged_at = NULL, research_run_id = NULL, research_checkpoint_id = NULL,
|
|
1084
|
+
updated_at = strftime('%Y-%m-%dT%H:%M:%fZ', 'now')
|
|
997
1085
|
WHERE id = ?`,
|
|
998
1086
|
).run(
|
|
999
1087
|
JSON.stringify(classification), JSON.stringify(gaps),
|
|
@@ -1034,6 +1122,7 @@ function applyCompatibleUpgrades(db, fromVersion = latestSchemaVersion(db), { le
|
|
|
1034
1122
|
WORKFLOW_SCHEMA_VERSION, AUTHORITY_SCHEMA_VERSION, SEMANTIC_SCHEMA_VERSION,
|
|
1035
1123
|
DIALOGUE_SCHEMA_VERSION, GIT_AUTHORITY_SCHEMA_VERSION, ADAPTIVE_SCHEMA_VERSION,
|
|
1036
1124
|
DECISION_COMPLETION_SCHEMA_VERSION, ARTIFACT_REGISTRY_SCHEMA_VERSION,
|
|
1125
|
+
KERNEL_SCHEMA_VERSION, CHECKPOINT_NATIVE_SCHEMA_VERSION,
|
|
1037
1126
|
].includes(fromVersion) && !workflowMigration) {
|
|
1038
1127
|
db.prepare(
|
|
1039
1128
|
`INSERT INTO migration_history
|
|
@@ -1051,7 +1140,8 @@ function applyCompatibleUpgrades(db, fromVersion = latestSchemaVersion(db), { le
|
|
|
1051
1140
|
if (fromVersion && ![
|
|
1052
1141
|
AUTHORITY_SCHEMA_VERSION, SEMANTIC_SCHEMA_VERSION, DIALOGUE_SCHEMA_VERSION,
|
|
1053
1142
|
GIT_AUTHORITY_SCHEMA_VERSION, ADAPTIVE_SCHEMA_VERSION, DECISION_COMPLETION_SCHEMA_VERSION,
|
|
1054
|
-
ARTIFACT_REGISTRY_SCHEMA_VERSION,
|
|
1143
|
+
ARTIFACT_REGISTRY_SCHEMA_VERSION, KERNEL_SCHEMA_VERSION,
|
|
1144
|
+
CHECKPOINT_NATIVE_SCHEMA_VERSION,
|
|
1055
1145
|
].includes(fromVersion) && !authorityMigration) {
|
|
1056
1146
|
db.prepare(
|
|
1057
1147
|
`INSERT INTO migration_history
|
|
@@ -1069,7 +1159,8 @@ function applyCompatibleUpgrades(db, fromVersion = latestSchemaVersion(db), { le
|
|
|
1069
1159
|
if (fromVersion && ![
|
|
1070
1160
|
SEMANTIC_SCHEMA_VERSION, DIALOGUE_SCHEMA_VERSION, GIT_AUTHORITY_SCHEMA_VERSION,
|
|
1071
1161
|
ADAPTIVE_SCHEMA_VERSION, DECISION_COMPLETION_SCHEMA_VERSION,
|
|
1072
|
-
ARTIFACT_REGISTRY_SCHEMA_VERSION,
|
|
1162
|
+
ARTIFACT_REGISTRY_SCHEMA_VERSION, KERNEL_SCHEMA_VERSION,
|
|
1163
|
+
CHECKPOINT_NATIVE_SCHEMA_VERSION,
|
|
1073
1164
|
].includes(fromVersion) && !semanticMigration) {
|
|
1074
1165
|
db.prepare(
|
|
1075
1166
|
`INSERT INTO migration_history
|
|
@@ -1087,6 +1178,7 @@ function applyCompatibleUpgrades(db, fromVersion = latestSchemaVersion(db), { le
|
|
|
1087
1178
|
if (fromVersion && ![
|
|
1088
1179
|
DIALOGUE_SCHEMA_VERSION, GIT_AUTHORITY_SCHEMA_VERSION, ADAPTIVE_SCHEMA_VERSION,
|
|
1089
1180
|
DECISION_COMPLETION_SCHEMA_VERSION, ARTIFACT_REGISTRY_SCHEMA_VERSION,
|
|
1181
|
+
KERNEL_SCHEMA_VERSION, CHECKPOINT_NATIVE_SCHEMA_VERSION,
|
|
1090
1182
|
].includes(fromVersion)
|
|
1091
1183
|
&& !dialogueMigration) {
|
|
1092
1184
|
db.prepare(
|
|
@@ -1104,7 +1196,8 @@ function applyCompatibleUpgrades(db, fromVersion = latestSchemaVersion(db), { le
|
|
|
1104
1196
|
).get();
|
|
1105
1197
|
if (fromVersion && ![
|
|
1106
1198
|
GIT_AUTHORITY_SCHEMA_VERSION, ADAPTIVE_SCHEMA_VERSION, DECISION_COMPLETION_SCHEMA_VERSION,
|
|
1107
|
-
ARTIFACT_REGISTRY_SCHEMA_VERSION,
|
|
1199
|
+
ARTIFACT_REGISTRY_SCHEMA_VERSION, KERNEL_SCHEMA_VERSION,
|
|
1200
|
+
CHECKPOINT_NATIVE_SCHEMA_VERSION,
|
|
1108
1201
|
].includes(fromVersion)
|
|
1109
1202
|
&& !gitStateMigration) {
|
|
1110
1203
|
db.prepare(
|
|
@@ -1123,7 +1216,8 @@ function applyCompatibleUpgrades(db, fromVersion = latestSchemaVersion(db), { le
|
|
|
1123
1216
|
).get();
|
|
1124
1217
|
if (fromVersion && ![
|
|
1125
1218
|
ADAPTIVE_SCHEMA_VERSION, DECISION_COMPLETION_SCHEMA_VERSION,
|
|
1126
|
-
ARTIFACT_REGISTRY_SCHEMA_VERSION,
|
|
1219
|
+
ARTIFACT_REGISTRY_SCHEMA_VERSION, KERNEL_SCHEMA_VERSION,
|
|
1220
|
+
CHECKPOINT_NATIVE_SCHEMA_VERSION,
|
|
1127
1221
|
].includes(fromVersion) && !adaptiveMigration) {
|
|
1128
1222
|
db.prepare(
|
|
1129
1223
|
`INSERT INTO migration_history
|
|
@@ -1142,6 +1236,7 @@ function applyCompatibleUpgrades(db, fromVersion = latestSchemaVersion(db), { le
|
|
|
1142
1236
|
).get();
|
|
1143
1237
|
if (fromVersion && ![
|
|
1144
1238
|
DECISION_COMPLETION_SCHEMA_VERSION, ARTIFACT_REGISTRY_SCHEMA_VERSION,
|
|
1239
|
+
KERNEL_SCHEMA_VERSION, CHECKPOINT_NATIVE_SCHEMA_VERSION,
|
|
1145
1240
|
].includes(fromVersion) && !completionMigration) {
|
|
1146
1241
|
db.prepare(
|
|
1147
1242
|
`INSERT INTO migration_history
|
|
@@ -1159,6 +1254,8 @@ function applyCompatibleUpgrades(db, fromVersion = latestSchemaVersion(db), { le
|
|
|
1159
1254
|
"SELECT 1 FROM migration_history WHERE to_version = '20.0' AND status = 'success' LIMIT 1",
|
|
1160
1255
|
).get();
|
|
1161
1256
|
if (fromVersion && fromVersion !== ARTIFACT_REGISTRY_SCHEMA_VERSION
|
|
1257
|
+
&& fromVersion !== KERNEL_SCHEMA_VERSION
|
|
1258
|
+
&& fromVersion !== CHECKPOINT_NATIVE_SCHEMA_VERSION
|
|
1162
1259
|
&& !artifactRegistryMigration) {
|
|
1163
1260
|
db.prepare(
|
|
1164
1261
|
`INSERT INTO migration_history
|
|
@@ -1172,6 +1269,39 @@ function applyCompatibleUpgrades(db, fromVersion = latestSchemaVersion(db), { le
|
|
|
1172
1269
|
: 'Add the typed artifact registry, dependency graph, and orphan diagnostics',
|
|
1173
1270
|
);
|
|
1174
1271
|
}
|
|
1272
|
+
const kernelMigration = db.prepare(
|
|
1273
|
+
"SELECT 1 FROM migration_history WHERE to_version = '21.0' AND status = 'success' LIMIT 1",
|
|
1274
|
+
).get();
|
|
1275
|
+
if (fromVersion
|
|
1276
|
+
&& fromVersion !== KERNEL_SCHEMA_VERSION
|
|
1277
|
+
&& fromVersion !== CHECKPOINT_NATIVE_SCHEMA_VERSION
|
|
1278
|
+
&& !kernelMigration) {
|
|
1279
|
+
db.prepare(
|
|
1280
|
+
`INSERT INTO migration_history
|
|
1281
|
+
(from_version, to_version, direction, status, notes)
|
|
1282
|
+
VALUES (?, ?, 'forward', 'success', ?)`,
|
|
1283
|
+
).run(
|
|
1284
|
+
ARTIFACT_REGISTRY_SCHEMA_VERSION,
|
|
1285
|
+
KERNEL_SCHEMA_VERSION,
|
|
1286
|
+
'Add the seven-tool persistence kernel, reversible stage checkpoints, canonical context envelopes, normalized decisions, worker packets, and Grok runtime authority',
|
|
1287
|
+
);
|
|
1288
|
+
}
|
|
1289
|
+
const checkpointNativeMigration = db.prepare(
|
|
1290
|
+
"SELECT 1 FROM migration_history WHERE to_version = '22.0' AND status = 'success' LIMIT 1",
|
|
1291
|
+
).get();
|
|
1292
|
+
if (fromVersion
|
|
1293
|
+
&& fromVersion !== CHECKPOINT_NATIVE_SCHEMA_VERSION
|
|
1294
|
+
&& !checkpointNativeMigration) {
|
|
1295
|
+
db.prepare(
|
|
1296
|
+
`INSERT INTO migration_history
|
|
1297
|
+
(from_version, to_version, direction, status, notes)
|
|
1298
|
+
VALUES (?, ?, 'forward', 'success', ?)`,
|
|
1299
|
+
).run(
|
|
1300
|
+
KERNEL_SCHEMA_VERSION,
|
|
1301
|
+
CHECKPOINT_NATIVE_SCHEMA_VERSION,
|
|
1302
|
+
'Bind Baseline research to Stage Checkpoints and add byte digests for Context Envelopes and Worker Packets',
|
|
1303
|
+
);
|
|
1304
|
+
}
|
|
1175
1305
|
db.exec('CREATE INDEX IF NOT EXISTS tasks_change ON tasks(change_id) WHERE change_id IS NOT NULL');
|
|
1176
1306
|
db.exec('CREATE INDEX IF NOT EXISTS events_change ON events(change_id, id)');
|
|
1177
1307
|
ensureActiveSessionLeaseIndex(db);
|
|
@@ -1179,7 +1309,7 @@ function applyCompatibleUpgrades(db, fromVersion = latestSchemaVersion(db), { le
|
|
|
1179
1309
|
'INSERT OR IGNORE INTO schema_version (version, description) VALUES (?, ?)',
|
|
1180
1310
|
).run(
|
|
1181
1311
|
EXPECTED_VERSION,
|
|
1182
|
-
'
|
|
1312
|
+
'Checkpoint-native baseline authority plus byte-bound Context Envelopes and Worker Packets',
|
|
1183
1313
|
);
|
|
1184
1314
|
})();
|
|
1185
1315
|
}
|
|
@@ -1212,6 +1342,7 @@ function initStateDb(dbPath) {
|
|
|
1212
1342
|
WORKFLOW_SCHEMA_VERSION, AUTHORITY_SCHEMA_VERSION, SEMANTIC_SCHEMA_VERSION,
|
|
1213
1343
|
DIALOGUE_SCHEMA_VERSION, GIT_AUTHORITY_SCHEMA_VERSION, ADAPTIVE_SCHEMA_VERSION,
|
|
1214
1344
|
DECISION_COMPLETION_SCHEMA_VERSION, ARTIFACT_REGISTRY_SCHEMA_VERSION,
|
|
1345
|
+
KERNEL_SCHEMA_VERSION, CHECKPOINT_NATIVE_SCHEMA_VERSION,
|
|
1215
1346
|
].includes(fromVersion);
|
|
1216
1347
|
backupPath = migrationBackup(db, dbPath, fromVersion, existing);
|
|
1217
1348
|
// This must precede every ALTER, table rebuild, or index creation. Runtime
|