ultra-builder-pro-cli 0.24.1 → 0.24.2
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/CHANGELOG.md +21 -0
- package/README.md +10 -0
- package/agents/code-reviewer.md +4 -5
- package/agents/debugger.md +8 -8
- package/docs/AGENT-CONTEXT.md +16 -4
- package/docs/ARCHITECTURE.md +24 -5
- package/docs/STATE-DB-ACCESS-POLICY.md +8 -1
- package/mcp-server/lib/artifact-registry.cjs +7 -56
- package/mcp-server/lib/change-packet.cjs +4 -32
- package/mcp-server/lib/change-workflow.cjs +33 -2757
- package/mcp-server/lib/legacy-change-workflow.cjs +2809 -0
- package/mcp-server/lib/task-expander.cjs +6 -1
- package/mcp-server/lib/ultra-facade.cjs +121 -15
- package/mcp-server/server.cjs +1 -1
- package/package.json +1 -1
|
@@ -81,7 +81,11 @@ function expandTask(db, {
|
|
|
81
81
|
});
|
|
82
82
|
|
|
83
83
|
return ops.tx(db, () => {
|
|
84
|
-
changes.assertTaskCreationAllowed(
|
|
84
|
+
const admission = changes.assertTaskCreationAllowed(
|
|
85
|
+
db,
|
|
86
|
+
{ change_id: parent.change_id },
|
|
87
|
+
{ rootDir },
|
|
88
|
+
);
|
|
85
89
|
for (const child of normalized) {
|
|
86
90
|
ops.createTask(db, child);
|
|
87
91
|
}
|
|
@@ -89,6 +93,7 @@ function expandTask(db, {
|
|
|
89
93
|
return {
|
|
90
94
|
parent_id: parent.id,
|
|
91
95
|
children: normalized,
|
|
96
|
+
diagnostics: admission.diagnostics,
|
|
92
97
|
};
|
|
93
98
|
});
|
|
94
99
|
}
|
|
@@ -135,6 +135,48 @@ function rememberResult(db, {
|
|
|
135
135
|
});
|
|
136
136
|
}
|
|
137
137
|
|
|
138
|
+
function rememberRejectedAttempt(db, tool, input, result) {
|
|
139
|
+
if (!db || result?.accepted !== false) return result;
|
|
140
|
+
const nested = Array.isArray(result.results)
|
|
141
|
+
? result.results.flatMap((item) => item.diagnostics || [])
|
|
142
|
+
: [];
|
|
143
|
+
const diagnostics = [...(result.diagnostics || []), ...nested]
|
|
144
|
+
.map((item) => ({
|
|
145
|
+
code: item.code || 'NEEDS_ATTENTION',
|
|
146
|
+
severity: item.severity || 'needs_attention',
|
|
147
|
+
message: item.message || null,
|
|
148
|
+
...(item.details === undefined ? {} : { details: item.details }),
|
|
149
|
+
}));
|
|
150
|
+
const entries = Array.isArray(input.entries) ? input.entries : [];
|
|
151
|
+
const changeIds = [...new Set(entries.flatMap((entry) => [
|
|
152
|
+
entry.data?.change_id,
|
|
153
|
+
entry.kind === 'change_contract' ? entry.data?.id : null,
|
|
154
|
+
]).filter(Boolean))];
|
|
155
|
+
const taskIds = [...new Set(entries.flatMap((entry) => [
|
|
156
|
+
entry.kind.startsWith('task_') ? entry.data?.id : null,
|
|
157
|
+
input.scope?.task_id,
|
|
158
|
+
]).filter(Boolean))];
|
|
159
|
+
const scopeChangeId = input.scope?.change_id || input.change_id || null;
|
|
160
|
+
ops.appendEvent(db, {
|
|
161
|
+
type: 'ultra_kernel_attempt',
|
|
162
|
+
change_id: changeIds.length === 1 ? changeIds[0] : scopeChangeId,
|
|
163
|
+
task_id: taskIds.length === 1 ? taskIds[0] : null,
|
|
164
|
+
payload: {
|
|
165
|
+
tool,
|
|
166
|
+
accepted: false,
|
|
167
|
+
mutable: result.mutable !== false,
|
|
168
|
+
operations: entries.map((entry) => `${entry.kind}:${entry.action}`),
|
|
169
|
+
idempotency_keys: entries.length > 0
|
|
170
|
+
? entries.map((entry) => entry.idempotency_key).filter(Boolean)
|
|
171
|
+
: [input.idempotency_key].filter(Boolean),
|
|
172
|
+
scope: input.scope || (input.change_id ? { change_id: input.change_id } : {}),
|
|
173
|
+
blockers: result.blockers || [],
|
|
174
|
+
diagnostics,
|
|
175
|
+
},
|
|
176
|
+
});
|
|
177
|
+
return result;
|
|
178
|
+
}
|
|
179
|
+
|
|
138
180
|
function diagnostic(error, severity = 'needs_attention') {
|
|
139
181
|
return {
|
|
140
182
|
code: errorCode(error),
|
|
@@ -144,6 +186,34 @@ function diagnostic(error, severity = 'needs_attention') {
|
|
|
144
186
|
};
|
|
145
187
|
}
|
|
146
188
|
|
|
189
|
+
function rejectedAttemptAudit(db) {
|
|
190
|
+
return db.prepare(
|
|
191
|
+
`SELECT id, ts, task_id, change_id, payload_json
|
|
192
|
+
FROM events
|
|
193
|
+
WHERE type = 'ultra_kernel_attempt'
|
|
194
|
+
ORDER BY id DESC
|
|
195
|
+
LIMIT 5`,
|
|
196
|
+
).all().map((row) => {
|
|
197
|
+
const payload = parseJson(row.payload_json, {});
|
|
198
|
+
return {
|
|
199
|
+
event_id: row.id,
|
|
200
|
+
recorded_at: row.ts,
|
|
201
|
+
tool: payload.tool || null,
|
|
202
|
+
task_id: row.task_id || null,
|
|
203
|
+
change_id: row.change_id || null,
|
|
204
|
+
operations: (payload.operations || []).slice(0, 12),
|
|
205
|
+
blockers: (payload.blockers || []).slice(0, 12),
|
|
206
|
+
diagnostics: (payload.diagnostics || []).slice(0, 8).map((item) => ({
|
|
207
|
+
code: item.code || 'NEEDS_ATTENTION',
|
|
208
|
+
severity: item.severity || 'needs_attention',
|
|
209
|
+
message: typeof item.message === 'string'
|
|
210
|
+
? item.message.slice(0, 500)
|
|
211
|
+
: null,
|
|
212
|
+
})),
|
|
213
|
+
};
|
|
214
|
+
});
|
|
215
|
+
}
|
|
216
|
+
|
|
147
217
|
function selectedScope(db, input = {}) {
|
|
148
218
|
const scope = input.scope || {};
|
|
149
219
|
const task = scope.task_id ? ops.readTask(db, scope.task_id) : null;
|
|
@@ -197,7 +267,28 @@ function readContext(db, input = {}, {
|
|
|
197
267
|
rootDir = process.cwd(),
|
|
198
268
|
runtime = 'unknown',
|
|
199
269
|
} = {}) {
|
|
200
|
-
|
|
270
|
+
const result = contextEnvelope.buildEnvelope(db, input, { rootDir, runtime });
|
|
271
|
+
const rejectedAttempts = rejectedAttemptAudit(db);
|
|
272
|
+
let visible = {
|
|
273
|
+
...result,
|
|
274
|
+
audit: {
|
|
275
|
+
rejected_attempts: rejectedAttempts,
|
|
276
|
+
},
|
|
277
|
+
};
|
|
278
|
+
delete visible.bytes;
|
|
279
|
+
const limit = input.detail === 'full'
|
|
280
|
+
? contextEnvelope.FULL_LIMIT
|
|
281
|
+
: contextEnvelope.SUMMARY_LIMIT;
|
|
282
|
+
while (Buffer.byteLength(JSON.stringify(visible)) > limit
|
|
283
|
+
&& rejectedAttempts.length > 0) {
|
|
284
|
+
rejectedAttempts.pop();
|
|
285
|
+
}
|
|
286
|
+
if (Buffer.byteLength(JSON.stringify(visible)) > limit) {
|
|
287
|
+
visible = { ...result };
|
|
288
|
+
delete visible.bytes;
|
|
289
|
+
}
|
|
290
|
+
visible.bytes = Buffer.byteLength(JSON.stringify(visible));
|
|
291
|
+
return visible;
|
|
201
292
|
}
|
|
202
293
|
|
|
203
294
|
function initializeProject(data = {}) {
|
|
@@ -241,7 +332,7 @@ function baselineRecord(db, action, data, rootDir) {
|
|
|
241
332
|
|
|
242
333
|
function changeContractRecord(db, action, data, rootDir) {
|
|
243
334
|
if (action === 'open') {
|
|
244
|
-
return changes.createChange(db, data, { rootDir
|
|
335
|
+
return changes.createChange(db, data, { rootDir });
|
|
245
336
|
}
|
|
246
337
|
if (action === 'revise') {
|
|
247
338
|
return {
|
|
@@ -249,7 +340,7 @@ function changeContractRecord(db, action, data, rootDir) {
|
|
|
249
340
|
db,
|
|
250
341
|
data.id,
|
|
251
342
|
data.patch || {},
|
|
252
|
-
{ rootDir
|
|
343
|
+
{ rootDir },
|
|
253
344
|
),
|
|
254
345
|
};
|
|
255
346
|
}
|
|
@@ -259,7 +350,7 @@ function changeContractRecord(db, action, data, rootDir) {
|
|
|
259
350
|
db,
|
|
260
351
|
data.id,
|
|
261
352
|
{ status: 'cancelled' },
|
|
262
|
-
{ rootDir
|
|
353
|
+
{ rootDir },
|
|
263
354
|
),
|
|
264
355
|
};
|
|
265
356
|
}
|
|
@@ -374,6 +465,17 @@ function applyRecord(db, entry, { rootDir }) {
|
|
|
374
465
|
if (kind === 'task_contract') return taskContractRecord(db, action, data);
|
|
375
466
|
if (kind === 'task_outcome') return taskOutcomeRecord(db, action, data, rootDir);
|
|
376
467
|
if (kind === 'artifact' && action === 'bind') {
|
|
468
|
+
const legacyWorkflowReference = data.owner_type === 'workflow'
|
|
469
|
+
|| [...(data.source_refs || []), ...(data.consumer_refs || [])]
|
|
470
|
+
.some((reference) => reference?.type === 'workflow');
|
|
471
|
+
if (legacyWorkflowReference) {
|
|
472
|
+
throw Object.assign(
|
|
473
|
+
new Error(
|
|
474
|
+
'workflow-owned artifact authority is retired and remains read-only history',
|
|
475
|
+
),
|
|
476
|
+
{ code: 'LEGACY_AUTHORITY_READ_ONLY' },
|
|
477
|
+
);
|
|
478
|
+
}
|
|
377
479
|
return artifactRegistry.recordArtifact(db, data, { rootDir });
|
|
378
480
|
}
|
|
379
481
|
if (kind === 'event' && action === 'append') {
|
|
@@ -897,7 +999,7 @@ async function archive(db, input = {}, {
|
|
|
897
999
|
const result = changes.archiveChange(
|
|
898
1000
|
db,
|
|
899
1001
|
{ id: input.change_id, ...(input.payload || {}) },
|
|
900
|
-
{ rootDir
|
|
1002
|
+
{ rootDir },
|
|
901
1003
|
);
|
|
902
1004
|
const output = {
|
|
903
1005
|
accepted: true,
|
|
@@ -929,22 +1031,26 @@ async function archive(db, input = {}, {
|
|
|
929
1031
|
}
|
|
930
1032
|
|
|
931
1033
|
async function dispatch(name, input, db, context = {}) {
|
|
932
|
-
|
|
933
|
-
if (name === 'ultra.
|
|
934
|
-
if (name === 'ultra.
|
|
935
|
-
if (name === 'ultra.
|
|
936
|
-
if (name === 'ultra.
|
|
937
|
-
if (name === 'ultra.
|
|
1034
|
+
let result;
|
|
1035
|
+
if (name === 'ultra.context') result = readContext(db, input, context);
|
|
1036
|
+
else if (name === 'ultra.record') result = await record(db, input, context);
|
|
1037
|
+
else if (name === 'ultra.checkpoint') result = await checkpoint(db, input, context);
|
|
1038
|
+
else if (name === 'ultra.sync') result = sync(db, input, context);
|
|
1039
|
+
else if (name === 'ultra.session') result = await session(db, input, context);
|
|
1040
|
+
else if (name === 'ultra.archive') result = await archive(db, input, context);
|
|
938
1041
|
if (name === 'ultra.doctor') {
|
|
939
|
-
|
|
1042
|
+
result = doctor.runDoctor(db, {
|
|
940
1043
|
rootDir: context.rootDir || process.cwd(),
|
|
941
1044
|
repair: input.repair === true,
|
|
942
1045
|
project: context.projector,
|
|
943
1046
|
});
|
|
944
1047
|
}
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
1048
|
+
if (result === undefined) {
|
|
1049
|
+
const error = new Error(`unhandled public tool ${name}`);
|
|
1050
|
+
error.code = 'UNKNOWN_TOOL';
|
|
1051
|
+
throw error;
|
|
1052
|
+
}
|
|
1053
|
+
return rememberRejectedAttempt(db, name, input, result);
|
|
948
1054
|
}
|
|
949
1055
|
|
|
950
1056
|
module.exports = {
|
package/mcp-server/server.cjs
CHANGED
|
@@ -284,7 +284,7 @@ function startServer({
|
|
|
284
284
|
);
|
|
285
285
|
const own = processed.jobs.find((item) => item.id === job.id);
|
|
286
286
|
runtimeMeta = {
|
|
287
|
-
|
|
287
|
+
projection_commit: 'committed',
|
|
288
288
|
projection_status: own?.status || 'failed',
|
|
289
289
|
projection_job_id: job.id,
|
|
290
290
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ultra-builder-pro-cli",
|
|
3
|
-
"version": "0.24.
|
|
3
|
+
"version": "0.24.2",
|
|
4
4
|
"description": "Explicitly invoked Ultra Builder Pro workflows for Claude Code, OpenCode, Codex CLI, Kimi Code, and Grok Build, with a project-local MCP persistence and safety kernel.",
|
|
5
5
|
"bin": {
|
|
6
6
|
"ultra-builder-pro-cli": "bin/install.js",
|