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,54 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://ultra-builder-pro.dev/spec/context-file.v4.5.schema.json",
4
+ "title": "context-file projection (v4.5)",
5
+ "description": "Schema for the parsed representation of .ultra/tasks/contexts/task-*.md. The header is regenerated by the projector from state.db (D32). Body sections are author-owned; status MUST NOT appear in body. Trace: PLAN §7.1, D17, D21.",
6
+ "type": "object",
7
+ "required": ["header", "body"],
8
+ "additionalProperties": false,
9
+ "properties": {
10
+ "header": {
11
+ "type": "object",
12
+ "required": ["task_id", "title", "status", "schema_version"],
13
+ "additionalProperties": false,
14
+ "properties": {
15
+ "task_id": { "type": "string" },
16
+ "title": { "type": "string" },
17
+ "status": {
18
+ "type": "string",
19
+ "enum": ["pending", "in_progress", "completed", "blocked", "expanded"],
20
+ "x-derived": true,
21
+ "description": "DERIVED from state.db tasks.status; written by projector, not by humans"
22
+ },
23
+ "priority": { "type": "string", "enum": ["P0", "P1", "P2", "P3"] },
24
+ "type": { "type": "string", "enum": ["architecture", "feature", "bugfix"] },
25
+ "session_id": { "type": "string", "x-derived": true },
26
+ "schema_version": { "const": "4.5" },
27
+ "generated_at": { "type": "string", "format": "date-time" }
28
+ }
29
+ },
30
+ "body": {
31
+ "type": "object",
32
+ "required": ["sections"],
33
+ "additionalProperties": false,
34
+ "properties": {
35
+ "sections": {
36
+ "type": "array",
37
+ "items": {
38
+ "type": "object",
39
+ "required": ["heading", "content"],
40
+ "additionalProperties": false,
41
+ "properties": {
42
+ "heading": {
43
+ "type": "string",
44
+ "not": { "pattern": "^[Ss]tatus" },
45
+ "description": "body sections cannot be 'Status' — that lives only in header (D17)"
46
+ },
47
+ "content": { "type": "string" }
48
+ }
49
+ }
50
+ }
51
+ }
52
+ }
53
+ }
54
+ }
@@ -0,0 +1,136 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://ultra-builder-pro.dev/spec/mcp-tools.schema.json",
4
+ "title": "MCP tools manifest",
5
+ "description": "Meta-schema describing the shape of spec/mcp-tools.yaml. The manifest itself is the single source for MCP tool contracts (PLAN R19).",
6
+ "type": "object",
7
+ "required": ["version", "info", "tools"],
8
+ "additionalProperties": false,
9
+ "properties": {
10
+ "version": { "type": "string", "pattern": "^[0-9]+\\.[0-9]+(\\.[0-9]+)?$" },
11
+ "info": {
12
+ "type": "object",
13
+ "required": ["title", "phase", "trace_to"],
14
+ "additionalProperties": false,
15
+ "properties": {
16
+ "title": { "type": "string" },
17
+ "phase": { "type": "string" },
18
+ "trace_to": { "type": "string" },
19
+ "notes": { "type": "string" }
20
+ }
21
+ },
22
+ "families": {
23
+ "type": "array",
24
+ "items": {
25
+ "type": "object",
26
+ "required": ["name", "description"],
27
+ "additionalProperties": false,
28
+ "properties": {
29
+ "name": { "type": "string", "pattern": "^[a-z]+$" },
30
+ "description": { "type": "string", "minLength": 10 },
31
+ "phase": { "type": "string" }
32
+ }
33
+ }
34
+ },
35
+ "tools": {
36
+ "type": "array",
37
+ "minItems": 1,
38
+ "items": { "$ref": "#/$defs/tool" }
39
+ }
40
+ },
41
+ "$defs": {
42
+ "tool": {
43
+ "type": "object",
44
+ "required": [
45
+ "name",
46
+ "family",
47
+ "description",
48
+ "phase",
49
+ "input_schema",
50
+ "output_schema",
51
+ "errors",
52
+ "cli_subcommand"
53
+ ],
54
+ "additionalProperties": false,
55
+ "properties": {
56
+ "name": {
57
+ "type": "string",
58
+ "pattern": "^[a-z][a-z_]*\\.[a-z][a-z_]*$",
59
+ "description": "family.verb naming convention (PLAN §7.3)"
60
+ },
61
+ "family": {
62
+ "type": "string",
63
+ "enum": ["task", "memory", "review", "impact", "skill", "session", "ask", "plan"]
64
+ },
65
+ "description": { "type": "string", "minLength": 10 },
66
+ "phase": {
67
+ "type": "string",
68
+ "pattern": "^[0-9]+(\\.[0-9]+)?[ab]?$",
69
+ "description": "earliest phase that implements this tool (e.g. 2, 4.5, 4.6a, 8a)"
70
+ },
71
+ "readonly": { "type": "boolean", "default": false },
72
+ "writer_role": {
73
+ "type": "string",
74
+ "enum": ["mcp", "cli", "orchestrator", "any"],
75
+ "default": "mcp",
76
+ "description": "which process is allowed to invoke (R25 access policy)"
77
+ },
78
+ "input_schema": { "$ref": "#/$defs/jsonSchemaFragment" },
79
+ "output_schema": { "$ref": "#/$defs/jsonSchemaFragment" },
80
+ "errors": {
81
+ "type": "array",
82
+ "minItems": 1,
83
+ "items": {
84
+ "type": "object",
85
+ "required": ["code", "description"],
86
+ "additionalProperties": false,
87
+ "properties": {
88
+ "code": { "type": "string", "pattern": "^[A-Z][A-Z0-9_]*$" },
89
+ "description": { "type": "string", "minLength": 5 },
90
+ "retriable": { "type": "boolean", "default": false }
91
+ }
92
+ }
93
+ },
94
+ "cli_subcommand": {
95
+ "type": "string",
96
+ "pattern": "^[a-z][a-z\\- ]*$",
97
+ "description": "ultra-tools subcommand path (e.g. 'task create', 'session spawn')"
98
+ },
99
+ "emits_events": {
100
+ "type": "array",
101
+ "items": { "type": "string" },
102
+ "description": "events.type values appended to state.db on success"
103
+ },
104
+ "trace_to": {
105
+ "type": "string",
106
+ "description": "PLAN section/decision id (e.g. §7.3, D33)"
107
+ }
108
+ }
109
+ },
110
+ "jsonSchemaFragment": {
111
+ "type": "object",
112
+ "description": "embedded JSON Schema (Draft 2020-12 subset). validate-mcp-tools.cjs compiles each fragment to ensure it is a usable schema.",
113
+ "required": ["type"],
114
+ "properties": {
115
+ "type": {},
116
+ "properties": {},
117
+ "required": {},
118
+ "additionalProperties": {},
119
+ "items": {},
120
+ "enum": {},
121
+ "oneOf": {},
122
+ "anyOf": {},
123
+ "allOf": {},
124
+ "$ref": {},
125
+ "format": {},
126
+ "pattern": {},
127
+ "minimum": {},
128
+ "maximum": {},
129
+ "minLength": {},
130
+ "maxLength": {},
131
+ "minItems": {},
132
+ "description": {}
133
+ }
134
+ }
135
+ }
136
+ }
@@ -0,0 +1,94 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://ultra-builder-pro.dev/spec/skill-manifest.schema.json",
4
+ "title": "Skill manifest (frontmatter)",
5
+ "description": "YAML frontmatter contract for skills/*/SKILL.md. Strict additionalProperties=false: any new field must be added here AND propagated through validate-skills.cjs (PLAN R19 single-source rule).",
6
+ "type": "object",
7
+ "required": ["name", "description"],
8
+ "additionalProperties": false,
9
+ "properties": {
10
+ "name": {
11
+ "type": "string",
12
+ "pattern": "^[a-z][a-z0-9\\-]*$",
13
+ "description": "kebab-case slug; matches the directory name"
14
+ },
15
+ "description": {
16
+ "type": "string",
17
+ "minLength": 10,
18
+ "description": "human-readable trigger sentence consumed by the runtime's skill router"
19
+ },
20
+ "runtime": {
21
+ "oneOf": [
22
+ { "type": "string", "enum": ["claude", "opencode", "codex", "gemini", "all"] },
23
+ {
24
+ "type": "array",
25
+ "items": { "type": "string", "enum": ["claude", "opencode", "codex", "gemini"] },
26
+ "minItems": 1,
27
+ "uniqueItems": true
28
+ }
29
+ ],
30
+ "description": "v4.5 — which runtime(s) this skill targets. Defaults to 'all' when absent (Phase 4 adapter installs everywhere)."
31
+ },
32
+ "mcp_tools_required": {
33
+ "type": "array",
34
+ "items": { "type": "string", "pattern": "^[a-z]+\\.[a-z_]+$" },
35
+ "uniqueItems": true,
36
+ "description": "v4.5 — MCP tool names this skill calls; Phase 3+ generators verify availability"
37
+ },
38
+ "cli_fallback": {
39
+ "type": "string",
40
+ "description": "v4.5 — ultra-tools subcommand to fall back to when MCP unreachable"
41
+ },
42
+ "complexity_hint": {
43
+ "type": "string",
44
+ "enum": ["haiku", "sonnet", "opus"],
45
+ "description": "v4.5 — model routing hint (Phase 7+)"
46
+ },
47
+ "argument-hint": {
48
+ "type": "string",
49
+ "description": "Claude Code convention: hint shown after slash-command name"
50
+ },
51
+ "allowed-tools": {
52
+ "type": "string",
53
+ "description": "Claude Code convention: comma-separated tool allowlist"
54
+ },
55
+ "user-invocable": {
56
+ "type": "boolean",
57
+ "description": "Claude Code convention: can the user call this via slash command"
58
+ },
59
+ "disable-model-invocation": {
60
+ "type": "boolean",
61
+ "description": "Claude Code convention: skill is not auto-invoked by the model"
62
+ },
63
+ "context": {
64
+ "type": "string",
65
+ "enum": ["fork", "main"],
66
+ "description": "Claude Code convention: 'fork' isolates skill output from main conversation"
67
+ },
68
+ "license": {
69
+ "type": "string",
70
+ "description": "third-party skill license (e.g. MIT)"
71
+ },
72
+ "metadata": {
73
+ "type": "object",
74
+ "additionalProperties": true,
75
+ "properties": {
76
+ "author": { "type": "string" },
77
+ "version": { "type": "string" }
78
+ },
79
+ "description": "third-party metadata block (vercel skills, etc.)"
80
+ }
81
+ },
82
+ "allOf": [
83
+ {
84
+ "if": { "required": ["user-invocable"], "properties": { "user-invocable": { "const": true } } },
85
+ "then": {
86
+ "not": {
87
+ "required": ["disable-model-invocation"],
88
+ "properties": { "disable-model-invocation": { "const": true } }
89
+ },
90
+ "errorMessage": "user-invocable=true cannot coexist with disable-model-invocation=true"
91
+ }
92
+ }
93
+ ]
94
+ }
@@ -0,0 +1,154 @@
1
+ -- Ultra Builder Pro — authoritative state schema
2
+ -- Phase 2 builds .ultra/state.db from this file. Source of truth for all
3
+ -- task / session / event / telemetry data. tasks.json and context md status
4
+ -- header are projections (PLAN §7.1, D18, D32).
5
+ --
6
+ -- Trace: docs/PLAN.zh-CN.md §7.1; decisions D18/D30/D31/D32/D37.
7
+ --
8
+ -- PRAGMAs are applied by mcp-server/lib/state-db.ts on connection open;
9
+ -- they cannot be persisted in CREATE statements but are documented here.
10
+ -- PRAGMA journal_mode=WAL; -- multi-reader / single-writer (R21)
11
+ -- PRAGMA synchronous=NORMAL; -- WAL durability vs perf
12
+ -- PRAGMA busy_timeout=5000; -- block up to 5s on lock (R25)
13
+ -- PRAGMA foreign_keys=ON; -- enforce FK constraints
14
+
15
+ -- ──────────────────────────── tasks ───────────────────────────────────────
16
+ -- Authoritative task row. tasks.json is generated from this table by the
17
+ -- projector (Phase 2.6). Manual edits to tasks.json are overwritten.
18
+ CREATE TABLE IF NOT EXISTS tasks (
19
+ id TEXT PRIMARY KEY,
20
+ title TEXT NOT NULL,
21
+ type TEXT NOT NULL CHECK (type IN ('architecture', 'feature', 'bugfix')),
22
+ priority TEXT NOT NULL CHECK (priority IN ('P0', 'P1', 'P2', 'P3')),
23
+ complexity INTEGER CHECK (complexity BETWEEN 1 AND 10),
24
+ status TEXT NOT NULL DEFAULT 'pending'
25
+ CHECK (status IN ('pending', 'in_progress', 'completed', 'blocked', 'expanded')),
26
+ deps TEXT, -- JSON array of task ids
27
+ files_modified TEXT, -- JSON array of paths (Phase 8B conflict detection)
28
+ session_id TEXT, -- current owning session (Phase 4.5)
29
+ stale INTEGER NOT NULL DEFAULT 0 CHECK (stale IN (0, 1)),
30
+ complexity_hint TEXT CHECK (complexity_hint IN ('haiku', 'sonnet', 'opus')),
31
+ tag TEXT, -- git branch tag (Phase 7.2)
32
+ trace_to TEXT, -- spec anchor reference
33
+ context_file TEXT, -- projection target path
34
+ completion_commit TEXT, -- backfilled hash (Phase 2.8)
35
+ parent_id TEXT REFERENCES tasks(id) ON DELETE SET NULL, -- Phase 8A.1: task.expand subtask→parent
36
+ created_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ', 'now')),
37
+ updated_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ', 'now'))
38
+ );
39
+
40
+ CREATE INDEX IF NOT EXISTS tasks_status ON tasks(status);
41
+ CREATE INDEX IF NOT EXISTS tasks_tag ON tasks(tag);
42
+ CREATE INDEX IF NOT EXISTS tasks_session ON tasks(session_id) WHERE session_id IS NOT NULL;
43
+ CREATE INDEX IF NOT EXISTS tasks_stale ON tasks(stale) WHERE stale = 1;
44
+ CREATE INDEX IF NOT EXISTS tasks_parent ON tasks(parent_id) WHERE parent_id IS NOT NULL;
45
+
46
+ -- ──────────────────────────── events ──────────────────────────────────────
47
+ -- Append-only event stream. id is the subscription cursor (D31, R26):
48
+ -- subscribers pull `id > since_id` to avoid same-ms event loss that
49
+ -- max(ts) would suffer.
50
+ CREATE TABLE IF NOT EXISTS events (
51
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
52
+ ts TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ', 'now')),
53
+ type TEXT NOT NULL,
54
+ task_id TEXT,
55
+ session_id TEXT,
56
+ runtime TEXT CHECK (runtime IS NULL OR runtime IN ('claude', 'opencode', 'codex', 'gemini')),
57
+ payload_json TEXT
58
+ );
59
+
60
+ CREATE INDEX IF NOT EXISTS events_ts_type ON events(ts, type);
61
+ CREATE INDEX IF NOT EXISTS events_task ON events(task_id, id);
62
+ CREATE INDEX IF NOT EXISTS events_session ON events(session_id, id);
63
+
64
+ -- ──────────────────────────── sessions ────────────────────────────────────
65
+ -- Authoritative session row. lease_expires_at + heartbeat_at live ONLY here
66
+ -- (D32, R29) — no lease.json file. Worktree + artifact_dir are filesystem
67
+ -- paths owned by the session.
68
+ CREATE TABLE IF NOT EXISTS sessions (
69
+ sid TEXT PRIMARY KEY,
70
+ task_id TEXT NOT NULL REFERENCES tasks(id),
71
+ runtime TEXT NOT NULL CHECK (runtime IN ('claude', 'opencode', 'codex', 'gemini')),
72
+ pid INTEGER,
73
+ worktree_path TEXT NOT NULL,
74
+ artifact_dir TEXT NOT NULL,
75
+ status TEXT NOT NULL DEFAULT 'running'
76
+ CHECK (status IN ('running', 'completed', 'crashed', 'orphan')),
77
+ lease_expires_at TEXT NOT NULL,
78
+ heartbeat_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ', 'now')),
79
+ started_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ', 'now'))
80
+ );
81
+
82
+ CREATE INDEX IF NOT EXISTS sessions_active ON sessions(status, task_id);
83
+ CREATE INDEX IF NOT EXISTS sessions_lease ON sessions(lease_expires_at) WHERE status = 'running';
84
+
85
+ -- ──────────────────────────── schema_version ──────────────────────────────
86
+ -- Cross-version misread guard (D30, R27). Single row per applied version.
87
+ CREATE TABLE IF NOT EXISTS schema_version (
88
+ version TEXT PRIMARY KEY,
89
+ applied_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ', 'now')),
90
+ description TEXT
91
+ );
92
+
93
+ -- ──────────────────────────── migration_history ───────────────────────────
94
+ -- Audit trail for every migration attempt (D30, R27).
95
+ CREATE TABLE IF NOT EXISTS migration_history (
96
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
97
+ from_version TEXT NOT NULL,
98
+ to_version TEXT NOT NULL,
99
+ direction TEXT NOT NULL CHECK (direction IN ('forward', 'rollback')),
100
+ ts TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ', 'now')),
101
+ status TEXT NOT NULL CHECK (status IN ('success', 'failed', 'dry_run')),
102
+ notes TEXT
103
+ );
104
+
105
+ CREATE INDEX IF NOT EXISTS migration_history_ts ON migration_history(ts);
106
+
107
+ -- ──────────────────────────── telemetry ───────────────────────────────────
108
+ -- Token / cost / tool-call counters per session.
109
+ CREATE TABLE IF NOT EXISTS telemetry (
110
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
111
+ session_id TEXT REFERENCES sessions(sid),
112
+ event_type TEXT NOT NULL CHECK (event_type IN ('tool_call', 'token_usage', 'cost')),
113
+ tokens_input INTEGER,
114
+ tokens_output INTEGER,
115
+ tool_name TEXT,
116
+ cost_usd REAL,
117
+ ts TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ', 'now'))
118
+ );
119
+
120
+ CREATE INDEX IF NOT EXISTS telemetry_session ON telemetry(session_id, ts);
121
+ CREATE INDEX IF NOT EXISTS telemetry_type ON telemetry(event_type, ts);
122
+
123
+ -- ──────────────────────────── specs_refs ──────────────────────────────────
124
+ -- Spec change tracking. Phase 5.3 staleness propagation reads this.
125
+ CREATE TABLE IF NOT EXISTS specs_refs (
126
+ spec_file TEXT NOT NULL,
127
+ section TEXT NOT NULL,
128
+ anchor TEXT,
129
+ last_modified_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ', 'now')),
130
+ PRIMARY KEY (spec_file, section)
131
+ );
132
+
133
+ -- ──────────────────────────── circuit_breaker ─────────────────────────────
134
+ -- Per-task failure accumulator (Phase 5.2). When failure_count crosses the
135
+ -- threshold, tripped_at is stamped and `task_circuit_broken` fires. Admission
136
+ -- control refuses new spawns for tripped tasks until manually reset.
137
+ CREATE TABLE IF NOT EXISTS circuit_breaker (
138
+ task_id TEXT PRIMARY KEY REFERENCES tasks(id) ON DELETE CASCADE,
139
+ failure_count INTEGER NOT NULL DEFAULT 0,
140
+ tripped_at TEXT,
141
+ last_failure_at TEXT,
142
+ last_failure_reason TEXT
143
+ );
144
+
145
+ CREATE INDEX IF NOT EXISTS circuit_breaker_tripped ON circuit_breaker(tripped_at)
146
+ WHERE tripped_at IS NOT NULL;
147
+
148
+ -- ──────────────────────────── seed: schema_version ────────────────────────
149
+ INSERT OR IGNORE INTO schema_version (version, description)
150
+ VALUES ('4.5', 'Phase 2 initial — tasks/events/sessions/schema_version/migration_history/telemetry/specs_refs');
151
+ INSERT OR IGNORE INTO schema_version (version, description)
152
+ VALUES ('5.2', 'Phase 5.2 — circuit_breaker table for per-task trip tracking');
153
+ INSERT OR IGNORE INTO schema_version (version, description)
154
+ VALUES ('8A.1', 'Phase 8A.1 — tasks.parent_id for task.expand parent→children');
@@ -0,0 +1,66 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://ultra-builder-pro.dev/spec/tasks.v4.5.schema.json",
4
+ "title": "tasks.json projection (v4.5)",
5
+ "description": "Read-only projection of the tasks table. Generated by the projector (Phase 2.6) — manual edits are overwritten. Status and dependencies are derived from state.db; do not write them through this file. Trace: PLAN §7.1, D21, D32.",
6
+ "type": "object",
7
+ "required": ["schema_version", "generated_at", "tasks"],
8
+ "additionalProperties": false,
9
+ "properties": {
10
+ "schema_version": { "const": "4.5" },
11
+ "generated_at": { "type": "string", "format": "date-time" },
12
+ "source": { "const": ".ultra/state.db", "description": "authoritative source (D32)" },
13
+ "tasks": {
14
+ "type": "array",
15
+ "items": { "$ref": "#/$defs/task" }
16
+ }
17
+ },
18
+ "$defs": {
19
+ "task": {
20
+ "type": "object",
21
+ "required": ["id", "title", "type", "priority", "status", "created_at", "updated_at"],
22
+ "additionalProperties": false,
23
+ "properties": {
24
+ "id": { "type": "string", "pattern": "^[a-zA-Z0-9_\\-]+$" },
25
+ "title": { "type": "string", "minLength": 3 },
26
+ "type": { "type": "string", "enum": ["architecture", "feature", "bugfix"] },
27
+ "priority": { "type": "string", "enum": ["P0", "P1", "P2", "P3"] },
28
+ "complexity": { "type": "integer", "minimum": 1, "maximum": 10 },
29
+ "status": {
30
+ "type": "string",
31
+ "enum": ["pending", "in_progress", "completed", "blocked", "expanded"],
32
+ "x-derived": true,
33
+ "description": "DERIVED from state.db tasks.status; never write through this projection"
34
+ },
35
+ "deps": {
36
+ "type": "array",
37
+ "items": { "type": "string" },
38
+ "x-derived": true,
39
+ "description": "DERIVED from state.db tasks.deps JSON"
40
+ },
41
+ "files_modified": {
42
+ "type": "array",
43
+ "items": { "type": "string" },
44
+ "description": "Phase 8B conflict surface; new in v4.5"
45
+ },
46
+ "session_id": {
47
+ "type": "string",
48
+ "x-derived": true,
49
+ "description": "DERIVED from state.db tasks.session_id (current owning session)"
50
+ },
51
+ "stale": {
52
+ "type": "boolean",
53
+ "x-derived": true,
54
+ "description": "DERIVED from staleness propagation (Phase 5.3)"
55
+ },
56
+ "complexity_hint": { "type": "string", "enum": ["haiku", "sonnet", "opus"] },
57
+ "tag": { "type": "string" },
58
+ "trace_to": { "type": "string" },
59
+ "context_file": { "type": "string" },
60
+ "completion_commit": { "type": "string", "pattern": "^[0-9a-f]{7,40}$" },
61
+ "created_at": { "type": "string", "format": "date-time" },
62
+ "updated_at": { "type": "string", "format": "date-time" }
63
+ }
64
+ }
65
+ }
66
+ }
@@ -0,0 +1,121 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * ultra-tools — runtime-agnostic state engine for Ultra Builder Pro.
5
+ *
6
+ * Shell fallback for Ultra task/session state, status, database maintenance,
7
+ * migration, and explicit legacy-memory cleanup. User interaction, skill
8
+ * discovery, and subagent delegation stay on each host's native surfaces.
9
+ *
10
+ * Usage:
11
+ * ultra-tools <subcommand> [...]
12
+ * ultra-tools --help
13
+ * ultra-tools --version
14
+ */
15
+
16
+ 'use strict';
17
+
18
+ const fs = require('node:fs');
19
+ const path = require('node:path');
20
+
21
+ const VERSION = (() => {
22
+ try {
23
+ const pkg = require(path.join(__dirname, '..', 'package.json'));
24
+ return pkg.version;
25
+ } catch (_err) {
26
+ return '0.1.0';
27
+ }
28
+ })();
29
+
30
+ const USAGE = `ultra-tools v${VERSION}
31
+
32
+ USAGE:
33
+ ultra-tools <subcommand> [args]
34
+
35
+ SUBCOMMANDS:
36
+ task create | update | list | get | delete
37
+ session spawn | close | get | list | admission | heartbeat | subscribe
38
+ status [--cost] [--since <duration>] [--json]
39
+ db init | checkpoint | vacuum | integrity | backup (Phase 2)
40
+ migrate --from=4.4 --to=4.5 [--dry|--rollback] (Phase 2)
41
+ legacy-memory inspect | archive | prune --confirm DELETE_ULTRA_LEGACY_MEMORY
42
+
43
+ --help / -h show this message
44
+ --version / -v show version
45
+
46
+ All state lives under .ultra/ in the project root.
47
+ `;
48
+
49
+ function readJsonIfExists(p) {
50
+ if (!fs.existsSync(p)) return null;
51
+ try { return JSON.parse(fs.readFileSync(p, 'utf8')); }
52
+ catch (err) {
53
+ fail(`malformed JSON at ${p}: ${err.message}`);
54
+ }
55
+ }
56
+
57
+ function fail(msg, code) {
58
+ process.stderr.write(`ultra-tools: ${msg}\n`);
59
+ process.exit(code || 1);
60
+ }
61
+
62
+ const dbCommand = require('./commands/db.cjs');
63
+ const migrateCommand = require('./commands/migrate.cjs');
64
+ const taskCommand = require('./commands/task.cjs');
65
+ const sessionCommand = require('./commands/session.cjs');
66
+ const statusCommand = require('./commands/status.cjs');
67
+ const legacyMemoryCommand = require('./commands/legacy-memory.cjs');
68
+
69
+ // Phase 6.2 — CLI telemetry: best-effort, never blocks the subcommand.
70
+ function emitCliTelemetry(sub, rest) {
71
+ try {
72
+ const dbPath = path.resolve('.ultra', 'state.db');
73
+ if (!fs.existsSync(dbPath)) return;
74
+ const Database = require('better-sqlite3');
75
+ const db = new Database(dbPath);
76
+ try {
77
+ const telemetry = require('../mcp-server/lib/telemetry.cjs');
78
+ telemetry.appendTelemetry(db, {
79
+ event_type: 'tool_call',
80
+ tool_name: `cli.${sub}`,
81
+ session_id: process.env.UBP_SESSION_ID || null,
82
+ rootDir: process.cwd(),
83
+ payload: { args: Array.isArray(rest) ? rest.slice(0, 4) : [] },
84
+ });
85
+ } finally { db.close(); }
86
+ } catch (_) { /* telemetry is opt-in side channel; never crash the CLI */ }
87
+ }
88
+
89
+ const SUBCOMMANDS = {
90
+ task: (args) => process.exit(taskCommand.dispatch(args)),
91
+ session: (args) => process.exit(sessionCommand.dispatch(args)),
92
+ status: (args) => process.exit(statusCommand.dispatch(args)),
93
+ db: (args) => process.exit(dbCommand.dispatch(args)),
94
+ migrate: (args) => process.exit(migrateCommand.dispatch(args)),
95
+ 'legacy-memory': (args) => process.exit(legacyMemoryCommand.dispatch(args)),
96
+ };
97
+
98
+ function main(argv) {
99
+ const args = argv.slice(2);
100
+ if (args.length === 0 || args[0] === '-h' || args[0] === '--help') {
101
+ process.stdout.write(USAGE);
102
+ return;
103
+ }
104
+ if (args[0] === '-v' || args[0] === '--version') {
105
+ process.stdout.write(`${VERSION}\n`);
106
+ return;
107
+ }
108
+
109
+ const [sub, ...rest] = args;
110
+ const handler = SUBCOMMANDS[sub];
111
+ if (!handler) fail(`unknown subcommand: ${sub}\n\n${USAGE}`);
112
+ emitCliTelemetry(sub, rest);
113
+ handler(rest);
114
+ }
115
+
116
+ // exports kept for unit tests (Phase 1+)
117
+ module.exports = { USAGE, SUBCOMMANDS, readJsonIfExists, VERSION, main };
118
+
119
+ if (require.main === module) {
120
+ main(process.argv);
121
+ }