ultra-builder-pro-cli 0.7.0 → 0.9.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/CHANGELOG.md +60 -1
- package/README.md +49 -23
- package/adapters/_shared/codex-assets.cjs +28 -0
- package/adapters/_shared/handbook.cjs +9 -1
- package/adapters/_shared/path-rewrite.cjs +3 -0
- package/adapters/_shared/provenance.cjs +286 -0
- package/adapters/_shared/runtime-assets.cjs +2 -1
- package/adapters/_shared/tests/handbook.test.cjs +6 -1
- package/adapters/_shared/tests/path-rewrite.test.cjs +3 -1
- package/adapters/_shared/tests/provenance.test.cjs +133 -0
- package/adapters/_shared/tests/runtime-assets.test.cjs +4 -1
- package/adapters/claude.js +33 -0
- package/adapters/codex.js +87 -0
- package/adapters/kimi.js +642 -0
- package/adapters/opencode.js +66 -0
- package/adapters/tests/codex.test.cjs +37 -0
- package/adapters/tests/kimi-hook.test.cjs +122 -0
- package/adapters/tests/kimi.test.cjs +255 -0
- package/agents/debugger.md +12 -0
- package/bin/handbook.js +2 -2
- package/bin/install.js +72 -12
- package/bin/orchestrator.js +1 -1
- package/commands/ultra-change.md +3 -2
- package/docs/AGENT-CONTEXT.md +5 -3
- package/docs/ARCHITECTURE.md +40 -6
- package/docs/PLAN.zh-CN.md +8 -6
- package/docs/ROADMAP.md +4 -4
- package/docs/RUNTIME-COMPAT-MATRIX.md +109 -58
- package/docs/USER-HANDBOOK-CONTRACT.md +4 -1
- package/hooks/README.md +6 -2
- package/hooks/adapters/kimi.py +162 -0
- package/hooks/workflow_checkpoint.py +15 -1
- package/hooks/workflow_resume.py +96 -7
- package/mcp-server/lib/change-workflow.cjs +69 -0
- package/mcp-server/lib/change-workflow.test.cjs +87 -0
- package/mcp-server/lib/state-db.cjs +85 -2
- package/mcp-server/lib/state-db.test.cjs +56 -0
- package/mcp-server/tests/init-project.test.cjs +2 -2
- package/mcp-server/tests/state-db.test.cjs +3 -3
- package/package.json +4 -2
- package/skills/ultra-change/SKILL.md +12 -3
- package/skills/ultra-deliver/SKILL.md +3 -1
- package/skills/ultra-doctor/SKILL.md +10 -3
- package/skills/ultra-review/SKILL.md +3 -3
- package/spec/mcp-tools.yaml +5 -5
- package/spec/schemas/skill-manifest.schema.json +2 -2
- package/spec/schemas/state-db.sql +4 -2
|
@@ -9,11 +9,13 @@ const path = require('node:path');
|
|
|
9
9
|
const {
|
|
10
10
|
EXPECTED_VERSION,
|
|
11
11
|
REQUIRED_TABLES,
|
|
12
|
+
SCHEMA_FILE,
|
|
12
13
|
initStateDb,
|
|
13
14
|
closeStateDb,
|
|
14
15
|
openStateDb,
|
|
15
16
|
tableNames,
|
|
16
17
|
} = require('./state-db.cjs');
|
|
18
|
+
const stateOps = require('./state-ops.cjs');
|
|
17
19
|
|
|
18
20
|
function tmpDbPath(prefix = 'ubp-state') {
|
|
19
21
|
const dir = fs.mkdtempSync(path.join(os.tmpdir(), `${prefix}-`));
|
|
@@ -114,3 +116,57 @@ test('Phase 8A.1 schema: tasks.parent_id column + tasks_parent partial index + s
|
|
|
114
116
|
fs.rmSync(dir, { recursive: true, force: true });
|
|
115
117
|
}
|
|
116
118
|
});
|
|
119
|
+
|
|
120
|
+
test('initStateDb migrates existing runtime constraints to Kimi without losing references', () => {
|
|
121
|
+
const { dir, file } = tmpDbPath('ubp-kimi-runtime-upgrade');
|
|
122
|
+
try {
|
|
123
|
+
const legacy = openStateDb(file);
|
|
124
|
+
const legacySchema = fs.readFileSync(SCHEMA_FILE, 'utf8').replaceAll(", 'kimi'", '');
|
|
125
|
+
legacy.exec(legacySchema);
|
|
126
|
+
legacy.prepare("DELETE FROM schema_version WHERE version = '9.1'").run();
|
|
127
|
+
legacy.prepare(
|
|
128
|
+
"INSERT INTO tasks (id, title, type, priority) VALUES ('task-old', 'Old', 'feature', 'P1')",
|
|
129
|
+
).run();
|
|
130
|
+
legacy.prepare(
|
|
131
|
+
`INSERT INTO sessions
|
|
132
|
+
(sid, task_id, runtime, worktree_path, artifact_dir, lease_expires_at)
|
|
133
|
+
VALUES ('session-old', 'task-old', 'codex', '/tmp/worktree', '/tmp/artifacts', '2099-01-01T00:00:00.000Z')`,
|
|
134
|
+
).run();
|
|
135
|
+
legacy.prepare(
|
|
136
|
+
"INSERT INTO telemetry (session_id, event_type, tool_name) VALUES ('session-old', 'tool_call', 'task.list')",
|
|
137
|
+
).run();
|
|
138
|
+
legacy.prepare(
|
|
139
|
+
`INSERT INTO incidents
|
|
140
|
+
(id, code, severity, message, session_id)
|
|
141
|
+
VALUES ('incident-old', 'OLD', 'warning', 'preserve me', 'session-old')`,
|
|
142
|
+
).run();
|
|
143
|
+
legacy.prepare(
|
|
144
|
+
"INSERT INTO events (type, session_id, runtime) VALUES ('session_spawned', 'session-old', 'codex')",
|
|
145
|
+
).run();
|
|
146
|
+
closeStateDb(legacy);
|
|
147
|
+
|
|
148
|
+
const upgraded = initStateDb(file);
|
|
149
|
+
assert.equal(upgraded.schema_version, '9.1');
|
|
150
|
+
assert.equal(upgraded.db.prepare("SELECT runtime FROM sessions WHERE sid = 'session-old'").get().runtime, 'codex');
|
|
151
|
+
assert.equal(upgraded.db.prepare("SELECT COUNT(*) AS n FROM telemetry WHERE session_id = 'session-old'").get().n, 1);
|
|
152
|
+
assert.equal(upgraded.db.prepare("SELECT COUNT(*) AS n FROM incidents WHERE session_id = 'session-old'").get().n, 1);
|
|
153
|
+
assert.deepEqual(upgraded.db.pragma('foreign_key_check'), []);
|
|
154
|
+
|
|
155
|
+
upgraded.db.prepare(
|
|
156
|
+
"INSERT INTO tasks (id, title, type, priority) VALUES ('task-kimi', 'Kimi', 'feature', 'P1')",
|
|
157
|
+
).run();
|
|
158
|
+
const session = stateOps.createSession(upgraded.db, {
|
|
159
|
+
sid: 'session-kimi',
|
|
160
|
+
task_id: 'task-kimi',
|
|
161
|
+
runtime: 'kimi',
|
|
162
|
+
worktree_path: '/tmp/kimi-worktree',
|
|
163
|
+
artifact_dir: '/tmp/kimi-artifacts',
|
|
164
|
+
});
|
|
165
|
+
assert.equal(session.runtime, 'kimi');
|
|
166
|
+
const event = stateOps.appendEvent(upgraded.db, { type: 'kimi-ready', runtime: 'kimi' });
|
|
167
|
+
assert.ok(event.event_id > 0);
|
|
168
|
+
closeStateDb(upgraded.db);
|
|
169
|
+
} finally {
|
|
170
|
+
fs.rmSync(dir, { recursive: true, force: true });
|
|
171
|
+
}
|
|
172
|
+
});
|
|
@@ -36,8 +36,8 @@ test('initProject copies bundled template into .ultra/', () => {
|
|
|
36
36
|
assert.ok(fs.existsSync(r.state_db_path));
|
|
37
37
|
const db = new Database(r.state_db_path, { readonly: true });
|
|
38
38
|
try {
|
|
39
|
-
const version = db.prepare("SELECT version FROM schema_version WHERE version = '9.
|
|
40
|
-
assert.equal(version.version, '9.
|
|
39
|
+
const version = db.prepare("SELECT version FROM schema_version WHERE version = '9.1'").get();
|
|
40
|
+
assert.equal(version.version, '9.1');
|
|
41
41
|
assert.ok(db.prepare("SELECT name FROM sqlite_master WHERE name = 'changes'").get());
|
|
42
42
|
} finally {
|
|
43
43
|
db.close();
|
|
@@ -8,7 +8,7 @@ const path = require('node:path');
|
|
|
8
8
|
|
|
9
9
|
const stateDb = require('../lib/state-db.cjs');
|
|
10
10
|
|
|
11
|
-
test('initStateDb upgrades a pre-9.
|
|
11
|
+
test('initStateDb upgrades a pre-9.1 database in place with task/event change linkage', () => {
|
|
12
12
|
const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'ubp-db-upgrade-'));
|
|
13
13
|
const file = path.join(dir, 'state.db');
|
|
14
14
|
try {
|
|
@@ -59,8 +59,8 @@ test('initStateDb upgrades a pre-9.0 database in place with task/event change li
|
|
|
59
59
|
assert.ok(columns.includes('change_id'));
|
|
60
60
|
const eventColumns = upgraded.db.prepare('PRAGMA table_info(events)').all().map((row) => row.name);
|
|
61
61
|
assert.ok(eventColumns.includes('change_id'));
|
|
62
|
-
assert.equal(upgraded.schema_version, '9.
|
|
63
|
-
assert.ok(upgraded.db.prepare("SELECT 1 FROM schema_version WHERE version = '9.
|
|
62
|
+
assert.equal(upgraded.schema_version, '9.1');
|
|
63
|
+
assert.ok(upgraded.db.prepare("SELECT 1 FROM schema_version WHERE version = '9.1'").get());
|
|
64
64
|
stateDb.closeStateDb(upgraded.db);
|
|
65
65
|
} finally {
|
|
66
66
|
fs.rmSync(dir, { recursive: true, force: true });
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ultra-builder-pro-cli",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "Multi-runtime installer for the Ultra Builder Pro agent engineering system — deploys commands, agents, skills, hooks, and MCP server to Claude Code, OpenCode, and
|
|
3
|
+
"version": "0.9.0",
|
|
4
|
+
"description": "Multi-runtime installer for the Ultra Builder Pro agent engineering system — deploys commands, agents, skills, hooks, and MCP server to Claude Code, OpenCode, Codex CLI, and Kimi Code.",
|
|
5
5
|
"bin": {
|
|
6
6
|
"ultra-builder-pro-cli": "bin/install.js",
|
|
7
7
|
"ubp": "bin/install.js",
|
|
@@ -60,6 +60,7 @@
|
|
|
60
60
|
"claude-code",
|
|
61
61
|
"opencode",
|
|
62
62
|
"codex",
|
|
63
|
+
"kimi-code",
|
|
63
64
|
"agent",
|
|
64
65
|
"cli",
|
|
65
66
|
"multi-runtime",
|
|
@@ -92,6 +93,7 @@
|
|
|
92
93
|
"verify:release": "npm run test:all && npm run test:hooks && npm audit --omit=dev --audit-level=high",
|
|
93
94
|
"prepublishOnly": "npm run verify:release",
|
|
94
95
|
"install:claude": "node bin/install.js --claude --local",
|
|
96
|
+
"install:kimi": "node bin/install.js --kimi --local",
|
|
95
97
|
"install:all": "node bin/install.js --all --local"
|
|
96
98
|
},
|
|
97
99
|
"dependencies": {
|
|
@@ -58,7 +58,7 @@ Choose the smallest honest kind:
|
|
|
58
58
|
| `quick` | localized fix or tiny behavior change | diff, tests, spec |
|
|
59
59
|
| `standard` | normal feature or cross-file change | diff, tests, spec, docs, review |
|
|
60
60
|
| `major` | architecture, public contract, migration, or broad redesign | diff, tests, spec, docs, review |
|
|
61
|
-
| `incident` | production/runtime failure
|
|
61
|
+
| `incident` | canonical debug lane for a production/runtime failure | diagnosis, diff, tests |
|
|
62
62
|
|
|
63
63
|
When uncertain between two kinds, choose the higher-risk kind. Classification
|
|
64
64
|
changes the proof required; it must not be used to bypass evidence.
|
|
@@ -91,14 +91,18 @@ The change directory is the bounded execution packet:
|
|
|
91
91
|
context-manifest.json
|
|
92
92
|
delta/ # required for standard and major
|
|
93
93
|
plan.md # required for standard and major
|
|
94
|
+
diagnosis.md # created and structurally required for incident
|
|
94
95
|
verification.md # generated by convergence
|
|
95
96
|
```
|
|
96
97
|
|
|
97
98
|
For `standard` and `major`, write delta documents under `delta/` describing
|
|
98
99
|
what changes relative to the current baseline. Do not copy the whole baseline.
|
|
99
100
|
Write `plan.md` with live entry points, files/contracts, tests, documentation,
|
|
100
|
-
and rollback. For `quick
|
|
101
|
-
|
|
101
|
+
and rollback. For `quick`, add only artifacts needed to make the decision and
|
|
102
|
+
evidence inspectable. For `incident`, complete the generated `diagnosis.md` with
|
|
103
|
+
non-empty `Reproduction`, `Hypotheses`, `Root cause`, `Regression test`, and
|
|
104
|
+
`Recovery` sections. Free-form convergence evidence never substitutes for this
|
|
105
|
+
durable diagnosis artifact.
|
|
102
106
|
|
|
103
107
|
Create at least one task through `task.create` with `change_id` set. Split only
|
|
104
108
|
when ownership, dependencies, or independent verification justify it. All task
|
|
@@ -116,6 +120,11 @@ context, not permission to silently refresh or mutate the external provider.
|
|
|
116
120
|
|
|
117
121
|
## 6. Route execution
|
|
118
122
|
|
|
123
|
+
- For `incident`, diagnosis is the first execution slice. Route it to the bundled
|
|
124
|
+
`debugger` agent when the Host exposes native subagents; otherwise the primary
|
|
125
|
+
Host follows the same four-phase method. Supply only the compiled change/task
|
|
126
|
+
context. The primary Host owns the fix, updates `diagnosis.md`, and reruns the
|
|
127
|
+
discriminating regression test.
|
|
119
128
|
- Implement one linked task with `/ultra-dev <task-id>`.
|
|
120
129
|
- Run `/ultra-test` for project-level evidence.
|
|
121
130
|
- Run `/ultra-review` when the change kind requires review.
|
|
@@ -141,7 +141,9 @@ evidence required by kind:
|
|
|
141
141
|
|
|
142
142
|
- `quick`: diff, tests, spec;
|
|
143
143
|
- `standard` / `major`: diff, tests, spec, docs, review;
|
|
144
|
-
- `incident`: diagnosis, diff, tests.
|
|
144
|
+
- `incident`: diagnosis, diff, tests. The diagnosis evidence must point to the
|
|
145
|
+
completed `diagnosis.md`; convergence separately validates all five required
|
|
146
|
+
debugging sections and cannot be satisfied by the evidence string alone.
|
|
145
147
|
|
|
146
148
|
Evidence must name concrete commands, artifacts, or file paths. If blockers are
|
|
147
149
|
returned, stop before tag/push and route to the owning workflow. Do not weaken
|
|
@@ -66,9 +66,16 @@ remaining incident unresolved.
|
|
|
66
66
|
For an installed hook that points to a missing cached file:
|
|
67
67
|
|
|
68
68
|
1. capture the exact hook config path and missing target;
|
|
69
|
-
2.
|
|
70
|
-
|
|
71
|
-
|
|
69
|
+
2. run the separate read-only installer boundary check:
|
|
70
|
+
`npx ultra-builder-pro-cli --<runtime> --local --doctor --json` (or use
|
|
71
|
+
`--global` when that is the actual install scope);
|
|
72
|
+
3. preserve its provenance, asset-hash, and host-contract findings;
|
|
73
|
+
4. reinstall or regenerate the host-native plugin through the adapter;
|
|
74
|
+
5. rerun both installer doctor and `system.doctor`, then a host hook smoke test.
|
|
75
|
+
|
|
76
|
+
`system.doctor` diagnoses project `.ultra/state.db` and workflow recovery.
|
|
77
|
+
Installer `ubp --doctor` diagnoses the installed plugin files and host wiring.
|
|
78
|
+
Neither report substitutes for the other.
|
|
72
79
|
|
|
73
80
|
Do not bypass a broken hook by changing application implementation, and do not
|
|
74
81
|
treat a hook failure as project-code evidence.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: ultra-review
|
|
3
|
-
description: "Parallel code review orchestration with
|
|
3
|
+
description: "Parallel code review orchestration with 5 specialized reviewers + coordinator. Zero context pollution - all output via JSON files."
|
|
4
4
|
user-invocable: true
|
|
5
5
|
runtime: all
|
|
6
6
|
mcp_tools_required:
|
|
@@ -32,7 +32,7 @@ Orchestrates parallel code review using specialized agents. All findings written
|
|
|
32
32
|
|
|
33
33
|
```
|
|
34
34
|
/ultra-review # Full review (smart skip based on diff content)
|
|
35
|
-
/ultra-review all # Force ALL
|
|
35
|
+
/ultra-review all # Force ALL 5 reviewers, no auto-skip (pre-merge gate)
|
|
36
36
|
/ultra-review quick # Quick review (review-code only)
|
|
37
37
|
/ultra-review security # Security focus (review-code + review-errors)
|
|
38
38
|
/ultra-review tests # Test quality focus (review-tests only)
|
|
@@ -138,7 +138,7 @@ echo "<diff_files>" | grep -E "\.(test|spec)\.(ts|tsx|js|jsx)$|test_.*\.py$|.*_t
|
|
|
138
138
|
grep -l "try\|catch\|\.catch\|throw\|Error(" <diff_files>
|
|
139
139
|
```
|
|
140
140
|
|
|
141
|
-
**Mode: `all`** → Force ALL
|
|
141
|
+
**Mode: `all`** → Force ALL 5 reviewers, no auto-skip. Use for pre-merge gates (`/ultra-dev`).
|
|
142
142
|
**Mode: `quick`** → review-code only
|
|
143
143
|
**Mode: `security`** → review-code + review-errors
|
|
144
144
|
**Mode: `tests`** → review-tests only
|
package/spec/mcp-tools.yaml
CHANGED
|
@@ -367,7 +367,7 @@ tools:
|
|
|
367
367
|
task_id: { type: string }
|
|
368
368
|
change_id: { type: string }
|
|
369
369
|
session_id: { type: string }
|
|
370
|
-
runtime: { type: string, enum: [claude, opencode, codex] }
|
|
370
|
+
runtime: { type: string, enum: [claude, opencode, codex, kimi] }
|
|
371
371
|
type:
|
|
372
372
|
type: string
|
|
373
373
|
enum:
|
|
@@ -452,7 +452,7 @@ tools:
|
|
|
452
452
|
additionalProperties: false
|
|
453
453
|
properties:
|
|
454
454
|
task_id: { type: string }
|
|
455
|
-
runtime: { type: string, enum: [claude, opencode, codex] }
|
|
455
|
+
runtime: { type: string, enum: [claude, opencode, codex, kimi] }
|
|
456
456
|
takeover: { type: boolean, default: false, description: 'override active lease (D33 takeover strategy)' }
|
|
457
457
|
worktree_base: { type: string }
|
|
458
458
|
output_schema:
|
|
@@ -554,7 +554,7 @@ tools:
|
|
|
554
554
|
additionalProperties: false
|
|
555
555
|
properties:
|
|
556
556
|
task_id: { type: string }
|
|
557
|
-
runtime: { type: string, enum: [claude, opencode, codex] }
|
|
557
|
+
runtime: { type: string, enum: [claude, opencode, codex, kimi] }
|
|
558
558
|
output_schema:
|
|
559
559
|
type: object
|
|
560
560
|
required: [can_spawn, recommended_action]
|
|
@@ -630,7 +630,7 @@ tools:
|
|
|
630
630
|
# ────────────────────────── change family ──────────────────────────────
|
|
631
631
|
- name: change.create
|
|
632
632
|
family: change
|
|
633
|
-
description: Create a continuous feature, fix, redesign, or incident change unit and its initial context manifest.
|
|
633
|
+
description: Create a continuous feature, fix, redesign, or incident change unit and its initial context manifest; incidents also register a five-section diagnosis artifact.
|
|
634
634
|
phase: '9'
|
|
635
635
|
writer_role: mcp
|
|
636
636
|
input_schema:
|
|
@@ -860,7 +860,7 @@ tools:
|
|
|
860
860
|
|
|
861
861
|
- name: change.converge
|
|
862
862
|
family: change
|
|
863
|
-
description: Deterministically verify task, spec, test, documentation, review, and
|
|
863
|
+
description: Deterministically verify task, spec, test, documentation, review, context, and incident diagnosis structure before closure.
|
|
864
864
|
phase: '9'
|
|
865
865
|
writer_role: mcp
|
|
866
866
|
input_schema:
|
|
@@ -19,10 +19,10 @@
|
|
|
19
19
|
},
|
|
20
20
|
"runtime": {
|
|
21
21
|
"oneOf": [
|
|
22
|
-
{ "type": "string", "enum": ["claude", "opencode", "codex", "all"] },
|
|
22
|
+
{ "type": "string", "enum": ["claude", "opencode", "codex", "kimi", "all"] },
|
|
23
23
|
{
|
|
24
24
|
"type": "array",
|
|
25
|
-
"items": { "type": "string", "enum": ["claude", "opencode", "codex"] },
|
|
25
|
+
"items": { "type": "string", "enum": ["claude", "opencode", "codex", "kimi"] },
|
|
26
26
|
"minItems": 1,
|
|
27
27
|
"uniqueItems": true
|
|
28
28
|
}
|
|
@@ -79,7 +79,7 @@ CREATE TABLE IF NOT EXISTS events (
|
|
|
79
79
|
task_id TEXT,
|
|
80
80
|
change_id TEXT,
|
|
81
81
|
session_id TEXT,
|
|
82
|
-
runtime TEXT CHECK (runtime IS NULL OR runtime IN ('claude', 'opencode', 'codex')),
|
|
82
|
+
runtime TEXT CHECK (runtime IS NULL OR runtime IN ('claude', 'opencode', 'codex', 'kimi')),
|
|
83
83
|
payload_json TEXT
|
|
84
84
|
);
|
|
85
85
|
|
|
@@ -95,7 +95,7 @@ CREATE INDEX IF NOT EXISTS events_change ON events(change_id, id);
|
|
|
95
95
|
CREATE TABLE IF NOT EXISTS sessions (
|
|
96
96
|
sid TEXT PRIMARY KEY,
|
|
97
97
|
task_id TEXT NOT NULL REFERENCES tasks(id),
|
|
98
|
-
runtime TEXT NOT NULL CHECK (runtime IN ('claude', 'opencode', 'codex')),
|
|
98
|
+
runtime TEXT NOT NULL CHECK (runtime IN ('claude', 'opencode', 'codex', 'kimi')),
|
|
99
99
|
pid INTEGER,
|
|
100
100
|
worktree_path TEXT NOT NULL,
|
|
101
101
|
artifact_dir TEXT NOT NULL,
|
|
@@ -272,3 +272,5 @@ INSERT OR IGNORE INTO schema_version (version, description)
|
|
|
272
272
|
VALUES ('8A.2', 'Phase 8A.2 — tasks.estimated_days preserved across MCP and v4.4 migration');
|
|
273
273
|
INSERT OR IGNORE INTO schema_version (version, description)
|
|
274
274
|
VALUES ('9.0', 'Continuous change units, context snapshots, trace links, incidents, projection outbox, and durable consumers');
|
|
275
|
+
INSERT OR IGNORE INTO schema_version (version, description)
|
|
276
|
+
VALUES ('9.1', 'Kimi runtime support in durable events and sessions');
|