ultra-builder-pro-cli 0.15.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 (71) hide show
  1. package/.ultra-template/specs/research-distillate.md +4 -3
  2. package/CHANGELOG.md +120 -1
  3. package/README.md +67 -30
  4. package/adapters/_shared/codex-assets.cjs +10 -5
  5. package/adapters/_shared/handbook.cjs +3 -2
  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/commands/ultra-think.md +2 -2
  19. package/docs/AGENT-CONTEXT.md +38 -18
  20. package/docs/ARCHITECTURE.md +91 -13
  21. package/docs/LEGACY-CLI-CROSSWALK.md +163 -0
  22. package/docs/PLAN.zh-CN.md +19 -12
  23. package/docs/ROADMAP.md +5 -3
  24. package/docs/RUNTIME-COMPAT-MATRIX.md +4 -4
  25. package/docs/STATE-DB-ACCESS-POLICY.md +8 -6
  26. package/docs/USER-HANDBOOK-CONTRACT.md +8 -2
  27. package/docs/WORKFLOW-LIFECYCLE.md +179 -39
  28. package/hooks/pre_stop_check.py +3 -2
  29. package/mcp-server/lib/baseline-workflow.cjs +84 -16
  30. package/mcp-server/lib/change-workflow.cjs +107 -39
  31. package/mcp-server/lib/context-spine.cjs +215 -87
  32. package/mcp-server/lib/decision-dialogue.cjs +713 -0
  33. package/mcp-server/lib/doctor.cjs +9 -0
  34. package/mcp-server/lib/git-bootstrap.cjs +240 -0
  35. package/mcp-server/lib/init-project.cjs +178 -41
  36. package/mcp-server/lib/project-breadcrumb.cjs +23 -14
  37. package/mcp-server/lib/state-db.cjs +279 -9
  38. package/mcp-server/lib/state-ops.cjs +64 -1
  39. package/mcp-server/lib/workflow-state.cjs +313 -205
  40. package/mcp-server/server.cjs +112 -34
  41. package/orchestrator/auto-merge.cjs +19 -0
  42. package/orchestrator/daemon.cjs +104 -0
  43. package/orchestrator/parallel-orchestrator.cjs +371 -49
  44. package/orchestrator/session-runner.cjs +354 -25
  45. package/package.json +2 -1
  46. package/skills/ultra-change/SKILL.md +69 -65
  47. package/skills/ultra-deliver/SKILL.md +37 -58
  48. package/skills/ultra-dev/SKILL.md +55 -49
  49. package/skills/ultra-doctor/SKILL.md +44 -49
  50. package/skills/ultra-init/SKILL.md +78 -100
  51. package/skills/ultra-plan/SKILL.md +78 -79
  52. package/skills/ultra-research/SKILL.md +99 -98
  53. package/skills/ultra-review/SKILL.md +38 -47
  54. package/skills/ultra-review/references/review-modes.md +5 -3
  55. package/skills/ultra-review/references/unified-schema.md +26 -6
  56. package/skills/ultra-review/scripts/review_wait.py +12 -0
  57. package/skills/ultra-status/SKILL.md +34 -40
  58. package/skills/ultra-test/SKILL.md +61 -48
  59. package/skills/ultra-think/SKILL.md +47 -47
  60. package/skills/ultra-think/references/decision-dialogue.md +106 -0
  61. package/spec/cli-protocol.md +46 -2
  62. package/spec/mcp-tools.yaml +444 -29
  63. package/spec/schemas/delivery-report.v1.schema.json +1 -46
  64. package/spec/schemas/mcp-tools.schema.json +1 -1
  65. package/spec/schemas/state-db.sql +66 -2
  66. package/spec/schemas/test-report.v1.schema.json +45 -14
  67. package/ultra-tools/cli.cjs +1 -1
  68. package/ultra-tools/commands/session.cjs +10 -3
  69. package/ultra-tools/commands/status.cjs +34 -14
  70. package/ultra-tools/commands/system.cjs +2 -2
  71. package/ultra-tools/commands/task.cjs +3 -0
@@ -4,6 +4,7 @@
4
4
  * ubp-orchestrator — Phase 5.4 daemon CLI.
5
5
  *
6
6
  * Subcommands:
7
+ * execute-plan resume the current plan through the first unfinished dependency wave.
7
8
  * run foreground daemon (debug / test).
8
9
  * start detached background daemon, writes .ultra/orchestrator.pid.
9
10
  * stop reads pidfile, SIGTERM the process, deletes pidfile.
@@ -12,9 +13,8 @@
12
13
  * Opt-in gate: `start` and `run` require settings.json
13
14
  * `orchestrator.auto_dispatch: true` — default off per PLAN Phase 5.4 AC.
14
15
  *
15
- * The daemon never launches real runtime children in this phase — session
16
- * rows + git worktrees are created, external adapters (Phase 4) attach to
17
- * the worktree out-of-band. command/args can be passed via env for testing.
16
+ * Dispatch requires both explicit opt-in and an explicit executable command.
17
+ * A daemon may never reserve a session/worktree without a real worker process.
18
18
  */
19
19
 
20
20
  'use strict';
@@ -56,6 +56,124 @@ function parseRuntimes() {
56
56
  return runtimes;
57
57
  }
58
58
 
59
+ function commandConfigError(code, message) {
60
+ const error = new Error(message);
61
+ error.code = code;
62
+ return error;
63
+ }
64
+
65
+ function resolveDispatchCommand(settings, env = process.env) {
66
+ const configured = settings?.orchestrator || {};
67
+ const fromEnvironment = typeof env.UBP_ORCH_COMMAND === 'string'
68
+ && env.UBP_ORCH_COMMAND.trim() !== '';
69
+ const command = fromEnvironment
70
+ ? env.UBP_ORCH_COMMAND.trim()
71
+ : (typeof configured.command === 'string' ? configured.command.trim() : '');
72
+ if (!command) {
73
+ throw commandConfigError(
74
+ 'ORCHESTRATOR_COMMAND_REQUIRED',
75
+ 'orchestrator dispatch requires orchestrator.command or UBP_ORCH_COMMAND',
76
+ );
77
+ }
78
+ if (/\s/.test(command) && !fs.existsSync(command)) {
79
+ throw commandConfigError(
80
+ 'ORCHESTRATOR_COMMAND_INVALID',
81
+ 'orchestrator.command must contain only the executable; put arguments in command_args',
82
+ );
83
+ }
84
+
85
+ let commandArgs;
86
+ if (fromEnvironment && env.UBP_ORCH_ARGS_JSON !== undefined) {
87
+ try {
88
+ commandArgs = JSON.parse(env.UBP_ORCH_ARGS_JSON);
89
+ } catch (error) {
90
+ throw commandConfigError(
91
+ 'ORCHESTRATOR_COMMAND_INVALID',
92
+ `UBP_ORCH_ARGS_JSON must be a JSON array: ${error.message}`,
93
+ );
94
+ }
95
+ } else {
96
+ commandArgs = configured.command_args === undefined ? [] : configured.command_args;
97
+ }
98
+ if (!Array.isArray(commandArgs) || commandArgs.some((arg) => typeof arg !== 'string')) {
99
+ throw commandConfigError(
100
+ 'ORCHESTRATOR_COMMAND_INVALID',
101
+ 'orchestrator command arguments must be an array of strings',
102
+ );
103
+ }
104
+ return {
105
+ command,
106
+ commandArgs: commandArgs.slice(),
107
+ source: fromEnvironment ? 'environment' : 'settings',
108
+ };
109
+ }
110
+
111
+ function parseExecutePlanArgs(argv = []) {
112
+ const options = {
113
+ planPath: null,
114
+ autoMerge: false,
115
+ mergeBaseBranch: 'main',
116
+ };
117
+ for (let index = 0; index < argv.length; index += 1) {
118
+ const arg = argv[index];
119
+ if (arg === '--auto-merge') {
120
+ options.autoMerge = true;
121
+ continue;
122
+ }
123
+ if (arg === '--plan' || arg === '--base-branch') {
124
+ const value = argv[index + 1];
125
+ if (!value || value.startsWith('--')) {
126
+ throw commandConfigError(
127
+ 'ORCHESTRATOR_ARGUMENT_INVALID',
128
+ `${arg} requires a value`,
129
+ );
130
+ }
131
+ if (arg === '--plan') options.planPath = value;
132
+ else options.mergeBaseBranch = value;
133
+ index += 1;
134
+ continue;
135
+ }
136
+ throw commandConfigError(
137
+ 'ORCHESTRATOR_ARGUMENT_INVALID',
138
+ `unknown execute-plan option: ${arg}`,
139
+ );
140
+ }
141
+ return options;
142
+ }
143
+
144
+ async function cmdExecutePlan(argv = []) {
145
+ const settings = readSettings();
146
+ const dispatch = resolveDispatchCommand(settings);
147
+ const options = parseExecutePlanArgs(argv);
148
+ const { initStateDb, closeStateDb } = require('../mcp-server/lib/state-db.cjs');
149
+ const parallelOrchestrator = require('../orchestrator/parallel-orchestrator.cjs');
150
+ const { db } = initStateDb(path.join(REPO_ROOT, '.ultra', 'state.db'));
151
+ try {
152
+ const result = await parallelOrchestrator.runPlan({
153
+ db,
154
+ repoRoot: REPO_ROOT,
155
+ planPath: options.planPath ? path.resolve(REPO_ROOT, options.planPath) : undefined,
156
+ runtimes: parseRuntimes(),
157
+ command: dispatch.command,
158
+ commandArgs: dispatch.commandArgs,
159
+ autoMerge: options.autoMerge,
160
+ mergeBaseBranch: options.mergeBaseBranch,
161
+ onError: (error) => process.stderr.write(`orchestrator error: ${error.message}\n`),
162
+ });
163
+ process.stdout.write(`${JSON.stringify({
164
+ ok: true,
165
+ data: {
166
+ ...result,
167
+ auto_merge: options.autoMerge,
168
+ merge_base_branch: options.mergeBaseBranch,
169
+ },
170
+ })}\n`);
171
+ return result;
172
+ } finally {
173
+ closeStateDb(db);
174
+ }
175
+ }
176
+
59
177
  function cmdRun(opts = {}) {
60
178
  const settings = readSettings();
61
179
  if (!opts.skipOptIn && !optInAllowed(settings)) {
@@ -68,11 +186,14 @@ function cmdRun(opts = {}) {
68
186
  const { initStateDb } = require('../mcp-server/lib/state-db.cjs');
69
187
  const { runDaemon } = require('../orchestrator/daemon.cjs');
70
188
  const runtimes = parseRuntimes();
189
+ const dispatch = resolveDispatchCommand(settings);
71
190
  const { db } = initStateDb(path.join(REPO_ROOT, '.ultra', 'state.db'));
72
191
  const handle = runDaemon({
73
192
  db,
74
193
  repoRoot: REPO_ROOT,
75
194
  runtimes,
195
+ command: dispatch.command,
196
+ commandArgs: dispatch.commandArgs,
76
197
  pollMs: Number(process.env.UBP_ORCH_POLL_MS || 1000),
77
198
  onError: (err) => process.stderr.write(`orchestrator error: ${err.message}\n`),
78
199
  });
@@ -85,7 +206,10 @@ function cmdRun(opts = {}) {
85
206
  };
86
207
  process.on('SIGTERM', () => shutdown('SIGTERM'));
87
208
  process.on('SIGINT', () => shutdown('SIGINT'));
88
- process.stderr.write(`orchestrator running (pollMs=${Number(process.env.UBP_ORCH_POLL_MS || 1000)}, runtimes=${runtimes.join(',')})\n`);
209
+ process.stderr.write(
210
+ `orchestrator running (pollMs=${Number(process.env.UBP_ORCH_POLL_MS || 1000)}, ` +
211
+ `runtimes=${runtimes.join(',')}, worker=${dispatch.command}, source=${dispatch.source})\n`,
212
+ );
89
213
  // Keep process alive while the setInterval is unref'd.
90
214
  setInterval(() => {}, 60000);
91
215
  }
@@ -96,6 +220,7 @@ function cmdStart() {
96
220
  process.stderr.write('orchestrator.auto_dispatch is not enabled; refusing to start.\n');
97
221
  process.exit(2);
98
222
  }
223
+ resolveDispatchCommand(settings);
99
224
  if (fs.existsSync(PIDFILE)) {
100
225
  const existing = Number(fs.readFileSync(PIDFILE, 'utf8'));
101
226
  try { process.kill(existing, 0); }
@@ -170,8 +295,9 @@ function cmdStatus() {
170
295
 
171
296
  function usage() {
172
297
  process.stderr.write(
173
- 'usage: ubp-orchestrator <run|start|stop|status>\n' +
298
+ 'usage: ubp-orchestrator <execute-plan|run|start|stop|status>\n' +
174
299
  '\n' +
300
+ ' execute-plan resume the first unfinished dependency wave [--plan <path>] [--auto-merge] [--base-branch <name>]\n' +
175
301
  ' run foreground daemon (requires opt-in)\n' +
176
302
  ' start detached background daemon (requires opt-in)\n' +
177
303
  ' stop terminate running daemon\n' +
@@ -179,18 +305,48 @@ function usage() {
179
305
  );
180
306
  }
181
307
 
182
- const argv = process.argv.slice(2);
183
- const subcommand = argv[0];
184
- switch (subcommand) {
185
- case 'run': cmdRun(); break;
186
- case 'start': cmdStart(); break;
187
- case 'stop': cmdStop(); break;
188
- case 'status': cmdStatus(); break;
189
- case '-h':
190
- case '--help':
191
- case 'help':
192
- usage(); process.exit(0);
193
- break;
194
- default:
195
- usage(); process.exit(1);
308
+ async function main(argv = process.argv.slice(2)) {
309
+ const subcommand = argv[0];
310
+ try {
311
+ switch (subcommand) {
312
+ case 'execute-plan': await cmdExecutePlan(argv.slice(1)); break;
313
+ case 'run': cmdRun(); break;
314
+ case 'start': cmdStart(); break;
315
+ case 'stop': cmdStop(); break;
316
+ case 'status': cmdStatus(); break;
317
+ case '-h':
318
+ case '--help':
319
+ case 'help':
320
+ usage(); process.exit(0);
321
+ break;
322
+ default:
323
+ usage(); process.exit(1);
324
+ }
325
+ } catch (error) {
326
+ process.stderr.write(
327
+ `orchestrator configuration error${error.code ? ` [${error.code}]` : ''}: ${error.message}\n`,
328
+ );
329
+ process.exit(2);
330
+ }
331
+ }
332
+
333
+ if (require.main === module) {
334
+ main().catch((error) => {
335
+ process.stderr.write(`orchestrator fatal error: ${error.message}\n`);
336
+ process.exit(2);
337
+ });
196
338
  }
339
+
340
+ module.exports = {
341
+ readSettings,
342
+ optInAllowed,
343
+ parseRuntimes,
344
+ parseExecutePlanArgs,
345
+ resolveDispatchCommand,
346
+ cmdExecutePlan,
347
+ cmdRun,
348
+ cmdStart,
349
+ cmdStop,
350
+ cmdStatus,
351
+ main,
352
+ };
@@ -1,5 +1,5 @@
1
1
  ---
2
- description: Open or resume a bounded continuous change with linked authoritative tasks and context
2
+ description: Capture or revise one bounded Change Contract without starting downstream workflows
3
3
  argument-hint: "[change-id-or-title] [quick|standard|major|incident]"
4
4
  workflow-ref: "@skills/ultra-change/SKILL.md"
5
5
  ---
@@ -1,10 +1,10 @@
1
1
  ---
2
- description: Converge current evidence and specification learning into an archived or released baseline
3
- argument-hint: "[version-type]"
2
+ description: Converge current evidence and archive local Ultra authority without external release effects
3
+ argument-hint: "[change-id]"
4
4
  workflow-ref: "@skills/ultra-deliver/SKILL.md"
5
5
  ---
6
6
 
7
7
  # Converge and deliver
8
8
 
9
- Read and follow `@skills/ultra-deliver/SKILL.md`, using `$ARGUMENTS` only for an explicitly requested version policy.
9
+ Read and follow `@skills/ultra-deliver/SKILL.md`, using `$ARGUMENTS` only to select the change.
10
10
  Treat the referenced skill as the only workflow definition.
@@ -1,5 +1,5 @@
1
1
  ---
2
- description: Initialize a new project or adopt an existing repository into authoritative Ultra baseline state
2
+ description: Create or recover Ultra project authority without implicitly starting research
3
3
  argument-hint: "[name] [type] [stack] [auto|greenfield|brownfield] [--scope <path>]"
4
4
  workflow-ref: "@skills/ultra-init/SKILL.md"
5
5
  ---
@@ -1,5 +1,5 @@
1
1
  ---
2
- description: Convert validated requirements into dependency-valid Ultra tasks with bounded context and exact verification
2
+ description: Persist dependency-valid vertical task contracts from an accepted Change Contract
3
3
  argument-hint: "[scope]"
4
4
  workflow-ref: "@skills/ultra-plan/SKILL.md"
5
5
  ---
@@ -1,10 +1,10 @@
1
1
  ---
2
- description: Research unresolved product or architecture decisions and update the authoritative baseline specifications
2
+ description: Build evidence with model-selected semantic coverage and adaptive user alignment
3
3
  argument-hint: "[scope-or-question]"
4
4
  workflow-ref: "@skills/ultra-research/SKILL.md"
5
5
  ---
6
6
 
7
- # Research a baseline
7
+ # Research one bounded question or baseline
8
8
 
9
9
  Read and follow `@skills/ultra-research/SKILL.md`, using `$ARGUMENTS` to bound the research scope.
10
10
  Treat the referenced skill as the only workflow definition.
@@ -0,0 +1,10 @@
1
+ ---
2
+ description: Review one plan, task diff, or aggregate change on independent specification and engineering axes
3
+ argument-hint: "[plan|task|change] [id]"
4
+ workflow-ref: "@skills/ultra-review/SKILL.md"
5
+ ---
6
+
7
+ # Review one bounded Ultra scope
8
+
9
+ Read and follow `@skills/ultra-review/SKILL.md`, using `$ARGUMENTS` to select the review mode and authority.
10
+ Treat the referenced skill as the only workflow definition.
@@ -1,5 +1,5 @@
1
1
  ---
2
- description: Report authoritative Ultra health, readiness, evidence freshness, and one next action
2
+ description: Report authoritative Ultra health, evidence freshness, and valid capability transitions
3
3
  argument-hint: "[task-or-change-id]"
4
4
  workflow-ref: "@skills/ultra-status/SKILL.md"
5
5
  ---
@@ -1,5 +1,5 @@
1
1
  ---
2
- description: Run the independent pre-delivery verification gate and record current acceptance evidence
2
+ description: Run independent, risk-selected verification and record current acceptance evidence
3
3
  argument-hint: "[scope]"
4
4
  workflow-ref: "@skills/ultra-test/SKILL.md"
5
5
  ---
@@ -1,10 +1,10 @@
1
1
  ---
2
- description: Analyze a consequential question with evidence, uncertainty, and proportionate stress testing
2
+ description: Resolve a consequential question through evidence or one-decision-at-a-time alignment
3
3
  argument-hint: "[question]"
4
4
  workflow-ref: "@skills/ultra-think/SKILL.md"
5
5
  ---
6
6
 
7
- # Analyze a consequential question
7
+ # Align on a consequential question
8
8
 
9
9
  Read and follow `@skills/ultra-think/SKILL.md`, treating `$ARGUMENTS` as the question to resolve.
10
10
  Treat the referenced skill as the only workflow definition.
@@ -37,15 +37,15 @@ native command or skill -> MCP workflow-state operation -> .ultra/state.db
37
37
  | MCP | `mcp-server/server.cjs` | Authoritative typed operations over `.ultra/state.db` |
38
38
  | CLI | `ultra-tools`, `ubp-orchestrator` | Selected initialization, backup-first recovery, automation, and diagnostics; not a change-state mirror |
39
39
 
40
- `.ultra/state.db` is the only durable Ultra authority for baselines, changes, tasks,
40
+ `.ultra/state.db` is the only durable Ultra authority for baselines, changes, decisions, tasks,
41
41
  workflow runs/steps, sessions, events, incidents, projection jobs/cursors, telemetry, review evidence,
42
42
  and circuit-breaker state. `tasks.json`, context Markdown, execution plans, and
43
43
  reports are projections or workflow artifacts.
44
44
 
45
45
  ## 3. Live MCP and declared contracts
46
46
 
47
- `spec/mcp-tools.yaml` declares and the bundled server registers 41 tools across
48
- seven families:
47
+ `spec/mcp-tools.yaml` declares and the bundled server registers 50 tools across
48
+ eight families:
49
49
 
50
50
  | Family | Live tools |
51
51
  |---|---|
@@ -53,13 +53,15 @@ seven families:
53
53
  | `task.*` | create, update, list, get, switch_tag, delete, init_project, expand, parse_prd, dependency_topo, append_event, subscribe_events |
54
54
  | `session.*` | spawn, close, get, list, admission_check, heartbeat, subscribe_events |
55
55
  | `change.*` | create, update, get, list, context, breadcrumb, learning_propose, learning_resolve, converge, archive |
56
+ | `decision.*` | thread_start, get, list, open, resolve, delegate, defer, supersede, checkpoint |
56
57
  | `workflow.*` | start, get, list, step, complete |
57
58
  | `system.*` | doctor |
58
59
  | `plan.*` | export, get |
59
60
 
60
- Review, repository impact discovery, skill loading, and user interaction remain
61
- host-native capabilities rather than fake MCP contracts. The generated Codex
62
- capability map documents those replacements.
61
+ Review, repository impact discovery, skill loading, and decision presentation remain
62
+ host-native capabilities rather than fake MCP contracts. MCP stores only normalized
63
+ decision authority and checkpoints; it never generates questions or retains prompts
64
+ and transcripts. The generated Codex capability map documents host replacements.
63
65
 
64
66
  The complete write, transition, invalidation, and recovery contract lives in
65
67
  [`WORKFLOW-LIFECYCLE.md`](./WORKFLOW-LIFECYCLE.md).
@@ -67,19 +69,37 @@ The complete write, transition, invalidation, and recovery contract lives in
67
69
  Any new MCP contract starts in `spec/mcp-tools.yaml` with valid and invalid
68
70
  fixtures. Do not add an ad-hoc server handler first.
69
71
 
70
- ## 4. Context Spine contract
72
+ ## 4. Human-agent alignment contract
71
73
 
72
- Context Manifest v2 is an immutable DB-backed role handoff, not a static codebase summary.
74
+ `skills/ultra-think/references/decision-dialogue.md` is the single reusable prompt
75
+ contract for load-bearing owner choices. Research, change, and plan read it at their
76
+ decision boundaries. They inspect evidence first, expose only the earliest unresolved
77
+ choice, include a recommendation and durable effects, and stop the turn. Dev, test,
78
+ review, and deliver route back to the same thread instead of deciding for the owner.
79
+
80
+ One partial unique index permits only one open item per thread. `decision.resolve`,
81
+ `decision.delegate`, and `decision.defer` preserve the source of authority;
82
+ `decision.supersede` preserves history when evidence or intent changes. Prepare and
83
+ confirm checkpointing bind a material accepted cluster to current artifact digests
84
+ when interruption recovery needs that boundary. Status and breadcrumb return only the
85
+ current question plus allowed and mechanically required transitions, so recovery does
86
+ not require replaying conversation history.
87
+
88
+ ## 5. Context Spine contract
89
+
90
+ Context Manifest v3 is an immutable DB-backed role handoff, not a static codebase summary.
73
91
  `change.context` compiles required references, digests, readiness, context budget,
74
- public seam, exact verification command, and one next action for `plan`,
75
- `implement`, `check`, or `review`. The default 12-file, about 12k-token, and 40%
92
+ public seam, exact verification command, Change/task authority digests, and valid
93
+ transitions for `plan`, `implement`, `check`, or `review`. The default 12-file,
94
+ about 12k-token, and 40%
76
95
  fresh-context values are attention guidance. Overflow produces warnings; it does
77
96
  not block work or require raising a threshold. Prefer direct reads, bounded
78
97
  excerpts, or a smaller slice when they preserve correctness, and retain all
79
98
  necessary context when they do not.
80
99
 
81
100
  `change.breadcrumb` is the only compact router. Hooks may inject its change/task,
82
- role, gate, readiness, blockers, and one next action. They must not inject intent
101
+ role, gate, readiness, blockers, `allowed_transitions`, and `required_transition`.
102
+ They must not inject intent
83
103
  bodies, transcripts, external memory, or graph payloads. Missing references,
84
104
  digest drift, HEAD drift, or a missing execution seam blocks readiness. Context
85
105
  size and baseline drift are advisory for a change that is already active. New ordinary
@@ -92,7 +112,7 @@ through approve/reject/apply transitions in `change.learning_resolve`. Unresolve
92
112
  learning blocks convergence. Review contributes two independent axes,
93
113
  `spec_fidelity` and `engineering_standards`; neither can replace the other.
94
114
 
95
- ## 5. Native host presentation
115
+ ## 6. Native host presentation
96
116
 
97
117
  | Host | Plugin form | Workflow entry | Hook form | Collaboration companions |
98
118
  |---|---|---|---|---|
@@ -105,7 +125,7 @@ The current host remains primary. Collaboration skills call another runtime
105
125
  only when explicitly requested, use it as a read-only advisor, and return the
106
126
  evidence to the primary host for final verification.
107
127
 
108
- ## 6. Hook boundary
128
+ ## 7. Hook boundary
109
129
 
110
130
  The canonical Python hook bundle contains seven executable workflow hooks plus
111
131
  the shared read-only `context_spine.py` breadcrumb helper:
@@ -133,7 +153,7 @@ reject an edit, stop, or tool call.
133
153
  Generic command blocking, post-edit governance, and unrelated user hooks are not
134
154
  copied into Ultra Builder Pro.
135
155
 
136
- ## 7. Memory boundary
156
+ ## 8. Memory boundary
137
157
 
138
158
  Ultra Builder Pro has no memory MCP family, recall skill, prompt capture,
139
159
  transcript capture, observation journal, or session-summary hook. Persistent
@@ -151,7 +171,7 @@ ultra-tools legacy-memory prune --confirm DELETE_ULTRA_LEGACY_MEMORY
151
171
 
152
172
  Archive before prune; the confirmation token is intentionally required.
153
173
 
154
- ## 8. Project state layout
174
+ ## 9. Project state layout
155
175
 
156
176
  ```text
157
177
  .ultra/
@@ -159,7 +179,7 @@ Archive before prune; the confirmation token is intentionally required.
159
179
  ├── runtime/
160
180
  │ └── checkpoint.json # advisory breadcrumb recovery projection
161
181
  ├── changes/
162
- │ ├── active/<id>/ # intent, delta, plan, context v2, learning, verification
182
+ │ ├── active/<id>/ # intent, delta, plan, context v3, learning, verification
163
183
  │ └── archive/ # converged packets after baseline reconciliation
164
184
  ├── tasks/ # projections and task contexts
165
185
  ├── specs/ # research/product/architecture artifacts
@@ -171,7 +191,7 @@ Archive before prune; the confirmation token is intentionally required.
171
191
  └── delivery/<workflow-id>.json
172
192
  ```
173
193
 
174
- ## 9. User handbook integration
194
+ ## 10. User handbook integration
175
195
 
176
196
  General engineering doctrine remains user-owned in `CLAUDE.md` or `AGENTS.md`.
177
197
  Ultra Builder Pro contributes one managed section only. Preview or apply it with:
@@ -186,7 +206,7 @@ timestamped backup, replaces only the marked block, and can migrate the old
186
206
  Codex `## Ultra Builder Pro Runtime Contract` section without touching the next
187
207
  user section. Plugin adapters themselves do not silently overwrite handbooks.
188
208
 
189
- ## 10. Verification
209
+ ## 11. Verification
190
210
 
191
211
  Run `npm run test:all`, `python3 -m pytest hooks/tests -q`, and `npm audit`.
192
212
  Adapter tests assert the allowlisted assets, native manifests, hook boundary,