ultra-builder-pro-cli 0.14.0 → 0.16.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.
Files changed (163) hide show
  1. package/.ultra-template/docs/research/README.md +11 -7
  2. package/.ultra-template/specs/architecture.md +36 -36
  3. package/.ultra-template/specs/discovery.md +46 -33
  4. package/.ultra-template/specs/product.md +38 -29
  5. package/.ultra-template/specs/research-distillate.md +48 -0
  6. package/.ultra-template/tasks/contexts/TEMPLATE.md +11 -28
  7. package/CHANGELOG.md +77 -1
  8. package/README.md +46 -24
  9. package/adapters/_shared/codex-assets.cjs +6 -2
  10. package/adapters/_shared/file-ops.cjs +6 -2
  11. package/adapters/_shared/handbook.cjs +2 -1
  12. package/adapters/claude.js +3 -2
  13. package/adapters/codex.js +1 -0
  14. package/adapters/kimi.js +3 -2
  15. package/adapters/opencode.js +3 -2
  16. package/agents/review-coordinator.md +9 -6
  17. package/commands/ultra-change.md +1 -1
  18. package/commands/ultra-plan.md +1 -1
  19. package/commands/ultra-research.md +1 -1
  20. package/commands/ultra-think.md +2 -2
  21. package/docs/AGENT-CONTEXT.md +43 -19
  22. package/docs/ARCHITECTURE.md +54 -13
  23. package/docs/PLAN.zh-CN.md +4 -2
  24. package/docs/ROADMAP.md +10 -4
  25. package/docs/RUNTIME-COMPAT-MATRIX.md +4 -4
  26. package/docs/STATE-DB-ACCESS-POLICY.md +33 -29
  27. package/docs/USER-HANDBOOK-CONTRACT.md +8 -2
  28. package/docs/WORKFLOW-LIFECYCLE.md +342 -0
  29. package/hooks/README.md +6 -1
  30. package/hooks/health_check.py +12 -3
  31. package/hooks/subagent_tracker.py +52 -77
  32. package/mcp-server/hook-event.cjs +34 -0
  33. package/mcp-server/lib/archive-journal.cjs +17 -5
  34. package/mcp-server/lib/baseline-workflow.cjs +158 -18
  35. package/mcp-server/lib/change-workflow.cjs +598 -85
  36. package/mcp-server/lib/context-spine.cjs +305 -25
  37. package/mcp-server/lib/decision-dialogue.cjs +713 -0
  38. package/mcp-server/lib/doctor.cjs +42 -3
  39. package/mcp-server/lib/init-project.cjs +210 -16
  40. package/mcp-server/lib/plan-store.cjs +4 -1
  41. package/mcp-server/lib/pricing.cjs +7 -10
  42. package/mcp-server/lib/project-breadcrumb.cjs +15 -0
  43. package/mcp-server/lib/projector.cjs +57 -3
  44. package/mcp-server/lib/spec-learning.cjs +79 -2
  45. package/mcp-server/lib/state-db.cjs +168 -8
  46. package/mcp-server/lib/state-ops.cjs +160 -9
  47. package/mcp-server/lib/workflow-state.cjs +2305 -0
  48. package/mcp-server/server.cjs +215 -15
  49. package/orchestrator/daemon.cjs +1 -2
  50. package/orchestrator/dispatch-rules.cjs +5 -31
  51. package/orchestrator/planner/plan-builder.cjs +21 -12
  52. package/package.json +13 -3
  53. package/skills/ultra-change/SKILL.md +94 -80
  54. package/skills/ultra-change/references/change-contract.md +36 -0
  55. package/skills/ultra-deliver/SKILL.md +76 -79
  56. package/skills/ultra-deliver/references/baseline-reconciliation.md +20 -0
  57. package/skills/ultra-dev/SKILL.md +62 -59
  58. package/skills/ultra-doctor/SKILL.md +61 -82
  59. package/skills/ultra-init/SKILL.md +101 -103
  60. package/skills/ultra-init/references/brownfield-adoption.md +2 -2
  61. package/skills/ultra-plan/SKILL.md +99 -85
  62. package/skills/ultra-plan/references/semantic-preflight.md +18 -0
  63. package/skills/ultra-research/SKILL.md +102 -60
  64. package/skills/ultra-research/references/00-problem-validation.md +36 -0
  65. package/skills/ultra-research/references/01-opportunity-discovery.md +33 -0
  66. package/skills/ultra-research/references/02-market-assessment.md +30 -0
  67. package/skills/ultra-research/references/03-competitive-landscape.md +31 -0
  68. package/skills/ultra-research/references/04-product-strategy.md +32 -0
  69. package/skills/ultra-research/references/05-assumptions-validation.md +31 -0
  70. package/skills/ultra-research/references/10-user-personas.md +29 -0
  71. package/skills/ultra-research/references/11-user-scenarios.md +28 -0
  72. package/skills/ultra-research/references/20-user-stories.md +30 -0
  73. package/skills/ultra-research/references/21-features-scope.md +29 -0
  74. package/skills/ultra-research/references/22-success-metrics.md +28 -0
  75. package/skills/ultra-research/references/30-architecture-context.md +30 -0
  76. package/skills/ultra-research/references/31-solution-strategy.md +28 -0
  77. package/skills/ultra-research/references/32-building-blocks.md +28 -0
  78. package/skills/ultra-research/references/40-deployment.md +29 -0
  79. package/skills/ultra-research/references/41-quality-risks.md +28 -0
  80. package/skills/ultra-research/references/99-synthesis.md +35 -0
  81. package/skills/ultra-review/SKILL.md +63 -73
  82. package/skills/ultra-review/references/review-modes.md +27 -0
  83. package/skills/ultra-review/references/unified-schema.md +25 -0
  84. package/skills/ultra-review/scripts/review_wait.py +40 -3
  85. package/skills/ultra-status/SKILL.md +41 -41
  86. package/skills/ultra-test/SKILL.md +54 -55
  87. package/skills/ultra-think/SKILL.md +26 -12
  88. package/skills/ultra-think/references/decision-dialogue.md +130 -0
  89. package/skills/ultra-verify/SKILL.md +1 -1
  90. package/skills/ultra-verify/references/{confidence-system.md → evidence-status.md} +3 -3
  91. package/spec/cli-protocol.md +17 -3
  92. package/spec/mcp-tools.yaml +683 -64
  93. package/spec/schemas/baseline-reconciliation.v1.schema.json +73 -0
  94. package/spec/schemas/delivery-report.v1.schema.json +111 -0
  95. package/spec/schemas/mcp-tools.schema.json +1 -1
  96. package/spec/schemas/state-db.sql +140 -1
  97. package/spec/schemas/tasks.v4.5.schema.json +8 -1
  98. package/spec/schemas/test-report.v1.schema.json +194 -0
  99. package/ultra-tools/cli.cjs +1 -1
  100. package/ultra-tools/commands/migrate.cjs +3 -3
  101. package/ultra-tools/commands/status.cjs +228 -12
  102. package/.ultra-template/delivery-report.json +0 -9
  103. package/.ultra-template/test-report.json +0 -8
  104. package/adapters/_shared/tests/file-ops.test.cjs +0 -54
  105. package/adapters/_shared/tests/frontmatter.test.cjs +0 -47
  106. package/adapters/_shared/tests/handbook.test.cjs +0 -101
  107. package/adapters/_shared/tests/path-rewrite.test.cjs +0 -60
  108. package/adapters/_shared/tests/provenance.test.cjs +0 -133
  109. package/adapters/_shared/tests/resolve-target.test.cjs +0 -75
  110. package/adapters/_shared/tests/runtime-assets.test.cjs +0 -149
  111. package/adapters/_shared/tests/settings-merge.test.cjs +0 -85
  112. package/adapters/_shared/tests/validate.test.cjs +0 -30
  113. package/adapters/tests/claude.test.cjs +0 -138
  114. package/adapters/tests/codex-hook.test.cjs +0 -142
  115. package/adapters/tests/codex.test.cjs +0 -430
  116. package/adapters/tests/kimi-hook.test.cjs +0 -149
  117. package/adapters/tests/kimi.test.cjs +0 -259
  118. package/adapters/tests/opencode.test.cjs +0 -357
  119. package/mcp-server/lib/archive-journal.test.cjs +0 -35
  120. package/mcp-server/lib/baseline-workflow.test.cjs +0 -477
  121. package/mcp-server/lib/change-workflow.test.cjs +0 -971
  122. package/mcp-server/lib/context-spine.test.cjs +0 -93
  123. package/mcp-server/lib/doctor.test.cjs +0 -148
  124. package/mcp-server/lib/plan-store.test.cjs +0 -132
  125. package/mcp-server/lib/prd-parser.test.cjs +0 -82
  126. package/mcp-server/lib/project-breadcrumb.test.cjs +0 -112
  127. package/mcp-server/lib/runtime-state.test.cjs +0 -92
  128. package/mcp-server/lib/spec-learning.test.cjs +0 -67
  129. package/mcp-server/lib/state-db.test.cjs +0 -314
  130. package/mcp-server/lib/task-expander.test.cjs +0 -169
  131. package/mcp-server/lib/topo.test.cjs +0 -158
  132. package/mcp-server/tests/circuit-breaker.test.cjs +0 -125
  133. package/mcp-server/tests/commit-hash-flow.test.cjs +0 -117
  134. package/mcp-server/tests/concurrency-update.test.cjs +0 -96
  135. package/mcp-server/tests/concurrency.test.cjs +0 -112
  136. package/mcp-server/tests/db-ops.test.cjs +0 -121
  137. package/mcp-server/tests/init-project.test.cjs +0 -393
  138. package/mcp-server/tests/migrate.test.cjs +0 -232
  139. package/mcp-server/tests/projector.test.cjs +0 -162
  140. package/mcp-server/tests/server-contract.test.cjs +0 -1467
  141. package/mcp-server/tests/staleness.test.cjs +0 -190
  142. package/mcp-server/tests/state-db.test.cjs +0 -106
  143. package/mcp-server/tests/state-ops.test.cjs +0 -449
  144. package/mcp-server/tests/tagged-tasks.test.cjs +0 -163
  145. package/mcp-server/tests/telemetry.test.cjs +0 -219
  146. package/orchestrator/planner/plan-builder.test.cjs +0 -165
  147. package/orchestrator/tests/auto-merge.test.cjs +0 -216
  148. package/orchestrator/tests/daemon.test.cjs +0 -311
  149. package/orchestrator/tests/dispatch-rules.test.cjs +0 -124
  150. package/orchestrator/tests/parallel-orchestrator.test.cjs +0 -233
  151. package/orchestrator/tests/phase-8b-gate.test.cjs +0 -183
  152. package/orchestrator/tests/recovery.test.cjs +0 -190
  153. package/orchestrator/tests/session-runner.test.cjs +0 -314
  154. package/orchestrator/tests/skill-miner.test.cjs +0 -147
  155. package/orchestrator/tests/worktree-manager.test.cjs +0 -148
  156. package/skills/ultra-research/references/architecture.md +0 -38
  157. package/skills/ultra-research/references/problem-product.md +0 -39
  158. package/skills/ultra-research/references/quality-delivery.md +0 -34
  159. package/skills/ultra-research/references/synthesis.md +0 -38
  160. package/skills/ultra-research/references/users-scope.md +0 -40
  161. package/ultra-tools/legacy-memory.test.cjs +0 -80
  162. package/ultra-tools/status-command.test.cjs +0 -181
  163. package/ultra-tools/system-command.test.cjs +0 -309
@@ -1,190 +0,0 @@
1
- 'use strict';
2
-
3
- // Phase 5.3 — Task staleness consumer:
4
- // • markTasksStaleBySpecSections: UPDATE pending tasks whose trace_to
5
- // matches a changed spec section → stale=1 + task_stale_marked event.
6
- // • consumeSpecChangedEvents: pulls unprocessed spec_changed events from
7
- // the event stream and applies the rule above, advancing a cursor.
8
-
9
- const test = require('node:test');
10
- const assert = require('node:assert/strict');
11
- const fs = require('node:fs');
12
- const os = require('node:os');
13
- const path = require('node:path');
14
-
15
- const { initStateDb, closeStateDb } = require('../lib/state-db.cjs');
16
- const ops = require('../lib/state-ops.cjs');
17
- const projector = require('../lib/projector.cjs');
18
-
19
- function freshDb() {
20
- const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'ubp-stale-'));
21
- const file = path.join(dir, 'state.db');
22
- const init = initStateDb(file);
23
- return { dir, db: init.db };
24
- }
25
-
26
- function teardown(dir, db) {
27
- try { closeStateDb(db); } catch (_) { /* ignore */ }
28
- try { fs.rmSync(dir, { recursive: true, force: true }); } catch (_) { /* ignore */ }
29
- }
30
-
31
- function seed(db, id, { trace_to, status = 'pending' } = {}) {
32
- ops.createTask(db, { id, title: `task ${id}`, type: 'feature', priority: 'P2', trace_to });
33
- if (status !== 'pending') ops.patchTask(db, id, { status });
34
- }
35
-
36
- test('markTasksStaleBySpecSections: marks pending tasks with matching trace_to', () => {
37
- const { dir, db } = freshDb();
38
- try {
39
- seed(db, 't-prod', { trace_to: 'product' });
40
- seed(db, 't-arch', { trace_to: 'arch' });
41
- seed(db, 't-exec', { trace_to: 'exec' });
42
-
43
- const result = ops.markTasksStaleBySpecSections(db, ['product']);
44
- assert.equal(result.marked_count, 1);
45
- assert.deepEqual(result.marked_ids, ['t-prod']);
46
-
47
- assert.equal(ops.readTask(db, 't-prod').stale, true);
48
- assert.equal(ops.readTask(db, 't-arch').stale, false);
49
- assert.equal(ops.readTask(db, 't-exec').stale, false);
50
- } finally { teardown(dir, db); }
51
- });
52
-
53
- test('markTasksStaleBySpecSections: multi-section update', () => {
54
- const { dir, db } = freshDb();
55
- try {
56
- seed(db, 't-a', { trace_to: 'product' });
57
- seed(db, 't-b', { trace_to: 'arch' });
58
- seed(db, 't-c', { trace_to: 'exec' });
59
-
60
- const result = ops.markTasksStaleBySpecSections(db, ['product', 'arch']);
61
- assert.equal(result.marked_count, 2);
62
- assert.ok(result.marked_ids.includes('t-a'));
63
- assert.ok(result.marked_ids.includes('t-b'));
64
- assert.equal(ops.readTask(db, 't-c').stale, false);
65
- } finally { teardown(dir, db); }
66
- });
67
-
68
- test('markTasksStaleBySpecSections: skips non-pending tasks', () => {
69
- const { dir, db } = freshDb();
70
- try {
71
- seed(db, 't-running', { trace_to: 'product' });
72
- ops.patchTask(db, 't-running', { status: 'in_progress' });
73
-
74
- seed(db, 't-done', { trace_to: 'product' });
75
- ops.patchTask(db, 't-done', { status: 'in_progress' });
76
- ops.patchTask(db, 't-done', { status: 'completed' });
77
-
78
- seed(db, 't-pending', { trace_to: 'product' });
79
-
80
- const result = ops.markTasksStaleBySpecSections(db, ['product']);
81
- assert.equal(result.marked_count, 1);
82
- assert.deepEqual(result.marked_ids, ['t-pending']);
83
- } finally { teardown(dir, db); }
84
- });
85
-
86
- test('markTasksStaleBySpecSections: emits task_stale_marked event per task', () => {
87
- const { dir, db } = freshDb();
88
- try {
89
- seed(db, 't-e1', { trace_to: 'product' });
90
- seed(db, 't-e2', { trace_to: 'product' });
91
-
92
- const { events: before } = ops.subscribeEventsSince(db, { since_id: 0, limit: 500 });
93
- ops.markTasksStaleBySpecSections(db, ['product']);
94
- const { events: after } = ops.subscribeEventsSince(db, { since_id: 0, limit: 500 });
95
-
96
- const marked = after.slice(before.length).filter((e) => e.type === 'task_stale_marked');
97
- assert.equal(marked.length, 2);
98
- const taskIds = marked.map((e) => e.task_id).sort();
99
- assert.deepEqual(taskIds, ['t-e1', 't-e2']);
100
- } finally { teardown(dir, db); }
101
- });
102
-
103
- test('markTasksStaleBySpecSections: idempotent — re-mark already-stale task does not double-emit', () => {
104
- const { dir, db } = freshDb();
105
- try {
106
- seed(db, 't-idem', { trace_to: 'product' });
107
- ops.markTasksStaleBySpecSections(db, ['product']);
108
-
109
- const { events: before } = ops.subscribeEventsSince(db, { since_id: 0, limit: 500 });
110
- ops.markTasksStaleBySpecSections(db, ['product']);
111
- const { events: after } = ops.subscribeEventsSince(db, { since_id: 0, limit: 500 });
112
-
113
- const newEvents = after.slice(before.length);
114
- const marked = newEvents.filter((e) => e.type === 'task_stale_marked');
115
- assert.equal(marked.length, 0, 'should not re-emit for already-stale task');
116
- } finally { teardown(dir, db); }
117
- });
118
-
119
- test('consumeSpecChangedEvents: processes queued events and advances cursor', () => {
120
- const { dir, db } = freshDb();
121
- try {
122
- seed(db, 't-c1', { trace_to: 'product' });
123
- seed(db, 't-c2', { trace_to: 'arch' });
124
-
125
- ops.appendEvent(db, { type: 'spec_changed', payload: { sections: ['product'] } });
126
- ops.appendEvent(db, { type: 'spec_changed', payload: { sections: ['arch'] } });
127
-
128
- const result = ops.consumeSpecChangedEvents(db, { since_id: 0 });
129
- assert.equal(result.processed, 2);
130
- assert.ok(result.next_since_id > 0);
131
- assert.equal(ops.readTask(db, 't-c1').stale, true);
132
- assert.equal(ops.readTask(db, 't-c2').stale, true);
133
- } finally { teardown(dir, db); }
134
- });
135
-
136
- test('consumeSpecChangedEvents: cursor prevents reprocessing', () => {
137
- const { dir, db } = freshDb();
138
- try {
139
- seed(db, 't-cur', { trace_to: 'product' });
140
- ops.appendEvent(db, { type: 'spec_changed', payload: { sections: ['product'] } });
141
-
142
- const first = ops.consumeSpecChangedEvents(db, { since_id: 0 });
143
- assert.equal(first.processed, 1);
144
-
145
- // second call from the new cursor — no new spec_changed events.
146
- const second = ops.consumeSpecChangedEvents(db, { since_id: first.next_since_id });
147
- assert.equal(second.processed, 0);
148
- assert.equal(second.next_since_id, first.next_since_id);
149
- } finally { teardown(dir, db); }
150
- });
151
-
152
- test('consumeSpecChangedEvents: ignores non-spec_changed events', () => {
153
- const { dir, db } = freshDb();
154
- try {
155
- seed(db, 't-other', { trace_to: 'product' });
156
- ops.appendEvent(db, { type: 'task_failure', task_id: 't-other', payload: { reason: 'noise' } });
157
-
158
- const result = ops.consumeSpecChangedEvents(db, { since_id: 0 });
159
- assert.equal(result.processed, 0);
160
- assert.equal(ops.readTask(db, 't-other').stale, false);
161
- } finally { teardown(dir, db); }
162
- });
163
-
164
- test('projector: stale task context md carries STALE banner before body', () => {
165
- const { dir, db } = freshDb();
166
- const rootDir = dir;
167
- try {
168
- seed(db, 't-proj', { trace_to: 'product' });
169
- ops.markTasksStaleBySpecSections(db, ['product']);
170
-
171
- const result = projector.projectContext(db, 't-proj', {}, { rootDir });
172
- const text = fs.readFileSync(result.path, 'utf8');
173
- // Banner goes after YAML frontmatter end + blank line.
174
- const frontmatterEnd = text.indexOf('\n---', 3);
175
- assert.ok(frontmatterEnd > 0, 'frontmatter should exist');
176
- const body = text.slice(frontmatterEnd + 4);
177
- assert.match(body, /⚠️\s*STALE/, 'stale banner should render');
178
- assert.match(body, /spec/i, 'banner should mention spec');
179
- } finally { teardown(dir, db); }
180
- });
181
-
182
- test('projector: non-stale task context md has no STALE banner', () => {
183
- const { dir, db } = freshDb();
184
- try {
185
- seed(db, 't-fresh', { trace_to: 'product' });
186
- const result = projector.projectContext(db, 't-fresh', {}, { rootDir: dir });
187
- const text = fs.readFileSync(result.path, 'utf8');
188
- assert.doesNotMatch(text, /STALE/);
189
- } finally { teardown(dir, db); }
190
- });
@@ -1,106 +0,0 @@
1
- 'use strict';
2
-
3
- const test = require('node:test');
4
- const assert = require('node:assert/strict');
5
- const fs = require('node:fs');
6
- const os = require('node:os');
7
- const path = require('node:path');
8
-
9
- const stateDb = require('../lib/state-db.cjs');
10
-
11
- test('initStateDb upgrades a pre-10.0 database through Context Spine into baseline authority', () => {
12
- const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'ubp-db-upgrade-'));
13
- const file = path.join(dir, 'state.db');
14
- try {
15
- const db = stateDb.openStateDb(file);
16
- db.exec(`
17
- CREATE TABLE tasks (
18
- id TEXT PRIMARY KEY,
19
- title TEXT NOT NULL,
20
- type TEXT NOT NULL,
21
- priority TEXT NOT NULL,
22
- complexity INTEGER,
23
- status TEXT NOT NULL DEFAULT 'pending',
24
- deps TEXT,
25
- files_modified TEXT,
26
- session_id TEXT,
27
- stale INTEGER NOT NULL DEFAULT 0,
28
- complexity_hint TEXT,
29
- tag TEXT,
30
- trace_to TEXT,
31
- context_file TEXT,
32
- completion_commit TEXT,
33
- parent_id TEXT,
34
- created_at TEXT NOT NULL,
35
- updated_at TEXT NOT NULL
36
- );
37
- CREATE TABLE events (
38
- id INTEGER PRIMARY KEY AUTOINCREMENT,
39
- ts TEXT NOT NULL,
40
- type TEXT NOT NULL,
41
- task_id TEXT,
42
- session_id TEXT,
43
- runtime TEXT,
44
- payload_json TEXT
45
- );
46
- CREATE TABLE schema_version (
47
- version TEXT PRIMARY KEY,
48
- applied_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ', 'now')),
49
- description TEXT
50
- );
51
- INSERT INTO schema_version (version, applied_at, description)
52
- VALUES ('8A.1', '2026-01-01T00:00:00.000Z', 'legacy fixture');
53
- `);
54
- stateDb.closeStateDb(db);
55
-
56
- const upgraded = stateDb.initStateDb(file);
57
- const columns = upgraded.db.prepare('PRAGMA table_info(tasks)').all().map((row) => row.name);
58
- assert.ok(columns.includes('estimated_days'));
59
- assert.ok(columns.includes('change_id'));
60
- const eventColumns = upgraded.db.prepare('PRAGMA table_info(events)').all().map((row) => row.name);
61
- assert.ok(eventColumns.includes('change_id'));
62
- assert.equal(upgraded.schema_version, '12.0');
63
- assert.ok(upgraded.backup_path);
64
- assert.ok(fs.existsSync(upgraded.backup_path));
65
- assert.ok(upgraded.db.prepare("SELECT 1 FROM schema_version WHERE version = '10.0'").get());
66
- const contextColumns = upgraded.db.prepare('PRAGMA table_info(context_snapshots)').all()
67
- .map((row) => row.name);
68
- for (const column of ['role', 'gate', 'next_action', 'readiness', 'context_json', 'token_budget']) {
69
- assert.ok(contextColumns.includes(column), column);
70
- }
71
- assert.ok(upgraded.db.prepare(
72
- "SELECT 1 FROM sqlite_master WHERE type = 'table' AND name = 'spec_learning_candidates'",
73
- ).get());
74
- const baseline = upgraded.db.prepare(
75
- "SELECT mode, status FROM baselines WHERE id = 'migrated-baseline'",
76
- ).get();
77
- assert.deepEqual(baseline, { mode: 'migrated', status: 'adopting' });
78
- const contextMigration = upgraded.db.prepare(
79
- "SELECT from_version, to_version, notes FROM migration_history WHERE to_version = '10.0' ORDER BY id DESC LIMIT 1",
80
- ).get();
81
- assert.equal(contextMigration.from_version, '9.1');
82
- assert.equal(contextMigration.to_version, '10.0');
83
- assert.match(contextMigration.notes, /Context Spine/);
84
- const baselineMigration = upgraded.db.prepare(
85
- "SELECT from_version, to_version, notes FROM migration_history WHERE to_version = '11.0' ORDER BY id DESC LIMIT 1",
86
- ).get();
87
- assert.equal(baselineMigration.from_version, '10.0');
88
- assert.match(baselineMigration.notes, /baseline adoption/i);
89
- const adoptionMigration = upgraded.db.prepare(
90
- "SELECT from_version, to_version, notes FROM migration_history WHERE to_version = '12.0' ORDER BY id DESC LIMIT 1",
91
- ).get();
92
- assert.equal(adoptionMigration.from_version, '11.0');
93
- assert.match(adoptionMigration.notes, /gap ledger|re-adoption/i);
94
- const migrated = upgraded.db.prepare(
95
- "SELECT gaps_json, worktree_state FROM baselines WHERE id = 'migrated-baseline'",
96
- ).get();
97
- assert.equal(migrated.worktree_state, 'unavailable');
98
- assert.equal(JSON.parse(migrated.gaps_json)[0].category, 'baseline_blocker');
99
- assert.ok(upgraded.db.prepare(
100
- "SELECT 1 FROM migration_history WHERE from_version = '8A.1' AND to_version = '9.1' AND notes LIKE '%Kimi%'",
101
- ).get());
102
- stateDb.closeStateDb(upgraded.db);
103
- } finally {
104
- fs.rmSync(dir, { recursive: true, force: true });
105
- }
106
- });