ultra-builder-pro-cli 0.16.0 → 0.17.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 (64) hide show
  1. package/.ultra-template/specs/research-distillate.md +4 -3
  2. package/CHANGELOG.md +86 -0
  3. package/README.md +54 -24
  4. package/adapters/_shared/codex-assets.cjs +10 -5
  5. package/adapters/_shared/handbook.cjs +1 -1
  6. package/adapters/_shared/interaction-contract.cjs +61 -0
  7. package/adapters/claude.js +1 -1
  8. package/adapters/opencode.js +1 -1
  9. package/bin/orchestrator.js +175 -19
  10. package/commands/ultra-change.md +1 -1
  11. package/commands/ultra-deliver.md +3 -3
  12. package/commands/ultra-init.md +1 -1
  13. package/commands/ultra-plan.md +1 -1
  14. package/commands/ultra-research.md +2 -2
  15. package/commands/ultra-review.md +10 -0
  16. package/commands/ultra-status.md +1 -1
  17. package/commands/ultra-test.md +1 -1
  18. package/docs/AGENT-CONTEXT.md +11 -8
  19. package/docs/ARCHITECTURE.md +67 -9
  20. package/docs/LEGACY-CLI-CROSSWALK.md +163 -0
  21. package/docs/PLAN.zh-CN.md +19 -13
  22. package/docs/RUNTIME-COMPAT-MATRIX.md +2 -2
  23. package/docs/WORKFLOW-LIFECYCLE.md +123 -59
  24. package/hooks/pre_stop_check.py +3 -2
  25. package/mcp-server/lib/baseline-workflow.cjs +84 -16
  26. package/mcp-server/lib/change-workflow.cjs +55 -35
  27. package/mcp-server/lib/context-spine.cjs +171 -105
  28. package/mcp-server/lib/git-bootstrap.cjs +240 -0
  29. package/mcp-server/lib/init-project.cjs +178 -41
  30. package/mcp-server/lib/project-breadcrumb.cjs +14 -14
  31. package/mcp-server/lib/state-db.cjs +257 -10
  32. package/mcp-server/lib/state-ops.cjs +64 -1
  33. package/mcp-server/lib/workflow-state.cjs +300 -205
  34. package/mcp-server/server.cjs +58 -34
  35. package/orchestrator/auto-merge.cjs +19 -0
  36. package/orchestrator/daemon.cjs +104 -0
  37. package/orchestrator/parallel-orchestrator.cjs +371 -49
  38. package/orchestrator/session-runner.cjs +354 -25
  39. package/package.json +2 -1
  40. package/skills/ultra-change/SKILL.md +69 -94
  41. package/skills/ultra-deliver/SKILL.md +37 -65
  42. package/skills/ultra-dev/SKILL.md +50 -52
  43. package/skills/ultra-doctor/SKILL.md +34 -49
  44. package/skills/ultra-init/SKILL.md +78 -105
  45. package/skills/ultra-plan/SKILL.md +78 -99
  46. package/skills/ultra-research/SKILL.md +99 -113
  47. package/skills/ultra-review/SKILL.md +38 -53
  48. package/skills/ultra-review/references/review-modes.md +5 -3
  49. package/skills/ultra-review/references/unified-schema.md +26 -6
  50. package/skills/ultra-review/scripts/review_wait.py +12 -0
  51. package/skills/ultra-status/SKILL.md +34 -44
  52. package/skills/ultra-test/SKILL.md +61 -54
  53. package/skills/ultra-think/SKILL.md +37 -51
  54. package/skills/ultra-think/references/decision-dialogue.md +87 -111
  55. package/spec/cli-protocol.md +35 -0
  56. package/spec/mcp-tools.yaml +145 -28
  57. package/spec/schemas/delivery-report.v1.schema.json +1 -46
  58. package/spec/schemas/state-db.sql +8 -2
  59. package/spec/schemas/test-report.v1.schema.json +45 -14
  60. package/ultra-tools/cli.cjs +1 -1
  61. package/ultra-tools/commands/session.cjs +10 -3
  62. package/ultra-tools/commands/status.cjs +19 -14
  63. package/ultra-tools/commands/system.cjs +2 -2
  64. package/ultra-tools/commands/task.cjs +3 -0
@@ -9,6 +9,7 @@
9
9
  const path = require('node:path');
10
10
  const { initStateDb, closeStateDb } = require('../../mcp-server/lib/state-db.cjs');
11
11
  const ops = require('../../mcp-server/lib/state-ops.cjs');
12
+ const sessionRunner = require('../../orchestrator/session-runner.cjs');
12
13
 
13
14
  const DEFAULT_DB_PATH = path.join('.ultra', 'state.db');
14
15
 
@@ -20,11 +21,12 @@ VERBS:
20
21
  reap [--grace-seconds <n>] orphan sweeper (Phase 4.5.6)
21
22
  get --sid <sid>
22
23
  heartbeat --sid <sid>
23
- close --sid <sid> --status completed|crashed|orphan
24
+ close --sid <sid> --status completed|crashed|orphan [--remove-worktree]
24
25
  subscribe --since-id <n> [--sid <sid>] [--limit <n>]
25
26
 
26
27
  GLOBAL FLAGS:
27
28
  --db <path> path to state.db (default: .ultra/state.db)
29
+ --repo-root <path> repository root for verified worktree cleanup (default: cwd)
28
30
  -h, --help show this message
29
31
  `;
30
32
 
@@ -44,6 +46,8 @@ function parseFlags(args) {
44
46
  case '--limit': flags.limit = Number(args[++i]); break;
45
47
  case '--since-id': flags.since_id = Number(args[++i]); break;
46
48
  case '--grace-seconds': flags.grace_seconds = Number(args[++i]); break;
49
+ case '--repo-root': flags.repo_root = args[++i]; break;
50
+ case '--remove-worktree': flags.remove_worktree = true; break;
47
51
  case '-h': case '--help': flags.help = true; break;
48
52
  default: flags._.push(a);
49
53
  }
@@ -127,8 +131,11 @@ function cmdClose(flags) {
127
131
  if (!flags.sid || !flags.status) { emit({ ok: false, error: { code: 'VALIDATION_ERROR', message: 'missing --sid or --status' } }); return 1; }
128
132
  return withDb(flags, (db) => {
129
133
  try {
130
- ops.updateSession(db, flags.sid, { status: flags.status });
131
- emit({ ok: true, data: { sid: flags.sid, status: flags.status } });
134
+ const result = sessionRunner.closeSession(
135
+ { db, repoRoot: path.resolve(flags.repo_root || process.cwd()), sid: flags.sid },
136
+ { status: flags.status, remove_worktree: flags.remove_worktree === true },
137
+ );
138
+ emit({ ok: true, data: result });
132
139
  return 0;
133
140
  } catch (err) {
134
141
  emit({ ok: false, error: { code: err.code || 'STATE_DB_ERROR', message: err.message } });
@@ -17,7 +17,7 @@ const { readBreadcrumb } = require('../../mcp-server/lib/context-spine.cjs');
17
17
 
18
18
  const USAGE = `ultra-tools status [flags]
19
19
 
20
- Reads .ultra/state.db and prints baseline, workflow, task, session, route, and
20
+ Reads .ultra/state.db and prints baseline, workflow, task, session, valid transitions, and
21
21
  cost-observability status.
22
22
 
23
23
  FLAGS:
@@ -174,20 +174,19 @@ function buildStatusPanel(db, { since = null, limit = 3, rootDir = process.cwd()
174
174
  status: 'unavailable', active: 0, awaiting_owner: 0, checkpoint_ready: 0,
175
175
  deferred_blocking: 0, stale_artifacts: [], current: null, current_thread_id: null,
176
176
  };
177
- let next;
177
+ let transitions;
178
178
  let breadcrumb = null;
179
179
  try {
180
180
  if (!tables.has('baselines')) {
181
- next = {
182
- action: 'Resume project initialization to migrate and establish baseline authority.',
183
- recommended_workflow: 'ultra-init', readiness: 'blocked',
181
+ transitions = {
182
+ allowed: ['ultra-init', 'ultra-status'], required: 'ultra-init', readiness: 'blocked',
184
183
  blockers: ['BASELINE_SCHEMA_MIGRATION_REQUIRED'], warnings: [],
185
184
  };
186
185
  } else {
187
186
  breadcrumb = readBreadcrumb(db, {}, { rootDir });
188
- next = {
189
- action: breadcrumb.next_action,
190
- recommended_workflow: breadcrumb.recommended_workflow,
187
+ transitions = {
188
+ allowed: breadcrumb.allowed_transitions,
189
+ required: breadcrumb.required_transition,
191
190
  readiness: breadcrumb.readiness,
192
191
  blockers: breadcrumb.blockers,
193
192
  warnings: breadcrumb.warnings,
@@ -197,9 +196,8 @@ function buildStatusPanel(db, { since = null, limit = 3, rootDir = process.cwd()
197
196
  };
198
197
  }
199
198
  } catch (error) {
200
- next = {
201
- action: 'Run ultra-doctor to inspect authoritative state.',
202
- recommended_workflow: 'ultra-doctor', readiness: 'blocked',
199
+ transitions = {
200
+ allowed: ['ultra-doctor', 'ultra-status'], required: 'ultra-doctor', readiness: 'blocked',
203
201
  blockers: [`STATUS_AUTHORITY_UNAVAILABLE:${error.code || 'unknown'}`], warnings: [],
204
202
  };
205
203
  }
@@ -256,7 +254,7 @@ function buildStatusPanel(db, { since = null, limit = 3, rootDir = process.cwd()
256
254
  changes,
257
255
  tasks: taskCounts,
258
256
  sessions,
259
- next,
257
+ transitions,
260
258
  by_runtime,
261
259
  top_tasks,
262
260
  total_cost_usd,
@@ -315,7 +313,8 @@ function renderHuman(panel) {
315
313
  lines.push(
316
314
  `Sessions: running=${panel.sessions.running} crashed=${panel.sessions.crashed} orphan=${panel.sessions.orphan}`,
317
315
  );
318
- lines.push(`Next: ${panel.next.action} (${panel.next.recommended_workflow})`);
316
+ lines.push(`Allowed transitions: ${panel.transitions.allowed.join(', ') || 'none'}`);
317
+ if (panel.transitions.required) lines.push(`Required transition: ${panel.transitions.required}`);
319
318
  lines.push(
320
319
  `Evidence: test=${panel.evidence.test.status} review=${panel.evidence.review.status} delivery=${panel.evidence.delivery.status}`,
321
320
  );
@@ -360,6 +359,11 @@ function resolveDbPath() {
360
359
  return path.resolve('.ultra', 'state.db');
361
360
  }
362
361
 
362
+ function resolveRootDir(dbPath) {
363
+ if (process.env.UBP_ROOT_DIR) return path.resolve(process.env.UBP_ROOT_DIR);
364
+ return path.dirname(path.dirname(dbPath));
365
+ }
366
+
363
367
  function dispatch(args) {
364
368
  let flags;
365
369
  try { flags = parseFlags(args); } catch (err) { return fail('USAGE_ERROR', err.message); }
@@ -377,7 +381,7 @@ function dispatch(args) {
377
381
  const Database = require('better-sqlite3');
378
382
  const db = new Database(dbPath, { readonly: true });
379
383
  try {
380
- const rootDir = path.dirname(path.dirname(dbPath));
384
+ const rootDir = resolveRootDir(dbPath);
381
385
  const panel = buildStatusPanel(db, { since, limit: flags.limit, rootDir });
382
386
  if (flags.json) {
383
387
  emit({ ok: true, data: panel });
@@ -398,4 +402,5 @@ module.exports = {
398
402
  renderHuman,
399
403
  parseSince,
400
404
  parseFlags,
405
+ resolveRootDir,
401
406
  };
@@ -213,7 +213,7 @@ async function dispatchRestore(args) {
213
213
  quarantined_state_path: path.join(recoveryDir, 'state.db'),
214
214
  schema_version: initialized.schema_version,
215
215
  schema_migration_backup_path: initialized.backup_path || null,
216
- next_action: 'Run ultra-tools system doctor, then ultra-init to inspect baseline readiness.',
216
+ recovery_guidance: 'Run ultra-tools system doctor, then ultra-init to inspect baseline readiness.',
217
217
  },
218
218
  });
219
219
  return 0;
@@ -284,7 +284,7 @@ async function dispatchRebaseline(args) {
284
284
  : null,
285
285
  baseline: initialized.baseline,
286
286
  copied_files: initialized.copied_files,
287
- next_action: 'Inspect the preserved evidence, record the brownfield baseline, and obtain owner approval before convergence.',
287
+ recovery_guidance: 'Inspect the preserved evidence, run explicit adoption research, record the brownfield baseline, and obtain owner approval before convergence.',
288
288
  },
289
289
  });
290
290
  return 0;
@@ -17,6 +17,7 @@ FLAGS (init-project):
17
17
  --project-type <type> web | api | cli | fullstack | other
18
18
  --stack <stack> tech stack descriptor (comma-separated ok)
19
19
  --mode <mode> auto | greenfield | brownfield (default: auto)
20
+ --git-mode <mode> auto | initialize | skip (default: auto)
20
21
  --scope <path> baseline scope; repeat for multiple paths (default: .)
21
22
  --resume preserve existing .ultra/ and install only missing assets
22
23
  --overwrite replace existing .ultra/ (backup created)
@@ -38,6 +39,7 @@ function parseInitFlags(args) {
38
39
  case '--project-type': flags.project_type = args[++i]; break;
39
40
  case '--stack': flags.stack = args[++i]; break;
40
41
  case '--mode': flags.mode = args[++i]; break;
42
+ case '--git-mode': flags.git_mode = args[++i]; break;
41
43
  case '--scope': flags.scope.push(args[++i]); break;
42
44
  case '--resume': flags.resume = true; break;
43
45
  case '--source-template': flags.source_template = args[++i]; break;
@@ -66,6 +68,7 @@ function dispatchInitProject(rawArgs) {
66
68
  project_type: flags.project_type,
67
69
  stack: flags.stack,
68
70
  mode: flags.mode || 'auto',
71
+ git_mode: flags.git_mode || 'auto',
69
72
  scope: flags.scope.length > 0 ? flags.scope : undefined,
70
73
  resume: !!flags.resume,
71
74
  overwrite: !!flags.overwrite,