ultra-builder-pro-cli 0.12.1 → 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 (57) hide show
  1. package/.ultra-template/docs/research/README.md +21 -44
  2. package/.ultra-template/specs/discovery.md +10 -0
  3. package/CHANGELOG.md +53 -1
  4. package/README.md +25 -9
  5. package/adapters/_shared/handbook.cjs +2 -2
  6. package/adapters/tests/codex.test.cjs +8 -0
  7. package/commands/ultra-init.md +1 -1
  8. package/docs/AGENT-CONTEXT.md +4 -3
  9. package/docs/ARCHITECTURE.md +32 -16
  10. package/docs/PLAN.zh-CN.md +5 -4
  11. package/docs/ROADMAP.md +1 -1
  12. package/docs/STATE-DB-ACCESS-POLICY.md +3 -3
  13. package/docs/USER-HANDBOOK-CONTRACT.md +5 -4
  14. package/hooks/context_spine.py +37 -4
  15. package/mcp-server/lib/archive-journal.cjs +192 -0
  16. package/mcp-server/lib/archive-journal.test.cjs +35 -0
  17. package/mcp-server/lib/baseline-workflow.cjs +404 -38
  18. package/mcp-server/lib/baseline-workflow.test.cjs +252 -0
  19. package/mcp-server/lib/change-workflow.cjs +249 -75
  20. package/mcp-server/lib/change-workflow.test.cjs +235 -1
  21. package/mcp-server/lib/context-spine.test.cjs +5 -0
  22. package/mcp-server/lib/doctor.cjs +14 -1
  23. package/mcp-server/lib/doctor.test.cjs +42 -4
  24. package/mcp-server/lib/init-project.cjs +292 -9
  25. package/mcp-server/lib/spec-learning.test.cjs +1 -1
  26. package/mcp-server/lib/state-authority.cjs +9 -3
  27. package/mcp-server/lib/state-db.cjs +154 -32
  28. package/mcp-server/lib/state-db.test.cjs +136 -4
  29. package/mcp-server/lib/state-ops.cjs +68 -6
  30. package/mcp-server/lib/task-expander.cjs +7 -1
  31. package/mcp-server/lib/task-expander.test.cjs +71 -0
  32. package/mcp-server/server.cjs +14 -3
  33. package/mcp-server/tests/init-project.test.cjs +162 -1
  34. package/mcp-server/tests/migrate.test.cjs +33 -0
  35. package/mcp-server/tests/server-contract.test.cjs +384 -6
  36. package/mcp-server/tests/state-db.test.cjs +14 -2
  37. package/mcp-server/tests/state-ops.test.cjs +108 -0
  38. package/package.json +1 -1
  39. package/skills/ultra-change/SKILL.md +18 -10
  40. package/skills/ultra-deliver/SKILL.md +13 -9
  41. package/skills/ultra-dev/SKILL.md +6 -4
  42. package/skills/ultra-doctor/SKILL.md +22 -7
  43. package/skills/ultra-init/SKILL.md +104 -59
  44. package/skills/ultra-init/references/brownfield-adoption.md +65 -37
  45. package/skills/ultra-plan/SKILL.md +8 -5
  46. package/skills/ultra-research/SKILL.md +12 -5
  47. package/skills/ultra-status/SKILL.md +6 -4
  48. package/spec/cli-protocol.md +11 -1
  49. package/spec/mcp-tools.yaml +95 -9
  50. package/spec/schemas/state-db.sql +11 -0
  51. package/ultra-tools/cli.cjs +9 -5
  52. package/ultra-tools/commands/migrate.cjs +62 -36
  53. package/ultra-tools/commands/status.cjs +18 -9
  54. package/ultra-tools/commands/system.cjs +340 -6
  55. package/ultra-tools/commands/task.cjs +7 -1
  56. package/ultra-tools/status-command.test.cjs +29 -0
  57. package/ultra-tools/system-command.test.cjs +252 -1
@@ -51,11 +51,18 @@ default.
51
51
  5. Validate cross-document consistency and trace each required behavior from problem
52
52
  or constraint to acceptance and architecture.
53
53
  6. Use `references/synthesis.md` for the completion check.
54
- 7. Call `baseline.record` with the complete current specification list, bounded evidence
55
- references, actual verification results, provider metadata, and explicit unknowns.
56
- Use the returned repository revision for convergence.
57
- 8. Present the baseline and any known-red verification to the owner. After explicit
58
- approval, call `baseline.converge`. Resolve deterministic blockers before routing.
54
+ 7. Record unresolved evidence as the baseline gap ledger: `baseline_blocker`,
55
+ `documentation_drift`, `known_defect`, `technical_debt`, `unknown`, or
56
+ `future_change`. Keep accepted non-blocking work out of the implementation backlog
57
+ until the owner selects it.
58
+ 8. Call `baseline.record` with the complete current specification list, bounded evidence
59
+ references, actual verification results, provider metadata, explicit unknowns,
60
+ classification, and the full gap ledger. Use the returned repository revision for
61
+ convergence.
62
+ 9. Present the baseline, open gaps, dirty-worktree state, and any known-red verification
63
+ to the owner. After explicit approval, call `baseline.converge`, setting acceptance
64
+ flags only for the exact known-red or dirty snapshot approved by the owner. Resolve
65
+ deterministic blockers before routing.
59
66
 
60
67
  ## Completion gate
61
68
 
@@ -12,8 +12,8 @@ authoritative; reports and Markdown are evidence or projections.
12
12
 
13
13
  1. Call `system.doctor` in read-only mode. If authority is unhealthy, route only to
14
14
  `ultra-doctor` and include the blocking diagnostic.
15
- 2. Call `baseline.get` for mode, lifecycle status, repository revision, specification
16
- digest health, known warnings, and adoption blockers.
15
+ 2. Call `baseline.get` for mode, lifecycle status, repository revision, branch,
16
+ worktree snapshot, specification digest health, gap ledger, and adoption blockers.
17
17
  3. Call `change.breadcrumb` for the active change, task, role, gate, readiness,
18
18
  blockers, advisory warnings, staleness, and next action.
19
19
  4. Call `task.list` and `session.list` for progress and active execution details.
@@ -30,7 +30,9 @@ Follow the breadcrumb's primary route and return one action, not a menu:
30
30
 
31
31
  - unhealthy authority: `ultra-doctor`;
32
32
  - missing Ultra project: `ultra-init`;
33
- - missing baseline evidence with no active change: `ultra-init`, then
33
+ - projection-only authority conflict: run the exact supported import command from the
34
+ MCP error, then `ultra-init`;
35
+ - migrated or missing baseline evidence with no active change: `ultra-init`, then
34
36
  `ultra-research` or `ultra-plan` according to the gap;
35
37
  - baseline or context-budget warning during an active change: keep the current route
36
38
  and surface the warning; do not turn it into a refusal;
@@ -50,7 +52,7 @@ Use a compact shape:
50
52
  ```text
51
53
  Ultra: <healthy|degraded> · <branch>@<head> · worktree <clean|dirty>
52
54
  Position: change=<id|none> task=<id|none> role=<role> gate=<gate>
53
- Baseline: <greenfield|brownfield|migrated>/<status> revision=<revision|none>
55
+ Baseline: <greenfield|brownfield|migrated>/<status> revision=<revision|none> gaps=<open>/<blocking>
54
56
  Readiness: <ready|blocked|stale> — <blockers or none>
55
57
  Warnings: <advisory conditions or none>
56
58
  Progress: <completed>/<total>; sessions=<active count>
@@ -120,10 +120,20 @@ as a fallback unless `ultra-tools <family> --help` lists it.
120
120
 
121
121
  Current executable maintenance surfaces are `task init-project`,
122
122
  `session close|get|list|admission|heartbeat|subscribe|reap`, `status`, `db`,
123
- `migrate`, and `legacy-memory`. In particular, `task create|update|list|get`
123
+ `migrate`, `system doctor|restore|rebaseline`, and `legacy-memory`. In particular, `task create|update|list|get`
124
124
  and all `change` lifecycle verbs are not CLI fallbacks. Change state must use
125
125
  the live MCP server; `system doctor` may additionally be exposed by the
126
126
  maintenance CLI because it is the recovery path when MCP startup is degraded.
127
+ `task init-project --resume` preserves existing `.ultra` files and installs only
128
+ missing current scaffold assets. Projection-only state uses the supported
129
+ `migrate --from=4.4 --to=4.5` or `--from=4.5 --to=12.0` transition before resume.
130
+ `system doctor --repair` applies supported schema upgrades with a pre-migration
131
+ backup before mechanical recovery.
132
+ `system restore` requires the exact `REPLACE_CORRUPT_ULTRA_STATE` confirmation and a
133
+ verified database inside `.ultra/backups`; it quarantines the corrupt state before
134
+ atomic replacement. `system rebaseline` requires the exact
135
+ `REBASELINE_CORRUPT_ULTRA_STATE` confirmation and preserves corrupt state plus the
136
+ legacy task projection before starting a new brownfield adoption.
127
137
  The full access policy lives in
128
138
  `docs/STATE-DB-ACCESS-POLICY.md` (Phase 2.2 / R25).
129
139
 
@@ -3,11 +3,11 @@
3
3
  # Validated by spec/schemas/mcp-tools.schema.json (run `npm run test:spec`).
4
4
  # Trace: PLAN §7.3, decisions D12 / D29 / D31-D34.
5
5
 
6
- version: '1.1'
6
+ version: '1.2'
7
7
 
8
8
  info:
9
9
  title: Ultra Builder Pro MCP tool contracts
10
- phase: '1.1'
10
+ phase: '1.2'
11
11
  trace_to: 'PLAN docs/PLAN.zh-CN.md §7.3'
12
12
  notes: |
13
13
  This published contract contains only tools registered by the MCP server.
@@ -32,7 +32,7 @@ tools:
32
32
  # ─────────────────────────── task family ────────────────────────────────
33
33
  - name: task.create
34
34
  family: task
35
- description: Create a new task in state.db. Emits task_created event. If `id` is omitted the server mints a uuid.
35
+ description: Create a new task in state.db. Emits task_created event. If `id` is omitted the server mints a uuid. Child tasks inherit the parent's change ownership; conflicting ownership is rejected.
36
36
  phase: '2'
37
37
  writer_role: mcp
38
38
  input_schema:
@@ -48,10 +48,10 @@ tools:
48
48
  estimated_days: { type: number, exclusiveMinimum: 0, description: 'estimated implementation effort in days' }
49
49
  deps: { type: array, items: { type: string } }
50
50
  files_modified: { type: array, items: { type: string }, description: 'Phase 8A conflict detection' }
51
- parent_id: { type: string, description: 'Phase 8A.3 parent reference for task.expand children' }
51
+ parent_id: { type: string, description: 'Phase 8A.3 parent reference; the child inherits this task change ownership' }
52
52
  tag: { type: string, description: 'git branch tag (Phase 7.2)' }
53
53
  trace_to: { type: string, description: 'spec anchor (e.g. spec/mcp-tools.yaml#task.create)' }
54
- change_id: { type: string, pattern: '^[a-zA-Z0-9_\-]+$', description: 'continuous change unit owning this task' }
54
+ change_id: { type: string, pattern: '^[a-zA-Z0-9_\-]+$', description: 'active or blocked continuous change unit owning this task; inherited from parent_id when omitted' }
55
55
  output_schema:
56
56
  type: object
57
57
  required: [id, status, created_at]
@@ -63,6 +63,11 @@ tools:
63
63
  errors:
64
64
  - { code: VALIDATION_ERROR, description: 'input failed schema validation' }
65
65
  - { code: DUPLICATE_TASK_ID, description: 'task id already exists' }
66
+ - { code: TASK_NOT_FOUND, description: 'parent task does not exist' }
67
+ - { code: CHANGE_NOT_FOUND, description: 'assigned change does not exist' }
68
+ - { code: CHANGE_NOT_MUTABLE, description: 'assigned change no longer accepts tasks' }
69
+ - { code: TASK_CHANGE_OWNERSHIP_MISMATCH, description: 'child ownership conflicts with its parent change' }
70
+ - { code: BASELINE_NOT_READY, description: 'ordinary task creation requires a ready baseline or an already-authorized active change' }
66
71
  - { code: LEGACY_STATE_MIGRATION_REQUIRED, description: 'non-empty v4.4 projection must be migrated before state-backed tools can run' }
67
72
  - { code: STATE_DB_LOCKED, description: 'database is locked', retriable: true }
68
73
  cli_subcommand: task create
@@ -106,6 +111,9 @@ tools:
106
111
  - { code: TASK_NOT_FOUND, description: 'no task with given id' }
107
112
  - { code: ILLEGAL_STATUS_TRANSITION, description: 'transition rejected by state machine' }
108
113
  - { code: VALIDATION_ERROR, description: 'patch failed schema validation' }
114
+ - { code: CHANGE_NOT_FOUND, description: 'assigned change does not exist' }
115
+ - { code: CHANGE_NOT_MUTABLE, description: 'assigned change no longer accepts task updates' }
116
+ - { code: TASK_CHANGE_OWNERSHIP_MISMATCH, description: 'task ownership conflicts with its parent or children' }
109
117
  - { code: LEGACY_STATE_MIGRATION_REQUIRED, description: 'non-empty v4.4 projection must be migrated before state-backed tools can run' }
110
118
  cli_subcommand: task update
111
119
  emits_events: [task_started, task_completed, task_blocked, task_stale_marked]
@@ -246,6 +254,17 @@ tools:
246
254
  enum: [auto, greenfield, brownfield]
247
255
  default: auto
248
256
  description: auto detects whether meaningful project content already exists
257
+ resume:
258
+ type: boolean
259
+ default: false
260
+ description: preserve an existing `.ultra/`, upgrade its schema, and install only missing current scaffold files
261
+ scope:
262
+ type: array
263
+ minItems: 1
264
+ uniqueItems: true
265
+ items: { type: string, minLength: 1 }
266
+ default: ['.']
267
+ description: project-relative repository roots governed by the initial baseline
249
268
  overwrite:
250
269
  type: boolean
251
270
  default: false
@@ -255,7 +274,7 @@ tools:
255
274
  description: override path to the template root (defaults to bundled templates/.ultra/)
256
275
  output_schema:
257
276
  type: object
258
- required: [created_path, state_db_path, status, mode, baseline, copied_files]
277
+ required: [created_path, state_db_path, status, mode, baseline, copied_files, repository_profile]
259
278
  additionalProperties: false
260
279
  properties:
261
280
  created_path:
@@ -266,28 +285,38 @@ tools:
266
285
  description: absolute path to the initialized authoritative SQLite database
267
286
  status:
268
287
  type: string
269
- enum: [created, overwritten]
288
+ enum: [created, overwritten, resumed]
270
289
  mode:
271
290
  type: string
272
291
  enum: [greenfield, brownfield]
273
292
  baseline:
274
293
  type: object
275
- required: [id, mode, status]
294
+ required: [id, mode, status, scope]
276
295
  additionalProperties: true
277
296
  copied_files:
278
297
  type: array
279
298
  items: { type: string }
280
299
  description: paths relative to created_path
300
+ repository_profile:
301
+ type: object
302
+ description: bounded classification evidence used to route greenfield or brownfield adoption
281
303
  backup_path:
282
304
  type: string
283
305
  description: set only when status=overwritten
306
+ migration_backup_path:
307
+ type: string
308
+ description: pre-migration database backup created while resuming an older schema
284
309
  errors:
285
310
  - { code: ULTRA_DIR_EXISTS, description: '.ultra/ already exists and overwrite=false' }
286
311
  - { code: TEMPLATE_MISSING, description: 'source_template path does not exist' }
287
312
  - { code: TARGET_NOT_DIR, description: 'target_dir is not a directory' }
313
+ - { code: BASELINE_SCOPE_MISSING, description: 'a selected baseline scope does not exist' }
314
+ - { code: LEGACY_STATE_MIGRATION_REQUIRED, description: 'projection-only tasks must be imported before resume' }
315
+ - { code: STATE_AUTHORITY_CONFLICT, description: 'projection tasks and authoritative state cannot be reconciled automatically' }
316
+ - { code: STATE_PROJECTION_INVALID, description: 'the existing task projection is malformed' }
288
317
  - { code: IO_ERROR, description: 'filesystem write failed', retriable: true }
289
318
  cli_subcommand: task init-project
290
- emits_events: [project_initialized]
319
+ emits_events: [project_initialized, project_resumed]
291
320
  trace_to: 'PLAN §6 Phase 3.1'
292
321
 
293
322
  - name: task.expand
@@ -313,6 +342,9 @@ tools:
313
342
  errors:
314
343
  - { code: TASK_NOT_FOUND, description: 'parent id missing' }
315
344
  - { code: ALREADY_EXPANDED, description: 'task is already expanded' }
345
+ - { code: CHANGE_NOT_FOUND, description: 'the parent task change does not exist' }
346
+ - { code: CHANGE_NOT_MUTABLE, description: 'the parent task change no longer accepts children' }
347
+ - { code: BASELINE_NOT_READY, description: 'child creation requires a ready baseline or the parent task to belong to an already-authorized active change' }
316
348
  cli_subcommand: task expand
317
349
  emits_events: [task_expanded]
318
350
  trace_to: '§7.3, D34'
@@ -329,6 +361,7 @@ tools:
329
361
  prd_path: { type: string }
330
362
  prd_text: { type: string }
331
363
  tag: { type: string }
364
+ change_id: { type: string, pattern: '^[a-zA-Z0-9_\-]+$', description: 'continuous change unit that will own every persisted parsed task' }
332
365
  dry_run: { type: boolean, default: false, description: 'when true, do not persist to state.db — used by ultra-plan gate to preview before approve' }
333
366
  output_schema:
334
367
  type: object
@@ -340,6 +373,9 @@ tools:
340
373
  errors:
341
374
  - { code: NO_INPUT, description: 'one of prd_path or prd_text required' }
342
375
  - { code: PARSE_FAILED, description: 'PRD could not be parsed into tasks' }
376
+ - { code: CHANGE_NOT_FOUND, description: 'assigned change does not exist' }
377
+ - { code: CHANGE_NOT_MUTABLE, description: 'assigned change no longer accepts tasks' }
378
+ - { code: BASELINE_NOT_READY, description: 'persisting parsed tasks requires a ready baseline or an already-authorized active change' }
343
379
  cli_subcommand: task parse-prd
344
380
  emits_events: [task_created]
345
381
  trace_to: '§7.3, D34'
@@ -652,6 +688,15 @@ tools:
652
688
  type: object
653
689
  required: [project_name, mode]
654
690
  additionalProperties: false
691
+ allOf:
692
+ - if:
693
+ required: [replace_ready]
694
+ properties: { replace_ready: { const: true } }
695
+ then: { required: [replacement_authorization] }
696
+ - if: { required: [replacement_authorization] }
697
+ then:
698
+ required: [replace_ready]
699
+ properties: { replace_ready: { const: true } }
655
700
  properties:
656
701
  id: { type: string, pattern: '^[a-zA-Z0-9_\-]+$', default: project-baseline }
657
702
  project_name: { type: string, minLength: 1 }
@@ -661,6 +706,15 @@ tools:
661
706
  scope: { type: array, minItems: 1, items: { type: string, minLength: 1 }, default: ['.'] }
662
707
  repository_revision: { type: string, minLength: 1 }
663
708
  replace_ready: { type: boolean, default: false }
709
+ replacement_authorization:
710
+ type: object
711
+ required: [approved_by, reason]
712
+ additionalProperties: false
713
+ properties:
714
+ approved_by: { type: string, minLength: 1 }
715
+ reason: { type: string, minLength: 3 }
716
+ replace_migrated: { type: boolean, default: false, description: explicitly supersede a compatibility-only migrated baseline and start evidence-backed adoption }
717
+ classification: { type: object, description: bounded repository classification evidence; content is limited to 32 KiB }
664
718
  provider_refs:
665
719
  type: object
666
720
  additionalProperties: false
@@ -696,6 +750,9 @@ tools:
696
750
  errors:
697
751
  - { code: BASELINE_EXISTS, description: 'a ready baseline requires explicit replacement' }
698
752
  - { code: BASELINE_IN_PROGRESS, description: 'another adoption is already active' }
753
+ - { code: BASELINE_REPLACEMENT_AUTHORIZATION_REQUIRED, description: 'ready-baseline replacement lacks durable owner approval and rationale' }
754
+ - { code: BASELINE_REPLACEMENT_INVALID, description: 'replacement flags do not match the current baseline lifecycle or authorization payload' }
755
+ - { code: BASELINE_SCOPE_MISSING, description: 'a selected baseline scope does not exist' }
699
756
  - { code: PROVIDER_CONTENT_FORBIDDEN, description: 'provider payload content must remain external' }
700
757
  cli_subcommand: baseline start
701
758
  emits_events: [baseline_started]
@@ -754,6 +811,22 @@ tools:
754
811
  summary: { type: string, minLength: 1 }
755
812
  blocking: { type: boolean }
756
813
  owner: { type: string, minLength: 1 }
814
+ gaps:
815
+ type: array
816
+ items:
817
+ type: object
818
+ required: [id, category, summary]
819
+ additionalProperties: false
820
+ properties:
821
+ id: { type: string, pattern: '^[a-zA-Z0-9_\-]+$' }
822
+ category: { type: string, enum: [baseline_blocker, documentation_drift, known_defect, technical_debt, unknown, future_change] }
823
+ status: { type: string, enum: [open, accepted, resolved, deferred], default: open }
824
+ blocking: { type: boolean, default: false }
825
+ summary: { type: string, minLength: 1 }
826
+ evidence_refs: { type: array, uniqueItems: true, items: { type: string, minLength: 1 }, default: [] }
827
+ owner: { type: ['string', 'null'], minLength: 1 }
828
+ resolution: { type: string, minLength: 1 }
829
+ classification: { type: object, description: bounded repository classification evidence; content is limited to 32 KiB }
757
830
  provider_refs:
758
831
  type: object
759
832
  additionalProperties: false
@@ -790,6 +863,7 @@ tools:
790
863
  - { code: BASELINE_NOT_FOUND, description: 'baseline id does not exist' }
791
864
  - { code: BASELINE_NOT_MUTABLE, description: 'ready and superseded baselines are immutable' }
792
865
  - { code: BASELINE_SPEC_MISSING, description: 'a declared specification file does not exist' }
866
+ - { code: BASELINE_SCOPE_MISSING, description: 'a selected baseline scope does not exist' }
793
867
  - { code: PROVIDER_CONTENT_FORBIDDEN, description: 'provider payload content must remain external' }
794
868
  cli_subcommand: baseline record
795
869
  emits_events: [baseline_recorded]
@@ -831,6 +905,7 @@ tools:
831
905
  approved_by: { type: string, minLength: 1 }
832
906
  approval_note: { type: string, minLength: 3 }
833
907
  accept_known_red: { type: boolean, default: false }
908
+ accept_dirty_worktree: { type: boolean, default: false, description: explicitly freeze the exact recorded dirty-worktree digest into the baseline }
834
909
  output_schema:
835
910
  type: object
836
911
  required: [ready, status, blockers, baseline]
@@ -843,6 +918,7 @@ tools:
843
918
  errors:
844
919
  - { code: BASELINE_NOT_FOUND, description: 'baseline id does not exist' }
845
920
  - { code: BASELINE_NOT_CONVERGEABLE, description: 'baseline lifecycle does not allow convergence' }
921
+ - { code: BASELINE_NOT_READY, description: 'baseline evidence, gaps, revision, branch, worktree, or verification still blocks convergence' }
846
922
  cli_subcommand: baseline converge
847
923
  emits_events: [baseline_blocked, baseline_converged]
848
924
 
@@ -862,6 +938,14 @@ tools:
862
938
  kind: { type: string, enum: [quick, standard, major, incident] }
863
939
  intent: { type: string, minLength: 3 }
864
940
  base_commit: { type: string, pattern: '^[0-9a-f]{7,40}$' }
941
+ baseline_bypass:
942
+ type: object
943
+ required: [reason, approved_by]
944
+ additionalProperties: false
945
+ properties:
946
+ reason: { type: string, minLength: 3 }
947
+ approved_by: { type: string, minLength: 1 }
948
+ description: incident-only break-glass approval when the project baseline is unhealthy
865
949
  docs_impact:
866
950
  type: object
867
951
  additionalProperties: false
@@ -907,6 +991,8 @@ tools:
907
991
  - { code: DUPLICATE_CHANGE_ID, description: 'change id already exists' }
908
992
  - { code: PROVIDER_CONTENT_FORBIDDEN, description: 'provider payload content must remain external' }
909
993
  - { code: VALIDATION_ERROR, description: 'change input failed validation' }
994
+ - { code: BASELINE_NOT_READY, description: 'ordinary work is blocked until the project baseline is healthy' }
995
+ - { code: BASELINE_BYPASS_REQUIRED, description: 'an incident on an unhealthy baseline requires explicit break-glass approval' }
910
996
  cli_subcommand: change create
911
997
  emits_events: [change_created, context_updated]
912
998
 
@@ -27,10 +27,18 @@ CREATE TABLE IF NOT EXISTS baselines (
27
27
  repository_root TEXT NOT NULL DEFAULT '.',
28
28
  scope_json TEXT NOT NULL DEFAULT '["."]',
29
29
  repository_revision TEXT,
30
+ repository_branch TEXT,
31
+ worktree_state TEXT NOT NULL DEFAULT 'unavailable'
32
+ CHECK (worktree_state IN ('clean', 'dirty', 'unavailable')),
33
+ worktree_digest TEXT,
34
+ worktree_files_json TEXT NOT NULL DEFAULT '[]',
35
+ worktree_accepted INTEGER NOT NULL DEFAULT 0 CHECK (worktree_accepted IN (0, 1)),
30
36
  spec_refs_json TEXT NOT NULL DEFAULT '[]',
31
37
  evidence_json TEXT NOT NULL DEFAULT '[]',
32
38
  verification_json TEXT NOT NULL DEFAULT '[]',
33
39
  unknowns_json TEXT NOT NULL DEFAULT '[]',
40
+ gaps_json TEXT NOT NULL DEFAULT '[]',
41
+ classification_json TEXT NOT NULL DEFAULT '{}',
34
42
  provider_refs_json TEXT NOT NULL DEFAULT '{}',
35
43
  approved_by TEXT,
36
44
  approval_note TEXT,
@@ -53,6 +61,7 @@ CREATE TABLE IF NOT EXISTS changes (
53
61
  intent TEXT NOT NULL,
54
62
  docs_impact_json TEXT NOT NULL DEFAULT '{"status":"unknown","files":[],"rationale":null}',
55
63
  provider_refs_json TEXT NOT NULL DEFAULT '{}',
64
+ baseline_bypass_json TEXT,
56
65
  base_commit TEXT,
57
66
  artifact_root TEXT NOT NULL,
58
67
  created_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ', 'now')),
@@ -336,3 +345,5 @@ INSERT OR IGNORE INTO schema_version (version, description)
336
345
  VALUES ('10.0', 'Role-scoped context snapshots, deterministic breadcrumbs, and approval-gated specification learning');
337
346
  INSERT OR IGNORE INTO schema_version (version, description)
338
347
  VALUES ('11.0', 'Greenfield and brownfield baseline adoption, convergence, and drift authority');
348
+ INSERT OR IGNORE INTO schema_version (version, description)
349
+ VALUES ('12.0', 'Evidence-backed repository snapshots, gap ledger, safe re-adoption, and incident break-glass governance');
@@ -20,7 +20,7 @@ const path = require('node:path');
20
20
 
21
21
  const VERSION = (() => {
22
22
  try {
23
- const pkg = require(path.join(__dirname, '..', 'package.json'));
23
+ const pkg = require('../package.json');
24
24
  return pkg.version;
25
25
  } catch (_err) {
26
26
  return '0.1.0';
@@ -35,10 +35,10 @@ USAGE:
35
35
  SUBCOMMANDS:
36
36
  task init-project
37
37
  session close | get | list | admission | heartbeat | subscribe | reap
38
- system doctor [--repair]
38
+ system doctor [--repair] | restore | rebaseline
39
39
  status [--cost] [--since <duration>] [--json]
40
40
  db init | checkpoint | vacuum | integrity | backup (Phase 2)
41
- migrate --from=4.4 --to=4.5 [--dry|--rollback] (Phase 2)
41
+ migrate --from=<4.4|4.5> --to=<4.5|12.0> [--dry|--rollback]
42
42
  legacy-memory inspect | archive | prune --confirm DELETE_ULTRA_LEGACY_MEMORY
43
43
 
44
44
  --help / -h show this message
@@ -68,7 +68,11 @@ const statusCommand = require('./commands/status.cjs');
68
68
  const legacyMemoryCommand = require('./commands/legacy-memory.cjs');
69
69
  const systemCommand = require('./commands/system.cjs');
70
70
 
71
- // Phase 6.2 — CLI telemetry: best-effort, never blocks the subcommand.
71
+ // Session commands run only against healthy authority and may emit best-effort
72
+ // telemetry. Initialization, diagnosis, migration, and recovery commands must
73
+ // never open state.db before their own evidence-preserving checks.
74
+ const TELEMETRY_SUBCOMMANDS = new Set(['session']);
75
+
72
76
  function emitCliTelemetry(sub, rest) {
73
77
  try {
74
78
  const dbPath = path.resolve('.ultra', 'state.db');
@@ -112,7 +116,7 @@ function main(argv) {
112
116
  const [sub, ...rest] = args;
113
117
  const handler = SUBCOMMANDS[sub];
114
118
  if (!handler) fail(`unknown subcommand: ${sub}\n\n${USAGE}`);
115
- emitCliTelemetry(sub, rest);
119
+ if (TELEMETRY_SUBCOMMANDS.has(sub)) emitCliTelemetry(sub, rest);
116
120
  handler(rest);
117
121
  }
118
122