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.
Files changed (47) hide show
  1. package/CHANGELOG.md +60 -1
  2. package/README.md +49 -23
  3. package/adapters/_shared/codex-assets.cjs +28 -0
  4. package/adapters/_shared/handbook.cjs +9 -1
  5. package/adapters/_shared/path-rewrite.cjs +3 -0
  6. package/adapters/_shared/provenance.cjs +286 -0
  7. package/adapters/_shared/runtime-assets.cjs +2 -1
  8. package/adapters/_shared/tests/handbook.test.cjs +6 -1
  9. package/adapters/_shared/tests/path-rewrite.test.cjs +3 -1
  10. package/adapters/_shared/tests/provenance.test.cjs +133 -0
  11. package/adapters/_shared/tests/runtime-assets.test.cjs +4 -1
  12. package/adapters/claude.js +33 -0
  13. package/adapters/codex.js +87 -0
  14. package/adapters/kimi.js +642 -0
  15. package/adapters/opencode.js +66 -0
  16. package/adapters/tests/codex.test.cjs +37 -0
  17. package/adapters/tests/kimi-hook.test.cjs +122 -0
  18. package/adapters/tests/kimi.test.cjs +255 -0
  19. package/agents/debugger.md +12 -0
  20. package/bin/handbook.js +2 -2
  21. package/bin/install.js +72 -12
  22. package/bin/orchestrator.js +1 -1
  23. package/commands/ultra-change.md +3 -2
  24. package/docs/AGENT-CONTEXT.md +5 -3
  25. package/docs/ARCHITECTURE.md +40 -6
  26. package/docs/PLAN.zh-CN.md +8 -6
  27. package/docs/ROADMAP.md +4 -4
  28. package/docs/RUNTIME-COMPAT-MATRIX.md +109 -58
  29. package/docs/USER-HANDBOOK-CONTRACT.md +4 -1
  30. package/hooks/README.md +6 -2
  31. package/hooks/adapters/kimi.py +162 -0
  32. package/hooks/workflow_checkpoint.py +15 -1
  33. package/hooks/workflow_resume.py +96 -7
  34. package/mcp-server/lib/change-workflow.cjs +69 -0
  35. package/mcp-server/lib/change-workflow.test.cjs +87 -0
  36. package/mcp-server/lib/state-db.cjs +85 -2
  37. package/mcp-server/lib/state-db.test.cjs +56 -0
  38. package/mcp-server/tests/init-project.test.cjs +2 -2
  39. package/mcp-server/tests/state-db.test.cjs +3 -3
  40. package/package.json +4 -2
  41. package/skills/ultra-change/SKILL.md +12 -3
  42. package/skills/ultra-deliver/SKILL.md +3 -1
  43. package/skills/ultra-doctor/SKILL.md +10 -3
  44. package/skills/ultra-review/SKILL.md +3 -3
  45. package/spec/mcp-tools.yaml +5 -5
  46. package/spec/schemas/skill-manifest.schema.json +2 -2
  47. 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.0'").get();
40
- assert.equal(version.version, '9.0');
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.0 database in place with task/event change linkage', () => {
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.0');
63
- assert.ok(upgraded.db.prepare("SELECT 1 FROM schema_version WHERE version = '9.0'").get());
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.7.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 Codex CLI.",
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 requiring diagnosis | diagnosis, diff, tests |
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` and `incident`, add only artifacts needed to make the
101
- decision and evidence inspectable.
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. verify the currently installed plugin/cache version;
70
- 3. reinstall or regenerate the host-native plugin through the adapter;
71
- 4. rerun read-only doctor and a host hook smoke test.
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 6 specialized agents + coordinator. Zero context pollution - all output via JSON files."
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 6 agents, no auto-skip (pre-merge gate)
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 6 agents, no auto-skip. Use for pre-merge gates (`/ultra-dev`).
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
@@ -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 context evidence before closure.
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');