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.
- package/.ultra-template/docs/research/README.md +4 -4
- package/CHANGELOG.md +45 -0
- package/README.md +21 -18
- package/adapters/_shared/codex-assets.cjs +121 -65
- package/adapters/_shared/interaction-contract.cjs +7 -1
- package/adapters/_shared/provenance.cjs +7 -2
- package/adapters/_shared/runtime-assets.cjs +3 -2
- package/adapters/_shared/runtime-native.cjs +132 -0
- package/adapters/claude.js +60 -30
- package/adapters/codex.js +178 -81
- package/adapters/grok.js +372 -0
- package/adapters/kimi.js +7 -3
- package/adapters/opencode.js +210 -32
- package/agents/code-reviewer.md +4 -2
- package/agents/debugger.md +4 -1
- package/agents/review-code.md +7 -3
- package/agents/review-comments.md +7 -4
- package/agents/review-coordinator.md +11 -7
- package/agents/review-design.md +8 -4
- package/agents/review-errors.md +8 -4
- package/agents/review-spec.md +8 -5
- package/agents/review-tests.md +7 -4
- package/agents/tdd-runner.md +5 -2
- package/bin/install.js +9 -4
- package/bin/orchestrator.js +4 -13
- package/docs/AGENT-CONTEXT.md +141 -229
- package/docs/ARCHITECTURE.md +203 -494
- package/docs/ARTIFACT-AUTHORITY.md +26 -22
- package/docs/PLUGIN-ISOLATION-CONTRACT.md +12 -9
- package/docs/ROADMAP.md +85 -110
- package/docs/RUNTIME-COMPAT-MATRIX.md +139 -175
- package/docs/SKILL-AUTHORING.md +3 -3
- package/docs/STATE-DB-ACCESS-POLICY.md +13 -8
- package/docs/WORKFLOW-LIFECYCLE.md +174 -448
- package/hooks/README.md +11 -8
- package/hooks/active_task_context.py +16 -16
- package/hooks/adapters/grok.py +134 -0
- package/hooks/{context_spine.py → context_envelope.py} +26 -22
- package/hooks/health_check.py +19 -29
- package/hooks/pre_stop_check.py +22 -12
- package/hooks/subagent_tracker.py +1 -1
- package/hooks/workflow_checkpoint.py +14 -13
- package/hooks/workflow_context.py +11 -12
- package/hooks/workflow_resume.py +14 -13
- package/mcp-server/{breadcrumb.cjs → hook-context.cjs} +7 -9
- package/mcp-server/lib/baseline-workflow.cjs +36 -38
- package/mcp-server/lib/canonical-json.cjs +19 -0
- package/mcp-server/lib/change-workflow.cjs +596 -44
- package/mcp-server/lib/context-envelope.cjs +508 -0
- package/mcp-server/lib/decision-records.cjs +337 -0
- package/mcp-server/lib/doctor.cjs +91 -33
- package/mcp-server/lib/init-project.cjs +78 -39
- package/mcp-server/lib/managed-file-write.cjs +116 -0
- package/mcp-server/lib/plan-checkpoint.cjs +177 -0
- package/mcp-server/lib/project-context.cjs +178 -0
- package/mcp-server/lib/stage-checkpoints.cjs +309 -0
- package/mcp-server/lib/state-db.cjs +155 -24
- package/mcp-server/lib/task-ledger.cjs +522 -13
- package/mcp-server/lib/ultra-facade.cjs +630 -442
- package/mcp-server/lib/worker-packet.cjs +358 -0
- package/mcp-server/server.cjs +200 -1103
- package/orchestrator/daemon.cjs +27 -9
- package/orchestrator/parallel-orchestrator.cjs +111 -76
- package/orchestrator/session-runner.cjs +135 -34
- package/package.json +10 -3
- package/skills/ultra-change/SKILL.md +9 -8
- package/skills/ultra-deliver/SKILL.md +3 -3
- package/skills/ultra-dev/SKILL.md +18 -11
- package/skills/ultra-doctor/SKILL.md +2 -2
- package/skills/ultra-init/SKILL.md +6 -5
- package/skills/ultra-init/references/brownfield-adoption.md +11 -8
- package/skills/ultra-plan/SKILL.md +10 -8
- package/skills/ultra-research/SKILL.md +12 -7
- package/skills/ultra-review/SKILL.md +9 -6
- package/skills/ultra-review/references/unified-schema.md +2 -0
- package/skills/ultra-review/scripts/review_wait.py +8 -0
- package/skills/ultra-status/SKILL.md +2 -2
- package/skills/ultra-test/SKILL.md +4 -2
- package/skills/ultra-think/SKILL.md +7 -7
- package/skills/ultra-think/references/interaction-boundary.md +56 -0
- package/spec/cli-protocol.md +80 -199
- package/spec/mcp-tools.yaml +37 -2804
- package/spec/schemas/state-db.sql +107 -4
- package/spec/schemas/{task-ledger.v1.schema.json → task-ledger.v2.schema.json} +70 -6
- package/ultra-tools/commands/status.cjs +369 -243
- package/mcp-server/lib/context-spine.cjs +0 -1208
- package/mcp-server/lib/decision-dialogue.cjs +0 -1128
- package/mcp-server/lib/project-breadcrumb.cjs +0 -173
- package/mcp-server/lib/spec-learning.cjs +0 -284
- package/mcp-server/lib/workflow-state.cjs +0 -3129
- 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,
|
|
53
|
-
|
|
54
|
-
the authoritative gap ledger. The final synthesis also binds the
|
|
55
|
-
and research distillate. Do not create a condensed duplicate
|
|
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,
|
|
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,
|
|
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
|
|
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** |
|
|
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
|
-
|
|
130
|
-
|
|
131
|
-
|
|
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**,
|
|
169
|
-
|
|
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 #
|
|
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
|
-
|
|
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
|
|
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.
|
|
589
|
-
|
|
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
|
|
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(
|
|
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', '
|
|
460
|
-
path.join(runtimeRoot, '
|
|
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
|
-
|
|
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:
|
|
565
|
-
args:
|
|
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
|
|
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
|
|
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:
|
|
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,
|
|
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(
|
|
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
|
-
'
|
|
84
|
+
'context_envelope.py',
|
|
84
85
|
'health_check.py',
|
|
85
86
|
'pre_stop_check.py',
|
|
86
87
|
'runtime_paths.py',
|