ultra-builder-pro-cli 0.20.0 → 0.22.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 (109) hide show
  1. package/.ultra-template/docs/research/README.md +26 -5
  2. package/.ultra-template/specs/discovery.md +1 -1
  3. package/.ultra-template/tasks/tasks.json +10 -3
  4. package/.ultra-template/templates/task-context.md +19 -0
  5. package/CHANGELOG.md +106 -0
  6. package/README.md +215 -41
  7. package/adapters/_shared/codex-assets.cjs +69 -11
  8. package/adapters/_shared/interaction-contract.cjs +36 -3
  9. package/adapters/_shared/runtime-assets.cjs +41 -1
  10. package/adapters/claude.js +7 -5
  11. package/adapters/codex.js +1 -1
  12. package/adapters/kimi.js +2 -8
  13. package/adapters/opencode.js +43 -30
  14. package/bin/orchestrator.js +64 -24
  15. package/docs/AGENT-CONTEXT.md +89 -49
  16. package/docs/ARCHITECTURE.md +112 -45
  17. package/docs/ARTIFACT-AUTHORITY.md +274 -0
  18. package/docs/COMMIT-HASH-BACKFILL.md +33 -90
  19. package/docs/DECISIONS.md +14 -6
  20. package/docs/LEGACY-CLI-CROSSWALK.md +16 -6
  21. package/docs/PLUGIN-ISOLATION-CONTRACT.md +6 -4
  22. package/docs/ROADMAP.md +20 -6
  23. package/docs/RUNTIME-COMPAT-MATRIX.md +29 -16
  24. package/docs/STATE-DB-ACCESS-POLICY.md +43 -13
  25. package/docs/WORKFLOW-LIFECYCLE.md +105 -50
  26. package/hooks/README.md +10 -8
  27. package/hooks/active_task_context.py +105 -18
  28. package/hooks/context_spine.py +16 -4
  29. package/hooks/health_check.py +5 -4
  30. package/hooks/pre_stop_check.py +5 -2
  31. package/hooks/runtime_paths.py +396 -0
  32. package/hooks/subagent_tracker.py +5 -2
  33. package/hooks/workflow_checkpoint.py +16 -3
  34. package/hooks/workflow_context.py +11 -3
  35. package/hooks/workflow_resume.py +7 -4
  36. package/mcp-server/breadcrumb.cjs +20 -2
  37. package/mcp-server/lib/archive-journal.cjs +1026 -111
  38. package/mcp-server/lib/archive-mutation-worker.py +365 -0
  39. package/mcp-server/lib/artifact-registry.cjs +1127 -0
  40. package/mcp-server/lib/baseline-workflow.cjs +69 -28
  41. package/mcp-server/lib/change-packet.cjs +818 -0
  42. package/mcp-server/lib/change-workflow.cjs +932 -176
  43. package/mcp-server/lib/context-paths.cjs +142 -0
  44. package/mcp-server/lib/context-spine.cjs +511 -45
  45. package/mcp-server/lib/decision-dialogue.cjs +345 -3
  46. package/mcp-server/lib/delivery-transaction.cjs +471 -0
  47. package/mcp-server/lib/doctor-backup-worker.cjs +328 -0
  48. package/mcp-server/lib/doctor.cjs +401 -11
  49. package/mcp-server/lib/git-bootstrap.cjs +458 -47
  50. package/mcp-server/lib/init-project.cjs +240 -95
  51. package/mcp-server/lib/plan-publication-worker.cjs +830 -0
  52. package/mcp-server/lib/plan-store.cjs +700 -5
  53. package/mcp-server/lib/project-breadcrumb.cjs +23 -4
  54. package/mcp-server/lib/projector.cjs +211 -42
  55. package/mcp-server/lib/runtime-paths.cjs +1687 -0
  56. package/mcp-server/lib/safe-project-file.cjs +385 -0
  57. package/mcp-server/lib/spec-learning.cjs +28 -12
  58. package/mcp-server/lib/state-authority.cjs +19 -3
  59. package/mcp-server/lib/state-db.cjs +263 -9
  60. package/mcp-server/lib/state-ops.cjs +254 -50
  61. package/mcp-server/lib/task-ledger.cjs +1342 -0
  62. package/mcp-server/lib/telemetry.cjs +12 -3
  63. package/mcp-server/lib/workflow-state.cjs +610 -58
  64. package/mcp-server/server.cjs +423 -42
  65. package/orchestrator/daemon.cjs +2 -10
  66. package/orchestrator/parallel-orchestrator.cjs +314 -50
  67. package/orchestrator/planner/plan-builder.cjs +1 -1
  68. package/orchestrator/recovery.cjs +125 -7
  69. package/orchestrator/session-close-journal-worker.cjs +5 -0
  70. package/orchestrator/session-close-journal.cjs +1014 -0
  71. package/orchestrator/session-runner.cjs +679 -69
  72. package/orchestrator/worktree-manager.cjs +186 -35
  73. package/package.json +2 -3
  74. package/skills/cc-collab/SKILL.md +4 -1
  75. package/skills/codex-collab/SKILL.md +5 -2
  76. package/skills/ultra-change/SKILL.md +34 -8
  77. package/skills/ultra-deliver/SKILL.md +26 -11
  78. package/skills/ultra-dev/SKILL.md +52 -10
  79. package/skills/ultra-doctor/SKILL.md +16 -3
  80. package/skills/ultra-init/SKILL.md +22 -11
  81. package/skills/ultra-plan/SKILL.md +58 -18
  82. package/skills/ultra-research/SKILL.md +37 -35
  83. package/skills/ultra-review/SKILL.md +14 -8
  84. package/skills/ultra-status/SKILL.md +18 -9
  85. package/skills/ultra-test/SKILL.md +11 -5
  86. package/skills/ultra-think/SKILL.md +6 -2
  87. package/skills/ultra-think/references/decision-dialogue.md +17 -6
  88. package/skills/ultra-verify/SKILL.md +4 -1
  89. package/spec/cli-protocol.md +21 -7
  90. package/spec/mcp-tools.yaml +629 -44
  91. package/spec/schemas/change-delta.v1.schema.json +153 -0
  92. package/spec/schemas/context-file.v4.5.schema.json +1 -1
  93. package/spec/schemas/documentation-reconciliation.v1.schema.json +106 -0
  94. package/spec/schemas/mcp-tools.schema.json +1 -1
  95. package/spec/schemas/state-db.sql +51 -14
  96. package/spec/schemas/task-ledger.v1.schema.json +217 -0
  97. package/spec/schemas/tasks.v4.5.schema.json +1 -1
  98. package/ultra-tools/cli.cjs +3 -2
  99. package/ultra-tools/commands/db.cjs +76 -25
  100. package/ultra-tools/commands/migrate.cjs +1000 -82
  101. package/ultra-tools/commands/session.cjs +34 -8
  102. package/ultra-tools/commands/status.cjs +32 -6
  103. package/ultra-tools/commands/system.cjs +129 -22
  104. package/.ultra-template/tasks/contexts/TEMPLATE.md +0 -19
  105. package/commands/learn.md +0 -10
  106. package/orchestrator/skill-miner.cjs +0 -133
  107. package/output-styles/coding-vibes.md +0 -67
  108. package/output-styles/structural-thinking.md +0 -61
  109. package/skills/learn/SKILL.md +0 -58
@@ -6,7 +6,7 @@
6
6
  * Subcommands:
7
7
  * execute-plan resume the current plan through the first unfinished dependency wave.
8
8
  * run foreground daemon (debug / test).
9
- * start detached background daemon, writes .ultra/orchestrator.pid.
9
+ * start detached background daemon, writes .ultra/.runtime/orchestrator.pid.
10
10
  * stop reads pidfile, SIGTERM the process, deletes pidfile.
11
11
  * status prints pidfile + running session summary.
12
12
  *
@@ -23,10 +23,12 @@ const fs = require('node:fs');
23
23
  const path = require('node:path');
24
24
  const { spawn } = require('node:child_process');
25
25
  const { isSupportedRuntime } = require('../adapters/_shared/runtime-assets.cjs');
26
+ const runtimePaths = require('../mcp-server/lib/runtime-paths.cjs');
26
27
 
27
28
  const REPO_ROOT = process.env.UBP_REPO_ROOT || process.cwd();
28
- const PIDFILE = path.join(REPO_ROOT, '.ultra', 'orchestrator.pid');
29
- const LOGFILE = path.join(REPO_ROOT, '.ultra', 'orchestrator.log');
29
+ const RUNTIME_PATHS = runtimePaths.pathsFor(REPO_ROOT);
30
+ const PIDFILE = RUNTIME_PATHS.orchestratorPidPath;
31
+ const LOGFILE = RUNTIME_PATHS.orchestratorLogPath;
30
32
  const SETTINGS_FILES = [
31
33
  path.join(REPO_ROOT, 'settings.json'),
32
34
  path.join(REPO_ROOT, '.claude', 'settings.json'),
@@ -111,6 +113,7 @@ function resolveDispatchCommand(settings, env = process.env) {
111
113
  function parseExecutePlanArgs(argv = []) {
112
114
  const options = {
113
115
  planPath: null,
116
+ changeId: null,
114
117
  autoMerge: false,
115
118
  mergeBaseBranch: 'main',
116
119
  };
@@ -120,7 +123,7 @@ function parseExecutePlanArgs(argv = []) {
120
123
  options.autoMerge = true;
121
124
  continue;
122
125
  }
123
- if (arg === '--plan' || arg === '--base-branch') {
126
+ if (arg === '--plan' || arg === '--change' || arg === '--base-branch') {
124
127
  const value = argv[index + 1];
125
128
  if (!value || value.startsWith('--')) {
126
129
  throw commandConfigError(
@@ -129,6 +132,7 @@ function parseExecutePlanArgs(argv = []) {
129
132
  );
130
133
  }
131
134
  if (arg === '--plan') options.planPath = value;
135
+ else if (arg === '--change') options.changeId = value;
132
136
  else options.mergeBaseBranch = value;
133
137
  index += 1;
134
138
  continue;
@@ -138,21 +142,43 @@ function parseExecutePlanArgs(argv = []) {
138
142
  `unknown execute-plan option: ${arg}`,
139
143
  );
140
144
  }
145
+ if (options.planPath && options.changeId) {
146
+ throw commandConfigError(
147
+ 'ORCHESTRATOR_ARGUMENT_INVALID',
148
+ '--plan is explicit legacy compatibility and cannot be combined with --change',
149
+ );
150
+ }
141
151
  return options;
142
152
  }
143
153
 
154
+ function validateOrchestratorRuntime(rootDir = REPO_ROOT, {
155
+ forMutation = false,
156
+ } = {}) {
157
+ return runtimePaths.validateProjectLayout(rootDir, {
158
+ env: {},
159
+ forMutation,
160
+ validateRuntimeTree: true,
161
+ });
162
+ }
163
+
164
+ function openNoFollow(file, flags) {
165
+ const noFollow = fs.constants.O_NOFOLLOW || 0;
166
+ return fs.openSync(file, flags | noFollow, 0o600);
167
+ }
168
+
144
169
  async function cmdExecutePlan(argv = []) {
145
170
  const settings = readSettings();
146
171
  const dispatch = resolveDispatchCommand(settings);
147
172
  const options = parseExecutePlanArgs(argv);
148
173
  const { initStateDb, closeStateDb } = require('../mcp-server/lib/state-db.cjs');
149
174
  const parallelOrchestrator = require('../orchestrator/parallel-orchestrator.cjs');
150
- const { db } = initStateDb(path.join(REPO_ROOT, '.ultra', 'state.db'));
175
+ const { db } = initStateDb(runtimePaths.ensureRuntimeState(REPO_ROOT).stateDbPath);
151
176
  try {
152
177
  const result = await parallelOrchestrator.runPlan({
153
178
  db,
154
179
  repoRoot: REPO_ROOT,
155
180
  planPath: options.planPath ? path.resolve(REPO_ROOT, options.planPath) : undefined,
181
+ changeId: options.changeId,
156
182
  runtimes: parseRuntimes(),
157
183
  command: dispatch.command,
158
184
  commandArgs: dispatch.commandArgs,
@@ -187,7 +213,7 @@ function cmdRun(opts = {}) {
187
213
  const { runDaemon } = require('../orchestrator/daemon.cjs');
188
214
  const runtimes = parseRuntimes();
189
215
  const dispatch = resolveDispatchCommand(settings);
190
- const { db } = initStateDb(path.join(REPO_ROOT, '.ultra', 'state.db'));
216
+ const { db } = initStateDb(runtimePaths.ensureRuntimeState(REPO_ROOT).stateDbPath);
191
217
  const handle = runDaemon({
192
218
  db,
193
219
  repoRoot: REPO_ROOT,
@@ -221,39 +247,51 @@ function cmdStart() {
221
247
  process.exit(2);
222
248
  }
223
249
  resolveDispatchCommand(settings);
224
- if (fs.existsSync(PIDFILE)) {
225
- const existing = Number(fs.readFileSync(PIDFILE, 'utf8'));
250
+ const layout = validateOrchestratorRuntime(REPO_ROOT, { forMutation: true });
251
+ const pidfile = layout.orchestratorPidPath;
252
+ const logfile = layout.orchestratorLogPath;
253
+ if (fs.existsSync(pidfile)) {
254
+ const existing = Number(fs.readFileSync(pidfile, 'utf8'));
226
255
  try { process.kill(existing, 0); }
227
- catch (_) { fs.unlinkSync(PIDFILE); }
228
- if (fs.existsSync(PIDFILE)) {
256
+ catch (_) { fs.unlinkSync(pidfile); }
257
+ if (fs.existsSync(pidfile)) {
229
258
  process.stderr.write(`orchestrator already running (pid=${existing}).\n`);
230
259
  process.exit(1);
231
260
  }
232
261
  }
233
- fs.mkdirSync(path.dirname(PIDFILE), { recursive: true });
234
- const out = fs.openSync(LOGFILE, 'a');
235
- const err = fs.openSync(LOGFILE, 'a');
262
+ fs.mkdirSync(layout.orchestratorDir, { recursive: true });
263
+ const appendFlags = fs.constants.O_APPEND | fs.constants.O_CREAT | fs.constants.O_WRONLY;
264
+ const out = openNoFollow(logfile, appendFlags);
265
+ const err = openNoFollow(logfile, appendFlags);
236
266
  const child = spawn(process.execPath, [__filename, 'run'], {
237
267
  detached: true,
238
268
  stdio: ['ignore', out, err],
239
269
  env: { ...process.env, UBP_REPO_ROOT: REPO_ROOT },
240
270
  });
241
271
  child.unref();
242
- fs.writeFileSync(PIDFILE, String(child.pid));
243
- process.stdout.write(`orchestrator started (pid=${child.pid}, log=${LOGFILE})\n`);
272
+ const pidFd = openNoFollow(
273
+ pidfile,
274
+ fs.constants.O_CREAT | fs.constants.O_TRUNC | fs.constants.O_WRONLY,
275
+ );
276
+ try { fs.writeFileSync(pidFd, String(child.pid)); }
277
+ finally { fs.closeSync(pidFd); }
278
+ process.stdout.write(`orchestrator started (pid=${child.pid}, log=${logfile})\n`);
244
279
  }
245
280
 
246
281
  function cmdStop() {
247
- if (!fs.existsSync(PIDFILE)) {
282
+ const { orchestratorPidPath: pidfile } = validateOrchestratorRuntime(REPO_ROOT, {
283
+ forMutation: true,
284
+ });
285
+ if (!fs.existsSync(pidfile)) {
248
286
  process.stderr.write('no pidfile found; orchestrator not running.\n');
249
287
  process.exit(1);
250
288
  }
251
- const pid = Number(fs.readFileSync(PIDFILE, 'utf8'));
289
+ const pid = Number(fs.readFileSync(pidfile, 'utf8'));
252
290
  try { process.kill(pid, 'SIGTERM'); }
253
291
  catch (err) {
254
292
  if (err.code === 'ESRCH') {
255
293
  process.stderr.write(`pid ${pid} already dead; cleaning pidfile.\n`);
256
- fs.unlinkSync(PIDFILE);
294
+ fs.unlinkSync(pidfile);
257
295
  return;
258
296
  }
259
297
  throw err;
@@ -262,22 +300,23 @@ function cmdStop() {
262
300
  setTimeout(() => {
263
301
  try { process.kill(pid, 0); }
264
302
  catch (_) { /* dead; good */ }
265
- if (fs.existsSync(PIDFILE)) fs.unlinkSync(PIDFILE);
303
+ if (fs.existsSync(pidfile)) fs.unlinkSync(pidfile);
266
304
  process.stdout.write(`orchestrator stopped (pid=${pid})\n`);
267
305
  }, 200);
268
306
  }
269
307
 
270
308
  function cmdStatus() {
271
- const out = { pidfile: PIDFILE, running: false };
272
- if (fs.existsSync(PIDFILE)) {
273
- const pid = Number(fs.readFileSync(PIDFILE, 'utf8'));
309
+ const { orchestratorPidPath: pidfile } = validateOrchestratorRuntime(REPO_ROOT);
310
+ const out = { pidfile, running: false };
311
+ if (fs.existsSync(pidfile)) {
312
+ const pid = Number(fs.readFileSync(pidfile, 'utf8'));
274
313
  try { process.kill(pid, 0); out.pid = pid; out.running = true; }
275
314
  catch (_) { out.pid = pid; out.running = false; out.note = 'pidfile stale'; }
276
315
  }
277
316
  // Session summary.
278
317
  try {
279
318
  const Database = require('better-sqlite3');
280
- const dbPath = path.join(REPO_ROOT, '.ultra', 'state.db');
319
+ const dbPath = runtimePaths.locateStateDb(REPO_ROOT);
281
320
  if (fs.existsSync(dbPath)) {
282
321
  const db = new Database(dbPath, { readonly: true });
283
322
  const counts = db.prepare(
@@ -297,7 +336,7 @@ function usage() {
297
336
  process.stderr.write(
298
337
  'usage: ubp-orchestrator <execute-plan|run|start|stop|status>\n' +
299
338
  '\n' +
300
- ' execute-plan resume the first unfinished dependency wave [--plan <path>] [--auto-merge] [--base-branch <name>]\n' +
339
+ ' execute-plan resume the first unfinished dependency wave [--change <id>] [--plan <legacy-path>] [--auto-merge] [--base-branch <name>]\n' +
301
340
  ' run foreground daemon (requires opt-in)\n' +
302
341
  ' start detached background daemon (requires opt-in)\n' +
303
342
  ' stop terminate running daemon\n' +
@@ -343,6 +382,7 @@ module.exports = {
343
382
  parseRuntimes,
344
383
  parseExecutePlanArgs,
345
384
  resolveDispatchCommand,
385
+ validateOrchestratorRuntime,
346
386
  cmdExecutePlan,
347
387
  cmdRun,
348
388
  cmdStart,
@@ -7,9 +7,9 @@ and Kimi Code plugins.
7
7
 
8
8
  Ultra Builder Pro owns only:
9
9
 
10
- - twelve public workflows: `learn`, `ultra-init`, `ultra-research`, `ultra-plan`,
11
- `ultra-dev`, `ultra-test`, `ultra-review`, `ultra-deliver`, `ultra-status`, and
12
- `ultra-think`, plus the daily `ultra-change` and diagnostic `ultra-doctor`;
10
+ - eleven public capabilities: `ultra-init`, `ultra-research`, `ultra-plan`,
11
+ `ultra-dev`, `ultra-test`, `ultra-review`, `ultra-deliver`, `ultra-status`,
12
+ `ultra-think`, `ultra-change`, and `ultra-doctor`;
13
13
  - four internal agent-only rule skills: `code-review-expert`, `security-rules`,
14
14
  `integration-rules`, and `testing-rules`;
15
15
  - the host-specific collaboration companions, `ultra-verify`, and host-native
@@ -25,36 +25,46 @@ not put it in a plugin until that allowlist classifies it.
25
25
  ## 2. Three-layer architecture
26
26
 
27
27
  ```text
28
- native command or skill -> MCP workflow-state operation -> .ultra/state.db
28
+ native command or skill -> MCP workflow-state operation -> .ultra/.runtime/state.db
29
+ | \
30
+ | -> .ultra/tasks/tasks.json (Git checkpoint)
31
+ | -> .ultra/.runtime/projections/ (local views)
29
32
  ^
30
- |
31
33
  selected CLI init / doctor / diagnostics / orchestration
32
34
  ```
33
35
 
34
36
  | Layer | Artifact | Contract |
35
37
  |---|---|---|
36
38
  | Skill/command | `skills/*/SKILL.md`, `commands/*.md` | Model-facing workflow and host-native entry point |
37
- | MCP | `mcp-server/server.cjs` | Authoritative typed operations over `.ultra/state.db` |
39
+ | MCP | `mcp-server/server.cjs` | Authoritative typed operations over `.ultra/.runtime/state.db` |
38
40
  | CLI | `ultra-tools`, `ubp-orchestrator` | Selected initialization, backup-first recovery, automation, and diagnostics; not a change-state mirror |
39
41
 
40
- `.ultra/state.db` is the only durable Ultra authority for baselines, changes, decisions, tasks,
41
- workflow runs/steps, sessions, events, incidents, projection jobs/cursors, telemetry, review evidence,
42
- and circuit-breaker state. `tasks.json`, context Markdown, execution plans, and
43
- reports are projections or workflow artifacts.
42
+ `.ultra/` is project-local cross-session workflow memory for normalized intent,
43
+ progress, tasks, bounded context, specifications, evidence, provenance, and recovery.
44
+ `.ultra/.runtime/state.db` is checkout-local lifecycle, index, transition, freshness,
45
+ and coordination authority for baselines, changes, decisions, tasks, workflow
46
+ runs/steps, sessions, events, incidents, projection jobs/cursors, telemetry, review
47
+ evidence, and circuit-breaker state. Registered digest-bound specifications and
48
+ reports carry semantic or evidence bodies. `.ultra/tasks/tasks.json` is the
49
+ MCP-published portable baseline/Change/task checkpoint; it is not live lease or session
50
+ authority. Generated task views, runtime checkpoints, and collaboration scratch are
51
+ not independent authority. See
52
+ [`ARTIFACT-AUTHORITY.md`](./ARTIFACT-AUTHORITY.md).
44
53
 
45
54
  ## 3. Live MCP and declared contracts
46
55
 
47
- `spec/mcp-tools.yaml` declares and the bundled server registers 51 tools across
48
- eight families:
56
+ `spec/mcp-tools.yaml` declares and the bundled server registers 60 tools across
57
+ nine families:
49
58
 
50
59
  | Family | Live tools |
51
60
  |---|---|
52
61
  | `baseline.*` | start, record, get, converge |
53
- | `task.*` | create, update, list, get, switch_tag, delete, init_project, expand, parse_prd, dependency_topo, append_event, subscribe_events |
62
+ | `task.*` | create, update, list, get, switch_tag, delete, init_project, expand, parse_prd, dependency_topo, append_event, subscribe_events, ledger_get, ledger_publish, ledger_import |
54
63
  | `session.*` | spawn, close, get, list, admission_check, heartbeat, subscribe_events |
55
- | `change.*` | create, update, get, list, context, breadcrumb, learning_propose, learning_resolve, converge, archive |
64
+ | `change.*` | create, update, delta, documentation_reconcile, get, list, context, breadcrumb, learning_propose, learning_resolve, converge, archive |
56
65
  | `decision.*` | thread_start, get, list, open, resolve, delegate, defer, supersede, complete, checkpoint |
57
- | `workflow.*` | start, get, list, step, complete |
66
+ | `workflow.*` | start, get, list, step, revise, supersede, complete |
67
+ | `artifact.*` | record, get |
58
68
  | `system.*` | doctor |
59
69
  | `plan.*` | export, get |
60
70
 
@@ -81,35 +91,55 @@ review, and deliver route back to the same thread instead of deciding for the ow
81
91
  One partial unique index permits only one open item per thread. `decision.resolve`,
82
92
  `decision.delegate`, and `decision.defer` preserve the source of authority;
83
93
  `decision.supersede` preserves history when evidence or intent changes.
84
- `decision.complete` closes settled normalized state without manufacturing an approval
85
- receipt. Prepare and confirm checkpointing remain optional and bind only a material
86
- accepted cluster to current artifact digests when interruption recovery needs that
87
- boundary. Status and breadcrumb return only the current question plus allowed and
88
- mechanically required transitions, so recovery does not require replaying conversation
89
- history.
94
+ After normalization, the host applies accepted intent through the owning MCP operation
95
+ or digest-bound artifact, reads it back, and records typed `applied_refs` when another
96
+ authority changed. Row-backed references require the exact field and canonical value;
97
+ specification and artifact references require the exact file digest. Active proposals
98
+ are never recalled as accepted intent. `decision.complete` then closes settled state without manufacturing
99
+ an approval receipt. Prepare and confirm checkpointing remain optional and bind only a
100
+ material accepted cluster to current artifact digests when interruption recovery needs
101
+ that boundary. Status and breadcrumb return the current unresolved question, accepted
102
+ intent relevant to the active authority, and allowed or mechanically required
103
+ transitions, so recovery does not require replaying conversation history.
90
104
 
91
105
  ## 5. Context Spine contract
92
106
 
93
107
  Context Manifest v3 is an immutable DB-backed role handoff, not a static codebase summary.
94
108
  `change.context` compiles required references, digests, readiness, context budget,
95
109
  public seam, exact verification command, Change/task authority digests, and valid
96
- transitions for `plan`, `implement`, `check`, or `review`. The default 12-file,
97
- about 12k-token, and 40%
110
+ transitions for `plan`, `implement`, `check`, or `review`. Compilation never updates
111
+ Change or provider authority; provider metadata changes through `change.update`.
112
+ Snapshots are selected exactly by `change_id`, nullable `task_id`, `role`, and `gate`,
113
+ so a review packet cannot satisfy implementation or planning evidence.
114
+
115
+ Implementation packets inline only the selected task, direct dependency/integration
116
+ neighborhood, and the restored task-context contract. Referenced file bodies remain
117
+ lazy. The token estimate includes inline Change/task authority plus referenced-file
118
+ estimates. Context refs preserve `expected_digest`, `anchor`, `scope`, and one of
119
+ `digest`, `existence`, or `advisory` freshness. Current consumers revalidate these
120
+ policies instead of trusting an old manifest.
121
+
122
+ The default 12-file, about 12k-token, and 40%
98
123
  fresh-context values are attention guidance. Overflow produces warnings; it does
99
124
  not block work or require raising a threshold. Prefer direct reads, bounded
100
125
  excerpts, or a smaller slice when they preserve correctness, and retain all
101
126
  necessary context when they do not.
102
127
 
103
128
  `change.breadcrumb` is the only compact router. Hooks may inject its change/task,
104
- role, gate, readiness, blockers, `allowed_transitions`, and `required_transition`.
105
- They must not inject intent
106
- bodies, transcripts, external memory, or graph payloads. Missing references,
107
- digest drift, HEAD drift, or a missing execution seam blocks readiness. Context
129
+ role, gate, readiness, blockers, bounded normalized accepted intent,
130
+ `allowed_transitions`, and `required_transition`. They must not inject raw prompts,
131
+ interaction transcripts, external-memory payloads, or graph payloads. Missing references,
132
+ required digest drift, HEAD drift, or a missing execution seam blocks readiness. Context
108
133
  size and baseline drift are advisory for a change that is already active. New ordinary
109
134
  work requires a healthy baseline. Only an explicitly approved incident break-glass may
110
135
  start without it; incident archive records a blocking reconciliation gap. Revision and
111
136
  tracked-spec integrity are reconciled and rechecked atomically for ordinary archive.
112
137
 
138
+ The plan workflow records a `plan/planning` manifest before design and exports only
139
+ `<artifact_root>/plan.json` plus deterministic `plan.md`. Both bind the planning
140
+ snapshot digest. The global `.ultra/execution-plan.json` is legacy read-only
141
+ compatibility and must not receive new plan writes.
142
+
113
143
  Stable discoveries use `change.learning_propose`; they reach the baseline only
114
144
  through approve/reject/apply transitions in `change.learning_resolve`. Unresolved
115
145
  learning blocks convergence. Review contributes two independent axes,
@@ -119,10 +149,14 @@ learning blocks convergence. Review contributes two independent axes,
119
149
 
120
150
  | Host | Plugin form | Workflow entry | Hook form | Collaboration companions |
121
151
  |---|---|---|---|---|
122
- | Claude Code | `.claude-plugin/plugin.json`, native commands/skills/agents, `.mcp.json` | `/ultra-*`, `/learn` | native `hooks/hooks.json` | `codex-collab`, `ultra-verify` |
123
- | Codex | personal plugin with `.codex-plugin/plugin.json`, namespaced skills, TOML agents, `.mcp.json` | `$ultra-builder-pro:ultra-*`, `$ultra-builder-pro:learn` | native `hooks/hooks.json` through the Codex wire adapter | `cc-collab`, `ultra-verify` |
124
- | OpenCode | config bundle plus native JavaScript plugin | `/ultra-*`, `/learn` | `event`, system transform, compaction, and tool lifecycle handlers | `cc-collab`, `codex-collab`, `ultra-verify` |
125
- | Kimi Code 0.26+ | managed `kimi.plugin.json` plugin with commands, skills, hooks, and MCP | `/ultra-builder-pro:ultra-*`, `/ultra-builder-pro:learn` | native hooks through the Kimi wire adapter | `cc-collab`, `codex-collab`, `ultra-verify` |
152
+ | Claude Code | `.claude-plugin/plugin.json`, native commands/skills/agents, `.mcp.json` | `/ultra-builder-pro:ultra-*` | native `hooks/hooks.json` | `codex-collab`, `ultra-verify` |
153
+ | Codex | personal plugin with `.codex-plugin/plugin.json`, namespaced skills, TOML agents, `.mcp.json` | `$ultra-builder-pro:ultra-*` | native `hooks/hooks.json` through the Codex wire adapter | `cc-collab`, `ultra-verify` |
154
+ | OpenCode | config bundle plus native JavaScript plugin | `/ultra-*` | `event`, system transform, compaction, and tool lifecycle handlers | `cc-collab`, `codex-collab`, `ultra-verify` |
155
+ | Kimi Code 0.26+ | managed `kimi.plugin.json` plugin with commands, skills, hooks, and MCP | `/ultra-builder-pro:ultra-*` | native hooks through the Kimi wire adapter | `cc-collab`, `codex-collab`, `ultra-verify` |
156
+
157
+ `spec/interaction-contract.json` carries the same exact public-capability graph for
158
+ every host. Adapters translate the question and invocation surfaces; they never own
159
+ semantic selection or durable state.
126
160
 
127
161
  The current host remains primary. Collaboration skills call another runtime
128
162
  only when explicitly requested, use it as a read-only advisor, and return the
@@ -146,22 +180,24 @@ OpenCode plugin invoke the same bundled JavaScript `change.breadcrumb` reader
146
180
  through the thin `context_spine.py` bridge. No hook reimplements the state query.
147
181
  `health_check.py` and
148
182
  `workflow_context.py` may inspect any initialized project;
149
- `active_task_context.py` always protects the task projection but limits ordinary
183
+ `active_task_context.py` protects both the MCP-owned Git checkpoint and local task
184
+ projection but limits ordinary
150
185
  edit guidance to an active workflow. Compact/stop/subagent hooks remain
151
186
  active-workflow scoped. OpenCode natively injects baseline/change context and
152
- protects the projection; full health inspection is available through
187
+ protects both managed task paths; full health inspection is available through
153
188
  `system.doctor` rather than a session-start health hook.
154
189
  Advisory baseline or context-budget warnings are presentation only and never
155
190
  reject an edit, stop, or tool call.
156
191
  Generic command blocking, post-edit governance, and unrelated user hooks are not
157
192
  copied into Ultra Builder Pro.
158
193
 
159
- ## 8. Memory boundary
194
+ ## 8. Workflow-memory boundary
160
195
 
161
- Ultra Builder Pro has no memory MCP family, recall skill, prompt capture,
162
- transcript capture, observation journal, or session-summary hook. Persistent
163
- cross-session memory belongs to a separately installed provider such as
164
- cloud-mem/claude-mem. Code graph content is equally external. A change context
196
+ Ultra Builder Pro has no general memory MCP family, general recall skill, prompt
197
+ capture, transcript capture, observation journal, or session-summary hook. It does
198
+ retain its own project-local cross-session workflow memory under `.ultra/`.
199
+ General conversational or episodic memory belongs to a separately installed provider
200
+ such as cloud-mem/claude-mem. Code-graph content is equally external. A change context
165
201
  may contain only provider metadata references, never provider payload content.
166
202
 
167
203
  Old Ultra data is never deleted during install. The explicit migration path is:
@@ -173,25 +209,29 @@ ultra-tools legacy-memory prune --confirm DELETE_ULTRA_LEGACY_MEMORY
173
209
  ```
174
210
 
175
211
  Archive before prune; the confirmation token is intentionally required.
212
+ This CLI is an operator-invoked migration cleanup surface only. Hooks, MCP, and
213
+ sessions never call it, and it cannot collect, recall, or reflect memory.
176
214
 
177
215
  ## 9. Project state layout
178
216
 
179
217
  ```text
180
218
  .ultra/
181
- ├── state.db # authoritative SQLite store
182
- ├── runtime/
183
- │ └── checkpoint.json # advisory breadcrumb recovery projection
219
+ ├── .runtime/
220
+ │ ├── state.db # authoritative SQLite lifecycle/index store
221
+ │ ├── checkpoint.json # advisory breadcrumb recovery projection
222
+ │ └── projections/ # generated checkout-local task views
184
223
  ├── changes/
185
- │ ├── active/<id>/ # intent, delta, plan, context v3, learning, verification
224
+ │ ├── active/<id>/ # all Change semantics and evidence
225
+ │ │ ├── intent.md, findings.md, progress.md
226
+ │ │ ├── research/, delta/, documentation/, plan.json, plan.md
227
+ │ │ └── contexts/, test/, review/, delivery/
186
228
  │ └── archive/ # converged packets after baseline reconciliation
187
- ├── tasks/ # projections and task contexts
229
+ ├── tasks/
230
+ │ └── tasks.json # MCP-published Git team checkpoint
231
+ ├── templates/
232
+ │ └── task-context.md # authored task-context template
188
233
  ├── specs/ # research/product/architecture artifacts
189
- ├── sessions/ # bounded runtime artifacts
190
- ├── reviews/ # immutable review evidence by session id
191
- └── reports/
192
- ├── templates/ # blank report schemas; never evidence
193
- ├── tests/<workflow-id>.json
194
- └── delivery/<workflow-id>.json
234
+ └── reports/templates/ # blank report schemas; never evidence
195
235
  ```
196
236
 
197
237
  ## 10. Plugin and user-instruction isolation