ultra-builder-pro-cli 0.16.0 → 0.17.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 (64) hide show
  1. package/.ultra-template/specs/research-distillate.md +4 -3
  2. package/CHANGELOG.md +86 -0
  3. package/README.md +54 -24
  4. package/adapters/_shared/codex-assets.cjs +10 -5
  5. package/adapters/_shared/handbook.cjs +1 -1
  6. package/adapters/_shared/interaction-contract.cjs +61 -0
  7. package/adapters/claude.js +1 -1
  8. package/adapters/opencode.js +1 -1
  9. package/bin/orchestrator.js +175 -19
  10. package/commands/ultra-change.md +1 -1
  11. package/commands/ultra-deliver.md +3 -3
  12. package/commands/ultra-init.md +1 -1
  13. package/commands/ultra-plan.md +1 -1
  14. package/commands/ultra-research.md +2 -2
  15. package/commands/ultra-review.md +10 -0
  16. package/commands/ultra-status.md +1 -1
  17. package/commands/ultra-test.md +1 -1
  18. package/docs/AGENT-CONTEXT.md +11 -8
  19. package/docs/ARCHITECTURE.md +67 -9
  20. package/docs/LEGACY-CLI-CROSSWALK.md +163 -0
  21. package/docs/PLAN.zh-CN.md +19 -13
  22. package/docs/RUNTIME-COMPAT-MATRIX.md +2 -2
  23. package/docs/WORKFLOW-LIFECYCLE.md +123 -59
  24. package/hooks/pre_stop_check.py +3 -2
  25. package/mcp-server/lib/baseline-workflow.cjs +84 -16
  26. package/mcp-server/lib/change-workflow.cjs +55 -35
  27. package/mcp-server/lib/context-spine.cjs +171 -105
  28. package/mcp-server/lib/git-bootstrap.cjs +240 -0
  29. package/mcp-server/lib/init-project.cjs +178 -41
  30. package/mcp-server/lib/project-breadcrumb.cjs +14 -14
  31. package/mcp-server/lib/state-db.cjs +257 -10
  32. package/mcp-server/lib/state-ops.cjs +64 -1
  33. package/mcp-server/lib/workflow-state.cjs +300 -205
  34. package/mcp-server/server.cjs +58 -34
  35. package/orchestrator/auto-merge.cjs +19 -0
  36. package/orchestrator/daemon.cjs +104 -0
  37. package/orchestrator/parallel-orchestrator.cjs +371 -49
  38. package/orchestrator/session-runner.cjs +354 -25
  39. package/package.json +2 -1
  40. package/skills/ultra-change/SKILL.md +69 -94
  41. package/skills/ultra-deliver/SKILL.md +37 -65
  42. package/skills/ultra-dev/SKILL.md +50 -52
  43. package/skills/ultra-doctor/SKILL.md +34 -49
  44. package/skills/ultra-init/SKILL.md +78 -105
  45. package/skills/ultra-plan/SKILL.md +78 -99
  46. package/skills/ultra-research/SKILL.md +99 -113
  47. package/skills/ultra-review/SKILL.md +38 -53
  48. package/skills/ultra-review/references/review-modes.md +5 -3
  49. package/skills/ultra-review/references/unified-schema.md +26 -6
  50. package/skills/ultra-review/scripts/review_wait.py +12 -0
  51. package/skills/ultra-status/SKILL.md +34 -44
  52. package/skills/ultra-test/SKILL.md +61 -54
  53. package/skills/ultra-think/SKILL.md +37 -51
  54. package/skills/ultra-think/references/decision-dialogue.md +87 -111
  55. package/spec/cli-protocol.md +35 -0
  56. package/spec/mcp-tools.yaml +145 -28
  57. package/spec/schemas/delivery-report.v1.schema.json +1 -46
  58. package/spec/schemas/state-db.sql +8 -2
  59. package/spec/schemas/test-report.v1.schema.json +45 -14
  60. package/ultra-tools/cli.cjs +1 -1
  61. package/ultra-tools/commands/session.cjs +10 -3
  62. package/ultra-tools/commands/status.cjs +19 -14
  63. package/ultra-tools/commands/system.cjs +2 -2
  64. package/ultra-tools/commands/task.cjs +3 -0
@@ -9,9 +9,9 @@ host and project owner. It is the operational companion to
9
9
 
10
10
  | Surface | Owns | Must not own |
11
11
  |---|---|---|
12
- | Active host and owner | Product judgment, research content, implementation, review findings, release authorization | Durable workflow status or fabricated evidence digests |
12
+ | Active host and owner | Product judgment, research content, implementation, review findings, and authorization for destructive or external effects | Durable workflow status or fabricated evidence digests |
13
13
  | Skill | One reusable procedure and its evidence requirements | Project state, static product doctrine, host-specific tool fiction |
14
- | MCP | IDs, transitions, task contracts, evidence references, output hashes, gate verdicts, next action | Research prose, code generation, memory, or model calls |
14
+ | MCP | IDs, valid transitions, hard recovery requirements, task contracts, evidence references, output hashes, and gate verdicts | Semantic route selection, research prose, code generation, memory, or model calls |
15
15
  | `.ultra/state.db` | Baseline, change, decision, task, workflow, session, event, incident, projection, and evidence authority | Prompts, transcripts, external memory, or code-graph payloads |
16
16
  | Generated JSON and Markdown | Read-only projections and durable artifacts | Independent lifecycle authority |
17
17
  | Hook | Compact DB-derived lifecycle observation, minimal event metadata, and projection protection | Generic engineering judgment, prompt/transcript capture, parallel lifecycle logs, or arbitrary edit blocking |
@@ -20,7 +20,8 @@ Prompt input can supply facts, content paths, reasons, owner decisions, and
20
20
  evidence references. MCP reads the current repository and DB, validates those
21
21
  inputs, hashes outputs, and derives status. Prompt input cannot override a task's
22
22
  public seam, verification command, context references, workflow summary, gate
23
- verdict, output digest, or next action.
23
+ verdict, output digest, or transition validity. A host recommendation is never stored
24
+ as MCP authority.
24
25
 
25
26
  Load-bearing owner choices are normalized through `decision.*`; Prompt prose is not
26
27
  durable authority. The host acquires observable facts autonomously, exposes one
@@ -34,10 +35,12 @@ authority, and no new stage may start on an archived or cancelled change. Doctor
34
35
  recovers a legacy change without this link into an explicitly blocked workflow;
35
36
  it does not fabricate the missing provenance.
36
37
 
37
- Ultra does not select an MVP. Product scope and delivery posture are owner
38
- decisions. A reduced research mode is valid only for an explicitly bounded active
39
- change with a recorded selection reason; initial greenfield and brownfield
40
- baselines always use all seventeen research steps.
38
+ Ultra does not select an MVP. Product scope and material delivery posture are owner
39
+ decisions. The seventeen research areas are a coverage catalog, not a forced
40
+ questionnaire. Initial greenfield and brownfield research must disposition every area
41
+ as `execute`, `verify_existing`, `reuse`, `not_applicable`, or accepted `deferred`;
42
+ only selected necessary work executes. Bounded change research records the same
43
+ selection rationale over its smaller scope.
41
44
 
42
45
  ## 2. How `ultra-init` classifies a repository
43
46
 
@@ -65,9 +68,22 @@ worktree digests and accepted dirty files are restricted to that scope.
65
68
 
66
69
  Classification and readiness are separate. Initialization immediately creates
67
70
  or resumes `.ultra/state.db`, installs only the required scaffold, records the
68
- classification, opens an `init` workflow, and opens `full` research for
69
- greenfield or `adoption` research for brownfield. Empty templates are not an
70
- approved baseline.
71
+ classification, and completes an `init` workflow after read-back verification. It
72
+ does not create a research run. A later explicit `ultra-research` invocation selects
73
+ `full` for greenfield or `adoption` for brownfield, records coverage dispositions, and
74
+ works toward baseline readiness. Empty templates are not an approved baseline.
75
+
76
+ With `git_mode: auto`, initialization preserves an existing repository and HEAD.
77
+ When Git is absent it initializes `main` and adds the symlink-safe `.ultra` rule to
78
+ `.gitignore`; an existing repository keeps its tracked ignore file unchanged. Init
79
+ does not create a commit, remote, tag, or push. The resulting `unborn` worktree state
80
+ is durable authority, not equivalent to a non-Git workspace. Full/adoption research
81
+ must obtain explicit approval for one local checkpoint commit before
82
+ `baseline.record`; until then `BASELINE_GIT_HEAD_REQUIRED` blocks convergence.
83
+
84
+ Init completion means only that local authority, Git state, scaffold, and
85
+ classification are usable. Baseline readiness is a separate research and convergence
86
+ outcome; failure there never reopens or blocks the completed init workflow.
71
87
 
72
88
  ## 3. Durable status machines
73
89
 
@@ -124,6 +140,40 @@ traceability, slice kind, public seam, exact verification command, acceptance
124
140
  checks, context references, resolved documentation impact, owner, and valid
125
141
  dependencies.
126
142
 
143
+ A semantic Change update marks all derived tasks stale. Clearing that marker requires
144
+ one complete execution-contract rebind through `task.update`; a marker-only clear is
145
+ rejected. MCP validates the resulting contract and appends
146
+ `task_contract_reconciled` with the current Change authority digest before a new plan
147
+ may converge.
148
+
149
+ A session process and a task have different status machines. Process exit zero closes
150
+ the execution transport but leaves the task `in_progress` until development,
151
+ integration, test, and review gates converge. Process failure marks the task `blocked`
152
+ and records failure/circuit evidence. `session.close` preserves the worktree by
153
+ default. Explicit removal succeeds only after Git proves it is clean and its commit is
154
+ integrated into the current checkout.
155
+
156
+ Dependency-wave automation advances only when every task in the current wave is
157
+ `completed` or `expanded` in the DB. A successful worker exit with open gates emits
158
+ `wave_paused` and `plan_paused`; it cannot start dependent work. Re-running the plan
159
+ resumes the first unfinished wave. Explicit auto-merge is additionally gated by task
160
+ completion, an exact completion commit, a ready dev workflow, a current task review,
161
+ clean committed work, and successful integration; otherwise the worktree remains
162
+ recoverable. Legacy tasks without change ownership retain their compatibility path,
163
+ but cannot satisfy the current change workflow contract.
164
+
165
+ Every session worktree resolves its ignored `.ultra` entry to the project authority
166
+ directory. Automated workers receive the central DB path and the isolated checkout
167
+ root separately; their supplied environment cannot override those bindings. If a
168
+ legacy `.ultra/` rule does not ignore the link itself, Ultra adds a repository-local
169
+ `info/exclude` entry without changing tracked files. A missing, tracked, still
170
+ unignored, or conflicting authority entry fails before the session row or worker is
171
+ created and the provisional worktree is removed. A process that already has
172
+ `UBP_SESSION_ID` must reuse that lease and worktree; nested spawn and worker-side close
173
+ are rejected, so the supervising parent alone settles the lease from the real process
174
+ exit. Authority drift detected after wave selection pauses the plan without recording
175
+ execution failure.
176
+
127
177
  ### Workflow run and step
128
178
 
129
179
  ```text
@@ -160,19 +210,19 @@ case. It never stores the conversation transcript.
160
210
 
161
211
  ## 4. Write and verification lifecycle
162
212
 
163
- | Stage | Authoritative writes | Completion verification | Next route |
213
+ | Stage | Authoritative writes | Completion verification | Available continuation |
164
214
  |---|---|---|---|
165
- | `init` | Baseline classification/scope, init run, research run, initialization event, projection job | DB/schema opens, scaffold/projection succeeds; baseline convergence later completes init | `research`, re-adoption, or `change` for an already-ready baseline |
166
- | `research` | Ordered step evidence, decision threads/checkpoints, typed semantic records with source digests, one immutable report per selected step, output paths and SHA-256 digests | Every load-bearing owner decision is confirmed; every report has the required structure; semantic kinds/attributes/source anchors are valid and current; full/adoption synthesis binds the current three specifications and distillate; all digests remain current | `baseline.record`, then approval/convergence; bounded change research returns to its change |
215
+ | `init` | Baseline classification/scope, Git bootstrap state, completed init run, initialization event, projection job | DB/schema opens, scaffold/projection and read-back succeed; existing Git is preserved or missing local Git is initialized | Explicitly chosen `research`, `status`, or `doctor`; an already-ready project may also enter `change` |
216
+ | `research` | Coverage dispositions, selected step evidence, material decision checkpoints, typed semantic records with source digests, immutable reports, output paths and SHA-256 digests | Every coverage area is dispositioned; only executed/verified/reused areas require work evidence; synthesis binds current specifications and distillate; all material decisions and digests are current | Baseline record/convergence for initial research; bounded change research returns to its owning change |
167
217
  | baseline convergence | Spec/source/runtime refs, verification results, known failures, unknowns, gaps, branch/HEAD/worktree, approval | Full/adoption research complete; required discovery/product/architecture refs current; revision/worktree exact; blocking gaps resolved or explicitly accepted where allowed | `change` for every initial or daily outcome |
168
- | `change` | Baseline-bound alignment checkpoint, complete Change Contract, profile/risk rationale, research disposition, intent/delta artifacts, linked change run, initial context snapshot | The linked alignment thread is confirmed; selected change research is current; current plan task set matches DB; task-bound context is ready; one next action is derived | selected `research`, then `plan`, or `dev` for an already approved current plan |
169
- | `plan` | Plan decision checkpoint, plan-step evidence, complete change-owned task rows, acceptance coverage matrix, change-bound `.ultra/execution-plan.json`, explicit plan approval | Blocking planning choices are confirmed; every Change acceptance id is owned by a task; task trace targets resolve; quick has one task; ownership/dependencies valid; no cycles; exported topology and digest exactly match the current change task set | `dev` for the first dependency-ready task |
170
- | `dev` | Task/session transitions, step evidence, immutable implementation context, completion/review references | Task completed; no live session; task contract unchanged; starting context and review artifacts valid; completion commits remain ancestors of current HEAD | Next task, then aggregate `test` |
171
- | `test` | Immutable checking context and `.ultra/reports/tests/<workflow-id>.json` | Report change/task set, full HEAD, worktree digest, context digest, commands, public seam, blockers, and all acceptance/regression/integration/static/build/performance/security/recovery dimensions agree; every omission has a not-applicable rationale | `review` when passing, otherwise resume `dev`/`test` |
172
- | `review` | Immutable review context, `task`/`change`/`plan` mode, worker selection provenance, two specialist axes, coordinated summary | Current diff/HEAD and context match; selected/skipped workers match recorded rationale; both axes complete; P0/P1 and axis verdicts deterministically derive final verdict | `deliver` only from approved `change` mode, otherwise resume implementation |
173
- | `deliver` | Convergence context, verified learning resolutions, schema-validated semantic reconciliation manifest, change archive, durable release-authorization decision, immutable delivery report | Tasks/test/change-review current; every baseline update has an anchored before/after semantic record; `change.converge` derives evidence from DB and accepts no Prompt verdicts; archive and baseline transaction agree; external actions have evidence | Report completion or start the next `change` |
174
- | `status` | None | Reads doctor, baseline, workflows, breadcrumb, tasks, sessions, Git, and DB-referenced reports | One exact current route |
175
- | `doctor` | None by default; explicit repair writes only mechanical recovery state | Re-runs integrity, schema, workflow-output, projection, session, incident, archive, and install checks | Exact repair, restore/rebaseline decision, or workflow route |
218
+ | `change` | Complete Change Contract, profile/risk rationale, research disposition, intent/delta artifacts, and a completed capture run; a decision thread only when material intent remains unresolved | Intent, acceptance, recovery, classification, and research disposition are complete and bound to the baseline | Host selects among bounded `research`, `plan`, current `dev`, `think`, or `status` using allowed transitions |
219
+ | `plan` | Selected planning evidence, complete change-owned task rows, acceptance coverage matrix, and change-bound `.ultra/execution-plan.json`; approval only for a material owner decision | Every Change acceptance id is owned by a task; trace targets, ownership, dependencies, topology, task contracts, and exported digest match current authority | Any dependency-ready task may enter `dev` |
220
+ | `dev` | Task/session transitions, real worktree, step evidence, immutable implementation context, completion/review references | Task completed; no live session; task contract unchanged; starting context and review artifacts valid; completion commits are integrated and remain ancestors of current HEAD | Next task, then aggregate `test` |
221
+ | `test` | Immutable checking context, an explicit risk-selected verification profile, and `.ultra/reports/tests/<workflow-id>.json` | Selected dimensions and acceptance pass; every excluded dimension has a rationale; report change/task set, HEAD, worktree, context, commands, blockers, and digests agree | `review` when passing, otherwise resume `dev`/`test` |
222
+ | `review` | Immutable review context, `task`/`change`/`plan` mode, risk-selected worker provenance, two mandatory specialist axes, and coordinated summary | Current diff/HEAD and context match; the complete worker roster is selected or skipped with rationale; completed workers match specialist artifacts; both axes complete; findings and axis verdicts derive the final verdict | `deliver` only from a passing `change` review, otherwise resume implementation or checking |
223
+ | `deliver` | Convergence context, verified learning resolutions, semantic reconciliation manifest, local change archive, and immutable delivery report | Tasks/test/change-review are current; baseline semantic updates are anchored; archive and baseline transaction agree; the report contains no release action | Report local completion or start the next `change`; publish/deploy/push are separate explicitly authorized operations |
224
+ | `status` | None | Reads doctor, baseline, workflows, breadcrumb, tasks, sessions, Git, and DB-referenced reports | Shows allowed transitions, any hard required transition, and a host-owned recommendation |
225
+ | `doctor` | None by default; explicit repair writes only mechanical recovery state | Re-runs integrity, schema, workflow-output, projection, session, incident, archive, and install checks | Mechanically required recovery when unique; otherwise a set of safe recovery capabilities |
176
226
 
177
227
  Every mutating MCP operation appends an event and enqueues projection work when
178
228
  the corresponding read-only view can change. Projection failure is recorded as
@@ -183,28 +233,30 @@ emitted by their owning DB mutation and never act as a substitute state transiti
183
233
  ## 5. Human-agent alignment lifecycle
184
234
 
185
235
  The host first reads `decision.list` and resumes matching authority. It starts a new
186
- thread only for a new decision cluster. For every current decision it must:
236
+ thread only for a new material decision cluster. Before asking, it must:
187
237
 
188
238
  1. inspect repository, runtime, tests, specifications, and primary-source evidence;
189
239
  2. resolve evidence-answerable facts without asking the owner;
190
- 3. call `decision.open` for the earliest unresolved owner choice with a recommendation,
191
- no more than three credible alternatives, evidence refs, and durable effects;
192
- 4. present that one choice and end the turn;
193
- 5. normalize the next owner response with `decision.resolve`, explicit reversible
240
+ 3. normalize an unambiguous decision already present in the current user request
241
+ instead of asking for redundant confirmation;
242
+ 4. ask only when the remaining choice changes intent, public behavior, compatibility,
243
+ security, material cost, external effects, or recovery. Use the host-native
244
+ question surface declared by `spec/interaction-contract.json`;
245
+ 5. present the earliest dependent choice with a recommendation, credible alternatives,
246
+ evidence refs, and durable effects. Up to three independent low-load facts may be
247
+ grouped when that reduces inconsistency;
248
+ 6. normalize the owner response with `decision.resolve`, explicit reversible
194
249
  delegation with `decision.delegate`, or a consequence-bearing deferral with
195
250
  `decision.defer`;
196
- 6. prepare one compact checkpoint, obtain one owner approval, update the affected
197
- artifact, and confirm the checkpoint with its current digest. Workflow- and
198
- change-bound threads must bind an artifact. If a shared specification will keep
199
- evolving, bind a stable per-thread decision projection rather than the mutable
200
- working draft.
251
+ 7. prepare a compact checkpoint only when a material decision cluster changes a
252
+ durable contract and interruption recovery needs an artifact-bound boundary.
201
253
 
202
254
  `ultra-think` owns this interaction protocol. `ultra-research`, `ultra-change`, and
203
255
  `ultra-plan` invoke it at their decision boundaries. `ultra-dev`, `ultra-test`,
204
256
  `ultra-review`, and `ultra-deliver` stop and route back to the same thread when new
205
257
  owner authority is required; they never answer on the owner's behalf. `ultra-status`
206
- shows only the current decision and exact route, while `ultra-doctor` diagnoses stale
207
- checkpoint artifacts and recovery state.
258
+ shows only the current decision and transition set, while `ultra-doctor` diagnoses
259
+ stale checkpoint artifacts and recovery state.
208
260
 
209
261
  When only a bound artifact changes, the same resolved thread is prepared and approved
210
262
  again against the current digest; this is checkpoint renewal, not a fabricated decision
@@ -213,7 +265,7 @@ opens one replacement.
213
265
 
214
266
  ## 6. Context and prompt follow-through
215
267
 
216
- `change.context` compiles an immutable Context Manifest v2 snapshot. It combines:
268
+ `change.context` compiles an immutable Context Manifest v3 snapshot. It combines:
217
269
 
218
270
  - the bound baseline/change/task identity;
219
271
  - a role and lifecycle gate;
@@ -221,13 +273,14 @@ opens one replacement.
221
273
  - local file hashes, current HEAD, branch, and worktree digest;
222
274
  - optional metadata-only external memory or graph references;
223
275
  - advisory file/token/context-share budgets;
224
- - readiness blockers and one DB-derived next action.
276
+ - the current Change and task authority digests;
277
+ - readiness blockers, `allowed_transitions`, and a `required_transition` only for a
278
+ unique hard-recovery path.
225
279
 
226
280
  Critical stage workflows bind a matching snapshot as a durable output:
227
281
 
228
282
  | Workflow | Required role | Required gate |
229
283
  |---|---|---|
230
- | `change` | `plan` or `implement` | `planning` or `implementation` |
231
284
  | `dev` | `implement` | `implementation` |
232
285
  | `test` | `check` | `verification` |
233
286
  | `review` | `review` | `review` |
@@ -236,13 +289,18 @@ Critical stage workflows bind a matching snapshot as a durable output:
236
289
  The snapshot path and digest are then carried into test, review, and delivery
237
290
  reports. This prevents a later Prompt from claiming evidence gathered under a
238
291
  different context. File and token budgets warn; they do not block legitimate
239
- work. Missing authority, required refs, task contracts, outputs, approval, or
292
+ work. Missing authority, required refs, task contracts, outputs, required owner
293
+ decisions, or
240
294
  current gate evidence do block.
241
295
 
242
296
  ## 7. Invalidation rules
243
297
 
244
298
  - Changing a task contract invalidates contexts and gates that depended on the
245
299
  former contract.
300
+ - Changing accepted Change intent, contract, classification, research disposition,
301
+ provider evidence, or documentation impact marks all derived tasks stale and
302
+ invalidates compiled contexts. Planning or task reconciliation must explicitly
303
+ clear staleness before execution.
246
304
  - Changing required source/spec content invalidates the recorded output or
247
305
  context digest.
248
306
  - Changing a research semantic source invalidates that workflow even when its immutable
@@ -266,21 +324,25 @@ current gate evidence do block.
266
324
  ### New project
267
325
 
268
326
  ```text
269
- ultra-init -> full research (17 steps with one-decision checkpoints) -> baseline approval
270
- -> initial change alignment -> plan checkpoint -> dev per task -> test -> review -> deliver
327
+ ultra-init -> Git/scaffold/authority verification -> init completed
328
+ -> explicit ultra-research -> disposition 17 coverage areas -> selected evidence work
329
+ -> local checkpoint when Git is unborn -> baseline approval
330
+ -> ultra-change -> optional bounded research/plan -> dev -> risk-selected test/review
331
+ -> local deliver/archive
271
332
  ```
272
333
 
273
334
  ### Existing project
274
335
 
275
336
  ```text
276
- ultra-init -> brownfield adoption research (17 steps with one-decision checkpoints)
277
- -> characterization and known-red evidence -> gap ledger -> owner approval
278
- -> first selected change alignment -> plan checkpoint -> dev -> test -> review -> deliver
337
+ ultra-init -> preserve Git/classify brownfield -> init completed
338
+ -> explicit adoption research -> disposition 17 coverage areas
339
+ -> selected characterization/known-red evidence -> gap ledger -> owner approval
340
+ -> first ultra-change -> optional bounded research/plan -> dev -> test/review -> deliver
279
341
  ```
280
342
 
281
343
  Adoption records the system that exists. It does not force the owner to recreate
282
344
  market, persona, or roadmap claims that cannot be supported; those remain
283
- `Unknown` or explicit gaps while every semantic step is still processed.
345
+ `Unknown`, `not_applicable`, accepted `deferred`, or explicit gaps with evidence.
284
346
 
285
347
  ### Earlier Ultra project
286
348
 
@@ -294,8 +356,9 @@ Migration preserves prior files and rows but never carries old approval forward.
294
356
  ### Daily maintenance
295
357
 
296
358
  ```text
297
- ultra-status -> ultra-change capture/alignment -> plan if task contracts are absent
298
- -> dev -> test -> review -> deliver -> reconciled baseline
359
+ ultra-status -> ultra-change intent capture
360
+ -> host chooses bounded research, plan, current task, think, or status
361
+ -> dev -> risk-selected test -> review -> deliver -> reconciled baseline
299
362
  ```
300
363
 
301
364
  Quick changes shorten the artifact burden only where the machine contract allows;
@@ -307,21 +370,22 @@ evidence rather than bypassing them.
307
370
 
308
371
  | Entry | Owns | Normal handoff |
309
372
  |---|---|---|
310
- | `ultra-init` | classification, scope, scaffold, baseline/run creation | `ultra-research`; an already-ready project routes to `ultra-change` |
311
- | `ultra-research` | evidence acquisition, seventeen-step semantic coverage, research decisions | baseline approval then `ultra-change`; bounded research returns to `ultra-plan` |
312
- | `ultra-think` | one current owner decision or read-only diagnosis | exact invoking workflow and step after checkpoint confirmation |
313
- | `ultra-change` | outcome capture, alignment, Change Contract, risk/research routing | selected `ultra-research`, then `ultra-plan`; approved existing plan may route to `ultra-dev` |
314
- | `ultra-plan` | plan decisions, task contracts, dependencies, approval | first ready task through `ultra-dev` |
373
+ | `ultra-init` | classification, scope, Git/scaffold bootstrap, and init verification | stops completed; exposes research/status/doctor and any already-valid change capability |
374
+ | `ultra-research` | coverage disposition, selected evidence acquisition, synthesis, and material research decisions | baseline convergence or return to the owning change |
375
+ | `ultra-think` | one material owner decision or read-only diagnosis | returns to the invoking capability after any needed checkpoint |
376
+ | `ultra-change` | outcome capture, Change Contract, risk/research routing | host selects research, plan, current dev work, think, or status |
377
+ | `ultra-plan` | task contracts, dependencies, acceptance coverage, optional material approval | any dependency-ready task through `ultra-dev` |
315
378
  | `ultra-dev` | one task/session vertical slice and focused review | next `ultra-dev` task or aggregate `ultra-test` |
316
- | `ultra-test` | change-level acceptance and regression gate | `ultra-review` on pass, `ultra-dev` on implementation failure |
317
- | `ultra-review` | independent specification and engineering verdicts | `ultra-deliver` on approval; otherwise `ultra-dev` or `ultra-test` |
318
- | `ultra-deliver` | convergence, reconciliation, archive, authorized release evidence | `ultra-status` or the next `ultra-change` |
319
- | `ultra-status` | read-only authoritative position and one route | whichever exact workflow owns the current step |
320
- | `ultra-doctor` | read-only diagnosis and authorized mechanical recovery | exact recovered workflow, `ultra-init`, or `ultra-think` |
321
-
322
- Every row routes to `ultra-think` when owner authority is missing and to
323
- `ultra-doctor` when state or installed-runtime authority is unhealthy. Neither route
324
- creates a parallel workflow or substitutes a Prompt summary for the DB state.
379
+ | `ultra-test` | risk-selected change acceptance and verification profile | `ultra-review` on pass, `ultra-dev`/`ultra-test` on failure |
380
+ | `ultra-review` | independent specification and engineering axes plus risk-selected workers | `ultra-deliver` on approval; otherwise implementation or checking |
381
+ | `ultra-deliver` | convergence, reconciliation, local archive, and delivery evidence | `ultra-status` or the next `ultra-change`; external release is separate |
382
+ | `ultra-status` | read-only authority and transition set | host recommendation among allowed transitions |
383
+ | `ultra-doctor` | read-only diagnosis and authorized mechanical recovery | required recovery only when unique; otherwise safe alternatives |
384
+
385
+ Every row permits `ultra-think` when material owner authority is missing and permits
386
+ `ultra-doctor` when state or installed-runtime authority is unhealthy. MCP makes one
387
+ of them required only when no safe alternative exists. Neither capability creates a
388
+ parallel workflow or substitutes a Prompt summary for DB state.
325
389
 
326
390
  ## 9. Recovery and diagnosis
327
391
 
@@ -35,13 +35,14 @@ def main() -> None:
35
35
  allow_stop()
36
36
  return
37
37
  if breadcrumb and breadcrumb.get("change_id"):
38
+ allowed = ", ".join(breadcrumb.get("allowed_transitions") or []) or "none"
39
+ required = breadcrumb.get("required_transition") or "none"
38
40
  print(
39
41
  "[Ultra stop advisory] Active Ultra change remains open: "
40
42
  f"change={breadcrumb['change_id']}, "
41
43
  f"task={breadcrumb.get('task_id') or 'none'}, "
42
44
  f"gate={breadcrumb.get('gate') or 'alignment'}, "
43
- f"route={breadcrumb.get('recommended_workflow') or 'ultra-status'}. "
44
- f"Next: {breadcrumb.get('next_action') or 'Inspect Ultra status.'} "
45
+ f"allowed_transitions={allowed}, required_transition={required}. "
45
46
  "Stop is allowed; resume or explicitly archive the change later.",
46
47
  file=sys.stderr,
47
48
  )
@@ -40,20 +40,33 @@ function gitHead(rootDir) {
40
40
  return result.status === 0 ? result.stdout.trim() : null;
41
41
  }
42
42
 
43
+ function gitRepositoryRoot(rootDir) {
44
+ const result = spawnSync('git', ['rev-parse', '--show-toplevel'], {
45
+ cwd: rootDir, encoding: 'utf8', stdio: ['ignore', 'pipe', 'pipe'],
46
+ });
47
+ return result.status === 0 ? result.stdout.trim() : null;
48
+ }
49
+
43
50
  function gitBranch(rootDir) {
44
- const result = spawnSync('git', ['branch', '--show-current'], {
51
+ let result = spawnSync('git', ['symbolic-ref', '--quiet', '--short', 'HEAD'], {
45
52
  cwd: rootDir, encoding: 'utf8', stdio: ['ignore', 'pipe', 'pipe'],
46
53
  });
54
+ if (result.status !== 0) {
55
+ result = spawnSync('git', ['branch', '--show-current'], {
56
+ cwd: rootDir, encoding: 'utf8', stdio: ['ignore', 'pipe', 'pipe'],
57
+ });
58
+ }
47
59
  return result.status === 0 ? (result.stdout.trim() || null) : null;
48
60
  }
49
61
 
50
62
  function gitWorktreeSnapshot(rootDir, scope = ['.']) {
51
- const head = gitHead(rootDir);
52
- if (!head) {
63
+ const repositoryRoot = gitRepositoryRoot(rootDir);
64
+ if (!repositoryRoot) {
53
65
  return {
54
66
  head: null, branch: null, state: 'unavailable', digest: null, files: [],
55
67
  };
56
68
  }
69
+ const head = gitHead(rootDir);
57
70
  const selectedScope = Array.isArray(scope) && scope.length > 0 ? scope : ['.'];
58
71
  const pathspecs = selectedScope.map((item) => (
59
72
  item === '.' ? '.' : `:(literal)${item}`
@@ -63,10 +76,12 @@ function gitWorktreeSnapshot(rootDir, scope = ['.']) {
63
76
  'git', ['status', '--porcelain=v1', '-z', '--untracked-files=all', ...args],
64
77
  { cwd: rootDir, encoding: 'buffer', stdio: ['ignore', 'pipe', 'pipe'], maxBuffer: 32 * 1024 * 1024 },
65
78
  );
66
- const diff = spawnSync(
67
- 'git', ['diff', '--binary', '--no-ext-diff', 'HEAD', ...args],
68
- { cwd: rootDir, encoding: 'buffer', stdio: ['ignore', 'pipe', 'pipe'], maxBuffer: 32 * 1024 * 1024 },
69
- );
79
+ const diff = head
80
+ ? spawnSync(
81
+ 'git', ['diff', '--binary', '--no-ext-diff', 'HEAD', ...args],
82
+ { cwd: rootDir, encoding: 'buffer', stdio: ['ignore', 'pipe', 'pipe'], maxBuffer: 32 * 1024 * 1024 },
83
+ )
84
+ : { status: 0, stdout: Buffer.alloc(0) };
70
85
  const untracked = spawnSync(
71
86
  'git', ['ls-files', '--others', '--exclude-standard', '-z', ...args],
72
87
  { cwd: rootDir, encoding: 'buffer', stdio: ['ignore', 'pipe', 'pipe'], maxBuffer: 32 * 1024 * 1024 },
@@ -79,7 +94,7 @@ function gitWorktreeSnapshot(rootDir, scope = ['.']) {
79
94
  const statusText = status.stdout.toString('utf8');
80
95
  const files = statusText.split('\0').filter(Boolean);
81
96
  const digest = crypto.createHash('sha256');
82
- digest.update(head).update('\0').update(gitBranch(rootDir) || '').update('\0');
97
+ digest.update(head || 'unborn').update('\0').update(gitBranch(rootDir) || '').update('\0');
83
98
  digest.update(status.stdout).update(diff.stdout);
84
99
  for (const relative of untracked.stdout.toString('utf8').split('\0').filter(Boolean).sort()) {
85
100
  digest.update(relative).update('\0');
@@ -93,7 +108,7 @@ function gitWorktreeSnapshot(rootDir, scope = ['.']) {
93
108
  return {
94
109
  head,
95
110
  branch: gitBranch(rootDir),
96
- state: files.length > 0 ? 'dirty' : 'clean',
111
+ state: head ? (files.length > 0 ? 'dirty' : 'clean') : 'unborn',
97
112
  digest: digest.digest('hex'),
98
113
  files,
99
114
  };
@@ -464,6 +479,55 @@ function startBaseline(db, input = {}, { rootDir = process.cwd(), emitEvent = tr
464
479
  });
465
480
  }
466
481
 
482
+ function refreshInProgressBaseline(db, input = {}, {
483
+ rootDir = process.cwd(), emitEvent = true,
484
+ } = {}) {
485
+ const current = readBaseline(db, input.id);
486
+ if (!current) {
487
+ throw new BaselineWorkflowError('BASELINE_NOT_FOUND', `baseline ${input.id || '(current)'} not found`);
488
+ }
489
+ if (!['draft', 'adopting', 'blocked'].includes(current.status)) return current;
490
+ const projectName = input.project_name === undefined
491
+ ? current.project_name
492
+ : nonEmpty(input.project_name, 'project_name');
493
+ const projectType = input.project_type === undefined ? current.project_type : input.project_type;
494
+ const stack = input.stack === undefined ? current.stack : input.stack;
495
+ const classification = input.classification === undefined
496
+ ? current.classification
497
+ : normalizeClassification(input.classification);
498
+ const snapshot = gitWorktreeSnapshot(rootDir, current.scope);
499
+ const repositoryRevision = snapshot.head
500
+ || (snapshot.state === 'unborn' ? null : current.repository_revision);
501
+ const ts = nowIso();
502
+ return ops.tx(db, () => {
503
+ db.prepare(
504
+ `UPDATE baselines SET project_name = ?, project_type = ?, stack = ?,
505
+ repository_revision = ?, repository_branch = ?, worktree_state = ?,
506
+ worktree_digest = ?, worktree_files_json = ?, classification_json = ?,
507
+ updated_at = ? WHERE id = ?`,
508
+ ).run(
509
+ projectName, projectType || null, stack || null,
510
+ repositoryRevision, snapshot.branch, snapshot.state, snapshot.digest,
511
+ JSON.stringify(snapshot.files), JSON.stringify(classification), ts, current.id,
512
+ );
513
+ if (emitEvent) {
514
+ ops.appendEventInTx(db, {
515
+ type: 'baseline_metadata_refreshed',
516
+ payload: {
517
+ baseline_id: current.id,
518
+ project_name: projectName,
519
+ project_type: projectType || null,
520
+ stack: stack || null,
521
+ repository_revision: repositoryRevision,
522
+ repository_branch: snapshot.branch,
523
+ worktree_state: snapshot.state,
524
+ },
525
+ });
526
+ }
527
+ return readBaseline(db, current.id);
528
+ });
529
+ }
530
+
467
531
  function recordBaseline(db, input = {}, { rootDir = process.cwd(), emitEvent = true } = {}) {
468
532
  const current = readBaseline(db, input.id);
469
533
  if (!current) throw new BaselineWorkflowError('BASELINE_NOT_FOUND', `baseline ${input.id} not found`);
@@ -484,6 +548,12 @@ function recordBaseline(db, input = {}, { rootDir = process.cwd(), emitEvent = t
484
548
  ? current.provider_refs
485
549
  : providerRefs.normalizeProviderRefs(input.provider_refs, BaselineWorkflowError);
486
550
  const snapshot = gitWorktreeSnapshot(rootDir, scope);
551
+ if (snapshot.state === 'unborn') {
552
+ throw new BaselineWorkflowError(
553
+ 'BASELINE_GIT_HEAD_REQUIRED',
554
+ 'Git is initialized but has no commit; create an owner-authorized local checkpoint commit before recording the baseline',
555
+ );
556
+ }
487
557
  if (snapshot.head && input.repository_revision && input.repository_revision !== snapshot.head) {
488
558
  throw new BaselineWorkflowError(
489
559
  'BASELINE_REVISION_MISMATCH', 'repository_revision does not match current Git HEAD',
@@ -667,6 +737,7 @@ function convergenceBlockers(db, baseline, input, rootDir) {
667
737
  if (!expected) blockers.add('BASELINE_REVISION_REQUIRED');
668
738
  else if (baseline.repository_revision !== expected) blockers.add('BASELINE_REVISION_MISMATCH');
669
739
  const snapshot = gitWorktreeSnapshot(rootDir, baseline.scope);
740
+ if (snapshot.state === 'unborn') blockers.add('BASELINE_GIT_HEAD_REQUIRED');
670
741
  if (snapshot.head && expected && snapshot.head !== expected) blockers.add('BASELINE_HEAD_STALE');
671
742
  if (baseline.repository_branch && snapshot.branch
672
743
  && baseline.repository_branch !== snapshot.branch) blockers.add('BASELINE_BRANCH_STALE');
@@ -725,7 +796,6 @@ function convergeBaseline(db, input = {}, { rootDir = process.cwd(), emitEvent =
725
796
  type: 'baseline_blocked', payload: { baseline_id: current.id, blockers },
726
797
  });
727
798
  }
728
- workflows.blockInitializationInTx(db, current.id, blockers);
729
799
  });
730
800
  return { ready: false, status: 'blocked', blockers, baseline: readBaseline(db, current.id) };
731
801
  }
@@ -745,12 +815,6 @@ function convergeBaseline(db, input = {}, { rootDir = process.cwd(), emitEvent =
745
815
  type: 'baseline_converged', payload: { baseline_id: current.id, revision: current.repository_revision },
746
816
  });
747
817
  }
748
- workflows.completeInitializationInTx(db, {
749
- ...current,
750
- approved_by: String(input.approved_by).trim(),
751
- research_run_id: research.id,
752
- converged_at: ts,
753
- });
754
818
  });
755
819
  return { ready: true, status: 'ready', blockers: [], baseline: readBaseline(db, current.id) };
756
820
  }
@@ -786,6 +850,9 @@ function inspectBaseline(db, { rootDir = process.cwd(), id } = {}) {
786
850
  const snapshot = gitWorktreeSnapshot(
787
851
  rootDir, Array.isArray(baseline.scope) && baseline.scope.length > 0 ? baseline.scope : ['.'],
788
852
  );
853
+ if (snapshot.state === 'unborn') {
854
+ blockers.push('BASELINE_GIT_HEAD_REQUIRED');
855
+ }
789
856
  if (snapshot.head && baseline.repository_revision && snapshot.head !== baseline.repository_revision) {
790
857
  blockers.push('BASELINE_HEAD_STALE');
791
858
  } else if (!snapshot.head && baseline.repository_revision?.startsWith('workspace:')) {
@@ -905,6 +972,7 @@ function appendGap(db, input = {}, options = {}) {
905
972
  module.exports = {
906
973
  BaselineWorkflowError,
907
974
  startBaseline,
975
+ refreshInProgressBaseline,
908
976
  recordBaseline,
909
977
  convergeBaseline,
910
978
  readBaseline,