ultra-builder-pro-cli 0.5.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 (206) hide show
  1. package/.ultra-template/delivery-report.json +9 -0
  2. package/.ultra-template/docs/research/README.md +53 -0
  3. package/.ultra-template/specs/architecture.md +250 -0
  4. package/.ultra-template/specs/discovery.md +248 -0
  5. package/.ultra-template/specs/product.md +223 -0
  6. package/.ultra-template/tasks/contexts/TEMPLATE.md +57 -0
  7. package/.ultra-template/tasks/tasks.json +33 -0
  8. package/.ultra-template/test-report.json +8 -0
  9. package/CHANGELOG.md +194 -0
  10. package/LICENSE +21 -0
  11. package/README.md +187 -0
  12. package/adapters/_shared/codex-assets.cjs +1128 -0
  13. package/adapters/_shared/codex-ultra-tools-entry.cjs +11 -0
  14. package/adapters/_shared/file-ops.cjs +115 -0
  15. package/adapters/_shared/frontmatter.cjs +52 -0
  16. package/adapters/_shared/handbook.cjs +144 -0
  17. package/adapters/_shared/md-to-toml.cjs +54 -0
  18. package/adapters/_shared/path-rewrite.cjs +79 -0
  19. package/adapters/_shared/rtk-detect.cjs +86 -0
  20. package/adapters/_shared/runtime-assets.cjs +70 -0
  21. package/adapters/_shared/settings-merge.cjs +76 -0
  22. package/adapters/_shared/tests/file-ops.test.cjs +54 -0
  23. package/adapters/_shared/tests/frontmatter.test.cjs +47 -0
  24. package/adapters/_shared/tests/handbook.test.cjs +86 -0
  25. package/adapters/_shared/tests/md-to-toml.test.cjs +48 -0
  26. package/adapters/_shared/tests/path-rewrite.test.cjs +60 -0
  27. package/adapters/_shared/tests/resolve-target.test.cjs +85 -0
  28. package/adapters/_shared/tests/rtk-detect.test.cjs +116 -0
  29. package/adapters/_shared/tests/runtime-assets.test.cjs +107 -0
  30. package/adapters/_shared/tests/settings-merge.test.cjs +85 -0
  31. package/adapters/_shared/tests/validate.test.cjs +30 -0
  32. package/adapters/_shared/validate.cjs +24 -0
  33. package/adapters/claude.js +182 -0
  34. package/adapters/codex.js +385 -0
  35. package/adapters/gemini.js +204 -0
  36. package/adapters/opencode.js +506 -0
  37. package/adapters/tests/claude.test.cjs +117 -0
  38. package/adapters/tests/codex-hook.test.cjs +90 -0
  39. package/adapters/tests/codex.test.cjs +356 -0
  40. package/adapters/tests/gemini.test.cjs +112 -0
  41. package/adapters/tests/opencode.test.cjs +246 -0
  42. package/agents/code-reviewer.md +102 -0
  43. package/agents/debugger.md +127 -0
  44. package/agents/review-code.md +125 -0
  45. package/agents/review-comments.md +98 -0
  46. package/agents/review-coordinator.md +146 -0
  47. package/agents/review-design.md +133 -0
  48. package/agents/review-errors.md +87 -0
  49. package/agents/review-tests.md +93 -0
  50. package/agents/tdd-runner.md +92 -0
  51. package/bin/handbook.js +54 -0
  52. package/bin/install.js +254 -0
  53. package/bin/orchestrator.js +214 -0
  54. package/commands/learn.md +41 -0
  55. package/commands/ultra-deliver.md +45 -0
  56. package/commands/ultra-dev.md +50 -0
  57. package/commands/ultra-init.md +51 -0
  58. package/commands/ultra-plan.md +49 -0
  59. package/commands/ultra-research.md +59 -0
  60. package/commands/ultra-status.md +46 -0
  61. package/commands/ultra-test.md +48 -0
  62. package/commands/ultra-think.md +45 -0
  63. package/docs/AGENT-CONTEXT.md +143 -0
  64. package/docs/ARCHITECTURE.md +197 -0
  65. package/docs/COMMIT-HASH-BACKFILL.md +101 -0
  66. package/docs/LEGACY-HERMES.md +1175 -0
  67. package/docs/PLAN.zh-CN.md +1683 -0
  68. package/docs/ROADMAP.md +102 -0
  69. package/docs/RUNTIME-COMPAT-MATRIX.md +98 -0
  70. package/docs/STATE-DB-ACCESS-POLICY.md +109 -0
  71. package/docs/USER-HANDBOOK-CONTRACT.md +61 -0
  72. package/hooks/README.md +24 -0
  73. package/hooks/active_task_context.py +44 -0
  74. package/hooks/adapters/codex.py +302 -0
  75. package/hooks/health_check.py +61 -0
  76. package/hooks/pre_stop_check.py +56 -0
  77. package/hooks/subagent_tracker.py +116 -0
  78. package/hooks/workflow_checkpoint.py +56 -0
  79. package/hooks/workflow_context.py +63 -0
  80. package/hooks/workflow_resume.py +50 -0
  81. package/mcp-server/lib/init-project.cjs +162 -0
  82. package/mcp-server/lib/llm-client.cjs +157 -0
  83. package/mcp-server/lib/llm-client.test.cjs +156 -0
  84. package/mcp-server/lib/plan-store.cjs +96 -0
  85. package/mcp-server/lib/plan-store.test.cjs +132 -0
  86. package/mcp-server/lib/prd-parser.cjs +110 -0
  87. package/mcp-server/lib/prd-parser.test.cjs +171 -0
  88. package/mcp-server/lib/pricing.cjs +53 -0
  89. package/mcp-server/lib/projector.cjs +158 -0
  90. package/mcp-server/lib/state-db.cjs +113 -0
  91. package/mcp-server/lib/state-db.test.cjs +116 -0
  92. package/mcp-server/lib/state-ops.cjs +725 -0
  93. package/mcp-server/lib/task-expander.cjs +123 -0
  94. package/mcp-server/lib/task-expander.test.cjs +253 -0
  95. package/mcp-server/lib/telemetry.cjs +72 -0
  96. package/mcp-server/lib/topo.cjs +131 -0
  97. package/mcp-server/lib/topo.test.cjs +158 -0
  98. package/mcp-server/server.cjs +482 -0
  99. package/mcp-server/tests/circuit-breaker.test.cjs +125 -0
  100. package/mcp-server/tests/commit-hash-flow.test.cjs +117 -0
  101. package/mcp-server/tests/concurrency-update.test.cjs +96 -0
  102. package/mcp-server/tests/concurrency.test.cjs +112 -0
  103. package/mcp-server/tests/db-ops.test.cjs +117 -0
  104. package/mcp-server/tests/init-project.test.cjs +141 -0
  105. package/mcp-server/tests/migrate.test.cjs +144 -0
  106. package/mcp-server/tests/projector.test.cjs +130 -0
  107. package/mcp-server/tests/server-contract.test.cjs +750 -0
  108. package/mcp-server/tests/staleness.test.cjs +190 -0
  109. package/mcp-server/tests/state-ops.test.cjs +286 -0
  110. package/mcp-server/tests/tagged-tasks.test.cjs +163 -0
  111. package/mcp-server/tests/telemetry.test.cjs +205 -0
  112. package/orchestrator/auto-merge.cjs +109 -0
  113. package/orchestrator/code-graph-watcher.cjs +121 -0
  114. package/orchestrator/daemon.cjs +112 -0
  115. package/orchestrator/dispatch-rules.cjs +93 -0
  116. package/orchestrator/parallel-orchestrator.cjs +195 -0
  117. package/orchestrator/planner/expand-prompt.cjs +62 -0
  118. package/orchestrator/planner/expand-prompt.test.cjs +52 -0
  119. package/orchestrator/planner/plan-builder.cjs +116 -0
  120. package/orchestrator/planner/plan-builder.test.cjs +165 -0
  121. package/orchestrator/planner/prd-prompt.cjs +44 -0
  122. package/orchestrator/planner/prd-prompt.test.cjs +30 -0
  123. package/orchestrator/recovery.cjs +70 -0
  124. package/orchestrator/session-runner.cjs +224 -0
  125. package/orchestrator/skill-miner.cjs +133 -0
  126. package/orchestrator/tests/auto-merge.test.cjs +216 -0
  127. package/orchestrator/tests/code-graph-watcher.test.cjs +183 -0
  128. package/orchestrator/tests/daemon.test.cjs +260 -0
  129. package/orchestrator/tests/dispatch-rules.test.cjs +122 -0
  130. package/orchestrator/tests/parallel-orchestrator.test.cjs +233 -0
  131. package/orchestrator/tests/phase-8b-gate.test.cjs +183 -0
  132. package/orchestrator/tests/recovery.test.cjs +190 -0
  133. package/orchestrator/tests/session-runner.test.cjs +314 -0
  134. package/orchestrator/tests/skill-miner.test.cjs +147 -0
  135. package/orchestrator/tests/worktree-manager.test.cjs +148 -0
  136. package/orchestrator/worktree-manager.cjs +131 -0
  137. package/output-styles/coding-vibes.md +67 -0
  138. package/output-styles/structural-thinking.md +61 -0
  139. package/package.json +109 -0
  140. package/settings.json +8 -0
  141. package/skills/cc-collab/SKILL.md +41 -0
  142. package/skills/code-review-expert/SKILL.md +118 -0
  143. package/skills/code-review-expert/references/code-quality-checklist.md +112 -0
  144. package/skills/code-review-expert/references/integration-checklist.md +46 -0
  145. package/skills/code-review-expert/references/removal-plan.md +52 -0
  146. package/skills/code-review-expert/references/security-checklist.md +100 -0
  147. package/skills/code-review-expert/references/solid-checklist.md +65 -0
  148. package/skills/codex-collab/SKILL.md +52 -0
  149. package/skills/codex-collab/evals/evals.json +40 -0
  150. package/skills/gemini-collab/SKILL.md +51 -0
  151. package/skills/gemini-collab/evals/evals.json +42 -0
  152. package/skills/integration-rules/SKILL.md +71 -0
  153. package/skills/learn/SKILL.md +117 -0
  154. package/skills/security-rules/SKILL.md +60 -0
  155. package/skills/testing-rules/SKILL.md +56 -0
  156. package/skills/ultra-deliver/SKILL.md +171 -0
  157. package/skills/ultra-dev/SKILL.md +324 -0
  158. package/skills/ultra-init/SKILL.md +148 -0
  159. package/skills/ultra-plan/SKILL.md +314 -0
  160. package/skills/ultra-research/SKILL.md +156 -0
  161. package/skills/ultra-research/steps/step-00-problem-validation.md +154 -0
  162. package/skills/ultra-research/steps/step-01-opportunity-discovery.md +172 -0
  163. package/skills/ultra-research/steps/step-02-market-assessment.md +195 -0
  164. package/skills/ultra-research/steps/step-03-competitive-landscape.md +197 -0
  165. package/skills/ultra-research/steps/step-04-product-strategy.md +196 -0
  166. package/skills/ultra-research/steps/step-05-assumptions-validation.md +234 -0
  167. package/skills/ultra-research/steps/step-10-user-personas.md +169 -0
  168. package/skills/ultra-research/steps/step-11-user-scenarios.md +181 -0
  169. package/skills/ultra-research/steps/step-20-user-stories.md +156 -0
  170. package/skills/ultra-research/steps/step-21-features-scope.md +157 -0
  171. package/skills/ultra-research/steps/step-22-success-metrics.md +195 -0
  172. package/skills/ultra-research/steps/step-30-architecture-context.md +154 -0
  173. package/skills/ultra-research/steps/step-31-solution-strategy.md +172 -0
  174. package/skills/ultra-research/steps/step-32-building-blocks.md +188 -0
  175. package/skills/ultra-research/steps/step-40-deployment.md +123 -0
  176. package/skills/ultra-research/steps/step-41-quality-risks.md +135 -0
  177. package/skills/ultra-research/steps/step-99-synthesis.md +188 -0
  178. package/skills/ultra-review/SKILL.md +437 -0
  179. package/skills/ultra-review/references/unified-schema.md +127 -0
  180. package/skills/ultra-review/scripts/review_verdict_update.py +99 -0
  181. package/skills/ultra-review/scripts/review_wait.py +120 -0
  182. package/skills/ultra-status/SKILL.md +162 -0
  183. package/skills/ultra-test/SKILL.md +195 -0
  184. package/skills/ultra-think/SKILL.md +109 -0
  185. package/skills/ultra-verify/SKILL.md +111 -0
  186. package/skills/ultra-verify/evals/evals.json +51 -0
  187. package/skills/ultra-verify/references/confidence-system.md +38 -0
  188. package/skills/ultra-verify/references/cross-verify-modes.md +73 -0
  189. package/skills/ultra-verify/scripts/verify_wait.py +131 -0
  190. package/spec/cli-protocol.md +118 -0
  191. package/spec/mcp-tools.yaml +658 -0
  192. package/spec/schemas/command-manifest.schema.json +47 -0
  193. package/spec/schemas/context-file.v4.5.schema.json +54 -0
  194. package/spec/schemas/mcp-tools.schema.json +136 -0
  195. package/spec/schemas/skill-manifest.schema.json +94 -0
  196. package/spec/schemas/state-db.sql +154 -0
  197. package/spec/schemas/tasks.v4.5.schema.json +66 -0
  198. package/ultra-tools/cli.cjs +121 -0
  199. package/ultra-tools/commands/db.cjs +175 -0
  200. package/ultra-tools/commands/legacy-memory.cjs +159 -0
  201. package/ultra-tools/commands/migrate.cjs +354 -0
  202. package/ultra-tools/commands/session.cjs +180 -0
  203. package/ultra-tools/commands/status.cjs +158 -0
  204. package/ultra-tools/commands/task.cjs +95 -0
  205. package/ultra-tools/legacy-memory.test.cjs +80 -0
  206. package/ultra-tools/status-command.test.cjs +132 -0
@@ -0,0 +1,113 @@
1
+ 'use strict';
2
+
3
+ const fs = require('node:fs');
4
+ const path = require('node:path');
5
+
6
+ const Database = require('better-sqlite3');
7
+
8
+ const REPO_ROOT = process.env.UBP_RUNTIME_ROOT
9
+ ? path.resolve(process.env.UBP_RUNTIME_ROOT)
10
+ : path.resolve(__dirname, '..', '..');
11
+ const SCHEMA_FILE = path.join(REPO_ROOT, 'spec', 'schemas', 'state-db.sql');
12
+ const EXPECTED_VERSION = '8A.1';
13
+
14
+ const REQUIRED_TABLES = Object.freeze([
15
+ 'tasks',
16
+ 'events',
17
+ 'sessions',
18
+ 'schema_version',
19
+ 'migration_history',
20
+ 'telemetry',
21
+ 'specs_refs',
22
+ 'circuit_breaker',
23
+ ]);
24
+
25
+ function readSchemaSql() {
26
+ if (!fs.existsSync(SCHEMA_FILE)) {
27
+ throw new Error(`state-db schema missing at ${SCHEMA_FILE}`);
28
+ }
29
+ return fs.readFileSync(SCHEMA_FILE, 'utf8');
30
+ }
31
+
32
+ function applyPragmas(db) {
33
+ db.pragma('journal_mode = WAL');
34
+ db.pragma('synchronous = NORMAL');
35
+ db.pragma('busy_timeout = 5000');
36
+ db.pragma('foreign_keys = ON');
37
+ }
38
+
39
+ function runScript(db, sql) {
40
+ const runner = db.exec.bind(db);
41
+ db.transaction(() => runner(sql))();
42
+ }
43
+
44
+ function openStateDb(dbPath) {
45
+ if (!dbPath) throw new Error('openStateDb: dbPath required');
46
+ fs.mkdirSync(path.dirname(dbPath), { recursive: true });
47
+ const db = new Database(dbPath);
48
+ applyPragmas(db);
49
+ return db;
50
+ }
51
+
52
+ function tableNames(db) {
53
+ return db
54
+ .prepare("SELECT name FROM sqlite_master WHERE type = 'table' AND name NOT LIKE 'sqlite_%'")
55
+ .all()
56
+ .map((r) => r.name);
57
+ }
58
+
59
+ function applySchema(db) {
60
+ runScript(db, readSchemaSql());
61
+ }
62
+
63
+ function ensureSchemaVersion(db) {
64
+ // schema_version is an audit trail — multiple rows across phase upgrades.
65
+ // Guard by checking whether the expected version row exists rather than
66
+ // relying on applied_at ordering (same-tick inserts from the seed block
67
+ // make `ORDER BY applied_at DESC LIMIT 1` non-deterministic).
68
+ const row = db.prepare('SELECT version FROM schema_version WHERE version = ?').get(EXPECTED_VERSION);
69
+ if (!row) {
70
+ const latest = db.prepare('SELECT version FROM schema_version ORDER BY applied_at DESC LIMIT 1').get();
71
+ throw new Error(
72
+ `state.db schema_version mismatch: expected '${EXPECTED_VERSION}', file has '${latest ? latest.version : '(empty)'}'`,
73
+ );
74
+ }
75
+ return row.version;
76
+ }
77
+
78
+ function initStateDb(dbPath) {
79
+ const db = openStateDb(dbPath);
80
+ const existing = new Set(tableNames(db));
81
+ const missing = REQUIRED_TABLES.filter((t) => !existing.has(t));
82
+ if (missing.length > 0) {
83
+ applySchema(db);
84
+ }
85
+ const version = ensureSchemaVersion(db);
86
+ return {
87
+ db,
88
+ path: dbPath,
89
+ schema_version: version,
90
+ created: missing.length > 0,
91
+ tables: tableNames(db).sort(),
92
+ };
93
+ }
94
+
95
+ function closeStateDb(db) {
96
+ if (db && typeof db.close === 'function') {
97
+ db.close();
98
+ }
99
+ }
100
+
101
+ module.exports = {
102
+ EXPECTED_VERSION,
103
+ REQUIRED_TABLES,
104
+ SCHEMA_FILE,
105
+ openStateDb,
106
+ applySchema,
107
+ applyPragmas,
108
+ ensureSchemaVersion,
109
+ initStateDb,
110
+ closeStateDb,
111
+ tableNames,
112
+ runScript,
113
+ };
@@ -0,0 +1,116 @@
1
+ 'use strict';
2
+
3
+ const test = require('node:test');
4
+ const assert = require('node:assert/strict');
5
+ const fs = require('node:fs');
6
+ const os = require('node:os');
7
+ const path = require('node:path');
8
+
9
+ const {
10
+ EXPECTED_VERSION,
11
+ REQUIRED_TABLES,
12
+ initStateDb,
13
+ closeStateDb,
14
+ openStateDb,
15
+ tableNames,
16
+ } = require('./state-db.cjs');
17
+
18
+ function tmpDbPath(prefix = 'ubp-state') {
19
+ const dir = fs.mkdtempSync(path.join(os.tmpdir(), `${prefix}-`));
20
+ return { dir, file: path.join(dir, 'state.db') };
21
+ }
22
+
23
+ test('initStateDb creates workflow tables without an Ultra memory store', () => {
24
+ const { dir, file } = tmpDbPath();
25
+ try {
26
+ const init = initStateDb(file);
27
+ assert.equal(init.created, true);
28
+ assert.equal(init.schema_version, EXPECTED_VERSION);
29
+ for (const t of REQUIRED_TABLES) {
30
+ assert.ok(init.tables.includes(t), `missing table ${t}`);
31
+ }
32
+ assert.ok(!init.tables.includes('memory_entries'));
33
+ assert.ok(!init.tables.includes('memory_fts'));
34
+ closeStateDb(init.db);
35
+ } finally {
36
+ fs.rmSync(dir, { recursive: true, force: true });
37
+ }
38
+ });
39
+
40
+ test('initStateDb applies WAL + busy_timeout + foreign_keys pragmas', () => {
41
+ const { dir, file } = tmpDbPath();
42
+ try {
43
+ const { db } = initStateDb(file);
44
+ assert.equal(db.pragma('journal_mode', { simple: true }), 'wal');
45
+ assert.equal(db.pragma('busy_timeout', { simple: true }), 5000);
46
+ assert.equal(db.pragma('foreign_keys', { simple: true }), 1);
47
+ closeStateDb(db);
48
+ } finally {
49
+ fs.rmSync(dir, { recursive: true, force: true });
50
+ }
51
+ });
52
+
53
+ test('initStateDb is idempotent — second call does not duplicate seed rows', () => {
54
+ const { dir, file } = tmpDbPath();
55
+ try {
56
+ const first = initStateDb(file);
57
+ const firstRows = first.db.prepare('SELECT COUNT(*) AS n FROM schema_version').get().n;
58
+ closeStateDb(first.db);
59
+
60
+ const second = initStateDb(file);
61
+ assert.equal(second.created, false, 'second init should not recreate schema');
62
+ assert.equal(second.schema_version, EXPECTED_VERSION);
63
+
64
+ const secondRows = second.db.prepare('SELECT COUNT(*) AS n FROM schema_version').get().n;
65
+ assert.equal(secondRows, firstRows, 'schema_version row count must not grow on re-init');
66
+ closeStateDb(second.db);
67
+ } finally {
68
+ fs.rmSync(dir, { recursive: true, force: true });
69
+ }
70
+ });
71
+
72
+ test('openStateDb on an empty file produces no tables until schema is applied', () => {
73
+ const { dir, file } = tmpDbPath();
74
+ try {
75
+ const db = openStateDb(file);
76
+ assert.deepEqual(tableNames(db), []);
77
+ closeStateDb(db);
78
+ } finally {
79
+ fs.rmSync(dir, { recursive: true, force: true });
80
+ }
81
+ });
82
+
83
+ test('Phase 8A.1 schema: tasks.parent_id column + tasks_parent partial index + seed row', () => {
84
+ const { dir, file } = tmpDbPath();
85
+ try {
86
+ const { db } = initStateDb(file);
87
+
88
+ const cols = db.prepare("PRAGMA table_info(tasks)").all();
89
+ const parentCol = cols.find((c) => c.name === 'parent_id');
90
+ assert.ok(parentCol, 'tasks.parent_id column must exist');
91
+ assert.equal(parentCol.type, 'TEXT');
92
+ assert.equal(parentCol.notnull, 0, 'parent_id must be nullable (top-level tasks)');
93
+
94
+ const indexRow = db
95
+ .prepare("SELECT name FROM sqlite_master WHERE type = 'index' AND name = 'tasks_parent'")
96
+ .get();
97
+ assert.ok(indexRow, 'tasks_parent index must exist');
98
+
99
+ const seedRow = db
100
+ .prepare("SELECT version, description FROM schema_version WHERE version = '8A.1'")
101
+ .get();
102
+ assert.ok(seedRow, 'schema_version row for 8A.1 must be seeded');
103
+ assert.match(seedRow.description, /parent_id/);
104
+
105
+ const fkInfo = db.prepare("PRAGMA foreign_key_list(tasks)").all();
106
+ const parentFk = fkInfo.find((fk) => fk.from === 'parent_id');
107
+ assert.ok(parentFk, 'parent_id must declare a foreign key to tasks(id)');
108
+ assert.equal(parentFk.table, 'tasks');
109
+ assert.equal(parentFk.to, 'id');
110
+ assert.equal(parentFk.on_delete, 'SET NULL');
111
+
112
+ closeStateDb(db);
113
+ } finally {
114
+ fs.rmSync(dir, { recursive: true, force: true });
115
+ }
116
+ });