ultra-builder-pro-cli 0.11.0 → 0.13.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 (75) hide show
  1. package/.ultra-template/docs/research/README.md +21 -44
  2. package/.ultra-template/specs/architecture.md +54 -223
  3. package/.ultra-template/specs/discovery.md +41 -228
  4. package/.ultra-template/specs/product.md +44 -200
  5. package/.ultra-template/tasks/contexts/TEMPLATE.md +36 -0
  6. package/.ultra-template/tasks/tasks.json +6 -0
  7. package/CHANGELOG.md +94 -1
  8. package/README.md +37 -9
  9. package/adapters/_shared/codex-assets.cjs +1 -1
  10. package/adapters/_shared/handbook.cjs +5 -4
  11. package/adapters/_shared/tests/handbook.test.cjs +4 -0
  12. package/adapters/opencode.js +8 -2
  13. package/adapters/tests/codex.test.cjs +10 -2
  14. package/adapters/tests/kimi-hook.test.cjs +1 -1
  15. package/adapters/tests/opencode.test.cjs +36 -1
  16. package/commands/ultra-init.md +3 -3
  17. package/docs/AGENT-CONTEXT.md +17 -8
  18. package/docs/ARCHITECTURE.md +51 -8
  19. package/docs/PLAN.zh-CN.md +9 -6
  20. package/docs/ROADMAP.md +5 -3
  21. package/docs/RUNTIME-COMPAT-MATRIX.md +8 -5
  22. package/docs/STATE-DB-ACCESS-POLICY.md +19 -13
  23. package/docs/USER-HANDBOOK-CONTRACT.md +9 -5
  24. package/hooks/README.md +4 -3
  25. package/hooks/adapters/codex.py +1 -1
  26. package/hooks/adapters/kimi.py +1 -1
  27. package/hooks/context_spine.py +153 -16
  28. package/hooks/health_check.py +11 -0
  29. package/hooks/pre_stop_check.py +6 -5
  30. package/mcp-server/lib/archive-journal.cjs +192 -0
  31. package/mcp-server/lib/archive-journal.test.cjs +35 -0
  32. package/mcp-server/lib/baseline-workflow.cjs +781 -0
  33. package/mcp-server/lib/baseline-workflow.test.cjs +477 -0
  34. package/mcp-server/lib/change-workflow.cjs +256 -85
  35. package/mcp-server/lib/change-workflow.test.cjs +436 -6
  36. package/mcp-server/lib/context-spine.cjs +74 -9
  37. package/mcp-server/lib/context-spine.test.cjs +20 -0
  38. package/mcp-server/lib/doctor.cjs +28 -1
  39. package/mcp-server/lib/doctor.test.cjs +63 -1
  40. package/mcp-server/lib/init-project.cjs +334 -16
  41. package/mcp-server/lib/provider-refs.cjs +42 -0
  42. package/mcp-server/lib/spec-learning.test.cjs +5 -0
  43. package/mcp-server/lib/state-authority.cjs +9 -3
  44. package/mcp-server/lib/state-db.cjs +202 -21
  45. package/mcp-server/lib/state-db.test.cjs +140 -3
  46. package/mcp-server/lib/state-ops.cjs +68 -6
  47. package/mcp-server/lib/task-expander.cjs +7 -1
  48. package/mcp-server/lib/task-expander.test.cjs +71 -0
  49. package/mcp-server/server.cjs +62 -6
  50. package/mcp-server/tests/init-project.test.cjs +216 -9
  51. package/mcp-server/tests/migrate.test.cjs +33 -0
  52. package/mcp-server/tests/server-contract.test.cjs +478 -3
  53. package/mcp-server/tests/state-db.test.cjs +23 -2
  54. package/mcp-server/tests/state-ops.test.cjs +108 -0
  55. package/package.json +1 -1
  56. package/skills/ultra-change/SKILL.md +32 -13
  57. package/skills/ultra-deliver/SKILL.md +19 -5
  58. package/skills/ultra-dev/SKILL.md +8 -2
  59. package/skills/ultra-doctor/SKILL.md +30 -9
  60. package/skills/ultra-init/SKILL.md +107 -66
  61. package/skills/ultra-init/references/brownfield-adoption.md +93 -0
  62. package/skills/ultra-plan/SKILL.md +15 -5
  63. package/skills/ultra-research/SKILL.md +17 -5
  64. package/skills/ultra-status/SKILL.md +15 -6
  65. package/spec/cli-protocol.md +15 -1
  66. package/spec/mcp-tools.yaml +316 -11
  67. package/spec/schemas/mcp-tools.schema.json +1 -1
  68. package/spec/schemas/state-db.sql +44 -2
  69. package/ultra-tools/cli.cjs +9 -5
  70. package/ultra-tools/commands/migrate.cjs +62 -36
  71. package/ultra-tools/commands/status.cjs +29 -2
  72. package/ultra-tools/commands/system.cjs +340 -6
  73. package/ultra-tools/commands/task.cjs +11 -2
  74. package/ultra-tools/status-command.test.cjs +49 -0
  75. package/ultra-tools/system-command.test.cjs +256 -0
@@ -8,7 +8,7 @@ const path = require('node:path');
8
8
 
9
9
  const stateDb = require('../lib/state-db.cjs');
10
10
 
11
- test('initStateDb upgrades a pre-10.0 database in place with Context Spine state', () => {
11
+ test('initStateDb upgrades a pre-10.0 database through Context Spine into baseline authority', () => {
12
12
  const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'ubp-db-upgrade-'));
13
13
  const file = path.join(dir, 'state.db');
14
14
  try {
@@ -59,7 +59,9 @@ test('initStateDb upgrades a pre-10.0 database in place with Context Spine state
59
59
  assert.ok(columns.includes('change_id'));
60
60
  const eventColumns = upgraded.db.prepare('PRAGMA table_info(events)').all().map((row) => row.name);
61
61
  assert.ok(eventColumns.includes('change_id'));
62
- assert.equal(upgraded.schema_version, '10.0');
62
+ assert.equal(upgraded.schema_version, '12.0');
63
+ assert.ok(upgraded.backup_path);
64
+ assert.ok(fs.existsSync(upgraded.backup_path));
63
65
  assert.ok(upgraded.db.prepare("SELECT 1 FROM schema_version WHERE version = '10.0'").get());
64
66
  const contextColumns = upgraded.db.prepare('PRAGMA table_info(context_snapshots)').all()
65
67
  .map((row) => row.name);
@@ -69,12 +71,31 @@ test('initStateDb upgrades a pre-10.0 database in place with Context Spine state
69
71
  assert.ok(upgraded.db.prepare(
70
72
  "SELECT 1 FROM sqlite_master WHERE type = 'table' AND name = 'spec_learning_candidates'",
71
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' });
72
78
  const contextMigration = upgraded.db.prepare(
73
79
  "SELECT from_version, to_version, notes FROM migration_history WHERE to_version = '10.0' ORDER BY id DESC LIMIT 1",
74
80
  ).get();
75
81
  assert.equal(contextMigration.from_version, '9.1');
76
82
  assert.equal(contextMigration.to_version, '10.0');
77
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');
78
99
  assert.ok(upgraded.db.prepare(
79
100
  "SELECT 1 FROM migration_history WHERE from_version = '8A.1' AND to_version = '9.1' AND notes LIKE '%Kimi%'",
80
101
  ).get());
@@ -20,6 +20,13 @@ function freshDb() {
20
20
  return { ...t, db: init.db };
21
21
  }
22
22
 
23
+ function seedChange(db, id, status = 'active') {
24
+ db.prepare(
25
+ `INSERT INTO changes (id, title, kind, status, intent, artifact_root)
26
+ VALUES (?, ?, 'quick', ?, ?, ?)`,
27
+ ).run(id, `Change ${id}`, status, `Intent for ${id}.`, `.ultra/changes/active/${id}`);
28
+ }
29
+
23
30
  test('createTask inserts a row, preserves estimated_days, defaults status=pending, emits task_created', () => {
24
31
  const { dir, db } = freshDb();
25
32
  try {
@@ -65,6 +72,107 @@ test('createTask rejects duplicates with DUPLICATE_TASK_ID', () => {
65
72
  }
66
73
  });
67
74
 
75
+ test('createTask preserves parent change ownership and rejects terminal change targets', () => {
76
+ const { dir, db } = freshDb();
77
+ try {
78
+ seedChange(db, 'change-a');
79
+ seedChange(db, 'change-b');
80
+ seedChange(db, 'change-closed', 'archived');
81
+ ops.createTask(db, {
82
+ id: 'parent-owned', title: 'owned parent', type: 'feature', priority: 'P1',
83
+ change_id: 'change-a',
84
+ });
85
+ const inherited = ops.createTask(db, {
86
+ id: 'child-inherited', title: 'inherited child', type: 'feature', priority: 'P1',
87
+ parent_id: 'parent-owned',
88
+ });
89
+ assert.equal(inherited.change_id, 'change-a');
90
+ assert.throws(
91
+ () => ops.createTask(db, {
92
+ id: 'child-mismatch', title: 'mismatched child', type: 'feature', priority: 'P1',
93
+ parent_id: 'parent-owned', change_id: 'change-b',
94
+ }),
95
+ (error) => error.code === 'TASK_CHANGE_OWNERSHIP_MISMATCH',
96
+ );
97
+ assert.throws(
98
+ () => ops.createTask(db, {
99
+ id: 'child-orphan', title: 'orphan child', type: 'feature', priority: 'P1',
100
+ parent_id: 'missing-parent',
101
+ }),
102
+ (error) => error.code === 'TASK_NOT_FOUND',
103
+ );
104
+ assert.throws(
105
+ () => ops.createTask(db, {
106
+ id: 'closed-change-task', title: 'closed change task', type: 'feature', priority: 'P1',
107
+ change_id: 'change-closed',
108
+ }),
109
+ (error) => error.code === 'CHANGE_NOT_MUTABLE',
110
+ );
111
+ } finally {
112
+ closeStateDb(db);
113
+ fs.rmSync(dir, { recursive: true, force: true });
114
+ }
115
+ });
116
+
117
+ test('patchTask keeps established ownership immutable and rejects terminal-change writes', () => {
118
+ const { dir, db } = freshDb();
119
+ try {
120
+ seedChange(db, 'change-a');
121
+ seedChange(db, 'change-b');
122
+ seedChange(db, 'change-ready', 'ready');
123
+ ops.createTask(db, {
124
+ id: 'patch-parent', title: 'patch parent', type: 'feature', priority: 'P1',
125
+ change_id: 'change-a',
126
+ });
127
+ ops.createTask(db, {
128
+ id: 'patch-child', title: 'patch child', type: 'feature', priority: 'P1',
129
+ parent_id: 'patch-parent',
130
+ });
131
+ assert.throws(
132
+ () => ops.patchTask(db, 'patch-child', { change_id: null }),
133
+ (error) => error.code === 'TASK_CHANGE_OWNERSHIP_MISMATCH',
134
+ );
135
+ assert.throws(
136
+ () => ops.patchTask(db, 'patch-child', { change_id: 'change-b' }),
137
+ (error) => error.code === 'TASK_CHANGE_OWNERSHIP_MISMATCH',
138
+ );
139
+ assert.throws(
140
+ () => ops.patchTask(db, 'patch-parent', { change_id: 'change-b' }),
141
+ (error) => error.code === 'TASK_CHANGE_OWNERSHIP_MISMATCH',
142
+ );
143
+ const root = ops.createTask(db, {
144
+ id: 'patch-root', title: 'owned root', type: 'feature', priority: 'P1',
145
+ change_id: 'change-a',
146
+ });
147
+ assert.equal(root.change_id, 'change-a');
148
+ assert.throws(
149
+ () => ops.patchTask(db, 'patch-root', { change_id: null }),
150
+ (error) => error.code === 'TASK_CHANGE_OWNERSHIP_MISMATCH',
151
+ );
152
+ assert.throws(
153
+ () => ops.patchTask(db, 'patch-root', { change_id: 'change-b' }),
154
+ (error) => error.code === 'TASK_CHANGE_OWNERSHIP_MISMATCH',
155
+ );
156
+ const standalone = ops.createTask(db, {
157
+ id: 'patch-standalone', title: 'patch standalone', type: 'feature', priority: 'P1',
158
+ });
159
+ assert.equal(standalone.change_id, null);
160
+ assert.equal(ops.patchTask(db, 'patch-standalone', { change_id: 'change-b' }).change_id, 'change-b');
161
+ assert.throws(
162
+ () => ops.patchTask(db, 'patch-root', { change_id: 'change-ready' }),
163
+ (error) => error.code === 'TASK_CHANGE_OWNERSHIP_MISMATCH',
164
+ );
165
+ db.prepare("UPDATE changes SET status = 'archived' WHERE id = 'change-a'").run();
166
+ assert.throws(
167
+ () => ops.patchTask(db, 'patch-root', { priority: 'P0' }),
168
+ (error) => error.code === 'CHANGE_NOT_MUTABLE',
169
+ );
170
+ } finally {
171
+ closeStateDb(db);
172
+ fs.rmSync(dir, { recursive: true, force: true });
173
+ }
174
+ });
175
+
68
176
  test('updateTaskStatus enforces the legal transition graph', () => {
69
177
  const { dir, db } = freshDb();
70
178
  try {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ultra-builder-pro-cli",
3
- "version": "0.11.0",
3
+ "version": "0.13.0",
4
4
  "description": "Multi-runtime installer for the Ultra Builder Pro agent engineering system — deploys commands, agents, skills, hooks, and MCP server to Claude Code, OpenCode, Codex CLI, and Kimi Code.",
5
5
  "bin": {
6
6
  "ultra-builder-pro-cli": "bin/install.js",
@@ -16,16 +16,25 @@ own their payloads; Ultra stores only provider references supplied by the user o
16
16
 
17
17
  ## Workflow
18
18
 
19
- 1. Call `change.list` and `change.breadcrumb`.
19
+ 1. Call `baseline.get`. State integrity failure routes to `ultra-doctor`.
20
+ - Create ordinary work only when the baseline is healthy and `ready`.
21
+ - Resume a change that was already active when baseline drift appears; record the
22
+ condition as a warning and restore baseline readiness before ordinary convergence.
23
+ - Create an `incident` on an unhealthy baseline only with an explicit
24
+ `baseline_bypass` containing the reason and approver.
25
+ - Route every other missing, migrated, incomplete, or stale baseline to `ultra-init`.
26
+ 2. Call `change.list` and `change.breadcrumb`.
20
27
  - Resume the single change that matches the requested outcome.
21
28
  - Require an explicit id when several changes could match.
22
29
  - Create a new change only when no existing packet represents the same outcome.
23
- 2. Capture the observable outcome, acceptance, non-goals, affected public seam,
30
+ 3. Capture the observable outcome, acceptance, non-goals, affected public seam,
24
31
  documentation impact, and unresolved decisions.
25
- 3. Classify the change as `quick`, `standard`, `major`, or `incident`. Ask only for a
32
+ 4. Classify the change as `quick`, `standard`, `major`, or `incident`. Ask only for a
26
33
  material product, risk, or recovery decision that repository evidence cannot answer.
27
- 4. Call `change.create` with a stable kebab-case id, or `change.update` when resuming.
28
- 5. Write the minimum artifact set required by the classification:
34
+ 5. Call `change.create` with a stable kebab-case id, or `change.update` when resuming.
35
+ For incident break-glass, persist the approved reason in `baseline_bypass`; never
36
+ infer approval from urgency.
37
+ 6. Write the minimum artifact set required by the classification:
29
38
 
30
39
  ```text
31
40
  .ultra/changes/active/<change-id>/
@@ -41,14 +50,17 @@ own their payloads; Ultra stores only provider references supplied by the user o
41
50
  Delta files describe differences from the baseline, not a second copy of it.
42
51
  Incident diagnosis records the symptom, earliest bad state, falsifiable
43
52
  hypotheses, evidence, root cause, and recovery boundary.
44
- 6. Create the smallest executable vertical slice with `task.create`. Each task needs
53
+ 7. Create the smallest executable vertical slice with `task.create`. Each task needs
45
54
  one outcome, bounded ownership, dependencies, a live public seam, an exact
46
55
  verification command, and documentation impact.
47
- 7. Compile `change.context` for the next role and gate. Include only required
48
- references and the task execution contract. Treat missing references, digest or
49
- HEAD drift, an exceeded context budget, and unknown documentation impact as
50
- blockers.
51
- 8. Call `change.breadcrumb` and return its single next action.
56
+ 8. Compile `change.context` for the next role and gate. Include only required
57
+ references and the task execution contract. Missing required references, digest or
58
+ HEAD drift, an absent public seam or verification command, and unknown
59
+ documentation impact are blockers. File count, token estimate, and context-share
60
+ thresholds are advisory warnings: narrow reads or split the slice when useful, but
61
+ never raise a threshold merely to make the warning disappear or refuse necessary
62
+ incident context.
63
+ 9. Call `change.breadcrumb` and return its single next action.
52
64
 
53
65
  ## Specification learning
54
66
 
@@ -61,5 +73,12 @@ verified.
61
73
  ## Completion gate
62
74
 
63
75
  Do not claim alignment while a material decision is unresolved, documentation impact
64
- is unknown, context is stale, or the next task is not executable from a bounded fresh
65
- context.
76
+ is unknown, context is stale, or the next task is not executable. Ordinary change
77
+ convergence requires a non-migrated `ready` baseline. Normal HEAD or tracked-spec drift
78
+ caused by the active change is reconciled at archive.
79
+
80
+ An approved break-glass incident may converge and archive while baseline adoption is
81
+ incomplete. Its archive must add an open `baseline_blocker` reconciliation gap owned by
82
+ the recorded approver. Report the incident as closed and the project baseline as not
83
+ ready until that gap is resolved. Every archive declares baseline updates or an exact
84
+ no-change reason; failed ordinary reconciliation rolls back state and artifacts.
@@ -10,10 +10,12 @@ review, and delivery reports are evidence artifacts.
10
10
 
11
11
  ## Bind current evidence
12
12
 
13
- 1. Call `change.list` and bind exactly one relevant change, or a null change id for an
14
- initial baseline.
15
- 2. Call `change.breadcrumb`. Block on stale context, incomplete linked tasks, or
16
- unresolved readiness.
13
+ 1. Call `baseline.get`, then `change.list`. Bind exactly one relevant change, or the
14
+ current draft/adopting baseline when this is the initial delivery.
15
+ 2. Call `change.breadcrumb`. Context-size warnings are advisory. Ordinary delivery
16
+ blocks on incomplete baseline adoption, stale execution context, incomplete linked
17
+ tasks, or unresolved readiness. An explicitly approved break-glass incident may
18
+ continue while baseline adoption is incomplete.
17
19
  3. Require a passing test report for the current full HEAD and at least one declared
18
20
  public seam.
19
21
  4. Require current independent `spec_fidelity` and `engineering_standards` review
@@ -33,6 +35,10 @@ Reconcile accepted delta content and documentation impact into baseline document
33
35
  Record updated paths or a specific no-change reason. Unknown documentation impact,
34
36
  unresolved placeholders, and behavior that exists only in the delta block convergence.
35
37
 
38
+ For an initial baseline without a change, call `baseline.record`, obtain explicit owner
39
+ approval, and call `baseline.converge`. Do not simulate initial delivery through a null
40
+ change record.
41
+
36
42
  ## Verify the release candidate
37
43
 
38
44
  Use a clean, reviewed release commit. Show any remaining diff and obtain explicit
@@ -53,7 +59,15 @@ delta, documentation, both independent review axes, and incident diagnosis when
53
59
  applicable. Do not collapse review axes or replace exact signal fields with prose.
54
60
 
55
61
  Resolve named blockers, rerun invalidated gates, then call `change.archive` with the
56
- summary and baseline updates.
62
+ summary and baseline updates or an exact no-change reason. Ordinary archive
63
+ reconciliation refreshes the authoritative baseline revision and digests, rechecks
64
+ health, and rolls back state and artifacts when any tracked digest or revision remains
65
+ stale.
66
+
67
+ For a break-glass incident, verify that archive returned `baseline_bypass: true` and
68
+ created the open reconciliation gap on the current baseline. Report incident delivery
69
+ separately from project baseline readiness. Resolve that gap through `ultra-init`
70
+ before starting ordinary work.
57
71
 
58
72
  ## Optional release
59
73
 
@@ -15,6 +15,12 @@ projected status fields. If task MCP access fails, stop and route state health t
15
15
 
16
16
  Read `change.breadcrumb` when a change is active. Stale context, blocked readiness,
17
17
  unknown documentation impact, or a HEAD mismatch blocks implementation.
18
+ Baseline-adoption and context-size warnings do not block an active slice. Address
19
+ them when practical without dropping required evidence or arbitrarily changing a
20
+ threshold. Ordinary convergence requires approved baseline availability; revision
21
+ and tracked-spec health are reconciled and verified at archive. An approved
22
+ break-glass incident may finish recovery first and must leave a blocking baseline
23
+ reconciliation gap.
18
24
 
19
25
  ## Workflow
20
26
 
@@ -36,8 +42,8 @@ unknown documentation impact, or a HEAD mismatch blocks implementation.
36
42
  utilities, keep IO at boundaries, include required errors and recovery, and preserve
37
43
  unrelated worktree changes.
38
44
  7. If the work reveals a stable requirement or public behavior absent from the
39
- baseline, call `change.learning_propose`. Do not edit the baseline silently or store
40
- the discovery as private Ultra memory.
45
+ baseline, call `change.learning_propose`. Do not edit the baseline silently or keep
46
+ the discovery only in transient conversation context.
41
47
  8. Verify in this order:
42
48
  - the original feedback-loop command;
43
49
  - adjacent focused tests;
@@ -15,8 +15,10 @@ Call `system.doctor` with `{ "repair": false }` and inspect:
15
15
  - open structured incidents;
16
16
  - event and projection cursor lag;
17
17
  - failed or interrupted projection jobs;
18
+ - interrupted archive journals;
18
19
  - orphan sessions;
19
20
  - missing active-change artifact roots;
21
+ - missing, incomplete, or stale project baseline readiness and specification digests;
20
22
  - the boundary to separately installed memory and code-graph providers.
21
23
 
22
24
  Do not infer health from generated task JSON. Do not mutate external provider state,
@@ -31,17 +33,35 @@ delete artifacts, or collect memory during diagnosis.
31
33
  - An orphan session may be reconciled; never kill unrelated processes blindly.
32
34
  - A missing change artifact requires version-control, backup, or deliberate recreation
33
35
  evidence rather than silent regeneration.
36
+ - Missing or incomplete baseline evidence routes to `ultra-init`. Doctor repair does
37
+ not approve a baseline, accept known-red verification, or invent adoption evidence.
38
+ Baseline readiness is an advisory workflow check, not state-database corruption and
39
+ not a reason for doctor repair.
40
+ - A compatibility `migrated` baseline requires explicit brownfield re-adoption and
41
+ cannot authorize ordinary changes.
42
+ - A corrupt SQLite file requires preserving the file, locating a verified backup, and
43
+ an explicit restore-or-rebaseline decision.
34
44
 
35
45
  ## Explicit repair
36
46
 
37
47
  After authorization, call `system.doctor` with `{ "repair": true }` or use the
38
- installed `ultra-tools system doctor --repair` fallback. The runtime must create a
39
- timestamped state database backup before any mechanical repair.
40
-
41
- Repair is limited to documented recovery operations such as reconciling orphan
42
- sessions, consuming staleness events, requeueing interrupted or failed projections,
43
- and regenerating projections from authoritative state. If backup fails, stop. Always
44
- inspect the post-repair report; a completed repair action does not imply healthy state.
48
+ installed `ultra-tools system doctor --repair` fallback. The CLI applies supported
49
+ schema upgrades to the packaged current schema and reports a pre-migration backup path. Doctor then
50
+ creates a second timestamped backup before runtime recovery.
51
+
52
+ Repair is limited to documented schema upgrades, archive-journal completion,
53
+ reconciling orphan sessions, consuming staleness events, requeueing interrupted or
54
+ failed projections, and regenerating projections from authoritative state. If either
55
+ backup fails, stop. Always inspect the post-repair report; a completed repair action
56
+ does not imply healthy state.
57
+
58
+ If SQLite integrity prevents doctor from opening authority, preserve the original
59
+ database, WAL, and SHM. After the owner chooses a recovery path, either run
60
+ `ultra-tools system restore --backup <managed-backup> --confirm
61
+ REPLACE_CORRUPT_ULTRA_STATE` or run `ultra-tools system rebaseline --project-name
62
+ <name> [--scope <path>] --confirm REBASELINE_CORRUPT_ULTRA_STATE`. Both commands
63
+ must report the recovery backup directory. A failed command must restore the
64
+ original authority, sidecars, and task projection before returning an error.
45
65
 
46
66
  ## Installed-plugin failures
47
67
 
@@ -58,8 +78,9 @@ host wiring. Neither substitutes for the other.
58
78
 
59
79
  ## Output
60
80
 
61
- Lead with `healthy` or `degraded`. List failing checks, incident identifiers, cursor
62
- lag, whether repair ran, the backup path, and each unresolved action with its owner.
81
+ Lead with `healthy` or `degraded`. List failing authority checks separately from
82
+ baseline warnings, incident identifiers, cursor lag, whether repair ran, the backup
83
+ path, and each unresolved action with its owner.
63
84
 
64
85
  Do not fix application code, delete state, reset Git, close healthy sessions, or
65
86
  install and repair external providers through this workflow.
@@ -1,70 +1,111 @@
1
1
  ---
2
2
  name: ultra-init
3
- description: Initialize an Ultra Builder Pro project with authoritative state, baseline specification files, and optional Git setup. Use when a repository has not yet been initialized for the Ultra workflow.
3
+ description: Initialize a new repository, adopt an existing codebase, or upgrade prior Ultra state into an evidence-backed project baseline. Use when `.ultra` is absent, baseline readiness is incomplete, or legacy project state must be migrated.
4
4
  ---
5
5
 
6
- # Initialize an Ultra project
7
-
8
- Create the project-local Ultra runtime without inventing product requirements or
9
- business tasks.
10
-
11
- ## Inputs
12
-
13
- Use the current working directory unless the user names another target. Inspect
14
- existing project manifests to infer:
15
-
16
- - project name;
17
- - project type;
18
- - primary technologies;
19
- - whether Git and `.ultra/` already exist.
20
-
21
- Ask only about unresolved ambiguity, optional Git initialization, or permission to
22
- replace an existing `.ultra/` directory. Never infer permission to overwrite it.
23
-
24
- ## Workflow
25
-
26
- 1. Resolve the absolute target directory and verify that it exists.
27
- 2. Derive the project metadata from repository evidence. Treat user-provided values
28
- as authoritative when they conflict with inference.
29
- 3. If `.ultra/` exists, stop and ask whether to keep it, cancel, or recreate it with
30
- `overwrite: true`. Explain that recreation first preserves a timestamped backup.
31
- 4. Call `task.init_project` with the smallest complete input:
32
-
33
- ```json
34
- {
35
- "target_dir": "/absolute/project/path",
36
- "project_name": "example",
37
- "project_type": "fullstack",
38
- "stack": "react,node,postgres",
39
- "overwrite": false
40
- }
41
- ```
42
-
43
- 5. Verify the returned `.ultra` path, `state_db_path`, status, and copied-file list.
44
- Confirm that the returned state database and baseline specification files exist.
45
- 6. If the user requested Git setup, initialize Git only when needed and add narrowly
46
- scoped ignore rules. Do not stage or commit without explicit authorization.
47
-
48
- If the MCP server cannot start, use the installed
49
- `ultra-tools task init-project` command only when it is available. The CLI and MCP
50
- must use the same initializer. Do not simulate initialization by creating projection
51
- files manually.
52
-
53
- ## Failure handling
54
-
55
- - `ULTRA_DIR_EXISTS`: return to the overwrite decision; do not retry automatically.
56
- - `TEMPLATE_MISSING`: stop and report an installation/package integrity failure.
57
- - `TARGET_NOT_DIR` or `VALIDATION_ERROR`: correct the input and retry once.
58
- - `IO_ERROR`: report the affected path and preserve any backup or partial evidence.
59
-
60
- ## Authority and output
61
-
62
- `.ultra/state.db` is the durable Ultra authority. Generated JSON and Markdown are
63
- projections or workflow artifacts and must not be edited to create state.
64
-
65
- Report the initialized path, state database path, backup path when present, Git
66
- action, and one next action. Route incomplete product intent to `ultra-research`;
67
- route an already validated baseline to `ultra-plan`.
68
-
69
- Do not create business tasks, browse the web, or rewrite an existing README as part
70
- of initialization.
6
+ # Establish the project baseline
7
+
8
+ Create or recover project-local Ultra authority, classify the repository, and finish
9
+ the applicable baseline workflow. Keep application source unchanged during adoption.
10
+
11
+ ## Authority rules
12
+
13
+ - Treat `.ultra/state.db` as the only durable Ultra authority.
14
+ - Preserve every existing `.ultra/` tree and migration backup.
15
+ - Require explicit authorization before replacing a healthy baseline or discarding a
16
+ corrupt database.
17
+ - Store only metadata references for external memory and code-graph providers.
18
+ - Create ordinary tasks only after the baseline is ready. Record characterization
19
+ needs and adoption gaps in the gap ledger until convergence.
20
+
21
+ ## Inspect and route
22
+
23
+ 1. Bind the repository root, Git branch and HEAD, worktree status, manifests, package
24
+ scripts, workspace markers, deployment files, and existing `.ultra/` assets.
25
+ 2. When `.ultra/` is absent, run **Bootstrap**.
26
+ 3. When `.ultra/tasks/tasks.json` contains tasks but `state.db` is absent or has no
27
+ tasks, run **Import projection-only state** before ordinary state-backed work.
28
+ 4. When `state.db` exists, run read-only project doctor first. Call `baseline.get`
29
+ only when doctor confirms that the current schema authority is readable. Route an
30
+ old schema to repair and a corrupt database to recovery without another DB read.
31
+ 5. After current authority is readable, call `task.init_project` with `resume: true` to install
32
+ only missing current scaffold files. Verify that existing artifacts were preserved.
33
+ 6. Route the result:
34
+ - healthy `ready` baseline: return `ultra-change` or `ultra-status`;
35
+ - `draft`, `adopting`, or baseline-blocked: resume the matching baseline;
36
+ - `migrated`: start evidence-backed brownfield re-adoption;
37
+ - old schema: run backup-first schema repair;
38
+ - corrupt database: preserve it and stop at the restore-or-rebaseline decision.
39
+
40
+ ## Bootstrap
41
+
42
+ Derive project metadata from repository evidence. Call `task.init_project` with
43
+ `mode: "auto"`. Pass `scope` when the user selected a monorepo boundary; otherwise use
44
+ the repository root. Use an explicit mode only when the user supplied an authoritative
45
+ classification.
46
+
47
+ Verify `repository_profile`, selected scope, detected mode, baseline lifecycle, schema
48
+ version, copied templates, initial projection, and `project_initialized` event.
49
+
50
+ ## Import projection-only state
51
+
52
+ Call `task.init_project` with `resume: true` as the single authority check and run the
53
+ exact supported backup-first import command returned in its structured error. Do not
54
+ infer an import path or edit the projection manually.
55
+
56
+ Verify imported task and event counts, backup path, current schema state, projection
57
+ parity, and the `migrated/adopting` compatibility baseline. Then call `baseline.start` with a
58
+ new id, `mode: "brownfield"`, `replace_migrated: true`, the selected scope, current
59
+ revision, and repository classification. Never treat the compatibility row as owner
60
+ approval.
61
+
62
+ For an older database schema, run `ultra-tools system doctor --repair`; verify both the
63
+ pre-migration backup and post-repair backup plus the current schema before continuing.
64
+ Then resume initialization to merge missing scaffold assets without overwriting the
65
+ project's existing baseline documents.
66
+
67
+ ## Complete the selected mode
68
+
69
+ For `brownfield`, `migrated`, or an incomplete existing adoption, read
70
+ `references/brownfield-adoption.md` completely and execute it through owner approval.
71
+
72
+ For `greenfield`, keep the baseline in `draft` until product and architecture intent is
73
+ evidence-backed. Route unresolved intent through `ultra-research`, record the complete
74
+ baseline snapshot, obtain owner approval, and converge it before planning.
75
+
76
+ ## Recovery handling
77
+
78
+ - `ULTRA_DIR_EXISTS`: inspect and resume the existing state.
79
+ - `LEGACY_STATE_MIGRATION_REQUIRED`: execute the returned migration command.
80
+ - `BASELINE_IN_PROGRESS`: resume the named row; never create a parallel authority.
81
+ - `BASELINE_EXISTS`: return the healthy route. Replacing a ready baseline is outside
82
+ ordinary initialization; stop for owner authorization before calling
83
+ `baseline.start` with a new id, `replace_ready: true`, and
84
+ `replacement_authorization: { approved_by, reason }`. The approval identity and
85
+ rationale must be persisted in the `baseline_started` event.
86
+ - `BASELINE_SCOPE_MISSING`: correct the selected monorepo boundary.
87
+ - `TEMPLATE_MISSING`: run installer doctor and reinstall through the host adapter.
88
+ - `STATE_DB_CORRUPT`: retain the database, inspect `.ultra/backups`, and obtain the
89
+ restore-or-rebaseline decision. Restore only a verified managed backup with
90
+ `ultra-tools system restore --backup <path> --confirm REPLACE_CORRUPT_ULTRA_STATE`.
91
+ When no valid backup exists and the owner explicitly accepts rebuilding authority,
92
+ run `ultra-tools system rebaseline --project-name <name> [--scope <path>] --confirm
93
+ REBASELINE_CORRUPT_ULTRA_STATE`; verify the quarantined database and legacy
94
+ projection paths before continuing adoption.
95
+ - `IO_ERROR`: verify rollback restoration and preserve every reported backup path.
96
+
97
+ ## Completion
98
+
99
+ Initialization is complete only when:
100
+
101
+ - current schema authority is readable;
102
+ - repository classification and scope are recorded;
103
+ - product and architecture baseline files exist;
104
+ - verification, unknowns, gaps, evidence, and provider references are recorded;
105
+ - explicit owner approval has converged the baseline to `ready`;
106
+ - `baseline.get` reports current health and project doctor has no authority failure.
107
+
108
+ Report the target, classification evidence, migration and backup paths, baseline id,
109
+ mode, status, revision, branch, worktree snapshot, verification results, gap summary,
110
+ approval state, and one exact next action. Stop at the approval step when owner consent
111
+ has not yet been provided.