ultra-builder-pro-cli 0.25.1 → 0.26.1

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 (243) hide show
  1. package/.ultra-template/changes/abandoned/.gitkeep +0 -0
  2. package/.ultra-template/contexts/TEMPLATE.md +94 -0
  3. package/.ultra-template/decisions/.gitkeep +1 -0
  4. package/.ultra-template/evidence/.gitkeep +1 -0
  5. package/.ultra-template/north-star.md +46 -0
  6. package/.ultra-template/research/.gitkeep +1 -0
  7. package/.ultra-template/specs/discovery.md +2 -2
  8. package/.ultra-template/tasks.json +3 -0
  9. package/.ultra-template/test-report.json +27 -0
  10. package/CHANGELOG.md +107 -1
  11. package/README.md +217 -579
  12. package/adapters/_shared/delegate-profiles/kimi-read-only.md +15 -0
  13. package/adapters/_shared/delegate-profiles/kimi-write.md +17 -0
  14. package/adapters/_shared/file-ops.cjs +76 -2
  15. package/adapters/_shared/host-profile.cjs +97 -0
  16. package/adapters/_shared/plugin-core.cjs +204 -0
  17. package/adapters/_shared/runtime-assets.cjs +31 -96
  18. package/adapters/claude.js +92 -291
  19. package/adapters/codex.js +309 -842
  20. package/adapters/grok.js +143 -1469
  21. package/adapters/kimi.js +124 -1053
  22. package/adapters/opencode.js +230 -742
  23. package/bin/delegate-worker.cjs +328 -0
  24. package/bin/delegate.cjs +463 -0
  25. package/bin/install.js +38 -11
  26. package/docs/ARCHITECTURE.md +125 -216
  27. package/docs/ARTIFACT-AUTHORITY.md +90 -268
  28. package/docs/DECISIONS.md +77 -87
  29. package/docs/PHILOSOPHY.md +208 -0
  30. package/docs/PLUGIN-ISOLATION-CONTRACT.md +65 -39
  31. package/docs/RUNTIME-COMPAT-MATRIX.md +140 -155
  32. package/docs/SKILL-AUTHORING.md +94 -73
  33. package/docs/WORKFLOW-LIFECYCLE.md +97 -189
  34. package/hooks/README.md +19 -37
  35. package/hooks/_common.py +113 -0
  36. package/hooks/adapters/codex.py +9 -16
  37. package/hooks/adapters/grok.py +5 -5
  38. package/hooks/adapters/kimi.py +8 -14
  39. package/hooks/block_dangerous_commands.py +201 -0
  40. package/hooks/compact_context.py +65 -0
  41. package/hooks/mid_workflow_recall.py +25 -0
  42. package/hooks/post_edit_guard.py +105 -0
  43. package/hooks/session_context.py +30 -0
  44. package/package.json +17 -52
  45. package/skills/ultra-change/SKILL.md +115 -50
  46. package/skills/ultra-change/references/change-contract.md +68 -3
  47. package/skills/ultra-delegate/SKILL.md +89 -0
  48. package/skills/ultra-delegate/references/delegation-contract.md +59 -0
  49. package/skills/ultra-delegate/scripts/delegate_wait.py +86 -0
  50. package/skills/ultra-deliver/SKILL.md +98 -42
  51. package/skills/ultra-deliver/references/baseline-reconciliation.md +39 -20
  52. package/skills/ultra-dev/SKILL.md +115 -62
  53. package/skills/ultra-dev/references/debugging.md +22 -0
  54. package/skills/ultra-domain-modeling/SKILL.md +79 -0
  55. package/skills/ultra-grilling/SKILL.md +118 -0
  56. package/skills/ultra-grilling/references/reframing.md +72 -0
  57. package/skills/ultra-init/SKILL.md +102 -37
  58. package/skills/ultra-init/references/brownfield-adoption.md +33 -83
  59. package/skills/ultra-init/scripts/init_project.cjs +84 -0
  60. package/skills/ultra-plan/SKILL.md +101 -68
  61. package/skills/ultra-research/SKILL.md +68 -48
  62. package/skills/ultra-research/references/00-problem-validation.md +5 -5
  63. package/skills/ultra-research/references/01-opportunity-discovery.md +3 -3
  64. package/skills/ultra-research/references/02-market-assessment.md +5 -4
  65. package/skills/ultra-research/references/03-competitive-landscape.md +3 -3
  66. package/skills/ultra-research/references/04-product-strategy.md +3 -3
  67. package/skills/ultra-research/references/05-assumptions-validation.md +5 -5
  68. package/skills/ultra-research/references/10-user-personas.md +3 -2
  69. package/skills/ultra-research/references/11-user-scenarios.md +3 -3
  70. package/skills/ultra-research/references/20-user-stories.md +4 -3
  71. package/skills/ultra-research/references/21-features-scope.md +3 -2
  72. package/skills/ultra-research/references/22-success-metrics.md +3 -3
  73. package/skills/ultra-research/references/30-architecture-context.md +3 -3
  74. package/skills/ultra-research/references/31-solution-strategy.md +3 -3
  75. package/skills/ultra-research/references/32-building-blocks.md +3 -3
  76. package/skills/ultra-research/references/40-deployment.md +3 -3
  77. package/skills/ultra-research/references/41-quality-risks.md +3 -3
  78. package/skills/ultra-research/references/99-synthesis.md +7 -7
  79. package/skills/ultra-review/SKILL.md +84 -32
  80. package/skills/ultra-review/references/code.md +17 -0
  81. package/skills/ultra-review/references/comments.md +12 -0
  82. package/skills/ultra-review/references/design.md +12 -0
  83. package/skills/ultra-review/references/errors.md +13 -0
  84. package/skills/ultra-review/references/spec.md +13 -0
  85. package/skills/ultra-review/references/tests.md +12 -0
  86. package/skills/ultra-review/references/worker-packet.md +40 -0
  87. package/skills/ultra-review/scripts/review_wait.py +26 -15
  88. package/skills/ultra-status/SKILL.md +61 -36
  89. package/skills/ultra-tdd/SKILL.md +81 -0
  90. package/skills/ultra-tdd/references/templates/README.md +20 -0
  91. package/skills/ultra-tdd/references/templates/feature-flag-default-audit.sh +79 -0
  92. package/skills/ultra-tdd/references/templates/persistence-real.ts +78 -0
  93. package/skills/ultra-tdd/references/templates/testcontainer-postgres.py +78 -0
  94. package/skills/ultra-tdd/references/templates/testcontainer-postgres.ts +73 -0
  95. package/skills/ultra-tdd/references/templates/vertical-slice.ts +66 -0
  96. package/skills/ultra-tdd/references/test-execution.md +18 -0
  97. package/skills/ultra-test/SKILL.md +75 -30
  98. package/skills/ultra-test/references/export-syntax.md +18 -0
  99. package/skills/ultra-test/scripts/worktree_digest.cjs +54 -0
  100. package/skills/ultra-think/SKILL.md +49 -27
  101. package/skills/ultra-think/references/autonomy-boundary.md +48 -0
  102. package/skills/ultra-think/references/interaction-boundary.md +18 -33
  103. package/.ultra-template/docs/research/README.md +0 -55
  104. package/.ultra-template/reports/templates/delivery-report.json +0 -17
  105. package/.ultra-template/reports/templates/test-report.json +0 -18
  106. package/.ultra-template/tasks/tasks.json +0 -15
  107. package/.ultra-template/templates/task-context.md +0 -19
  108. package/adapters/_shared/codex-assets.cjs +0 -725
  109. package/adapters/_shared/codex-ultra-tools-entry.cjs +0 -11
  110. package/adapters/_shared/interaction-contract.cjs +0 -129
  111. package/adapters/_shared/path-rewrite.cjs +0 -79
  112. package/adapters/_shared/runtime-native.cjs +0 -132
  113. package/adapters/_shared/settings-merge.cjs +0 -76
  114. package/agents/code-reviewer.md +0 -42
  115. package/agents/debugger.md +0 -40
  116. package/agents/review-code.md +0 -49
  117. package/agents/review-comments.md +0 -38
  118. package/agents/review-coordinator.md +0 -56
  119. package/agents/review-design.md +0 -40
  120. package/agents/review-errors.md +0 -43
  121. package/agents/review-spec.md +0 -39
  122. package/agents/review-tests.md +0 -40
  123. package/agents/tdd-runner.md +0 -38
  124. package/bin/orchestrator.js +0 -383
  125. package/commands/ultra-change.md +0 -10
  126. package/commands/ultra-deliver.md +0 -10
  127. package/commands/ultra-dev.md +0 -10
  128. package/commands/ultra-doctor.md +0 -10
  129. package/commands/ultra-init.md +0 -10
  130. package/commands/ultra-plan.md +0 -10
  131. package/commands/ultra-research.md +0 -10
  132. package/commands/ultra-review.md +0 -10
  133. package/commands/ultra-status.md +0 -10
  134. package/commands/ultra-test.md +0 -10
  135. package/commands/ultra-think.md +0 -10
  136. package/docs/AGENT-CONTEXT.md +0 -191
  137. package/docs/COMMIT-HASH-BACKFILL.md +0 -51
  138. package/docs/LEGACY-CLI-CROSSWALK.md +0 -175
  139. package/docs/ROADMAP.md +0 -101
  140. package/docs/STATE-DB-ACCESS-POLICY.md +0 -161
  141. package/hooks/active_task_context.py +0 -152
  142. package/hooks/context_envelope.py +0 -100
  143. package/hooks/health_check.py +0 -196
  144. package/hooks/pre_stop_check.py +0 -66
  145. package/hooks/runtime_paths.py +0 -396
  146. package/hooks/subagent_tracker.py +0 -88
  147. package/hooks/workflow_checkpoint.py +0 -76
  148. package/hooks/workflow_context.py +0 -48
  149. package/hooks/workflow_resume.py +0 -84
  150. package/mcp-server/hook-context.cjs +0 -38
  151. package/mcp-server/hook-event.cjs +0 -34
  152. package/mcp-server/lib/archive-journal.cjs +0 -1119
  153. package/mcp-server/lib/archive-mutation-worker.py +0 -365
  154. package/mcp-server/lib/artifact-registry.cjs +0 -1232
  155. package/mcp-server/lib/baseline-workflow.cjs +0 -1193
  156. package/mcp-server/lib/canonical-json.cjs +0 -19
  157. package/mcp-server/lib/change-authority.cjs +0 -26
  158. package/mcp-server/lib/change-packet.cjs +0 -790
  159. package/mcp-server/lib/change-workflow.cjs +0 -65
  160. package/mcp-server/lib/context-envelope.cjs +0 -581
  161. package/mcp-server/lib/context-paths.cjs +0 -142
  162. package/mcp-server/lib/decision-records.cjs +0 -423
  163. package/mcp-server/lib/delivery-transaction.cjs +0 -471
  164. package/mcp-server/lib/doctor-backup-worker.cjs +0 -328
  165. package/mcp-server/lib/doctor.cjs +0 -627
  166. package/mcp-server/lib/git-bootstrap.cjs +0 -651
  167. package/mcp-server/lib/init-project.cjs +0 -1021
  168. package/mcp-server/lib/kernel-change-workflow.cjs +0 -2029
  169. package/mcp-server/lib/legacy-change-workflow.cjs +0 -3032
  170. package/mcp-server/lib/managed-file-write.cjs +0 -172
  171. package/mcp-server/lib/plan-checkpoint.cjs +0 -177
  172. package/mcp-server/lib/plan-publication-worker.cjs +0 -830
  173. package/mcp-server/lib/plan-store.cjs +0 -794
  174. package/mcp-server/lib/prd-parser.cjs +0 -83
  175. package/mcp-server/lib/pricing.cjs +0 -44
  176. package/mcp-server/lib/project-context.cjs +0 -178
  177. package/mcp-server/lib/projector.cjs +0 -386
  178. package/mcp-server/lib/provider-refs.cjs +0 -42
  179. package/mcp-server/lib/runtime-paths.cjs +0 -1714
  180. package/mcp-server/lib/runtime-state.cjs +0 -222
  181. package/mcp-server/lib/safe-project-file.cjs +0 -385
  182. package/mcp-server/lib/stage-checkpoints.cjs +0 -463
  183. package/mcp-server/lib/state-authority.cjs +0 -95
  184. package/mcp-server/lib/state-db.cjs +0 -1580
  185. package/mcp-server/lib/state-ops.cjs +0 -1428
  186. package/mcp-server/lib/task-contract.cjs +0 -404
  187. package/mcp-server/lib/task-expander.cjs +0 -105
  188. package/mcp-server/lib/task-ledger.cjs +0 -1964
  189. package/mcp-server/lib/telemetry.cjs +0 -85
  190. package/mcp-server/lib/topo.cjs +0 -131
  191. package/mcp-server/lib/ultra-facade.cjs +0 -2684
  192. package/mcp-server/lib/worker-packet.cjs +0 -358
  193. package/mcp-server/server.cjs +0 -437
  194. package/orchestrator/auto-merge.cjs +0 -128
  195. package/orchestrator/daemon.cjs +0 -264
  196. package/orchestrator/dispatch-rules.cjs +0 -78
  197. package/orchestrator/parallel-orchestrator.cjs +0 -903
  198. package/orchestrator/planner/plan-builder.cjs +0 -125
  199. package/orchestrator/recovery.cjs +0 -188
  200. package/orchestrator/session-close-journal-worker.cjs +0 -5
  201. package/orchestrator/session-close-journal.cjs +0 -1014
  202. package/orchestrator/session-runner.cjs +0 -1153
  203. package/orchestrator/worktree-manager.cjs +0 -282
  204. package/settings.json +0 -7
  205. package/skills/cc-collab/SKILL.md +0 -42
  206. package/skills/code-review-expert/SKILL.md +0 -43
  207. package/skills/code-review-expert/references/correctness-reliability.md +0 -30
  208. package/skills/code-review-expert/references/design-boundaries.md +0 -26
  209. package/skills/code-review-expert/references/removal-plan.md +0 -24
  210. package/skills/codex-collab/SKILL.md +0 -49
  211. package/skills/codex-collab/evals/evals.json +0 -35
  212. package/skills/integration-rules/SKILL.md +0 -32
  213. package/skills/security-rules/SKILL.md +0 -38
  214. package/skills/testing-rules/SKILL.md +0 -32
  215. package/skills/ultra-doctor/SKILL.md +0 -41
  216. package/skills/ultra-plan/references/semantic-preflight.md +0 -20
  217. package/skills/ultra-verify/SKILL.md +0 -46
  218. package/skills/ultra-verify/evals/evals.json +0 -46
  219. package/skills/ultra-verify/references/cross-verify-modes.md +0 -28
  220. package/skills/ultra-verify/references/evidence-status.md +0 -21
  221. package/skills/ultra-verify/scripts/verify_wait.py +0 -94
  222. package/spec/cli-protocol.md +0 -102
  223. package/spec/mcp-tools.yaml +0 -312
  224. package/spec/schemas/baseline-reconciliation.v1.schema.json +0 -73
  225. package/spec/schemas/change-delta.v1.schema.json +0 -153
  226. package/spec/schemas/command-manifest.schema.json +0 -29
  227. package/spec/schemas/context-file.v4.5.schema.json +0 -54
  228. package/spec/schemas/delivery-report.v1.schema.json +0 -66
  229. package/spec/schemas/documentation-reconciliation.v1.schema.json +0 -106
  230. package/spec/schemas/mcp-tools.schema.json +0 -136
  231. package/spec/schemas/skill-manifest.schema.json +0 -24
  232. package/spec/schemas/state-db.sql +0 -641
  233. package/spec/schemas/task-ledger.v2.schema.json +0 -296
  234. package/spec/schemas/tasks.v4.5.schema.json +0 -96
  235. package/spec/schemas/test-report.v1.schema.json +0 -225
  236. package/ultra-tools/cli.cjs +0 -129
  237. package/ultra-tools/commands/db.cjs +0 -226
  238. package/ultra-tools/commands/legacy-memory.cjs +0 -159
  239. package/ultra-tools/commands/migrate.cjs +0 -1386
  240. package/ultra-tools/commands/session.cjs +0 -213
  241. package/ultra-tools/commands/status.cjs +0 -559
  242. package/ultra-tools/commands/system.cjs +0 -498
  243. package/ultra-tools/commands/task.cjs +0 -105
@@ -0,0 +1,40 @@
1
+ # Immutable Worker Packet
2
+
3
+ Create `.ultra/reviews/<session>/WORKER-PACKET.json` once, before starting any lens.
4
+ Serialize it as UTF-8 JSON with a trailing newline, compute SHA-256 over those exact
5
+ bytes, and never edit the file. A changed scope requires a new session and packet.
6
+
7
+ ```json
8
+ {
9
+ "$schema": "ultra-review-worker-packet-v1",
10
+ "session": "<session-id>",
11
+ "mode": "task | change | plan",
12
+ "created_at": "<ISO-8601>",
13
+ "head": "<full-git-head>",
14
+ "range": "<exact-diff-range>",
15
+ "change_id": "<active-change-id>",
16
+ "task_ids": ["<task-id>"],
17
+ "acceptance": ["<criterion with source path and heading>"],
18
+ "public_seams": ["<entry point or behavior>"],
19
+ "context_files": [
20
+ {"path": ".ultra/contexts/<task-id>.md", "sha256": "<digest>"}
21
+ ],
22
+ "diff_files": ["src/example.ts"],
23
+ "output_directory": ".ultra/reviews/<session>"
24
+ }
25
+ ```
26
+
27
+ All paths are repository-relative. `mode`, `head`, `range`, `change_id`, `task_ids`,
28
+ `acceptance`, `public_seams`, `context_files`, `diff_files`, and `output_directory` are
29
+ required. Arrays may be empty only when the selected mode makes the absence explicit
30
+ in the packet.
31
+
32
+ Give a selected worker only:
33
+
34
+ 1. this packet path and exact digest;
35
+ 2. `unified-schema.md`;
36
+ 3. its one lens reference.
37
+
38
+ The worker writes only its assigned JSON artifact. Its `packet_digest` must equal the
39
+ expected digest passed to `review_wait.py`; a merely well-formed digest is insufficient.
40
+ The coordinator owns worker selection, synthesis, repair, and the summary.
@@ -2,8 +2,8 @@
2
2
  """Wait for and validate Ultra review v2 artifacts.
3
3
 
4
4
  Usage:
5
- python3 review_wait.py <session_path> agents <artifact-stem> [<artifact-stem> ...]
6
- python3 review_wait.py <session_path> summary
5
+ python3 review_wait.py <session_path> agents --packet-digest <sha256> <artifact-stem> [<artifact-stem> ...]
6
+ python3 review_wait.py <session_path> summary --packet-digest <sha256>
7
7
 
8
8
  The agents mode validates the exact named JSON files. The summary mode validates the
9
9
  two-axis verdict contract. Timeout and poll intervals can be shortened in tests with
@@ -96,13 +96,15 @@ def validate_finding(finding, artifact_axis: str, seen_ids):
96
96
  return None
97
97
 
98
98
 
99
- def validate_specialist(data):
99
+ def validate_specialist(data, expected_packet_digest: str):
100
100
  if data.get("$schema") != FINDINGS_SCHEMA:
101
101
  return f"$schema must be {FINDINGS_SCHEMA}"
102
102
  if not nonempty_string(data.get("agent")):
103
103
  return "agent must be a non-empty string"
104
104
  if not digest_string(data.get("packet_digest")):
105
105
  return "packet_digest must be a lowercase SHA-256 digest"
106
+ if data["packet_digest"] != expected_packet_digest:
107
+ return f"packet_digest does not match expected immutable packet {expected_packet_digest}"
106
108
  axis = data.get("axis")
107
109
  if axis not in AXES:
108
110
  return "axis must be spec_fidelity or engineering_standards"
@@ -137,7 +139,7 @@ def validate_specialist(data):
137
139
  return None
138
140
 
139
141
 
140
- def evaluate_artifacts(session_path: Path, expected):
142
+ def evaluate_artifacts(session_path: Path, expected, expected_packet_digest: str):
141
143
  done = []
142
144
  missing = []
143
145
  invalid = []
@@ -149,7 +151,7 @@ def evaluate_artifacts(session_path: Path, expected):
149
151
  continue
150
152
  data, error = read_json(path)
151
153
  if error is None:
152
- error = validate_specialist(data)
154
+ error = validate_specialist(data, expected_packet_digest)
153
155
  if error:
154
156
  invalid.append(stem)
155
157
  errors[stem] = error
@@ -158,10 +160,12 @@ def evaluate_artifacts(session_path: Path, expected):
158
160
  return done, missing, invalid, errors
159
161
 
160
162
 
161
- def wait_for_agents(session_path: Path, expected, timeout: float) -> bool:
163
+ def wait_for_agents(session_path: Path, expected, expected_packet_digest: str, timeout: float) -> bool:
162
164
  deadline = time.monotonic() + timeout
163
165
  while True:
164
- done, missing, invalid, errors = evaluate_artifacts(session_path, expected)
166
+ done, missing, invalid, errors = evaluate_artifacts(
167
+ session_path, expected, expected_packet_digest
168
+ )
165
169
  if len(done) == len(expected):
166
170
  print(json.dumps({
167
171
  "status": "complete",
@@ -195,7 +199,7 @@ def expected_overall_verdict(data) -> str:
195
199
  return "APPROVE"
196
200
 
197
201
 
198
- def validate_summary(data):
202
+ def validate_summary(data, expected_packet_digest: str):
199
203
  if data.get("$schema") != SUMMARY_SCHEMA:
200
204
  return f"$schema must be {SUMMARY_SCHEMA}"
201
205
  if data.get("mode") not in REVIEW_MODES:
@@ -205,6 +209,8 @@ def validate_summary(data):
205
209
  return f"{field} must be a non-empty string"
206
210
  if not digest_string(data.get("packet_digest")):
207
211
  return "packet_digest must be a lowercase SHA-256 digest"
212
+ if data["packet_digest"] != expected_packet_digest:
213
+ return f"packet_digest does not match expected immutable packet {expected_packet_digest}"
208
214
  if data.get("worktree_digest") is not None and not nonempty_string(data.get("worktree_digest")):
209
215
  return "worktree_digest must be null or a non-empty string"
210
216
  task_ids = data.get("task_ids")
@@ -282,7 +288,7 @@ def validate_summary(data):
282
288
  return None
283
289
 
284
290
 
285
- def wait_for_summary(session_path: Path, timeout: float) -> bool:
291
+ def wait_for_summary(session_path: Path, expected_packet_digest: str, timeout: float) -> bool:
286
292
  summary_path = session_path / "SUMMARY.json"
287
293
  deadline = time.monotonic() + timeout
288
294
  last_error = "SUMMARY.json is missing"
@@ -290,7 +296,7 @@ def wait_for_summary(session_path: Path, timeout: float) -> bool:
290
296
  if summary_path.exists():
291
297
  data, error = read_json(summary_path)
292
298
  if error is None:
293
- error = validate_summary(data)
299
+ error = validate_summary(data, expected_packet_digest)
294
300
  if error is None:
295
301
  counts = {severity: 0 for severity in sorted(SEVERITIES)}
296
302
  for finding in data["findings"]:
@@ -319,19 +325,24 @@ def main():
319
325
  print(f"Error: session directory not found: {session_path}", file=sys.stderr)
320
326
  sys.exit(2)
321
327
 
328
+ if len(sys.argv) < 5 or sys.argv[3] != "--packet-digest" or not digest_string(sys.argv[4]):
329
+ print("Error: --packet-digest requires the expected lowercase SHA-256 digest", file=sys.stderr)
330
+ sys.exit(2)
331
+ expected_packet_digest = sys.argv[4]
332
+
322
333
  if mode == "agents":
323
- expected = sys.argv[3:]
334
+ expected = sys.argv[5:]
324
335
  if not expected or len(expected) != len(set(expected)) or not all(
325
336
  ARTIFACT_STEM.fullmatch(stem) for stem in expected
326
337
  ):
327
338
  print("Error: agents mode requires unique safe artifact stems", file=sys.stderr)
328
339
  sys.exit(2)
329
- ok = wait_for_agents(session_path, expected, DEFAULT_TIMEOUT)
340
+ ok = wait_for_agents(session_path, expected, expected_packet_digest, DEFAULT_TIMEOUT)
330
341
  elif mode == "summary":
331
- if len(sys.argv) != 3:
332
- print("Error: summary mode accepts no additional arguments", file=sys.stderr)
342
+ if len(sys.argv) != 5:
343
+ print("Error: summary mode accepts only --packet-digest", file=sys.stderr)
333
344
  sys.exit(2)
334
- ok = wait_for_summary(session_path, DEFAULT_TIMEOUT)
345
+ ok = wait_for_summary(session_path, expected_packet_digest, DEFAULT_TIMEOUT)
335
346
  else:
336
347
  print(f"Error: unknown mode '{mode}'. Use 'agents' or 'summary'.", file=sys.stderr)
337
348
  sys.exit(2)
@@ -1,40 +1,65 @@
1
1
  ---
2
2
  name: ultra-status
3
- description: Read authoritative Ultra health, workflows, decisions, changes, tasks, evidence freshness, and team checkpoint state. Use when the user asks what is complete, blocked, stale, or currently possible.
3
+ description: Infer the current Ultra workflow position, stale evidence, task risk, and installation health from repository files and host manifests. Use when the owner asks what is complete, blocked, stale, unhealthy, or useful to do next.
4
4
  ---
5
5
 
6
- # Report authoritative state
7
-
8
- This Skill is read-only.
9
-
10
- ## Read
11
-
12
- Call `ultra.context { stage: project, detail: full }`. Use `ultra.sync { action:
13
- inspect }` only when the user needs team-checkpoint detail. Do not import, publish,
14
- repair, compile context, or mutate state.
15
- Never fall back to the Git team checkpoint, generated task JSON, or report files as
16
- live authority when `ultra.context` reports missing or unhealthy local state.
17
-
18
- Report:
19
-
20
- ```text
21
- Ultra: <healthy|degraded> · <branch>@<head|unborn|non-git>
22
- Baseline: <mode>/<status> · gaps=<open>/<blocking>
23
- Stage checkpoints: drafts=<count> · accepted=<current|stale|none>
24
- Change: <id/status|none> · delta/docs=<state>
25
- Task: <id/status|none> · Sessions: <active>
26
- Evidence: plan=<state> · test=<state> · review=<axes> · delivery=<state>
27
- Team checkpoint: <current|drifted|revalidation_required|missing|invalid>
28
- Blockers: <hard mechanical blockers or none>
29
- Warnings: <advisory semantic diagnostics or none>
30
- Model recommendation: <capability and concise rationale>
31
- ```
32
-
33
- Treat warnings and failed draft checks as information, not mechanical orders. Only
34
- corruption, unsafe paths, real concurrency conflicts, permissions, or irreversible
35
- external effects are hard blockers.
36
-
37
- The host model recommends the next useful capability from accepted intent, current
38
- evidence, cost of interruption, and owner goal. SQLite does not choose the route.
39
- Separate verified facts, model inference, and unavailable evidence. Never invoke the
40
- recommendation automatically.
6
+ # Route from artifacts without changing them
7
+
8
+ This router is read-only. It reports verified files, model inference and unavailable
9
+ evidence separately, then recommends one explicit capability without invoking it.
10
+
11
+ ## Before you start
12
+
13
+ 1. Read `.ultra/tasks.json` if present; read the active task's `context_file` and
14
+ closing `## Resume Note`.
15
+ 2. Read `CONTEXT.md` and relevant `.ultra/decisions/` entries when they exist.
16
+ 3. Inspect Git `HEAD`, worktree status, active/archive Change directories and installed
17
+ host manifests without repairing them.
18
+
19
+ ## Definition of done
20
+
21
+ - The artifact route below is evaluated in order and the matching evidence is named.
22
+ - Stale test evidence, dirty worktree state and task graph risks are visible.
23
+ - Installation health reports exact missing or drifted files without mutation.
24
+ - The recommendation says why it follows; it does not launch the capability.
25
+
26
+ ## Infer the route
27
+
28
+ | Observable files | Recommendation |
29
+ |---|---|
30
+ | No `.ultra/` | `ultra-init` |
31
+ | Product specification missing or contains `[NEEDS CLARIFICATION]` | `ultra-research` |
32
+ | A new request exists and no active Change exists | `ultra-change` |
33
+ | An active Change exists and `.ultra/tasks.json` is missing or `tasks` is empty | `ultra-plan` |
34
+ | A frontier task is pending or in progress | `ultra-dev`, naming the task |
35
+ | All tasks completed and no current report | `ultra-test` |
36
+ | `test-report.passed` is false | `ultra-dev`, with blocking findings |
37
+ | Report passed and `git_commit` equals `HEAD` | `ultra-deliver` |
38
+ | No active Change and no new request | Report the idle state; do not manufacture work |
39
+
40
+ A report whose `git_commit` differs from `HEAD`, or whose recorded `worktree.diff_digest`
41
+ differs from the result of resolving the installed `ultra-test` Skill and running
42
+ `node <ultra-test-skill-dir>/scripts/worktree_digest.cjs --project <repository-root>`, is stale. A dirty
43
+ worktree is a warning, not evidence of failure.
44
+
45
+ ## Surface risk and installation health
46
+
47
+ List unmet task dependencies, any `in_progress` task older than 3 days, complexity
48
+ concentration and broken `trace_to` or `context_file` paths. These are sensors.
49
+
50
+ For installation health, compare the selected host's plugin path, skill inventory,
51
+ version, provenance and hook manifest against the installed files. Report broken links
52
+ and missing registrations. Recommend `ubp install` or `ubp update` as the reachable
53
+ repair; this read-only skill never performs it.
54
+
55
+ ## When the owner decides
56
+
57
+ The owner chooses the next workflow, risk disposition and any reinstall. Contradictory
58
+ file facts are reported as contradictions rather than silently selecting one.
59
+
60
+ ## References
61
+
62
+ - `../ultra-think/SKILL.md` — read only when contradictory evidence creates a real
63
+ decision rather than a mechanical repair.
64
+ - `../ultra-think/references/autonomy-boundary.md` — read before recommending a route
65
+ that would reduce an accepted commitment.
@@ -0,0 +1,81 @@
1
+ ---
2
+ name: ultra-tdd
3
+ description: Drive one slice of behavior through red then green — a failing test on a confirmed seam, then the smallest code that passes it. Use when another skill is about to write or change behavior and needs the feedback loop that proves the code actually runs, including a small change that goes straight to implementation.
4
+ ---
5
+
6
+ # Write one failing test on a seam, then just enough code to pass it
7
+
8
+ Without feedback from code that actually ran, the work is blind flying. This is
9
+ the loop that supplies it, and it serves Goal 3, Production-Ready.
10
+
11
+ ## Before you start
12
+
13
+ 1. Read the current task context for the seams already confirmed during
14
+ planning. Tests live on those, and choosing a new one is a planning decision.
15
+ 2. Run the repository's existing test command once, unchanged, to see what
16
+ passing currently looks like. Read `references/test-execution.md` before recording
17
+ that run or any red/green evidence.
18
+ 3. Read `CONTEXT.md` for vocabulary — test names carry the domain words.
19
+
20
+ ## Definition of done
21
+
22
+ - One slice is complete: one seam, one test, one minimal implementation.
23
+ - The test was observed failing before the implementation existed, and observed
24
+ passing after. Both runs are real command output.
25
+ - The test reads as a specification of behavior through a public interface, and
26
+ survives replacing the implementation underneath it.
27
+
28
+ ## Seams, and what a good test on one looks like
29
+
30
+ A seam is a place where behavior can change without editing at that place — the
31
+ module interface. Tests live on seams and never reach for internals. Prefer a
32
+ seam that already exists, take the highest one that works, and one is the ideal
33
+ number. Verify behavior through that public interface: a name like "user can
34
+ checkout with a valid cart" shows at a glance what capability exists, and one
35
+ logical assertion per test keeps it readable.
36
+
37
+ ## Red, then green
38
+
39
+ Write the failing test first and run it, so that red is observed rather than
40
+ assumed. Then write the smallest code that turns it green. Predict no later
41
+ tests and add no speculative capability. Then take the next slice.
42
+
43
+ Refactoring is not part of this loop; `ultra-review` owns it, because the
44
+ restructuring worth doing only becomes visible after three or four slices.
45
+
46
+ ## Three patterns that produce tests worth deleting
47
+
48
+ | Pattern | How you recognize it |
49
+ |---|---|
50
+ | Implementation-coupled | Mocks an internal collaborator, tests a private method, asserts on call counts or ordering, or reaches past the interface into the database. The check: behavior is unchanged after restructuring, yet the test breaks. |
51
+ | Tautological | Recomputes the expected value the same way the implementation does, so it can never fail. Expected values come from an independent source — a known literal, a hand-worked example, the specification. |
52
+ | All tests first | Writing every test before any implementation tests imagined behavior. It captures shape rather than user-visible behavior, is insensitive to real change, and freezes the test structure before the implementation is understood. Take one test, one implementation, and repeat. |
53
+
54
+ ## Mock only at the system boundary
55
+
56
+ External APIs, time and randomness, sometimes the filesystem. Prefer a real test
57
+ library over mocking the database. Your own classes, modules and internal
58
+ collaborators stay real.
59
+
60
+ Design for that boundary: inject dependencies, and give each external operation
61
+ its own named function rather than one generic fetcher — mocking then needs no
62
+ conditional logic, and which endpoints a test touches stays visible. When a real
63
+ dependency is the right answer, copy
64
+ `references/templates/testcontainer-postgres.ts` or
65
+ `references/templates/testcontainer-postgres.py`, and
66
+ `references/templates/vertical-slice.ts` for a path that runs end to end.
67
+
68
+ ## When the owner decides
69
+
70
+ Weakening an assertion, skipping a relevant test, or adjusting an expected value
71
+ to obtain green output crosses the C5 boundary — stop and surface it. A test that
72
+ is genuinely wrong about the specification is a specification question, so it
73
+ goes to the owner as one.
74
+
75
+ ## References
76
+
77
+ - `../ultra-think/references/autonomy-boundary.md` — read before replacing a real
78
+ dependency with a fake, or when a test stands between the work and green.
79
+ - `references/templates/README.md` — read when choosing which enabling template
80
+ fits the dependency you need to make real.
81
+ - `references/test-execution.md` — exact command, failure and result evidence contract.
@@ -0,0 +1,20 @@
1
+ # Enabling templates
2
+
3
+ These runnable examples make the real integration path cheaper than a fake. Read this
4
+ index when `ultra-tdd` reaches a database, feature flag, or multi-layer seam, then copy
5
+ only the smallest relevant file into the project and adapt it to repository conventions.
6
+
7
+ | Template | When to copy |
8
+ |---|---|
9
+ | [testcontainer-postgres.ts](testcontainer-postgres.ts) | A TypeScript/Node test needs real Postgres instead of an internal Repository mock |
10
+ | [testcontainer-postgres.py](testcontainer-postgres.py) | A pytest test needs real Postgres instead of a `MagicMock` Repository |
11
+ | [vertical-slice.ts](vertical-slice.ts) | One test must prove HTTP → use case → database → response |
12
+ | [persistence-real.ts](persistence-real.ts) | A Repository needs real storage rather than an in-memory `Map` |
13
+ | [feature-flag-default-audit.sh](feature-flag-default-audit.sh) | A Change must surface default-off flags that could hide unfinished work |
14
+
15
+ The templates travel with the `ultra-tdd` skill; they are rule-side examples, not
16
+ project authority. Do not copy this directory wholesale into `.ultra/`.
17
+
18
+ Each template must remain runnable after its documented dependencies are installed,
19
+ name the exact verification command in its header, stay short enough to inspect before
20
+ use, and state which Ultra principle makes the example preferable.
@@ -0,0 +1,79 @@
1
+ #!/usr/bin/env bash
2
+ # feature-flag-default-audit.sh
3
+ #
4
+ # Surface every `default off` / `enabled: false` / commented-out feature so the
5
+ # user knows what is *quietly* disabled. Catches the "agent shipped task by
6
+ # turning the feature off" failure mode v7 fixes.
7
+ #
8
+ # Usage:
9
+ # bash feature-flag-default-audit.sh [path]
10
+ #
11
+ # Default path: src/ (override with first arg)
12
+ #
13
+ # PHILOSOPHY: enables C5 (Bounded Autonomy) — default-off without rationale is
14
+ # scope reduction in disguise; this surfaces it so the user can decide.
15
+
16
+ set -euo pipefail
17
+
18
+ ROOT="${1:-src}"
19
+ if [ ! -d "$ROOT" ]; then
20
+ echo "[audit] path not found: $ROOT" >&2
21
+ exit 1
22
+ fi
23
+
24
+ echo "## Feature-flag default audit"
25
+ echo "Path: $ROOT"
26
+ echo "Generated: $(date -u +%Y-%m-%dT%H:%M:%SZ)"
27
+ echo ""
28
+
29
+ # Patterns we care about. Adjust per project conventions.
30
+ patterns=(
31
+ '\benabled:\s*false\b'
32
+ '\bdefault\s*[:=]\s*false\b'
33
+ '\bDISABLED\s*=\s*true\b'
34
+ '\bif\s*\(\s*false\s*\)'
35
+ 'FEATURE_[A-Z_]+\s*=\s*false'
36
+ )
37
+
38
+ found_any=0
39
+ for p in "${patterns[@]}"; do
40
+ hits=$(grep -REn "$p" "$ROOT" \
41
+ --include='*.ts' --include='*.tsx' \
42
+ --include='*.js' --include='*.jsx' \
43
+ --include='*.py' --include='*.go' \
44
+ --include='*.rs' --include='*.sol' \
45
+ --include='*.yaml' --include='*.yml' \
46
+ --include='*.json' --include='*.toml' 2>/dev/null || true)
47
+
48
+ if [ -n "$hits" ]; then
49
+ found_any=1
50
+ echo "### Pattern: $p"
51
+ echo '```'
52
+ echo "$hits"
53
+ echo '```'
54
+ echo ""
55
+ fi
56
+ done
57
+
58
+ # Also surface TODO-style "off until later" markers
59
+ todo_hits=$(grep -REn '(TODO|FIXME).*(enable|turn on|flip on)' "$ROOT" 2>/dev/null || true)
60
+ if [ -n "$todo_hits" ]; then
61
+ found_any=1
62
+ echo "### TODOs to re-enable later"
63
+ echo '```'
64
+ echo "$todo_hits"
65
+ echo '```'
66
+ echo ""
67
+ fi
68
+
69
+ if [ "$found_any" -eq 0 ]; then
70
+ echo "_No default-off features detected._"
71
+ exit 0
72
+ fi
73
+
74
+ echo "---"
75
+ echo ""
76
+ echo "**Action**: For each entry above, confirm with the user whether it is:"
77
+ echo "- (A) Pre-launch: feature is built but gated until release — fine"
78
+ echo "- (B) Genuine kill-switch: stays off in normal operation — fine, document why"
79
+ echo "- (C) Hiding incomplete work: agent shipped task by turning it off — **must fix**"
@@ -0,0 +1,78 @@
1
+ /**
2
+ * Real-persistence Repository skeleton (TypeScript)
3
+ *
4
+ * Why this exists: in-memory `Map` Repositories are a v7 anti-pattern. They
5
+ * pass tests, don't survive restart, hide migration bugs, and silently break
6
+ * production. This template shows the minimum real Repository.
7
+ *
8
+ * Required deps:
9
+ * pnpm add pg
10
+ * # Optional ORM: drizzle / prisma / kysely
11
+ *
12
+ * PHILOSOPHY: enables C4 progress.json `persistence_real` dimension. Pair with
13
+ * testcontainer-postgres.ts for the test side.
14
+ */
15
+
16
+ import type { Pool, PoolClient } from 'pg';
17
+
18
+ // Domain entity — keep separate from row shape
19
+ export type User = {
20
+ id: number;
21
+ email: string;
22
+ createdAt: Date;
23
+ };
24
+
25
+ // Optional: row→entity mapper if column names differ from field names
26
+ function rowToUser(row: { id: number; email: string; created_at: Date }): User {
27
+ return { id: row.id, email: row.email, createdAt: row.created_at };
28
+ }
29
+
30
+ export class UserRepo {
31
+ constructor(private readonly pool: Pool) {}
32
+
33
+ async create(input: { email: string }): Promise<User> {
34
+ const { rows } = await this.pool.query<{
35
+ id: number;
36
+ email: string;
37
+ created_at: Date;
38
+ }>(
39
+ `INSERT INTO users (email) VALUES ($1)
40
+ RETURNING id, email, created_at`,
41
+ [input.email],
42
+ );
43
+ return rowToUser(rows[0]);
44
+ }
45
+
46
+ async findById(id: number): Promise<User | null> {
47
+ const { rows } = await this.pool.query<{
48
+ id: number;
49
+ email: string;
50
+ created_at: Date;
51
+ }>(
52
+ `SELECT id, email, created_at FROM users WHERE id = $1`,
53
+ [id],
54
+ );
55
+ return rows[0] ? rowToUser(rows[0]) : null;
56
+ }
57
+
58
+ // Multi-statement work — pass in a client to keep it on a single connection
59
+ async withTransaction<T>(work: (client: PoolClient) => Promise<T>): Promise<T> {
60
+ const client = await this.pool.connect();
61
+ try {
62
+ await client.query('BEGIN');
63
+ const result = await work(client);
64
+ await client.query('COMMIT');
65
+ return result;
66
+ } catch (e) {
67
+ await client.query('ROLLBACK');
68
+ throw e;
69
+ } finally {
70
+ client.release();
71
+ }
72
+ }
73
+ }
74
+
75
+ // What this template intentionally does NOT do (and why):
76
+ // - No `Map<number, User>` field. That is the in-memory anti-pattern v7 surfaces.
77
+ // - No silent error swallowing (catch + return-null). Errors propagate; callers handle.
78
+ // - No mock-friendly singleton. Inject the Pool so testcontainers work cleanly.
@@ -0,0 +1,78 @@
1
+ """
2
+ Testcontainer-Postgres starter (Python / pytest)
3
+
4
+ Why this exists: Real DB in tests catches migration drift, schema bugs, and
5
+ concurrency issues that mocked Repositories silently miss. Prefer this to
6
+ `MagicMock(spec=Repo)` for any Repository or Service that touches data.
7
+
8
+ Required deps:
9
+ pip install testcontainers[postgres] psycopg[binary] pytest
10
+
11
+ Verify:
12
+ pytest tests/repo/test_user_repo_testcontainer.py -v
13
+
14
+ PHILOSOPHY: enables C2 (Enabling > Defensive) — the cheaper path becomes the
15
+ right path, so agents stop reaching for mocks under pressure.
16
+ """
17
+
18
+ from __future__ import annotations
19
+
20
+ import psycopg
21
+ import pytest
22
+ from testcontainers.postgres import PostgresContainer
23
+
24
+
25
+ @pytest.fixture(scope="module")
26
+ def pg():
27
+ """Module-scoped real Postgres. Slow on first pull, fast after."""
28
+ with PostgresContainer("postgres:16-alpine") as c:
29
+ with psycopg.connect(c.get_connection_url()) as conn:
30
+ with conn.cursor() as cur:
31
+ cur.execute("""
32
+ CREATE TABLE users (
33
+ id SERIAL PRIMARY KEY,
34
+ email TEXT UNIQUE NOT NULL,
35
+ created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
36
+ );
37
+ """)
38
+ conn.commit()
39
+ yield c
40
+
41
+
42
+ @pytest.fixture
43
+ def conn(pg):
44
+ """Per-test connection with truncate-reset so each test is independent."""
45
+ with psycopg.connect(pg.get_connection_url()) as c:
46
+ with c.cursor() as cur:
47
+ cur.execute("TRUNCATE users RESTART IDENTITY CASCADE")
48
+ c.commit()
49
+ yield c
50
+
51
+
52
+ def make_user_repo(conn):
53
+ """Replace with import from your real Repository."""
54
+ class UserRepo:
55
+ def create(self, email: str) -> dict:
56
+ with conn.cursor() as cur:
57
+ cur.execute(
58
+ "INSERT INTO users (email) VALUES (%s) RETURNING id, email, created_at",
59
+ (email,),
60
+ )
61
+ row = cur.fetchone()
62
+ conn.commit()
63
+ return {"id": row[0], "email": row[1], "created_at": row[2]}
64
+
65
+ def find_by_id(self, user_id: int) -> dict | None:
66
+ with conn.cursor() as cur:
67
+ cur.execute("SELECT id, email, created_at FROM users WHERE id = %s", (user_id,))
68
+ row = cur.fetchone()
69
+ return None if row is None else {"id": row[0], "email": row[1], "created_at": row[2]}
70
+
71
+ return UserRepo()
72
+
73
+
74
+ def test_insert_and_fetch_round_trips(conn):
75
+ repo = make_user_repo(conn)
76
+ created = repo.create("a@example.com")
77
+ found = repo.find_by_id(created["id"])
78
+ assert found == created