ultra-builder-pro-cli 0.23.0 → 0.24.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 (91) hide show
  1. package/.ultra-template/docs/research/README.md +4 -4
  2. package/CHANGELOG.md +45 -0
  3. package/README.md +21 -18
  4. package/adapters/_shared/codex-assets.cjs +121 -65
  5. package/adapters/_shared/interaction-contract.cjs +7 -1
  6. package/adapters/_shared/provenance.cjs +7 -2
  7. package/adapters/_shared/runtime-assets.cjs +3 -2
  8. package/adapters/_shared/runtime-native.cjs +132 -0
  9. package/adapters/claude.js +60 -30
  10. package/adapters/codex.js +178 -81
  11. package/adapters/grok.js +372 -0
  12. package/adapters/kimi.js +7 -3
  13. package/adapters/opencode.js +210 -32
  14. package/agents/code-reviewer.md +4 -2
  15. package/agents/debugger.md +4 -1
  16. package/agents/review-code.md +7 -3
  17. package/agents/review-comments.md +7 -4
  18. package/agents/review-coordinator.md +11 -7
  19. package/agents/review-design.md +8 -4
  20. package/agents/review-errors.md +8 -4
  21. package/agents/review-spec.md +8 -5
  22. package/agents/review-tests.md +7 -4
  23. package/agents/tdd-runner.md +5 -2
  24. package/bin/install.js +9 -4
  25. package/bin/orchestrator.js +4 -13
  26. package/docs/AGENT-CONTEXT.md +141 -229
  27. package/docs/ARCHITECTURE.md +203 -494
  28. package/docs/ARTIFACT-AUTHORITY.md +26 -22
  29. package/docs/PLUGIN-ISOLATION-CONTRACT.md +12 -9
  30. package/docs/ROADMAP.md +85 -110
  31. package/docs/RUNTIME-COMPAT-MATRIX.md +139 -175
  32. package/docs/SKILL-AUTHORING.md +3 -3
  33. package/docs/STATE-DB-ACCESS-POLICY.md +13 -8
  34. package/docs/WORKFLOW-LIFECYCLE.md +174 -448
  35. package/hooks/README.md +11 -8
  36. package/hooks/active_task_context.py +16 -16
  37. package/hooks/adapters/grok.py +134 -0
  38. package/hooks/{context_spine.py → context_envelope.py} +26 -22
  39. package/hooks/health_check.py +19 -29
  40. package/hooks/pre_stop_check.py +22 -12
  41. package/hooks/subagent_tracker.py +1 -1
  42. package/hooks/workflow_checkpoint.py +14 -13
  43. package/hooks/workflow_context.py +11 -12
  44. package/hooks/workflow_resume.py +14 -13
  45. package/mcp-server/{breadcrumb.cjs → hook-context.cjs} +7 -9
  46. package/mcp-server/lib/baseline-workflow.cjs +36 -38
  47. package/mcp-server/lib/canonical-json.cjs +19 -0
  48. package/mcp-server/lib/change-workflow.cjs +596 -44
  49. package/mcp-server/lib/context-envelope.cjs +508 -0
  50. package/mcp-server/lib/decision-records.cjs +337 -0
  51. package/mcp-server/lib/doctor.cjs +91 -33
  52. package/mcp-server/lib/init-project.cjs +78 -39
  53. package/mcp-server/lib/managed-file-write.cjs +116 -0
  54. package/mcp-server/lib/plan-checkpoint.cjs +177 -0
  55. package/mcp-server/lib/project-context.cjs +178 -0
  56. package/mcp-server/lib/stage-checkpoints.cjs +309 -0
  57. package/mcp-server/lib/state-db.cjs +155 -24
  58. package/mcp-server/lib/task-ledger.cjs +522 -13
  59. package/mcp-server/lib/ultra-facade.cjs +630 -442
  60. package/mcp-server/lib/worker-packet.cjs +358 -0
  61. package/mcp-server/server.cjs +200 -1103
  62. package/orchestrator/daemon.cjs +27 -9
  63. package/orchestrator/parallel-orchestrator.cjs +111 -76
  64. package/orchestrator/session-runner.cjs +135 -34
  65. package/package.json +10 -3
  66. package/skills/ultra-change/SKILL.md +9 -8
  67. package/skills/ultra-deliver/SKILL.md +3 -3
  68. package/skills/ultra-dev/SKILL.md +18 -11
  69. package/skills/ultra-doctor/SKILL.md +2 -2
  70. package/skills/ultra-init/SKILL.md +6 -5
  71. package/skills/ultra-init/references/brownfield-adoption.md +11 -8
  72. package/skills/ultra-plan/SKILL.md +10 -8
  73. package/skills/ultra-research/SKILL.md +12 -7
  74. package/skills/ultra-review/SKILL.md +9 -6
  75. package/skills/ultra-review/references/unified-schema.md +2 -0
  76. package/skills/ultra-review/scripts/review_wait.py +8 -0
  77. package/skills/ultra-status/SKILL.md +2 -2
  78. package/skills/ultra-test/SKILL.md +4 -2
  79. package/skills/ultra-think/SKILL.md +7 -7
  80. package/skills/ultra-think/references/interaction-boundary.md +56 -0
  81. package/spec/cli-protocol.md +80 -199
  82. package/spec/mcp-tools.yaml +37 -2804
  83. package/spec/schemas/state-db.sql +107 -4
  84. package/spec/schemas/{task-ledger.v1.schema.json → task-ledger.v2.schema.json} +70 -6
  85. package/ultra-tools/commands/status.cjs +369 -243
  86. package/mcp-server/lib/context-spine.cjs +0 -1208
  87. package/mcp-server/lib/decision-dialogue.cjs +0 -1128
  88. package/mcp-server/lib/project-breadcrumb.cjs +0 -173
  89. package/mcp-server/lib/spec-learning.cjs +0 -284
  90. package/mcp-server/lib/workflow-state.cjs +0 -3129
  91. package/skills/ultra-think/references/decision-dialogue.md +0 -155
@@ -49,7 +49,7 @@ copying memory, code-graph payloads, or large source material into Ultra.
49
49
 
50
50
  ## Completion
51
51
 
52
- Update the affected baseline specification, record the report through `workflow.step`,
53
- include it in `baseline.record` evidence when material, and record unresolved work in
54
- the authoritative gap ledger. The final synthesis also binds the three specifications
55
- and research distillate. Do not create a condensed duplicate of the baseline.
52
+ Update the affected baseline specification, register the report through typed
53
+ `ultra.record`, reference it from the Research Stage Checkpoint, and record unresolved
54
+ work in the authoritative gap ledger. The final synthesis also binds the baseline
55
+ specifications and research distillate. Do not create a condensed duplicate.
package/CHANGELOG.md CHANGED
@@ -7,6 +7,51 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [0.24.0] — 2026-07-30
11
+
12
+ ### Added
13
+
14
+ - Added normalized Decision Records, reversible Stage Checkpoints, bounded Context
15
+ Envelopes, and immutable Worker Packets as the shared evidence and handoff model
16
+ across Skills, Hooks, agents, SQLite, and tracked `.ultra` artifacts.
17
+ - Added a native Grok Build plugin so Claude Code, Codex, OpenCode, Kimi Code, and
18
+ Grok Build share the same eleven explicit workflows and seven-tool MCP kernel.
19
+ - Added schema 22 backup-first migration and real-history compatibility for v4.4,
20
+ v4.5, v0.22, and v0.23 state and team-ledger formats.
21
+ - Added packaged `better-sqlite3` provenance, platform and Node ABI verification,
22
+ and durable Doctor and archive workers for every supported host.
23
+
24
+ ### Changed
25
+
26
+ - Completed the MCP boundary reduction: Skills own adaptive semantic procedure;
27
+ MCP owns persistence, identity, transactions, leases, paths, recovery, and
28
+ irreversible safety; Hooks only observe or inject bounded context; agents consume
29
+ immutable Worker Packets without writing SQLite authority.
30
+ - Folded Plan artifact publication into the accepted Plan checkpoint so a later
31
+ export cannot invalidate its own authority.
32
+ - Replaced semantic supervisor failures with mutable diagnostics and repairable
33
+ drafts. Only corruption, unsafe paths, concurrency conflicts, permission failures,
34
+ and irreversible external effects remain hard blockers.
35
+ - Made `ultra.context`, `ultra.sync`, and `ultra.doctor` own their inspection and
36
+ repair preflight so an older valid ledger cannot block the tools required to
37
+ migrate it.
38
+ - Reduced packaged and documented MCP contracts to the exact seven public tools;
39
+ removed the retired fine-grained schemas, fixtures, and command bypasses.
40
+
41
+ ### Fixed
42
+
43
+ - Fixed accepted or stale workflow runs becoming permanently self-locked after an
44
+ artifact changed, and made reversible stages reopenable without rewriting
45
+ immutable accepted history.
46
+ - Fixed v0.23 team ledgers using `research_run_id` being rejected under the newer
47
+ `research_checkpoint_id` digest contract.
48
+ - Fixed native SQLite drivers and Doctor workers being absent or unresolved in
49
+ installed plugins.
50
+ - Fixed session acquisition, archive recovery, Context identity, and Worker Packet
51
+ cleanup paths leaving partial authority after failure.
52
+ - Fixed installed interaction guidance failing to render each host's native question
53
+ surface while keeping canonical Skills host-neutral.
54
+
10
55
  ## [0.23.0] — 2026-07-30
11
56
 
12
57
  ### Added
package/README.md CHANGED
@@ -2,8 +2,8 @@
2
2
 
3
3
  **An adaptive delivery harness for AI coding agents.**
4
4
 
5
- Ultra Builder Pro helps Claude Code, Codex, OpenCode, and Kimi Code carry a
6
- software project from an unclear request to a verified, recoverable delivery.
5
+ Ultra Builder Pro helps Claude Code, Codex, OpenCode, Kimi Code, and Grok Build
6
+ carry a software project from an unclear request to a verified, recoverable delivery.
7
7
  It keeps the user and the agent aligned, preserves project authority across
8
8
  sessions, and prevents specifications from quietly drifting away from the code.
9
9
 
@@ -44,7 +44,7 @@ Ultra Builder Pro addresses those gaps with four ideas:
44
44
  and asks the user only for material intent, scope, risk, or authorization
45
45
  decisions—normally one dependent decision at a time.
46
46
  3. **Durable project authority.** `.ultra/.runtime/state.db` records checkout-local
47
- lifecycle, decisions, workflows, evidence digests, sessions, incidents, and
47
+ lifecycle facts, decisions, checkpoints, evidence digests, sessions, incidents, and
48
48
  recovery state across host sessions. Tracked semantic artifacts plus the
49
49
  MCP-published `.ultra/tasks/tasks.json` checkpoint carry reviewed project intent
50
50
  across Git checkouts without committing SQLite, leases, or telemetry.
@@ -65,13 +65,13 @@ flowchart TB
65
65
  U["User<br/>goals, acceptance, trade-offs, risk, and external authorization"]
66
66
 
67
67
  subgraph HOST["Supported coding host"]
68
- UI["Host-native interaction<br/>Claude Code / Codex / OpenCode / Kimi Code"]
68
+ UI["Host-native interaction<br/>Claude Code / Codex / OpenCode / Kimi Code / Grok Build"]
69
69
  MODEL["Host agent<br/>inspect, recommend, implement, test, and review"]
70
70
  ADAPTER["Host adapter<br/>native questions, commands, tools, and lifecycle wiring"]
71
71
  end
72
72
 
73
73
  SKILLS["Eleven explicit Ultra Skills<br/>init / research / think / change / plan / dev<br/>test / review / deliver / status / doctor"]
74
- MCP["Ultra MCP safety kernel<br/>7 public tools; 60 hidden compatibility operations"]
74
+ MCP["Ultra MCP safety kernel<br/>exactly 7 public tools"]
75
75
  DB[(".ultra/.runtime/state.db<br/>SQLite lifecycle and index authority")]
76
76
  LEDGER[".ultra/tasks/tasks.json<br/>Git team checkpoint for portable baseline, Change, and task state"]
77
77
  VIEWS[".ultra/.runtime/projections<br/>checkout-local generated views"]
@@ -103,7 +103,7 @@ The responsibility split is deliberate:
103
103
  |---|---|
104
104
  | **User** | Product intent, semantic route selection, material scope and trade-offs, risk acceptance, destructive actions, publishing and deployment authorization |
105
105
  | **Host model** | Fact-finding, synthesis, research-coverage and route recommendations, reversible implementation decisions |
106
- | **Ultra MCP** | Durable checkpoints, evidence references, digests, team sync, leases, archive transactions, and mechanical recovery |
106
+ | **Ultra MCP** | Structure validation, durable checkpoints, evidence references, digests, team sync, leases, archive transactions, and mechanical recovery; never semantic route selection |
107
107
  | **Host adapter** | Native Skill discovery, user questions, tool invocation, installation, and runtime wiring |
108
108
  | **Hooks** | Fast lifecycle observation, current breadcrumb injection, and protection of MCP-owned checkpoint and generated projection paths |
109
109
 
@@ -126,10 +126,9 @@ The public model-facing surface is intentionally small:
126
126
  | `ultra.archive` | Converge and archive through the recoverable filesystem/DB boundary |
127
127
  | `ultra.doctor` | Inspect or repair mechanical health, backup first |
128
128
 
129
- The 0.22 fine-grained tools remain callable but undiscoverable for one compatibility
130
- release. Skills and new sessions use only the seven tools above. Workflow prose stays
131
- in Skills, model judgment stays with the host, and SQLite records what happened rather
132
- than deciding what the model is allowed to think next.
129
+ Retired fine-grained operation names are neither discoverable nor callable. Workflow
130
+ prose stays in Skills, model judgment stays with the host, and SQLite records what
131
+ happened rather than deciding what the model is allowed to think next.
133
132
 
134
133
  The enforcement gradient is:
135
134
 
@@ -165,8 +164,9 @@ and effects—not chain-of-thought, raw prompts, transcripts, or UI receipts.
165
164
 
166
165
  ## What you get
167
166
 
168
- - Native plugins for **Claude Code**, **OpenCode**, **Codex**, and **Kimi Code**.
169
- - One workflow vocabulary across all four hosts.
167
+ - Native plugins for **Claude Code**, **OpenCode**, **Codex**, **Kimi Code**, and
168
+ **Grok Build**.
169
+ - One workflow vocabulary across all five hosts.
170
170
  - Deterministic initialization for new, existing, monorepo, and older Ultra
171
171
  projects.
172
172
  - Evidence-backed greenfield research and brownfield adoption.
@@ -218,6 +218,7 @@ npx --yes ultra-builder-pro-cli@latest --claude --global
218
218
  npx --yes ultra-builder-pro-cli@latest --opencode --global
219
219
  npx --yes ultra-builder-pro-cli@latest --codex --global
220
220
  npx --yes ultra-builder-pro-cli@latest --kimi --global
221
+ npx --yes ultra-builder-pro-cli@latest --grok --global
221
222
  ```
222
223
 
223
224
  Use `--local` instead of `--global` to install into the current project's host
@@ -454,7 +455,7 @@ health without selecting product intent.
454
455
  ```text
455
456
  .ultra/
456
457
  .runtime/ # local mutable state; ignored by Git
457
- state.db # lifecycle, index, transition, and freshness authority
458
+ state.db # facts, indexes, checkpoints, leases, CAS, and recovery
458
459
  checkpoint.json # advisory recovery projection
459
460
  projections/ # generated local task and task-context views
460
461
  backups/ # verified migration and recovery snapshots
@@ -463,17 +464,18 @@ health without selecting product intent.
463
464
  worktrees/ # registered local Git worktrees
464
465
  telemetry/ # local operational telemetry
465
466
  specs/ # digest-bound product and architecture baseline
467
+ decisions/baseline/ # normalized accepted baseline decisions
466
468
  changes/
467
469
  active/<id>/ # all current Change semantics and evidence
468
470
  intent.md # accepted Change Contract
469
- findings.md # durable Change findings
471
+ decisions/ # normalized accepted Change decisions
470
472
  progress.md # generated human-readable projection
471
473
  research/ # Change-only findings and research reports
472
474
  delta/ # typed baseline overlay and semantic payloads
473
475
  documentation/ # documentation overlay and reconciliation evidence
474
476
  plan.json # machine-readable task topology
475
477
  plan.md # deterministic human plan projection
476
- contexts/ # immutable role/task context snapshots
478
+ contexts/ # immutable canonical Context Envelopes
477
479
  test/ # Change-scoped test reports
478
480
  review/ # Change-scoped review workers and summary
479
481
  delivery/ # Change-scoped delivery evidence
@@ -585,8 +587,9 @@ host's existing model session.
585
587
  - **A generated view disagrees with MCP:** trust `.ultra/.runtime/state.db`; never edit
586
588
  `.ultra/.runtime/projections/` by hand.
587
589
  - **A draft checkpoint is rejected:** use `ultra-status` to read the exact warnings
588
- and blockers, fix the same mutable draft, and retry. Use `workflow.abandon` through
589
- `ultra.record` only when intentionally cancelling the attempt.
590
+ and blockers, fix the same mutable draft, and retry. If the attempt is no longer
591
+ relevant, leave it as history and open a new draft revision; no hidden workflow
592
+ state must be cancelled first.
590
593
  - **Kimi reports a native-module ABI error:** ensure an external Node.js 22+
591
594
  executable is available on `PATH`; the generated Kimi MCP launcher uses
592
595
  `env node`.
@@ -616,7 +619,7 @@ and `test:rest`.
616
619
  |---|---|
617
620
  | [Architecture](./docs/ARCHITECTURE.md) | Components, authority boundaries, and live integration paths |
618
621
  | [Workflow Lifecycle](./docs/WORKFLOW-LIFECYCLE.md) | Command ownership, transitions, invalidation, recovery, and convergence |
619
- | [Runtime Compatibility Matrix](./docs/RUNTIME-COMPAT-MATRIX.md) | Claude Code, OpenCode, Codex, and Kimi presentation details |
622
+ | [Runtime Compatibility Matrix](./docs/RUNTIME-COMPAT-MATRIX.md) | Claude Code, OpenCode, Codex, Kimi Code, and Grok Build presentation details |
620
623
  | [Legacy CLI Crosswalk](./docs/LEGACY-CLI-CROSSWALK.md) | What was preserved, strengthened, or replaced from the original Ultra Builder Pro |
621
624
  | [Agent Context](./docs/AGENT-CONTEXT.md) | Context Manifest and host-agent execution contract |
622
625
  | [Plugin Isolation Contract](./docs/PLUGIN-ISOLATION-CONTRACT.md) | Plugin ownership, explicit activation, idle behavior, and user-instruction isolation |
@@ -30,44 +30,6 @@ const {
30
30
 
31
31
  const PLUGIN_NAME = 'ultra-builder-pro';
32
32
  const MANAGED_MARKER = 'Managed by Ultra Builder Pro Codex adapter.';
33
- const CODEX_NATIVE_MCP_REPLACEMENTS = Object.freeze({
34
- 'review.run': {
35
- surface: 'native_custom_agents',
36
- replacement: '$ultra-builder-pro:ultra-review with the installed review-* agents',
37
- },
38
- 'review.verdict': {
39
- surface: 'native_custom_agents',
40
- replacement: 'review-coordinator synthesis using the Ultra unified review artifact',
41
- },
42
- 'impact.radius': {
43
- surface: 'codex_code_discovery',
44
- replacement: 'indexed code graph tools when current, otherwise targeted repository reads',
45
- },
46
- 'impact.changes': {
47
- surface: 'codex_code_discovery',
48
- replacement: 'git diff plus indexed code graph tools when current',
49
- },
50
- 'impact.dependents': {
51
- surface: 'codex_code_discovery',
52
- replacement: 'indexed caller/dependency tracing when current, otherwise targeted repository search',
53
- },
54
- 'skill.resolve': {
55
- surface: 'plugin_skill_discovery',
56
- replacement: 'Codex plugin skill discovery with explicit $ultra-builder-pro:<skill> invocation',
57
- },
58
- 'skill.manifest': {
59
- surface: 'plugin_skill_discovery',
60
- replacement: 'the installed plugin skill SKILL.md and agents/openai.yaml contract',
61
- },
62
- 'ask.question': {
63
- surface: 'request_user_input',
64
- replacement: 'use request_user_input when available, otherwise ask one concise direct question',
65
- },
66
- 'ask.menu': {
67
- surface: 'request_user_input',
68
- replacement: 'use request_user_input when available, otherwise present one concise direct choice',
69
- },
70
- });
71
33
  const COMMAND_NAMES = Object.freeze(CORE_PUBLIC_SKILLS.filter((name) => name !== 'ultra-review'));
72
34
  const SKILL_REFERENCE_NAMES = Object.freeze([
73
35
  ...COMMAND_NAMES,
@@ -77,6 +39,11 @@ const SKILL_REFERENCE_NAMES = Object.freeze([
77
39
  ]);
78
40
  const CODEX_PRIMARY_SKILLS = new Set([...COMMAND_NAMES, 'ultra-review']);
79
41
  const TEXT_EXTENSIONS = new Set(['.md', '.json', '.py', '.sh', '.txt', '.yaml', '.yml']);
42
+ const NATIVE_PACKAGES = Object.freeze([
43
+ 'better-sqlite3',
44
+ 'bindings',
45
+ 'file-uri-to-path',
46
+ ]);
80
47
 
81
48
  function titleCase(name) {
82
49
  const special = { 'cc-collab': 'Claude Code Collaboration' };
@@ -273,7 +240,7 @@ function buildHooksManifest(pluginRoot) {
273
240
  };
274
241
  }
275
242
 
276
- function copyHooks(repoRoot, pluginRoot) {
243
+ function copyHooks(repoRoot, pluginRoot, publishedRoot = pluginRoot) {
277
244
  const sourceRoot = path.join(repoRoot, 'hooks');
278
245
  const targetRoot = path.join(pluginRoot, 'hooks');
279
246
  ensureDir(targetRoot);
@@ -287,7 +254,7 @@ function copyHooks(repoRoot, pluginRoot) {
287
254
  );
288
255
  writeAtomic(
289
256
  path.join(targetRoot, 'hooks.json'),
290
- JSON.stringify(buildHooksManifest(pluginRoot), null, 2) + '\n',
257
+ JSON.stringify(buildHooksManifest(publishedRoot), null, 2) + '\n',
291
258
  );
292
259
  }
293
260
 
@@ -322,6 +289,8 @@ function buildMcpRuntime(repoRoot, pluginRoot, { runtime = 'codex' } = {}) {
322
289
  buildRoot,
323
290
  '--no-cache',
324
291
  '--quiet',
292
+ '-e',
293
+ 'better-sqlite3',
325
294
  ], {
326
295
  cwd: repoRoot,
327
296
  encoding: 'utf8',
@@ -347,6 +316,8 @@ function buildMcpRuntime(repoRoot, pluginRoot, { runtime = 'codex' } = {}) {
347
316
  cliBuildRoot,
348
317
  '--no-cache',
349
318
  '--quiet',
319
+ '-e',
320
+ 'better-sqlite3',
350
321
  ], {
351
322
  cwd: repoRoot,
352
323
  encoding: 'utf8',
@@ -386,6 +357,8 @@ function buildMcpRuntime(repoRoot, pluginRoot, { runtime = 'codex' } = {}) {
386
357
  workerBuildRoot,
387
358
  '--no-cache',
388
359
  '--quiet',
360
+ '-e',
361
+ 'better-sqlite3',
389
362
  ], {
390
363
  cwd: repoRoot,
391
364
  encoding: 'utf8',
@@ -416,6 +389,52 @@ function buildMcpRuntime(repoRoot, pluginRoot, { runtime = 'codex' } = {}) {
416
389
  fs.copyFileSync(sourceFile, path.join(runtimeRoot, supportFile));
417
390
  }
418
391
 
392
+ const nodeModulesRoot = path.join(runtimeRoot, 'node_modules');
393
+ for (const packageName of NATIVE_PACKAGES) {
394
+ let packageFile;
395
+ try {
396
+ packageFile = require.resolve(`${packageName}/package.json`, { paths: [repoRoot] });
397
+ } catch (error) {
398
+ throw new Error(`Ultra native runtime dependency ${packageName} is unavailable: ${error.message}`);
399
+ }
400
+ copyTree(
401
+ path.dirname(packageFile),
402
+ path.join(nodeModulesRoot, packageName),
403
+ );
404
+ }
405
+ const nativeRelative = path.join(
406
+ 'node_modules',
407
+ 'better-sqlite3',
408
+ 'build',
409
+ 'Release',
410
+ 'better_sqlite3.node',
411
+ );
412
+ const nativeFile = path.join(runtimeRoot, nativeRelative);
413
+ if (!fs.existsSync(nativeFile) || !fs.statSync(nativeFile).isFile()) {
414
+ throw new Error(`Ultra native SQLite driver is missing after staging: ${nativeFile}`);
415
+ }
416
+ const betterSqlitePackage = JSON.parse(fs.readFileSync(
417
+ path.join(nodeModulesRoot, 'better-sqlite3', 'package.json'),
418
+ 'utf8',
419
+ ));
420
+ writeAtomic(path.join(runtimeRoot, 'native-runtime.json'), JSON.stringify({
421
+ schema_version: 1,
422
+ platform: process.platform,
423
+ arch: process.arch,
424
+ modules: process.versions.modules,
425
+ node_version: process.versions.node,
426
+ package: {
427
+ name: 'better-sqlite3',
428
+ version: betterSqlitePackage.version,
429
+ },
430
+ native_module: nativeRelative.split(path.sep).join('/'),
431
+ native_sha256: crypto.createHash('sha256').update(fs.readFileSync(nativeFile)).digest('hex'),
432
+ }, null, 2) + '\n');
433
+ fs.copyFileSync(
434
+ path.join(repoRoot, 'adapters', '_shared', 'runtime-native.cjs'),
435
+ path.join(runtimeRoot, 'runtime-native.cjs'),
436
+ );
437
+
419
438
  const runtimeBootstrap = runtime === 'kimi' ? `
420
439
  const fs = require('node:fs');
421
440
  const pluginRoot = path.resolve(__dirname, '..');
@@ -443,10 +462,12 @@ if (!process.env.UBP_ROOT_DIR) {
443
462
  const launcher = `'use strict';
444
463
 
445
464
  const path = require('node:path');
465
+ const { inspectRuntimeNative } = require('./runtime-native.cjs');
446
466
 
447
467
  process.env.UBP_RUNTIME_ROOT = path.resolve(__dirname, '..');
448
468
  ${runtimeBootstrap}
449
469
 
470
+ inspectRuntimeNative(__dirname);
450
471
  const { main } = require('./index.cjs');
451
472
 
452
473
  main().catch((error) => {
@@ -456,8 +477,8 @@ main().catch((error) => {
456
477
  `;
457
478
  writeAtomic(path.join(runtimeRoot, 'launch.cjs'), launcher);
458
479
  fs.copyFileSync(
459
- path.join(repoRoot, 'mcp-server', 'breadcrumb.cjs'),
460
- path.join(runtimeRoot, 'breadcrumb.cjs'),
480
+ path.join(repoRoot, 'mcp-server', 'hook-context.cjs'),
481
+ path.join(runtimeRoot, 'hook-context.cjs'),
461
482
  );
462
483
  fs.copyFileSync(
463
484
  path.join(repoRoot, 'mcp-server', 'hook-event.cjs'),
@@ -470,11 +491,7 @@ main().catch((error) => {
470
491
 
471
492
  const sourceToolsFile = path.join(repoRoot, 'spec', 'mcp-tools.yaml');
472
493
  const upstreamManifest = yaml.load(fs.readFileSync(sourceToolsFile, 'utf8'));
473
- const {
474
- LEGACY_TOOLS,
475
- PUBLIC_TOOLS,
476
- REGISTERED_TOOLS,
477
- } = require(path.join(repoRoot, 'mcp-server', 'server.cjs'));
494
+ const { REGISTERED_TOOLS } = require(path.join(repoRoot, 'mcp-server', 'server.cjs'));
478
495
  const registered = new Set(REGISTERED_TOOLS);
479
496
  const liveFamilies = new Set(
480
497
  upstreamManifest.tools.filter((tool) => registered.has(tool.name)).map((tool) => tool.family),
@@ -495,15 +512,6 @@ main().catch((error) => {
495
512
  path.join(specRoot, 'interaction-contract.json'),
496
513
  JSON.stringify(interactionContract(runtime), null, 2) + '\n',
497
514
  );
498
- if (runtime === 'codex') {
499
- fs.copyFileSync(sourceToolsFile, path.join(specRoot, 'upstream-mcp-tools.yaml'));
500
- writeAtomic(path.join(specRoot, 'codex-capability-map.json'), JSON.stringify({
501
- runtime: 'codex',
502
- live_mcp_tools: PUBLIC_TOOLS,
503
- compatibility_mcp_tools: LEGACY_TOOLS,
504
- codex_native_replacements: CODEX_NATIVE_MCP_REPLACEMENTS,
505
- }, null, 2) + '\n');
506
- }
507
515
  const sourceSchema = path.join(repoRoot, 'spec', 'schemas', 'state-db.sql');
508
516
  const targetSchema = path.join(specRoot, 'schemas', 'state-db.sql');
509
517
  ensureDir(path.dirname(targetSchema));
@@ -521,9 +529,49 @@ main().catch((error) => {
521
529
  launcher: path.join(runtimeRoot, 'launch.cjs'),
522
530
  bundle: path.join(runtimeRoot, 'index.cjs'),
523
531
  ultraTools: path.join(runtimeRoot, 'ultra-tools.cjs'),
532
+ nativeManifest: path.join(runtimeRoot, 'native-runtime.json'),
524
533
  };
525
534
  }
526
535
 
536
+ function mcpCommand(launcher) {
537
+ if (process.platform === 'win32') {
538
+ return { command: 'node.exe', args: [launcher] };
539
+ }
540
+ return { command: '/usr/bin/env', args: ['node', launcher] };
541
+ }
542
+
543
+ function inspectInstalledRuntime(runtimeRoot) {
544
+ const report = {
545
+ status: 'healthy',
546
+ checks: {},
547
+ issues: [],
548
+ };
549
+ try {
550
+ const detail = require(path.join(runtimeRoot, 'runtime-native.cjs'))
551
+ .inspectRuntimeNative(runtimeRoot);
552
+ report.checks.native_runtime = { status: 'pass', ...detail };
553
+ } catch (error) {
554
+ report.status = 'degraded';
555
+ report.checks.native_runtime = { status: 'fail' };
556
+ report.issues.push({
557
+ code: error.code || 'RUNTIME_NATIVE_MISSING',
558
+ message: error.message,
559
+ ...(error.details || {}),
560
+ });
561
+ }
562
+ return report;
563
+ }
564
+
565
+ function applyNativeDoctor(report, runtimeRoot) {
566
+ const native = inspectInstalledRuntime(runtimeRoot);
567
+ report.checks = { ...(report.checks || {}), ...native.checks };
568
+ report.issues = [...(report.issues || []), ...native.issues];
569
+ if (report.status !== 'missing') {
570
+ report.status = report.issues.length === 0 ? 'healthy' : 'degraded';
571
+ }
572
+ return report;
573
+ }
574
+
527
575
  function pluginContentHash(pluginRoot, baseVersion) {
528
576
  const hash = crypto.createHash('sha256');
529
577
  hash.update(baseVersion);
@@ -535,13 +583,14 @@ function pluginContentHash(pluginRoot, baseVersion) {
535
583
  return hash.digest('hex').slice(0, 12);
536
584
  }
537
585
 
538
- function buildPlugin({ repoRoot, pluginRoot }) {
586
+ function buildPlugin({ repoRoot, pluginRoot, publishedRoot = pluginRoot }) {
539
587
  if (fs.existsSync(pluginRoot)) {
540
588
  const marker = path.join(pluginRoot, '.ubp-managed');
541
- if (!fs.existsSync(marker)) {
589
+ const entries = fs.readdirSync(pluginRoot);
590
+ if (entries.length > 0 && !fs.existsSync(marker)) {
542
591
  throw new Error(`refusing to replace unmanaged plugin directory: ${pluginRoot}`);
543
592
  }
544
- removeTree(pluginRoot);
593
+ if (entries.length > 0) removeTree(pluginRoot);
545
594
  }
546
595
  ensureDir(pluginRoot);
547
596
 
@@ -555,14 +604,18 @@ function buildPlugin({ repoRoot, pluginRoot }) {
555
604
  installedSkills.push(name);
556
605
  }
557
606
 
558
- copyHooks(repoRoot, pluginRoot);
607
+ copyHooks(repoRoot, pluginRoot, publishedRoot);
559
608
  const mcpRuntime = buildMcpRuntime(repoRoot, pluginRoot);
609
+ const command = mcpCommand(path.join(
610
+ publishedRoot,
611
+ path.relative(pluginRoot, mcpRuntime.launcher),
612
+ ));
560
613
  writeAtomic(path.join(pluginRoot, '.mcp.json'), JSON.stringify({
561
614
  mcpServers: {
562
615
  [PLUGIN_NAME]: {
563
616
  type: 'stdio',
564
- command: process.execPath,
565
- args: [mcpRuntime.launcher],
617
+ command: command.command,
618
+ args: command.args,
566
619
  },
567
620
  },
568
621
  }, null, 2) + '\n');
@@ -576,7 +629,7 @@ function buildPlugin({ repoRoot, pluginRoot }) {
576
629
  const manifest = {
577
630
  name: PLUGIN_NAME,
578
631
  version,
579
- description: 'Codex-native Ultra Builder Pro workflows, agents, hooks, and MCP task state.',
632
+ description: 'Codex-native Ultra Builder Pro workflows with a persistent safety kernel.',
580
633
  author: { name: typeof pkg.author === 'string' ? pkg.author : 'Ultra Builder Pro contributors' },
581
634
  homepage: pkg.homepage,
582
635
  repository: 'https://github.com/rocky2431/ultra-builder-pro-cli',
@@ -587,7 +640,7 @@ function buildPlugin({ repoRoot, pluginRoot }) {
587
640
  interface: {
588
641
  displayName: 'Ultra Builder Pro',
589
642
  shortDescription: 'Codex-native engineering workflows and verification gates.',
590
- longDescription: 'Complete Codex adaptation of Ultra Builder Pro skills, command workflows, custom agents, lifecycle hooks, and project-local MCP state.',
643
+ longDescription: 'Complete Codex adaptation of Ultra Builder Pro skills, command workflows, custom agents, lifecycle hooks, and a project-local persistence and safety kernel.',
591
644
  developerName: typeof pkg.author === 'string' ? pkg.author : 'Ultra Builder Pro contributors',
592
645
  category: 'Developer Tools',
593
646
  capabilities: ['Interactive', 'Write'],
@@ -602,7 +655,7 @@ function buildPlugin({ repoRoot, pluginRoot }) {
602
655
  };
603
656
  writeAtomic(path.join(pluginRoot, '.codex-plugin', 'plugin.json'), JSON.stringify(manifest, null, 2) + '\n');
604
657
  writeAtomic(path.join(pluginRoot, '.ubp-managed'), JSON.stringify({ source: 'ubp', adapter: 'codex', version }, null, 2) + '\n');
605
- return { root: pluginRoot, version, skills: installedSkills.sort() };
658
+ return { root: publishedRoot, version, skills: installedSkills.sort() };
606
659
  }
607
660
 
608
661
  function tomlMultiline(value) {
@@ -663,6 +716,9 @@ module.exports = {
663
716
  buildCommandMap,
664
717
  buildHooksManifest,
665
718
  buildMcpRuntime,
719
+ inspectInstalledRuntime,
720
+ applyNativeDoctor,
721
+ mcpCommand,
666
722
  buildPlugin,
667
723
  buildAgentToml,
668
724
  installAgents,
@@ -23,10 +23,15 @@ const SURFACES = Object.freeze({
23
23
  fallback: 'direct_user_interaction',
24
24
  availability: 'interactive_non_auto_mode',
25
25
  }),
26
+ grok: Object.freeze({
27
+ primary: 'AskUserQuestion',
28
+ fallback: 'direct_user_interaction',
29
+ availability: 'interactive_session',
30
+ }),
26
31
  });
27
32
 
28
33
  const GENERIC_QUESTION_GUIDANCE =
29
- /Use the host-native structured question surface declared by the installed interaction\s+contract(?: when it exists)?\./g;
34
+ /Use the host-native (?:structured )?question surface declared by the installed interaction\s+contract(?: when it exists)?(?:;?\s+prefer its structured form when the host exposes one)?\./g;
30
35
 
31
36
  function interactionContract(runtime) {
32
37
  const question = SURFACES[runtime];
@@ -106,6 +111,7 @@ function interactionPrompt(runtime) {
106
111
  codex: 'Codex',
107
112
  opencode: 'OpenCode',
108
113
  kimi: 'Kimi Code',
114
+ grok: 'Grok Build',
109
115
  }[runtime];
110
116
  const primary = runtime === 'opencode' ? `\`${surface.primary}\`` : surface.primary;
111
117
  return `Use ${host} ${primary} when ${surface.availability.replaceAll('_', ' ')} permits it.`;
@@ -187,7 +187,8 @@ function assetRefsForTree(rootName, root, { exclude = [] } = {}) {
187
187
  function writeProvenance({
188
188
  file, adapter, packageInfo, repository, sourceCommit: commit = null,
189
189
  sourceDirty: dirty = null, sourceWorktreeDigest: worktreeDigest = null,
190
- roots: inputRoots, assets: inputAssets, contracts: inputContracts = {},
190
+ roots: inputRoots, assetRoots: inputAssetRoots = inputRoots,
191
+ assets: inputAssets, contracts: inputContracts = {},
191
192
  }) {
192
193
  if (!file || !adapter || !packageInfo?.name || !packageInfo?.version || !repository) {
193
194
  throw new Error('provenance file, adapter, package, version, and repository are required');
@@ -199,9 +200,13 @@ function writeProvenance({
199
200
  throw new Error('provenance source worktree digest must be a SHA-256 digest or null');
200
201
  }
201
202
  const roots = normalizeRoots(inputRoots);
203
+ const assetRoots = normalizeRoots(inputAssetRoots);
204
+ for (const root of Object.keys(roots)) {
205
+ if (!assetRoots[root]) throw new Error(`missing provenance asset root: ${root}`);
206
+ }
202
207
  const refs = normalizeAssetRefs(inputAssets, roots);
203
208
  const assets = refs.map((ref) => {
204
- const { target } = resolveRef(roots, ref);
209
+ const { target } = resolveRef(assetRoots, ref);
205
210
  const stat = fs.statSync(target);
206
211
  if (!stat.isFile()) throw new Error(`provenance asset is not a file: ${target}`);
207
212
  return { ...ref, size_bytes: stat.size, sha256: hashFile(target) };
@@ -56,13 +56,14 @@ const INTERNAL_AGENT_SKILLS = Object.freeze([
56
56
  'testing-rules',
57
57
  ]);
58
58
 
59
- const SUPPORTED_RUNTIMES = Object.freeze(['claude', 'opencode', 'codex', 'kimi']);
59
+ const SUPPORTED_RUNTIMES = Object.freeze(['claude', 'opencode', 'codex', 'kimi', 'grok']);
60
60
 
61
61
  const COLLAB_SKILLS_BY_RUNTIME = Object.freeze({
62
62
  claude: Object.freeze(['codex-collab', 'ultra-verify']),
63
63
  codex: Object.freeze(['cc-collab', 'ultra-verify']),
64
64
  opencode: Object.freeze(['cc-collab', 'codex-collab', 'ultra-verify']),
65
65
  kimi: Object.freeze(['cc-collab', 'codex-collab', 'ultra-verify']),
66
+ grok: Object.freeze(['cc-collab', 'codex-collab', 'ultra-verify']),
66
67
  });
67
68
 
68
69
  const MCP_DEPENDENT_SKILLS = Object.freeze([
@@ -80,7 +81,7 @@ const MCP_DEPENDENT_SKILLS = Object.freeze([
80
81
 
81
82
  const WORKFLOW_HOOK_FILES = Object.freeze([
82
83
  'active_task_context.py',
83
- 'context_spine.py',
84
+ 'context_envelope.py',
84
85
  'health_check.py',
85
86
  'pre_stop_check.py',
86
87
  'runtime_paths.py',