ultra-builder-pro-cli 0.26.2 → 5.0.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/contexts/TEMPLATE.md +70 -29
- package/.ultra-template/north-star.md +35 -18
- package/.ultra-template/tasks.json +1 -0
- package/.ultra-template/test-report.json +17 -1
- package/CHANGELOG.md +235 -1
- package/README.md +210 -50
- package/README.zh-CN.md +440 -0
- package/adapters/_shared/host-profile.cjs +3 -95
- package/adapters/_shared/plugin-core.cjs +61 -5
- package/adapters/_shared/runtime-assets.cjs +66 -5
- package/adapters/zcode.js +375 -0
- package/bin/delegate-worker.cjs +2 -325
- package/bin/delegate.cjs +3 -461
- package/bin/install.js +11 -6
- package/docs/ARCHITECTURE.md +133 -31
- package/docs/ARTIFACT-AUTHORITY.md +185 -24
- package/docs/DECISIONS.md +153 -18
- package/docs/PHILOSOPHY.md +58 -7
- package/docs/PLUGIN-ISOLATION-CONTRACT.md +34 -12
- package/docs/RUNTIME-COMPAT-MATRIX.md +195 -23
- package/docs/SKILL-AUTHORING.md +19 -6
- package/docs/WORKFLOW-LIFECYCLE.md +196 -44
- package/docs/evals/adversarial-review-2026-08-14.md +84 -0
- package/docs/evals/ultra-5-0-journey-results.md +62 -0
- package/docs/evals/ultra-5-0-live-acp-conformance.md +93 -0
- package/docs/evals/ultra-5-0-route-journeys.md +145 -0
- package/docs/evals/zcode-automation-2026-08-14.md +103 -0
- package/hooks/README.md +27 -4
- package/hooks/_common.py +1678 -61
- package/hooks/adapters/zcode.py +227 -0
- package/hooks/compact_context.py +176 -17
- package/hooks/mid_workflow_recall.py +27 -5
- package/hooks/post_edit_guard.py +133 -23
- package/hooks/session_context.py +707 -22
- package/package.json +7 -3
- package/skills/ultra-change/SKILL.md +69 -12
- package/skills/ultra-change/references/change-contract.md +93 -27
- package/skills/ultra-change/references/execution-grant.md +109 -0
- package/skills/ultra-change/references/primary-transfer.md +273 -0
- package/skills/ultra-change/scripts/validate_primary_transfer.cjs +1928 -0
- package/skills/ultra-delegate/SKILL.md +103 -8
- package/skills/ultra-delegate/patches/zcode-acp-0.1.0-zcode-0.16.5.patch +184 -0
- package/skills/ultra-delegate/references/delegation-contract.md +80 -1
- package/skills/ultra-delegate/scripts/acp-conformance.cjs +287 -0
- package/skills/ultra-delegate/scripts/acp-driver.cjs +762 -0
- package/skills/ultra-delegate/scripts/agent-execution-driver.cjs +320 -0
- package/skills/ultra-delegate/scripts/cli-driver.cjs +61 -0
- package/skills/ultra-delegate/scripts/delegate-worker.cjs +328 -0
- package/skills/ultra-delegate/scripts/delegate.cjs +690 -0
- package/skills/ultra-delegate/scripts/host-profile.cjs +267 -0
- package/skills/ultra-deliver/SKILL.md +98 -11
- package/skills/ultra-dev/SKILL.md +188 -42
- package/skills/ultra-grilling/SKILL.md +10 -7
- package/skills/ultra-grilling/references/reframing.md +7 -3
- package/skills/ultra-init/SKILL.md +56 -7
- package/skills/ultra-init/scripts/init_project.cjs +968 -21
- package/skills/ultra-plan/SKILL.md +91 -47
- package/skills/ultra-plan/references/task-evidence-v2.md +300 -0
- package/skills/ultra-plan/scripts/validate_task_evidence.cjs +859 -0
- package/skills/ultra-research/SKILL.md +70 -14
- package/skills/ultra-research/references/04-product-strategy.md +11 -2
- package/skills/ultra-research/references/21-features-scope.md +8 -0
- package/skills/ultra-research/references/22-success-metrics.md +4 -3
- package/skills/ultra-research/references/99-synthesis.md +19 -2
- package/skills/ultra-research/references/north-star-v2.md +168 -0
- package/skills/ultra-research/references/wayfinding.md +8 -0
- package/skills/ultra-research/scripts/validate_north_star.cjs +1174 -0
- package/skills/ultra-review/SKILL.md +201 -27
- package/skills/ultra-review/references/adversarial-evaluation.md +31 -0
- package/skills/ultra-review/references/spec.md +5 -0
- package/skills/ultra-review/references/unified-schema.md +146 -11
- package/skills/ultra-review/references/worker-packet.md +151 -8
- package/skills/ultra-review/scripts/review_wait.py +2653 -63
- package/skills/ultra-status/SKILL.md +129 -15
- package/skills/ultra-status/references/route-contract.md +100 -0
- package/skills/ultra-tdd/SKILL.md +11 -4
- package/skills/ultra-tdd/references/test-execution.md +6 -1
- package/skills/ultra-test/SKILL.md +161 -18
- package/skills/ultra-test/scripts/validate_review_transport.cjs +549 -0
- package/skills/ultra-test/scripts/worktree_digest.cjs +518 -30
- /package/{adapters/_shared → skills/ultra-delegate/scripts}/delegate-profiles/kimi-read-only.md +0 -0
- /package/{adapters/_shared → skills/ultra-delegate/scripts}/delegate-profiles/kimi-write.md +0 -0
package/bin/delegate.cjs
CHANGED
|
@@ -1,463 +1,5 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
const { execFileSync, spawn } = require('node:child_process');
|
|
7
|
-
|
|
8
|
-
const { hostProfile } = require('../adapters/_shared/host-profile.cjs');
|
|
9
|
-
const { writeAtomic } = require('../adapters/_shared/file-ops.cjs');
|
|
10
|
-
|
|
11
|
-
const PERMISSION_SCHEMA = 'ultra-delegation-permission-v1';
|
|
12
|
-
const RECEIPT_SCHEMA = 'ultra-delegation-receipt-v1';
|
|
13
|
-
const RESULT_SCHEMA = 'ultra-delegation-result-v1';
|
|
14
|
-
const PERMISSION_FIELDS = new Set(['$schema', 'writable_roots', 'external_effects']);
|
|
15
|
-
const PROTECTED_ROOT = '.ultra';
|
|
16
|
-
const RESULT_JSON_SCHEMA = Object.freeze({
|
|
17
|
-
type: 'object',
|
|
18
|
-
additionalProperties: false,
|
|
19
|
-
required: [
|
|
20
|
-
'$schema', 'status', 'summary', 'changed_files', 'checks', 'evidence',
|
|
21
|
-
'questions', 'residual_risks',
|
|
22
|
-
],
|
|
23
|
-
properties: {
|
|
24
|
-
$schema: { const: RESULT_SCHEMA },
|
|
25
|
-
status: { enum: ['finished', 'blocked', 'failed'] },
|
|
26
|
-
summary: { type: 'string', minLength: 1 },
|
|
27
|
-
changed_files: {
|
|
28
|
-
type: 'array', uniqueItems: true, items: { type: 'string', minLength: 1 },
|
|
29
|
-
},
|
|
30
|
-
checks: {
|
|
31
|
-
type: 'array',
|
|
32
|
-
items: {
|
|
33
|
-
type: 'object',
|
|
34
|
-
additionalProperties: false,
|
|
35
|
-
required: ['command', 'status'],
|
|
36
|
-
properties: {
|
|
37
|
-
command: { type: 'string', minLength: 1 },
|
|
38
|
-
status: { enum: ['passed', 'failed', 'not_run'] },
|
|
39
|
-
output_ref: { type: 'string', minLength: 1 },
|
|
40
|
-
},
|
|
41
|
-
},
|
|
42
|
-
},
|
|
43
|
-
evidence: { type: 'array', items: { type: 'string', minLength: 1 } },
|
|
44
|
-
questions: { type: 'array', items: { type: 'string', minLength: 1 } },
|
|
45
|
-
residual_risks: { type: 'array', items: { type: 'string', minLength: 1 } },
|
|
46
|
-
},
|
|
47
|
-
});
|
|
48
|
-
|
|
49
|
-
function inside(root, candidate) {
|
|
50
|
-
const relative = path.relative(root, candidate);
|
|
51
|
-
return relative !== '' && relative !== '..' && !relative.startsWith(`..${path.sep}`)
|
|
52
|
-
&& !path.isAbsolute(relative);
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
function atOrInside(root, candidate) {
|
|
56
|
-
return candidate === root || inside(root, candidate);
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
function projectPath(projectRoot, value, label, { directory = false } = {}) {
|
|
60
|
-
const lexical = path.resolve(projectRoot, value);
|
|
61
|
-
const resolved = fs.existsSync(lexical) ? fs.realpathSync(lexical) : lexical;
|
|
62
|
-
if (!inside(projectRoot, resolved)) throw new Error(`${label} must be inside the current project`);
|
|
63
|
-
if (directory && (!fs.existsSync(resolved) || !fs.statSync(resolved).isDirectory())) {
|
|
64
|
-
throw new Error(`${label} must be an existing directory`);
|
|
65
|
-
}
|
|
66
|
-
return resolved;
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
function sha256(file) {
|
|
70
|
-
return crypto.createHash('sha256').update(fs.readFileSync(file)).digest('hex');
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
function git(cwd, args) {
|
|
74
|
-
return execFileSync('git', args, {
|
|
75
|
-
cwd,
|
|
76
|
-
encoding: 'utf8',
|
|
77
|
-
maxBuffer: 16 * 1024 * 1024,
|
|
78
|
-
stdio: ['ignore', 'pipe', 'pipe'],
|
|
79
|
-
}).trim();
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
function observedChangedFiles(cwd, baseHead) {
|
|
83
|
-
const run = (args) => execFileSync('git', args, {
|
|
84
|
-
cwd,
|
|
85
|
-
encoding: 'buffer',
|
|
86
|
-
maxBuffer: 16 * 1024 * 1024,
|
|
87
|
-
stdio: ['ignore', 'pipe', 'pipe'],
|
|
88
|
-
}).toString('utf8').split('\0').filter(Boolean);
|
|
89
|
-
return [...new Set([
|
|
90
|
-
...run(['diff', '--name-only', '-z', baseHead, '--']),
|
|
91
|
-
...run(['ls-files', '--others', '--exclude-standard', '-z']),
|
|
92
|
-
].map((file) => file.split(path.sep).join('/')))].sort();
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
function validateWorktree(worktree) {
|
|
96
|
-
let top;
|
|
97
|
-
try {
|
|
98
|
-
top = fs.realpathSync(git(worktree, ['rev-parse', '--show-toplevel']));
|
|
99
|
-
} catch {
|
|
100
|
-
throw new Error('worktree must be a real Git worktree');
|
|
101
|
-
}
|
|
102
|
-
if (top !== worktree) throw new Error('worktree must be the root of a real Git worktree');
|
|
103
|
-
const registered = git(worktree, ['worktree', 'list', '--porcelain'])
|
|
104
|
-
.split('\n')
|
|
105
|
-
.filter((line) => line.startsWith('worktree '))
|
|
106
|
-
.map((line) => line.slice('worktree '.length))
|
|
107
|
-
.some((entry) => {
|
|
108
|
-
try { return fs.realpathSync(entry) === worktree; } catch { return false; }
|
|
109
|
-
});
|
|
110
|
-
if (!registered) throw new Error('worktree is not registered as a Git worktree');
|
|
111
|
-
const dirty = git(worktree, ['status', '--porcelain=v1', '--untracked-files=all']);
|
|
112
|
-
if (dirty) throw new Error('delegated Git worktree must start clean');
|
|
113
|
-
return git(worktree, ['rev-parse', 'HEAD']);
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
function readPermission(file, worktree) {
|
|
117
|
-
let payload;
|
|
118
|
-
try {
|
|
119
|
-
payload = JSON.parse(fs.readFileSync(file, 'utf8'));
|
|
120
|
-
} catch {
|
|
121
|
-
throw new Error('permission must be valid JSON');
|
|
122
|
-
}
|
|
123
|
-
if (!payload || Array.isArray(payload) || typeof payload !== 'object') {
|
|
124
|
-
throw new Error('permission must be a JSON object');
|
|
125
|
-
}
|
|
126
|
-
for (const key of Object.keys(payload)) {
|
|
127
|
-
if (!PERMISSION_FIELDS.has(key)) throw new Error(`unknown permission field: ${key}`);
|
|
128
|
-
}
|
|
129
|
-
if (payload.$schema !== PERMISSION_SCHEMA) {
|
|
130
|
-
throw new Error(`permission $schema must be ${PERMISSION_SCHEMA}`);
|
|
131
|
-
}
|
|
132
|
-
if (!Array.isArray(payload.writable_roots)) {
|
|
133
|
-
throw new Error('permission writable_roots must be an array');
|
|
134
|
-
}
|
|
135
|
-
const writableRoots = [];
|
|
136
|
-
const writableRootPaths = [];
|
|
137
|
-
for (const value of payload.writable_roots) {
|
|
138
|
-
if (typeof value !== 'string' || !value.trim() || path.isAbsolute(value)) {
|
|
139
|
-
throw new Error('permission writable_roots entries must be relative non-empty paths');
|
|
140
|
-
}
|
|
141
|
-
const resolved = path.resolve(worktree, value);
|
|
142
|
-
if (!atOrInside(worktree, resolved)) {
|
|
143
|
-
throw new Error('permission writable_roots must stay inside the delegated worktree');
|
|
144
|
-
}
|
|
145
|
-
if (!fs.existsSync(resolved) || !fs.statSync(resolved).isDirectory()) {
|
|
146
|
-
throw new Error(`permission writable_roots entry must be an existing directory: ${value}`);
|
|
147
|
-
}
|
|
148
|
-
const real = fs.realpathSync(resolved);
|
|
149
|
-
if (!atOrInside(worktree, real)) {
|
|
150
|
-
throw new Error('permission writable_roots must not escape through symlinks');
|
|
151
|
-
}
|
|
152
|
-
const normalized = path.relative(worktree, real).split(path.sep).join('/') || '.';
|
|
153
|
-
// `.ultra` is the project's memory and has exactly one writer: the primary host.
|
|
154
|
-
// Rejected here so the delegation never starts, and again against the actual diff
|
|
155
|
-
// in the worker, which also covers the `.` grant.
|
|
156
|
-
if (normalized === PROTECTED_ROOT || normalized.startsWith(`${PROTECTED_ROOT}/`)) {
|
|
157
|
-
throw new Error(`permission writable_roots must not include ${PROTECTED_ROOT}; the primary host is its only writer`);
|
|
158
|
-
}
|
|
159
|
-
if (!writableRoots.includes(normalized)) {
|
|
160
|
-
writableRoots.push(normalized);
|
|
161
|
-
writableRootPaths.push(real);
|
|
162
|
-
}
|
|
163
|
-
}
|
|
164
|
-
if (!Array.isArray(payload.external_effects)) {
|
|
165
|
-
throw new Error('permission external_effects must be an array');
|
|
166
|
-
}
|
|
167
|
-
if (payload.external_effects.length !== 0) {
|
|
168
|
-
throw new Error('permission external_effects must be empty; the primary host performs separately authorized effects');
|
|
169
|
-
}
|
|
170
|
-
return { writableRoots, writableRootPaths };
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
function delegatePrompt({ instruction, permission, worktree, readOnly }) {
|
|
174
|
-
return [
|
|
175
|
-
'Execute one bounded Ultra Builder Pro delegation in the isolated Git worktree.',
|
|
176
|
-
`Read the immutable instruction file: ${instruction}`,
|
|
177
|
-
`Read the immutable permission file: ${permission}`,
|
|
178
|
-
`Use this worktree as the only filesystem boundary: ${worktree}`,
|
|
179
|
-
readOnly
|
|
180
|
-
? 'This is read-only delegation. Do not create, modify, or delete any project file.'
|
|
181
|
-
: 'Modify only paths covered by permission.writable_roots.',
|
|
182
|
-
'Do not perform external effects, edit the primary checkout, or change Ultra task authority.',
|
|
183
|
-
`Return exactly one JSON object as the final response using $schema ${RESULT_SCHEMA}.`,
|
|
184
|
-
'The exact fields are status, summary, changed_files, checks, evidence, questions, and residual_risks.',
|
|
185
|
-
'status is finished, blocked, or failed. blocked requires at least one question.',
|
|
186
|
-
'changed_files must exactly list every repository-relative path changed in the worktree.',
|
|
187
|
-
'checks items use command, status (passed, failed, or not_run), and optional output_ref.',
|
|
188
|
-
'Do not write the receipt yourself. The launcher validates structured output, process exit, permissions, and the actual Git diff before publication.',
|
|
189
|
-
].join('\n');
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
function selectedBinary(runtime, fallback) {
|
|
193
|
-
return process.env[`UBP_DELEGATE_${runtime.toUpperCase()}_BIN`] || fallback;
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
function parsePairs(argv, allowed) {
|
|
197
|
-
const values = {};
|
|
198
|
-
for (let index = 0; index < argv.length; index += 2) {
|
|
199
|
-
const key = argv[index];
|
|
200
|
-
const value = argv[index + 1];
|
|
201
|
-
if (!allowed.has(key) || value === undefined || value === '') {
|
|
202
|
-
throw new Error(`invalid delegate argument: ${key || '<missing>'}`);
|
|
203
|
-
}
|
|
204
|
-
if (values[key]) throw new Error(`duplicate delegate argument: ${key}`);
|
|
205
|
-
values[key] = value;
|
|
206
|
-
}
|
|
207
|
-
return values;
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
function parseRun(argv) {
|
|
211
|
-
const values = parsePairs(argv, new Set([
|
|
212
|
-
'--to', '--instruction', '--permission', '--worktree', '--timeout',
|
|
213
|
-
]));
|
|
214
|
-
for (const key of ['--to', '--instruction', '--permission', '--worktree']) {
|
|
215
|
-
if (!values[key]) throw new Error(`delegate run requires ${key}`);
|
|
216
|
-
}
|
|
217
|
-
const timeout = values['--timeout'] === undefined ? 1800 : Number(values['--timeout']);
|
|
218
|
-
if (!Number.isFinite(timeout) || timeout <= 0 || timeout > 86400) {
|
|
219
|
-
throw new Error('delegate --timeout must be greater than 0 and at most 86400 seconds');
|
|
220
|
-
}
|
|
221
|
-
return {
|
|
222
|
-
to: values['--to'], instruction: values['--instruction'],
|
|
223
|
-
permission: values['--permission'], worktree: values['--worktree'],
|
|
224
|
-
timeoutMs: Math.ceil(timeout * 1000),
|
|
225
|
-
};
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
function readJson(file) {
|
|
229
|
-
return JSON.parse(fs.readFileSync(file, 'utf8'));
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
function processAlive(pid) {
|
|
233
|
-
if (!Number.isInteger(pid) || pid <= 0) return false;
|
|
234
|
-
try { process.kill(pid, 0); return true; } catch { return false; }
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
function run(argv, { projectRoot = process.cwd() } = {}) {
|
|
238
|
-
const args = parseRun(argv);
|
|
239
|
-
projectRoot = fs.realpathSync(projectRoot);
|
|
240
|
-
const profile = hostProfile(args.to);
|
|
241
|
-
const instruction = projectPath(projectRoot, args.instruction, 'instruction');
|
|
242
|
-
const permission = projectPath(projectRoot, args.permission, 'permission');
|
|
243
|
-
const worktree = projectPath(projectRoot, args.worktree, 'worktree', { directory: true });
|
|
244
|
-
if (!fs.statSync(instruction).isFile()) throw new Error('instruction must be a file');
|
|
245
|
-
if (!fs.statSync(permission).isFile()) throw new Error('permission must be a file');
|
|
246
|
-
if (path.dirname(instruction) !== path.dirname(permission)) {
|
|
247
|
-
throw new Error('instruction and permission must share one delegation directory');
|
|
248
|
-
}
|
|
249
|
-
const baseHead = validateWorktree(worktree);
|
|
250
|
-
const permissionContract = readPermission(permission, worktree);
|
|
251
|
-
const delegationRoot = path.dirname(instruction);
|
|
252
|
-
const delegationId = path.basename(delegationRoot);
|
|
253
|
-
const result = path.join(delegationRoot, 'result.json');
|
|
254
|
-
const receiptFile = path.join(delegationRoot, 'receipt.json');
|
|
255
|
-
const stdout = path.join(delegationRoot, 'stdout.log');
|
|
256
|
-
const stderr = path.join(delegationRoot, 'stderr.log');
|
|
257
|
-
const spec = path.join(delegationRoot, 'worker-spec.json');
|
|
258
|
-
const outputSchema = path.join(delegationRoot, 'result-schema.json');
|
|
259
|
-
const hostOutput = path.join(delegationRoot, 'host-result.json');
|
|
260
|
-
const lock = path.join(delegationRoot, 'run.lock');
|
|
261
|
-
const cancel = path.join(delegationRoot, 'cancel.request');
|
|
262
|
-
if (fs.existsSync(result)) throw new Error('delegation result.json already exists; use a new delegation id');
|
|
263
|
-
if (fs.existsSync(lock)) throw new Error('delegation is already running');
|
|
264
|
-
if (fs.existsSync(receiptFile) || fs.existsSync(spec) || fs.existsSync(outputSchema) || fs.existsSync(hostOutput)) {
|
|
265
|
-
throw new Error('delegation id already has run artifacts; cancel or use a new delegation id');
|
|
266
|
-
}
|
|
267
|
-
let lockFd;
|
|
268
|
-
try {
|
|
269
|
-
lockFd = fs.openSync(lock, 'wx', 0o600);
|
|
270
|
-
} catch (error) {
|
|
271
|
-
if (error.code === 'EEXIST') throw new Error('delegation is already running');
|
|
272
|
-
throw error;
|
|
273
|
-
}
|
|
274
|
-
const startedAt = new Date().toISOString();
|
|
275
|
-
const instructionDigest = sha256(instruction);
|
|
276
|
-
const permissionDigest = sha256(permission);
|
|
277
|
-
try {
|
|
278
|
-
fs.writeFileSync(lockFd, `${JSON.stringify({ pid: process.pid, started_at: startedAt })}\n`);
|
|
279
|
-
fs.closeSync(lockFd);
|
|
280
|
-
lockFd = undefined;
|
|
281
|
-
writeAtomic(outputSchema, `${JSON.stringify(RESULT_JSON_SCHEMA, null, 2)}\n`);
|
|
282
|
-
fs.chmodSync(outputSchema, 0o600);
|
|
283
|
-
const outputSchemaDigest = sha256(outputSchema);
|
|
284
|
-
const profileOptions = {
|
|
285
|
-
readOnly: permissionContract.writableRoots.length === 0,
|
|
286
|
-
writableRoots: permissionContract.writableRoots,
|
|
287
|
-
schemaFile: outputSchema,
|
|
288
|
-
schemaJson: JSON.stringify(RESULT_JSON_SCHEMA),
|
|
289
|
-
hostOutput,
|
|
290
|
-
};
|
|
291
|
-
const prompt = delegatePrompt({
|
|
292
|
-
instruction, permission, worktree, readOnly: profileOptions.readOnly,
|
|
293
|
-
});
|
|
294
|
-
const workerSpec = {
|
|
295
|
-
$schema: 'ultra-delegation-worker-spec-v1',
|
|
296
|
-
delegation_id: delegationId,
|
|
297
|
-
host: args.to,
|
|
298
|
-
command: selectedBinary(args.to, profile.binary),
|
|
299
|
-
args: profile.delegateArgv(prompt, worktree, profileOptions),
|
|
300
|
-
cwd: worktree,
|
|
301
|
-
instruction,
|
|
302
|
-
permission,
|
|
303
|
-
instruction_digest: instructionDigest,
|
|
304
|
-
permission_digest: permissionDigest,
|
|
305
|
-
output_schema: outputSchema,
|
|
306
|
-
output_schema_digest: outputSchemaDigest,
|
|
307
|
-
host_output: hostOutput,
|
|
308
|
-
read_only: profileOptions.readOnly,
|
|
309
|
-
writable_roots: permissionContract.writableRoots,
|
|
310
|
-
writable_root_paths: permissionContract.writableRootPaths,
|
|
311
|
-
base_head: baseHead,
|
|
312
|
-
started_at: startedAt,
|
|
313
|
-
timeout_ms: args.timeoutMs,
|
|
314
|
-
result,
|
|
315
|
-
stdout,
|
|
316
|
-
stderr,
|
|
317
|
-
lock,
|
|
318
|
-
cancel,
|
|
319
|
-
env: {
|
|
320
|
-
...(profile.delegateEnv ? profile.delegateEnv(profileOptions) : {}),
|
|
321
|
-
UBP_DELEGATE_INSTRUCTION_FILE: instruction,
|
|
322
|
-
UBP_DELEGATE_PERMISSION_FILE: permission,
|
|
323
|
-
UBP_DELEGATE_WORKTREE: worktree,
|
|
324
|
-
},
|
|
325
|
-
};
|
|
326
|
-
writeAtomic(spec, `${JSON.stringify(workerSpec, null, 2)}\n`);
|
|
327
|
-
fs.chmodSync(spec, 0o600);
|
|
328
|
-
const specDigest = sha256(spec);
|
|
329
|
-
const worker = spawn(process.execPath, [
|
|
330
|
-
path.join(__dirname, 'delegate-worker.cjs'), spec, specDigest,
|
|
331
|
-
], {
|
|
332
|
-
cwd: projectRoot,
|
|
333
|
-
detached: true,
|
|
334
|
-
stdio: 'ignore',
|
|
335
|
-
env: process.env,
|
|
336
|
-
});
|
|
337
|
-
if (!worker.pid) throw new Error('failed to start delegation worker');
|
|
338
|
-
worker.unref();
|
|
339
|
-
const receipt = {
|
|
340
|
-
$schema: RECEIPT_SCHEMA,
|
|
341
|
-
status: 'started',
|
|
342
|
-
delegation_id: delegationId,
|
|
343
|
-
host: args.to,
|
|
344
|
-
worker_pid: worker.pid,
|
|
345
|
-
instruction_digest: instructionDigest,
|
|
346
|
-
permission_digest: permissionDigest,
|
|
347
|
-
output_schema_digest: outputSchemaDigest,
|
|
348
|
-
spec_digest: specDigest,
|
|
349
|
-
base_head: baseHead,
|
|
350
|
-
started_at: startedAt,
|
|
351
|
-
timeout_ms: args.timeoutMs,
|
|
352
|
-
result_file: result,
|
|
353
|
-
read_only: profileOptions.readOnly,
|
|
354
|
-
stdout_file: stdout,
|
|
355
|
-
stderr_file: stderr,
|
|
356
|
-
cancel_command: `ubp delegate cancel --delegation ${delegationRoot}`,
|
|
357
|
-
};
|
|
358
|
-
writeAtomic(receiptFile, `${JSON.stringify(receipt, null, 2)}\n`);
|
|
359
|
-
writeAtomic(lock, `${JSON.stringify({ pid: worker.pid, started_at: startedAt })}\n`);
|
|
360
|
-
fs.chmodSync(lock, 0o600);
|
|
361
|
-
if (fs.existsSync(result)) {
|
|
362
|
-
try { fs.unlinkSync(lock); } catch (error) { if (error.code !== 'ENOENT') throw error; }
|
|
363
|
-
}
|
|
364
|
-
return receipt;
|
|
365
|
-
} catch (error) {
|
|
366
|
-
if (lockFd !== undefined) fs.closeSync(lockFd);
|
|
367
|
-
try { fs.unlinkSync(lock); } catch (unlinkError) { if (unlinkError.code !== 'ENOENT') throw unlinkError; }
|
|
368
|
-
for (const file of [spec, outputSchema, hostOutput]) {
|
|
369
|
-
try { fs.unlinkSync(file); } catch (unlinkError) { if (unlinkError.code !== 'ENOENT') throw unlinkError; }
|
|
370
|
-
}
|
|
371
|
-
throw error;
|
|
372
|
-
}
|
|
373
|
-
}
|
|
374
|
-
|
|
375
|
-
function delegationPath(projectRoot, value) {
|
|
376
|
-
return projectPath(projectRoot, value, 'delegation', { directory: true });
|
|
377
|
-
}
|
|
378
|
-
|
|
379
|
-
function status(argv, { projectRoot = process.cwd() } = {}) {
|
|
380
|
-
const values = parsePairs(argv, new Set(['--delegation']));
|
|
381
|
-
if (!values['--delegation']) throw new Error('delegate status requires --delegation');
|
|
382
|
-
projectRoot = fs.realpathSync(projectRoot);
|
|
383
|
-
const root = delegationPath(projectRoot, values['--delegation']);
|
|
384
|
-
const result = path.join(root, 'result.json');
|
|
385
|
-
if (fs.existsSync(result)) return readJson(result);
|
|
386
|
-
const receiptFile = path.join(root, 'receipt.json');
|
|
387
|
-
const receipt = fs.existsSync(receiptFile) ? readJson(receiptFile) : null;
|
|
388
|
-
const lockFile = path.join(root, 'run.lock');
|
|
389
|
-
const lock = fs.existsSync(lockFile) ? readJson(lockFile) : null;
|
|
390
|
-
const cancelling = fs.existsSync(path.join(root, 'cancel.request'));
|
|
391
|
-
return {
|
|
392
|
-
$schema: 'ultra-delegation-status-v1',
|
|
393
|
-
status: cancelling ? 'cancelling' : lock && processAlive(lock.pid) ? 'running' : receipt ? 'stalled' : 'not_started',
|
|
394
|
-
delegation_id: path.basename(root),
|
|
395
|
-
worker_pid: lock?.pid || receipt?.worker_pid || null,
|
|
396
|
-
result_file: result,
|
|
397
|
-
repair: receipt ? `ubp delegate cancel --delegation ${root}` : null,
|
|
398
|
-
};
|
|
399
|
-
}
|
|
400
|
-
|
|
401
|
-
function failureFromSpec(spec, failureType, summary) {
|
|
402
|
-
let finalHead = null;
|
|
403
|
-
let changedFiles = [];
|
|
404
|
-
try { finalHead = git(spec.cwd, ['rev-parse', 'HEAD']); } catch {}
|
|
405
|
-
try { changedFiles = observedChangedFiles(spec.cwd, spec.base_head); } catch {}
|
|
406
|
-
return {
|
|
407
|
-
$schema: RESULT_SCHEMA,
|
|
408
|
-
status: 'failed',
|
|
409
|
-
summary,
|
|
410
|
-
changed_files: changedFiles,
|
|
411
|
-
checks: [],
|
|
412
|
-
evidence: [],
|
|
413
|
-
questions: [],
|
|
414
|
-
residual_risks: [],
|
|
415
|
-
failure_type: failureType,
|
|
416
|
-
delegation_id: spec.delegation_id,
|
|
417
|
-
host: spec.host,
|
|
418
|
-
instruction_digest: spec.instruction_digest,
|
|
419
|
-
permission_digest: spec.permission_digest,
|
|
420
|
-
output_schema_digest: spec.output_schema_digest,
|
|
421
|
-
base_head: spec.base_head,
|
|
422
|
-
final_head: finalHead,
|
|
423
|
-
started_at: spec.started_at,
|
|
424
|
-
finished_at: new Date().toISOString(),
|
|
425
|
-
exit_code: null,
|
|
426
|
-
};
|
|
427
|
-
}
|
|
428
|
-
|
|
429
|
-
function cancel(argv, { projectRoot = process.cwd() } = {}) {
|
|
430
|
-
const values = parsePairs(argv, new Set(['--delegation']));
|
|
431
|
-
if (!values['--delegation']) throw new Error('delegate cancel requires --delegation');
|
|
432
|
-
projectRoot = fs.realpathSync(projectRoot);
|
|
433
|
-
const root = delegationPath(projectRoot, values['--delegation']);
|
|
434
|
-
const result = path.join(root, 'result.json');
|
|
435
|
-
if (fs.existsSync(result)) return { status: 'already_terminal', result: readJson(result) };
|
|
436
|
-
const specFile = path.join(root, 'worker-spec.json');
|
|
437
|
-
if (!fs.existsSync(specFile)) throw new Error('delegation has no worker spec to cancel');
|
|
438
|
-
const spec = readJson(specFile);
|
|
439
|
-
const request = path.join(root, 'cancel.request');
|
|
440
|
-
writeAtomic(request, `${JSON.stringify({ requested_at: new Date().toISOString() })}\n`);
|
|
441
|
-
const receiptFile = path.join(root, 'receipt.json');
|
|
442
|
-
const receipt = fs.existsSync(receiptFile) ? readJson(receiptFile) : null;
|
|
443
|
-
if (!processAlive(receipt?.worker_pid)) {
|
|
444
|
-
writeAtomic(result, `${JSON.stringify(failureFromSpec(spec, 'cancelled', 'Delegation cancelled after its worker stopped.'), null, 2)}\n`);
|
|
445
|
-
try { fs.unlinkSync(path.join(root, 'run.lock')); } catch (error) { if (error.code !== 'ENOENT') throw error; }
|
|
446
|
-
}
|
|
447
|
-
return {
|
|
448
|
-
$schema: 'ultra-delegation-cancel-v1',
|
|
449
|
-
status: 'cancel_requested',
|
|
450
|
-
delegation_id: path.basename(root),
|
|
451
|
-
result_file: result,
|
|
452
|
-
};
|
|
453
|
-
}
|
|
454
|
-
|
|
455
|
-
function handle(argv, options) {
|
|
456
|
-
if (argv[0] !== 'delegate') throw new Error('delegate command is required');
|
|
457
|
-
if (argv[1] === 'run') return run(argv.slice(2), options);
|
|
458
|
-
if (argv[1] === 'status') return status(argv.slice(2), options);
|
|
459
|
-
if (argv[1] === 'cancel') return cancel(argv.slice(2), options);
|
|
460
|
-
throw new Error('usage: ubp delegate <run|status|cancel> ...');
|
|
461
|
-
}
|
|
462
|
-
|
|
463
|
-
module.exports = { handle, run, status, cancel };
|
|
3
|
+
// Compatibility surface for one release cycle. The installed Skill owns the
|
|
4
|
+
// implementation used by both `ubp delegate` and direct Skill invocation.
|
|
5
|
+
module.exports = require('../skills/ultra-delegate/scripts/delegate.cjs');
|
package/bin/install.js
CHANGED
|
@@ -4,13 +4,13 @@
|
|
|
4
4
|
* ultra-builder-pro-cli — multi-runtime installer.
|
|
5
5
|
*
|
|
6
6
|
* Distributes fourteen Skills and five hooks to Claude Code, OpenCode, Codex CLI,
|
|
7
|
-
* Kimi Code,
|
|
7
|
+
* Kimi Code, Grok Build, and ZCode through runtime-specific adapters under adapters/.
|
|
8
8
|
* Install is idempotent and atomic; uninstall removes only managed assets.
|
|
9
9
|
*
|
|
10
10
|
* Usage:
|
|
11
11
|
* npx ultra-builder-pro-cli [options]
|
|
12
12
|
*
|
|
13
|
-
* --claude / --opencode / --codex / --kimi / --grok select runtime(s)
|
|
13
|
+
* --claude / --opencode / --codex / --kimi / --grok / --zcode select runtime(s)
|
|
14
14
|
* --all install to all supported runtimes
|
|
15
15
|
* -g, --global install to runtime's global config dir
|
|
16
16
|
* -l, --local project scope where the host supports it
|
|
@@ -57,7 +57,7 @@ function printBanner() {
|
|
|
57
57
|
paint('cyan', ' ╚═════╝ ╚═════╝ ╚═╝ ╚═════╝╚══════╝╚═╝'),
|
|
58
58
|
'',
|
|
59
59
|
` ${paint('bold', 'Ultra Builder Pro CLI')} ${paint('dim', 'v' + pkg.version)}`,
|
|
60
|
-
` ${paint('dim', 'Multi-runtime installer for Claude Code, OpenCode, Codex, Kimi Code,
|
|
60
|
+
` ${paint('dim', 'Multi-runtime installer for Claude Code, OpenCode, Codex, Kimi Code, Grok Build, and ZCode')}`,
|
|
61
61
|
'',
|
|
62
62
|
];
|
|
63
63
|
console.log(banner.join('\n'));
|
|
@@ -72,6 +72,7 @@ function printHelp() {
|
|
|
72
72
|
${paint('cyan', '--codex')} Codex CLI (OpenAI)
|
|
73
73
|
${paint('cyan', '--kimi')} Kimi Code (Moonshot AI)
|
|
74
74
|
${paint('cyan', '--grok')} Grok Build (xAI)
|
|
75
|
+
${paint('cyan', '--zcode')} ZCode (Z.AI)
|
|
75
76
|
${paint('cyan', '--all')} all supported runtimes
|
|
76
77
|
|
|
77
78
|
${paint('yellow', 'Scope:')}
|
|
@@ -90,7 +91,7 @@ function printHelp() {
|
|
|
90
91
|
${paint('dim', '# Install to Claude Code globally')}
|
|
91
92
|
npx ultra-builder-pro-cli --claude --global
|
|
92
93
|
|
|
93
|
-
${paint('dim', '# Install all
|
|
94
|
+
${paint('dim', '# Install all six native plugins in their user scopes')}
|
|
94
95
|
npx ultra-builder-pro-cli --all --global
|
|
95
96
|
|
|
96
97
|
${paint('dim', '# Uninstall from OpenCode')}
|
|
@@ -102,6 +103,9 @@ function printHelp() {
|
|
|
102
103
|
${paint('dim', '# Install to Grok Build globally')}
|
|
103
104
|
npx ultra-builder-pro-cli --grok --global
|
|
104
105
|
|
|
106
|
+
${paint('dim', '# Install to ZCode globally')}
|
|
107
|
+
npx ultra-builder-pro-cli --zcode --global
|
|
108
|
+
|
|
105
109
|
${paint('dim', '# Verify all host installations without changing them')}
|
|
106
110
|
npx ultra-builder-pro-cli --all --global --doctor
|
|
107
111
|
`);
|
|
@@ -129,6 +133,7 @@ function parseArgs(argv) {
|
|
|
129
133
|
case '--codex': runtimes.add('codex'); break;
|
|
130
134
|
case '--kimi': runtimes.add('kimi'); break;
|
|
131
135
|
case '--grok': runtimes.add('grok'); break;
|
|
136
|
+
case '--zcode': runtimes.add('zcode'); break;
|
|
132
137
|
case '--all':
|
|
133
138
|
SUPPORTED_RUNTIMES.forEach(r => runtimes.add(r));
|
|
134
139
|
break;
|
|
@@ -213,13 +218,13 @@ async function main() {
|
|
|
213
218
|
if (flags.json && !flags.doctor) bail('--json is available only with --doctor');
|
|
214
219
|
|
|
215
220
|
if (runtimes.length === 0) {
|
|
216
|
-
bail('no runtime selected; use --claude / --opencode / --codex / --kimi / --grok / --all');
|
|
221
|
+
bail('no runtime selected; use --claude / --opencode / --codex / --kimi / --grok / --zcode / --all');
|
|
217
222
|
}
|
|
218
223
|
|
|
219
224
|
const scope = resolveScope(flags);
|
|
220
225
|
const repoRoot = path.resolve(__dirname, '..');
|
|
221
226
|
const configDir = flags.configDir ? expandTilde(flags.configDir) : null;
|
|
222
|
-
const userScopedOnly = runtimes.filter((runtime) => ['kimi', 'grok'].includes(runtime));
|
|
227
|
+
const userScopedOnly = runtimes.filter((runtime) => ['kimi', 'grok', 'zcode'].includes(runtime));
|
|
223
228
|
if (scope === 'local' && !configDir && userScopedOnly.length) {
|
|
224
229
|
bail(`${userScopedOnly.join(', ')} plugins are user-scoped by their hosts; use --global or an isolated --config-dir`);
|
|
225
230
|
}
|