ultra-builder-pro-cli 0.20.0 → 0.22.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 (109) hide show
  1. package/.ultra-template/docs/research/README.md +26 -5
  2. package/.ultra-template/specs/discovery.md +1 -1
  3. package/.ultra-template/tasks/tasks.json +10 -3
  4. package/.ultra-template/templates/task-context.md +19 -0
  5. package/CHANGELOG.md +106 -0
  6. package/README.md +215 -41
  7. package/adapters/_shared/codex-assets.cjs +69 -11
  8. package/adapters/_shared/interaction-contract.cjs +36 -3
  9. package/adapters/_shared/runtime-assets.cjs +41 -1
  10. package/adapters/claude.js +7 -5
  11. package/adapters/codex.js +1 -1
  12. package/adapters/kimi.js +2 -8
  13. package/adapters/opencode.js +43 -30
  14. package/bin/orchestrator.js +64 -24
  15. package/docs/AGENT-CONTEXT.md +89 -49
  16. package/docs/ARCHITECTURE.md +112 -45
  17. package/docs/ARTIFACT-AUTHORITY.md +274 -0
  18. package/docs/COMMIT-HASH-BACKFILL.md +33 -90
  19. package/docs/DECISIONS.md +14 -6
  20. package/docs/LEGACY-CLI-CROSSWALK.md +16 -6
  21. package/docs/PLUGIN-ISOLATION-CONTRACT.md +6 -4
  22. package/docs/ROADMAP.md +20 -6
  23. package/docs/RUNTIME-COMPAT-MATRIX.md +29 -16
  24. package/docs/STATE-DB-ACCESS-POLICY.md +43 -13
  25. package/docs/WORKFLOW-LIFECYCLE.md +105 -50
  26. package/hooks/README.md +10 -8
  27. package/hooks/active_task_context.py +105 -18
  28. package/hooks/context_spine.py +16 -4
  29. package/hooks/health_check.py +5 -4
  30. package/hooks/pre_stop_check.py +5 -2
  31. package/hooks/runtime_paths.py +396 -0
  32. package/hooks/subagent_tracker.py +5 -2
  33. package/hooks/workflow_checkpoint.py +16 -3
  34. package/hooks/workflow_context.py +11 -3
  35. package/hooks/workflow_resume.py +7 -4
  36. package/mcp-server/breadcrumb.cjs +20 -2
  37. package/mcp-server/lib/archive-journal.cjs +1026 -111
  38. package/mcp-server/lib/archive-mutation-worker.py +365 -0
  39. package/mcp-server/lib/artifact-registry.cjs +1127 -0
  40. package/mcp-server/lib/baseline-workflow.cjs +69 -28
  41. package/mcp-server/lib/change-packet.cjs +818 -0
  42. package/mcp-server/lib/change-workflow.cjs +932 -176
  43. package/mcp-server/lib/context-paths.cjs +142 -0
  44. package/mcp-server/lib/context-spine.cjs +511 -45
  45. package/mcp-server/lib/decision-dialogue.cjs +345 -3
  46. package/mcp-server/lib/delivery-transaction.cjs +471 -0
  47. package/mcp-server/lib/doctor-backup-worker.cjs +328 -0
  48. package/mcp-server/lib/doctor.cjs +401 -11
  49. package/mcp-server/lib/git-bootstrap.cjs +458 -47
  50. package/mcp-server/lib/init-project.cjs +240 -95
  51. package/mcp-server/lib/plan-publication-worker.cjs +830 -0
  52. package/mcp-server/lib/plan-store.cjs +700 -5
  53. package/mcp-server/lib/project-breadcrumb.cjs +23 -4
  54. package/mcp-server/lib/projector.cjs +211 -42
  55. package/mcp-server/lib/runtime-paths.cjs +1687 -0
  56. package/mcp-server/lib/safe-project-file.cjs +385 -0
  57. package/mcp-server/lib/spec-learning.cjs +28 -12
  58. package/mcp-server/lib/state-authority.cjs +19 -3
  59. package/mcp-server/lib/state-db.cjs +263 -9
  60. package/mcp-server/lib/state-ops.cjs +254 -50
  61. package/mcp-server/lib/task-ledger.cjs +1342 -0
  62. package/mcp-server/lib/telemetry.cjs +12 -3
  63. package/mcp-server/lib/workflow-state.cjs +610 -58
  64. package/mcp-server/server.cjs +423 -42
  65. package/orchestrator/daemon.cjs +2 -10
  66. package/orchestrator/parallel-orchestrator.cjs +314 -50
  67. package/orchestrator/planner/plan-builder.cjs +1 -1
  68. package/orchestrator/recovery.cjs +125 -7
  69. package/orchestrator/session-close-journal-worker.cjs +5 -0
  70. package/orchestrator/session-close-journal.cjs +1014 -0
  71. package/orchestrator/session-runner.cjs +679 -69
  72. package/orchestrator/worktree-manager.cjs +186 -35
  73. package/package.json +2 -3
  74. package/skills/cc-collab/SKILL.md +4 -1
  75. package/skills/codex-collab/SKILL.md +5 -2
  76. package/skills/ultra-change/SKILL.md +34 -8
  77. package/skills/ultra-deliver/SKILL.md +26 -11
  78. package/skills/ultra-dev/SKILL.md +52 -10
  79. package/skills/ultra-doctor/SKILL.md +16 -3
  80. package/skills/ultra-init/SKILL.md +22 -11
  81. package/skills/ultra-plan/SKILL.md +58 -18
  82. package/skills/ultra-research/SKILL.md +37 -35
  83. package/skills/ultra-review/SKILL.md +14 -8
  84. package/skills/ultra-status/SKILL.md +18 -9
  85. package/skills/ultra-test/SKILL.md +11 -5
  86. package/skills/ultra-think/SKILL.md +6 -2
  87. package/skills/ultra-think/references/decision-dialogue.md +17 -6
  88. package/skills/ultra-verify/SKILL.md +4 -1
  89. package/spec/cli-protocol.md +21 -7
  90. package/spec/mcp-tools.yaml +629 -44
  91. package/spec/schemas/change-delta.v1.schema.json +153 -0
  92. package/spec/schemas/context-file.v4.5.schema.json +1 -1
  93. package/spec/schemas/documentation-reconciliation.v1.schema.json +106 -0
  94. package/spec/schemas/mcp-tools.schema.json +1 -1
  95. package/spec/schemas/state-db.sql +51 -14
  96. package/spec/schemas/task-ledger.v1.schema.json +217 -0
  97. package/spec/schemas/tasks.v4.5.schema.json +1 -1
  98. package/ultra-tools/cli.cjs +3 -2
  99. package/ultra-tools/commands/db.cjs +76 -25
  100. package/ultra-tools/commands/migrate.cjs +1000 -82
  101. package/ultra-tools/commands/session.cjs +34 -8
  102. package/ultra-tools/commands/status.cjs +32 -6
  103. package/ultra-tools/commands/system.cjs +129 -22
  104. package/.ultra-template/tasks/contexts/TEMPLATE.md +0 -19
  105. package/commands/learn.md +0 -10
  106. package/orchestrator/skill-miner.cjs +0 -133
  107. package/output-styles/coding-vibes.md +0 -67
  108. package/output-styles/structural-thinking.md +0 -61
  109. package/skills/learn/SKILL.md +0 -58
@@ -2,11 +2,14 @@
2
2
 
3
3
  const fs = require('node:fs');
4
4
  const path = require('node:path');
5
+ const { randomUUID } = require('node:crypto');
6
+ const Database = require('better-sqlite3');
5
7
 
6
8
  const { initStateDb, openStateDb, closeStateDb } = require('../../mcp-server/lib/state-db.cjs');
9
+ const runtimePaths = require('../../mcp-server/lib/runtime-paths.cjs');
7
10
 
8
- const DEFAULT_DB_PATH = path.join('.ultra', 'state.db');
9
- const DEFAULT_BACKUP_DIR = path.join('.ultra', 'backups');
11
+ const DEFAULT_DB_PATH = runtimePaths.STATE_DB_RELATIVE_PATH;
12
+ const DEFAULT_BACKUP_DIR = path.join(runtimePaths.RUNTIME_RELATIVE_DIR, 'backups');
10
13
 
11
14
  function parseFlags(args) {
12
15
  const flags = { _: [] };
@@ -50,9 +53,19 @@ function dispatch(args) {
50
53
  }
51
54
  }
52
55
 
56
+ function resolveAuthorityPath(flags, { migrateLegacy = true } = {}) {
57
+ const env = flags.path
58
+ ? { UBP_DB_PATH: path.resolve(flags.path) }
59
+ : process.env;
60
+ return runtimePaths.resolveConfiguredStateDb(process.cwd(), {
61
+ env,
62
+ migrateLegacy,
63
+ }).stateDbPath;
64
+ }
65
+
53
66
  function cmdInit(flags) {
54
- const dbPath = path.resolve(flags.path || DEFAULT_DB_PATH);
55
67
  try {
68
+ const dbPath = resolveAuthorityPath(flags, { migrateLegacy: true });
56
69
  const { db, schema_version, created, tables, path: actualPath } = initStateDb(dbPath);
57
70
  closeStateDb(db);
58
71
  emit({
@@ -80,13 +93,13 @@ function cmdInit(flags) {
80
93
  }
81
94
 
82
95
  function withOpenDb(flags, fn, errorCode) {
83
- const dbPath = path.resolve(flags.path || DEFAULT_DB_PATH);
84
- if (!fs.existsSync(dbPath)) {
85
- emit({ ok: false, error: { code: 'DB_NOT_FOUND', message: `state.db missing at ${dbPath}; run 'db init' first` } });
86
- return 2;
87
- }
88
96
  let db;
89
97
  try {
98
+ const dbPath = resolveAuthorityPath(flags, { migrateLegacy: true });
99
+ if (!fs.existsSync(dbPath)) {
100
+ emit({ ok: false, error: { code: 'DB_NOT_FOUND', message: `state.db missing at ${dbPath}; run 'db init' first` } });
101
+ return 2;
102
+ }
90
103
  db = openStateDb(dbPath);
91
104
  const data = fn(db, dbPath);
92
105
  emit({ ok: true, data: { path: dbPath, ...data } });
@@ -131,24 +144,54 @@ function defaultBackupPath() {
131
144
  return path.join(DEFAULT_BACKUP_DIR, `state-db-${ts}.db`);
132
145
  }
133
146
 
134
- function cmdBackup(flags) {
135
- const dbPath = path.resolve(flags.path || DEFAULT_DB_PATH);
136
- const targetPath = path.resolve(flags.to || defaultBackupPath());
137
- if (!fs.existsSync(dbPath)) {
138
- emit({ ok: false, error: { code: 'DB_NOT_FOUND', message: `state.db missing at ${dbPath}` } });
139
- return 2;
147
+ function quoteSqlString(value) {
148
+ return `'${String(value).replaceAll("'", "''")}'`;
149
+ }
150
+
151
+ function createOnlineBackup(db, targetPath, {
152
+ beforeSnapshot = null,
153
+ } = {}) {
154
+ const stage = path.join(
155
+ path.dirname(targetPath),
156
+ `.${path.basename(targetPath)}.snapshot-${process.pid}-${randomUUID()}`,
157
+ );
158
+ try {
159
+ if (beforeSnapshot) beforeSnapshot();
160
+ // VACUUM INTO is SQLite's synchronous, transactionally consistent
161
+ // snapshot primitive. It reads committed pages through SQLite rather than
162
+ // copying a main file that may lag committed WAL frames.
163
+ db.exec(`VACUUM INTO ${quoteSqlString(stage)}`);
164
+ const snapshot = new Database(stage, { readonly: true, fileMustExist: true });
165
+ try {
166
+ const integrity = snapshot.pragma('integrity_check');
167
+ if (integrity.length !== 1 || integrity[0].integrity_check !== 'ok') {
168
+ throw new Error('SQLite backup snapshot failed integrity_check');
169
+ }
170
+ } finally {
171
+ snapshot.close();
172
+ }
173
+ fs.renameSync(stage, targetPath);
174
+ return fs.statSync(targetPath).size;
175
+ } finally {
176
+ fs.rmSync(stage, { force: true });
140
177
  }
141
- fs.mkdirSync(path.dirname(targetPath), { recursive: true });
178
+ }
179
+
180
+ function cmdBackup(flags) {
142
181
  let db;
143
182
  try {
144
- // Flush WAL into the main file so a plain copy captures all committed
145
- // writes; fall back to copy-only on a fresh file with no WAL.
183
+ const dbPath = resolveAuthorityPath(flags, { migrateLegacy: true });
184
+ const targetPath = runtimePaths.assertManagedBackupDestination(
185
+ process.cwd(),
186
+ flags.to || defaultBackupPath(),
187
+ ).targetPath;
188
+ if (!fs.existsSync(dbPath)) {
189
+ emit({ ok: false, error: { code: 'DB_NOT_FOUND', message: `state.db missing at ${dbPath}` } });
190
+ return 2;
191
+ }
192
+ fs.mkdirSync(path.dirname(targetPath), { recursive: true });
146
193
  db = openStateDb(dbPath);
147
- db.pragma('wal_checkpoint(TRUNCATE)');
148
- closeStateDb(db);
149
- db = null;
150
- fs.copyFileSync(dbPath, targetPath);
151
- const size = fs.statSync(targetPath).size;
194
+ const size = createOnlineBackup(db, targetPath);
152
195
  emit({ ok: true, data: { source: dbPath, target: targetPath, size_bytes: size } });
153
196
  return 0;
154
197
  } catch (err) {
@@ -168,8 +211,16 @@ Verbs (Phase 2):
168
211
  integrity [--path <db>] run PRAGMA integrity_check
169
212
  backup [--path <db>] [--to <out>] online .backup() to a file
170
213
 
171
- Default db: .ultra/state.db
172
- Default backup: .ultra/backups/state-db-{iso}.db
214
+ Default db: .ultra/.runtime/state.db
215
+ Default backup: .ultra/.runtime/backups/state-db-{iso}.db
173
216
  `;
174
217
 
175
- module.exports = { dispatch, USAGE, DEFAULT_DB_PATH, DEFAULT_BACKUP_DIR };
218
+ module.exports = {
219
+ dispatch,
220
+ USAGE,
221
+ DEFAULT_DB_PATH,
222
+ DEFAULT_BACKUP_DIR,
223
+ _internal: {
224
+ createOnlineBackup,
225
+ },
226
+ };