ultra-builder-pro-cli 5.0.0 → 6.0.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 (159) hide show
  1. package/CHANGELOG.md +113 -3
  2. package/README.md +67 -478
  3. package/README.zh-CN.md +49 -422
  4. package/adapters/_shared/frontmatter.cjs +1 -18
  5. package/adapters/_shared/plugin-core.cjs +17 -83
  6. package/adapters/_shared/runtime-assets.cjs +6 -120
  7. package/adapters/claude.js +8 -24
  8. package/adapters/codex.js +16 -38
  9. package/bin/install.js +35 -57
  10. package/docs/PLUGIN-ISOLATION-CONTRACT.md +13 -101
  11. package/docs/examples/drive/claude-reviewer.sh +53 -0
  12. package/docs/examples/drive/claude-writer.sh +43 -0
  13. package/engine/FORMATS.md +1051 -0
  14. package/engine/checks.cjs +139 -0
  15. package/engine/cli.cjs +148 -0
  16. package/engine/completion.cjs +48 -0
  17. package/engine/context.cjs +94 -0
  18. package/engine/drive.cjs +220 -0
  19. package/engine/expect-worker.cjs +5 -0
  20. package/engine/expect.cjs +33 -0
  21. package/engine/formats.cjs +189 -0
  22. package/engine/git-state.cjs +112 -0
  23. package/engine/ledger.cjs +205 -0
  24. package/engine/loading.cjs +28 -0
  25. package/engine/merge.cjs +273 -0
  26. package/engine/milestone.cjs +89 -0
  27. package/engine/plan.cjs +232 -0
  28. package/engine/project.cjs +5 -0
  29. package/engine/signals.cjs +3 -0
  30. package/engine/states.cjs +175 -0
  31. package/hooks/session-start.cjs +54 -0
  32. package/package.json +17 -52
  33. package/skills/ultra/SKILL.md +395 -0
  34. package/.ultra-template/changes/abandoned/.gitkeep +0 -0
  35. package/.ultra-template/changes/active/.gitkeep +0 -1
  36. package/.ultra-template/changes/archive/.gitkeep +0 -1
  37. package/.ultra-template/contexts/TEMPLATE.md +0 -135
  38. package/.ultra-template/decisions/.gitkeep +0 -1
  39. package/.ultra-template/evidence/.gitkeep +0 -1
  40. package/.ultra-template/north-star.md +0 -52
  41. package/.ultra-template/project-brief.md +0 -28
  42. package/.ultra-template/research/.gitkeep +0 -1
  43. package/.ultra-template/specs/architecture.md +0 -81
  44. package/.ultra-template/specs/discovery.md +0 -74
  45. package/.ultra-template/specs/product.md +0 -80
  46. package/.ultra-template/specs/research-distillate.md +0 -57
  47. package/.ultra-template/tasks.json +0 -4
  48. package/.ultra-template/test-report.json +0 -44
  49. package/adapters/_shared/host-profile.cjs +0 -5
  50. package/adapters/grok.js +0 -242
  51. package/adapters/kimi.js +0 -232
  52. package/adapters/opencode.js +0 -408
  53. package/adapters/zcode.js +0 -375
  54. package/bin/delegate-worker.cjs +0 -5
  55. package/bin/delegate.cjs +0 -5
  56. package/docs/ARCHITECTURE.md +0 -274
  57. package/docs/ARTIFACT-AUTHORITY.md +0 -305
  58. package/docs/DECISIONS.md +0 -229
  59. package/docs/PHILOSOPHY.md +0 -261
  60. package/docs/RUNTIME-COMPAT-MATRIX.md +0 -315
  61. package/docs/SKILL-AUTHORING.md +0 -113
  62. package/docs/WORKFLOW-LIFECYCLE.md +0 -350
  63. package/docs/evals/adversarial-review-2026-08-14.md +0 -84
  64. package/docs/evals/ultra-5-0-journey-results.md +0 -62
  65. package/docs/evals/ultra-5-0-live-acp-conformance.md +0 -93
  66. package/docs/evals/ultra-5-0-route-journeys.md +0 -145
  67. package/docs/evals/zcode-automation-2026-08-14.md +0 -103
  68. package/hooks/README.md +0 -52
  69. package/hooks/_common.py +0 -1779
  70. package/hooks/adapters/codex.py +0 -295
  71. package/hooks/adapters/grok.py +0 -134
  72. package/hooks/adapters/kimi.py +0 -156
  73. package/hooks/adapters/zcode.py +0 -227
  74. package/hooks/block_dangerous_commands.py +0 -201
  75. package/hooks/compact_context.py +0 -224
  76. package/hooks/mid_workflow_recall.py +0 -47
  77. package/hooks/post_edit_guard.py +0 -215
  78. package/hooks/session_context.py +0 -741
  79. package/skills/ultra-change/SKILL.md +0 -165
  80. package/skills/ultra-change/references/change-contract.md +0 -199
  81. package/skills/ultra-change/references/execution-grant.md +0 -109
  82. package/skills/ultra-change/references/primary-transfer.md +0 -273
  83. package/skills/ultra-change/scripts/validate_primary_transfer.cjs +0 -1928
  84. package/skills/ultra-delegate/SKILL.md +0 -195
  85. package/skills/ultra-delegate/patches/zcode-acp-0.1.0-zcode-0.16.5.patch +0 -184
  86. package/skills/ultra-delegate/references/delegation-contract.md +0 -138
  87. package/skills/ultra-delegate/scripts/acp-conformance.cjs +0 -287
  88. package/skills/ultra-delegate/scripts/acp-driver.cjs +0 -762
  89. package/skills/ultra-delegate/scripts/agent-execution-driver.cjs +0 -320
  90. package/skills/ultra-delegate/scripts/cli-driver.cjs +0 -61
  91. package/skills/ultra-delegate/scripts/delegate-profiles/kimi-read-only.md +0 -15
  92. package/skills/ultra-delegate/scripts/delegate-profiles/kimi-write.md +0 -17
  93. package/skills/ultra-delegate/scripts/delegate-worker.cjs +0 -328
  94. package/skills/ultra-delegate/scripts/delegate.cjs +0 -690
  95. package/skills/ultra-delegate/scripts/delegate_wait.py +0 -86
  96. package/skills/ultra-delegate/scripts/host-profile.cjs +0 -267
  97. package/skills/ultra-deliver/SKILL.md +0 -194
  98. package/skills/ultra-deliver/references/baseline-reconciliation.md +0 -41
  99. package/skills/ultra-dev/SKILL.md +0 -265
  100. package/skills/ultra-dev/references/debugging.md +0 -22
  101. package/skills/ultra-domain-modeling/SKILL.md +0 -79
  102. package/skills/ultra-grilling/SKILL.md +0 -121
  103. package/skills/ultra-grilling/references/reframing.md +0 -76
  104. package/skills/ultra-init/SKILL.md +0 -143
  105. package/skills/ultra-init/references/brownfield-adoption.md +0 -32
  106. package/skills/ultra-init/scripts/init_project.cjs +0 -1031
  107. package/skills/ultra-plan/SKILL.md +0 -160
  108. package/skills/ultra-plan/references/task-evidence-v2.md +0 -300
  109. package/skills/ultra-plan/scripts/validate_task_evidence.cjs +0 -859
  110. package/skills/ultra-research/SKILL.md +0 -167
  111. package/skills/ultra-research/references/00-problem-validation.md +0 -36
  112. package/skills/ultra-research/references/01-opportunity-discovery.md +0 -33
  113. package/skills/ultra-research/references/02-market-assessment.md +0 -31
  114. package/skills/ultra-research/references/03-alternatives.md +0 -31
  115. package/skills/ultra-research/references/04-product-strategy.md +0 -41
  116. package/skills/ultra-research/references/05-assumptions-validation.md +0 -31
  117. package/skills/ultra-research/references/10-user-personas.md +0 -30
  118. package/skills/ultra-research/references/11-user-scenarios.md +0 -28
  119. package/skills/ultra-research/references/20-user-stories.md +0 -31
  120. package/skills/ultra-research/references/21-features-scope.md +0 -38
  121. package/skills/ultra-research/references/22-success-metrics.md +0 -33
  122. package/skills/ultra-research/references/30-architecture-context.md +0 -30
  123. package/skills/ultra-research/references/31-solution-strategy.md +0 -28
  124. package/skills/ultra-research/references/32-building-blocks.md +0 -28
  125. package/skills/ultra-research/references/40-deployment.md +0 -29
  126. package/skills/ultra-research/references/41-quality-risks.md +0 -28
  127. package/skills/ultra-research/references/99-synthesis.md +0 -59
  128. package/skills/ultra-research/references/north-star-v2.md +0 -168
  129. package/skills/ultra-research/references/wayfinding.md +0 -50
  130. package/skills/ultra-research/scripts/validate_north_star.cjs +0 -1174
  131. package/skills/ultra-review/SKILL.md +0 -275
  132. package/skills/ultra-review/references/adversarial-evaluation.md +0 -31
  133. package/skills/ultra-review/references/code.md +0 -17
  134. package/skills/ultra-review/references/comments.md +0 -12
  135. package/skills/ultra-review/references/design.md +0 -12
  136. package/skills/ultra-review/references/errors.md +0 -13
  137. package/skills/ultra-review/references/review-modes.md +0 -29
  138. package/skills/ultra-review/references/spec.md +0 -18
  139. package/skills/ultra-review/references/tests.md +0 -12
  140. package/skills/ultra-review/references/unified-schema.md +0 -284
  141. package/skills/ultra-review/references/worker-packet.md +0 -183
  142. package/skills/ultra-review/scripts/review_wait.py +0 -2943
  143. package/skills/ultra-status/SKILL.md +0 -209
  144. package/skills/ultra-status/references/route-contract.md +0 -100
  145. package/skills/ultra-tdd/SKILL.md +0 -91
  146. package/skills/ultra-tdd/references/templates/README.md +0 -20
  147. package/skills/ultra-tdd/references/templates/feature-flag-default-audit.sh +0 -79
  148. package/skills/ultra-tdd/references/templates/persistence-real.ts +0 -78
  149. package/skills/ultra-tdd/references/templates/testcontainer-postgres.py +0 -78
  150. package/skills/ultra-tdd/references/templates/testcontainer-postgres.ts +0 -73
  151. package/skills/ultra-tdd/references/templates/vertical-slice.ts +0 -66
  152. package/skills/ultra-tdd/references/test-execution.md +0 -23
  153. package/skills/ultra-test/SKILL.md +0 -244
  154. package/skills/ultra-test/references/export-syntax.md +0 -18
  155. package/skills/ultra-test/scripts/validate_review_transport.cjs +0 -549
  156. package/skills/ultra-test/scripts/worktree_digest.cjs +0 -576
  157. package/skills/ultra-think/SKILL.md +0 -56
  158. package/skills/ultra-think/references/autonomy-boundary.md +0 -48
  159. package/skills/ultra-think/references/interaction-boundary.md +0 -42
@@ -0,0 +1,395 @@
1
+ ---
2
+ name: ultra
3
+ description: Drive a project with the UBP v6 engine, from status and the initial interview
4
+ through specification and checks, planning, the node loop, milestone gates, and changes.
5
+ ---
6
+ # Ultra method (UBP v6)
7
+
8
+ You run a project through one entry point. The engine (`ubp`) owns the truth about
9
+ progress; you own judgment. Never write a progress number yourself: quote `ubp status`.
10
+
11
+ `ubp` always means `node __UBP_ENGINE_CLI__`, the engine bundled with this Skill,
12
+ regardless of PATH. Every command takes `--root <dir>` and `--json`. File formats and
13
+ exit codes: `__UBP_ENGINE_FORMATS__`.
14
+
15
+ ## Every session starts the same way
16
+
17
+ 1. `ubp status --json`. If `.ultra/spec.md` does not exist, the project has not started:
18
+ go to "0→1 interview".
19
+ 2. `git log --oneline -10` and `git status --short`.
20
+ 3. When the current milestone has a `journey`, run it once: `ubp check <journey>`. A red
21
+ journey at the start of a session is the first thing to fix.
22
+ 4. Choose the step from the status, and from nothing else:
23
+
24
+ | Status | Step |
25
+ |---|---|
26
+ | `drive` is set (the line ends with `drive 运行中`) and `UBP_DRIVE` is not (you are not that drive's writer or reviewer) | a drive may be running on this tree. When `ps -o command= -p <drive>` exits 0 and prints a full command line (program and arguments) without the word `drive`, the pid now belongs to another process and the lock is left over: remove `.ultra/.runtime/drive.lock` and read the status again. If `ps` fails, prints nothing or prints only a program name such as `(node)`, treat the drive as running. Otherwise brief no writer, start no drive and change no file: if this session started the drive, wait for its completion notice; if not, tell the Owner it is running (its pid is `drive`) and stop |
27
+ | `dirty: true` | commit or discard first; evidence from a dirty tree never counts |
28
+ | `gate: "fail"` | fix the reported `problems` (see "Plan") |
29
+ | `gate: "stale"` | `ubp gate`, which records the plan change |
30
+ | `next` is a node id | "Node loop" for that node |
31
+ | `next` is `检查` | `ubp check`, then triage every red or unknown check with "Escalation"; a red invariant prints its `fix` |
32
+ | `next` is `里程碑门` | "Milestone gate" |
33
+ | `next` is `全部完成` | report the line to the Owner; ask whether to plan another milestone |
34
+ | `next` is `无(受阻)` | read `nodes[].state` and `reasons`; repair the plan |
35
+
36
+ Whenever you report progress to the Owner, paste the line `ubp status` printed.
37
+
38
+ ## Roles
39
+
40
+ Each step names a role. One agent may play several, with two exceptions: the acceptance
41
+ author and the reviewer are never the writer of the code they judge. A writer is a fresh
42
+ context: a new subagent or delegated session that sees the node brief and the repository,
43
+ not your conversation.
44
+
45
+ Per node, the default is one fresh writer followed by your verification (Node loop step 4):
46
+ no per-node explorer, tester or second reviewer. In a measured comparison on nine nodes,
47
+ those extra roles cost three to five times the tokens, scored no higher on hidden checks, and
48
+ found one defect between them. Add a read, a review or a test run to a node only when you
49
+ judge that node risky. A reviewer from another vendor, when one is available, reviews the
50
+ whole branch at the milestone gate.
51
+
52
+ ## 0→1 interview (interviewer)
53
+
54
+ Goal: the Owner's intent, in their own words, before any specification.
55
+
56
+ - Ask one question at a time. Each carries your recommended answer and what would change it.
57
+ - Cover, in this order: the north star (for whom, and what they get), success and abandon
58
+ conditions, the boundary (what is out), what "elegant" means for this project, the
59
+ milestone split, and for each user-visible behavior how the Owner would tell it is done.
60
+ - Write `.ultra/records/interview.md`: each question, the Owner's answer verbatim, then your
61
+ reading, keeping facts apart from decisions.
62
+ - Stop when every requirement you are about to write has an Owner sentence behind it.
63
+ Three to five questions is normal. Needing more means you are asking for decisions you can
64
+ make: make them and log a ruling.
65
+
66
+ ## Specification and checks (planner, acceptance author)
67
+
68
+ `.ultra/spec.md`:
69
+
70
+ - Begin with `## Direction` (L0): north star, users, success and abandon conditions,
71
+ boundary, the meaning of elegance. Only the Owner changes this section.
72
+ - Then one `## REQ-<id> <title>` block per user-observable behavior: what the user does and
73
+ sees, then a line `Done when: <the Owner's acceptance sentence>`. Small fixes and internal
74
+ structure are not requirements.
75
+
76
+ Checks (acceptance author, never the writer):
77
+
78
+ - Every requirement has a covering check; every milestone has a `journey` check that walks the
79
+ user's whole path through the milestone, through the real interface.
80
+ - A requirement is green only when every check covering it passes. So a check covers only the
81
+ requirements it proves on its own, and a journey covers only the requirement for the user's
82
+ path (for example the web page), not every requirement it passes through: otherwise the
83
+ first node cannot finish until the last node's interface exists.
84
+ - Anything a check needs from the code (start command, port and data variables, a ready line,
85
+ markers in a page) is written in the spec as interface (L2), so a writer can meet it.
86
+ - `expect` must prove the tests ran, for example `^ℹ pass [1-9][0-9]*$` with
87
+ `node --test --test-reporter=spec`; a filter that matched nothing must not pass.
88
+ - Commit the test files before any implementation and run `ubp check`: every new check must be
89
+ red or unknown. A check that is green before the code exists proves nothing.
90
+ - For each key requirement, break the finished implementation once and see its check fail.
91
+ - A check never reads `.ultra/records/`.
92
+
93
+ ## Plan (planner)
94
+
95
+ `.ultra/plan.json`: milestones in delivery order, each with its requirements and `journey`;
96
+ nodes in plan order, each with `covers`, `depends` and `scope`.
97
+
98
+ - A node is one writer session: one to three requirements, a few path prefixes of scope, and
99
+ a brief that fits the default budget (`ubp context` exits 1 when it does not: split it).
100
+ - `depends` names the nodes whose interfaces this node uses, whose code it changes, or whose
101
+ conventions it must keep (for example "save before responding"): only their handoffs reach
102
+ its brief. Reordering `depends` is free (L3) and is not a recorded plan change; log a
103
+ ruling when you change it after the gate.
104
+ - The planner does not write product code.
105
+ - Before the gate, read the requirements against each other. Two that cannot both hold (for
106
+ example "each create gives a new code" and "creating the same link twice returns the first
107
+ code") are an L1 conflict for the Owner; a writer must never be left to pick one.
108
+ - Run `ubp gate` until it passes; it records the plan baseline.
109
+ - Project setup, once: `.ultra/.runtime/` in `.gitignore`, and
110
+ `.ultra/ledger/*.jsonl merge=union` in `.gitattributes`.
111
+ - Commit the truth files, ledger and records (`.ultra/spec.md`, `checks.json`, `plan.json`,
112
+ `rulings.md`, `ledger/`, `records/`) in their own commit after the gate passes and after
113
+ each milestone closure. They are engine-owned: committing them never stales evidence.
114
+
115
+ ## Node loop (controller and writer)
116
+
117
+ 1. `ubp context <node> > .ultra/.runtime/briefs/<node>.md`.
118
+ 2. Start a fresh writer with that brief, the workspace path and how to call `ubp`, and ask
119
+ it to say in its handoff what it noticed and left unchanged and what behavior no check
120
+ pins (the milestone demo lists them). Nothing else from your conversation goes in: what
121
+ the writer needs belongs in the spec, the checks, the scope or a dependency's handoff.
122
+ The writer must be able to run the checks where it works (a sandbox that forbids
123
+ listening on a local port cannot run a server's checks); a writer that cannot is the
124
+ wrong writer for that node, not a reason to weaken a check.
125
+ 3. The writer works test-first inside the scope, commits, runs the `ubp check <ids>` line of
126
+ its brief until those checks are green, writes `.ultra/records/handoffs/<node>.md`, and
127
+ runs `ubp node done <node>`.
128
+ 4. Verify, as controller: `ubp status --json` shows the node `done`; `git diff` of the
129
+ writer's commits stays inside the scope, touches no check file and adds no line to
130
+ `.ultra/ledger/approvals.jsonl` (a writer never approves); `ubp gate` still passes
131
+ (it validates the rulings the writer added); `ubp check` (every stale or unknown check)
132
+ turns no requirement of the current or a closed milestone from green to red (ratchet).
133
+ A violation is reverted in a new commit and the node is briefed again.
134
+ 5. Exits: converged (node done) → the next item; stalled (three attempts left a check red)
135
+ or impossible → "Escalation".
136
+
137
+ A node made `stale` by a requirement edit, whose checks are already green on the committed
138
+ code, needs no writer: the controller runs `ubp node done <node>`. When its checks are red,
139
+ brief a fresh writer with the new `ubp context`; the latest rulings and the review that led
140
+ to the edit go into the mission, not into the writer's memory.
141
+
142
+ One writer at a time on one work tree. Brief the next writer on a tree only after the
143
+ previous writer's completion notice has arrived: a progress note, a `node done` line or a
144
+ quiet log is not completion, and a writer still running will commit whatever it finds in the
145
+ tree. Parallel writers: see "Parallel writers and the merge gate".
146
+
147
+ When the Owner asks for an unattended run, give every node a `scope` that holds no check
148
+ file, commit everything, and start `ubp drive --writer <cmd> --reviewer <cmd> --json` in the
149
+ background, then wait for its completion notice: a drive runs for many writers, and a
150
+ foreground call is bounded by the host's command timeout (at most 10 minutes in Claude Code).
151
+ In Claude Code, run it with Bash `run_in_background`; on a host without background
152
+ commands, run `mkdir -p .ultra/.runtime`, start
153
+ `nohup <drive command> > .ultra/.runtime/drive.json 2> .ultra/.runtime/drive.err &`, tell
154
+ the Owner it is running and stop: a later session sees it in `ubp status` and, once `drive`
155
+ is null, reads `drive.json`, or `drive.err` when the drive printed no result. The writer command hands an agent `$UBP_BRIEF` and tells it to call the engine as
156
+ `eval "$UBP <args>"` (a login shell can put another `ubp` first on `PATH`). Headless Claude
157
+ Code examples are `docs/examples/drive/claude-writer.sh` and `claude-reviewer.sh` in the
158
+ ultra-builder-pro-cli package and repository; `--writer` takes a shell command line, so quote
159
+ a path that holds a space (`--writer "'<path>'"`). When the drive stops, first put back what
160
+ the stop names: each truth file a `truth-touched` problem names to its content at HEAD
161
+ (deleted when HEAD has none; `.ultra/ledger/` holds three, `milestones.jsonl`,
162
+ `approvals.jsonl` and `plan-log.jsonl`), what the reviewer changed on `reviewer-changed-tree`,
163
+ and the branch itself on `history-rewritten` (below). Only then commit the records the drive
164
+ left in `.ultra/ledger/` (records never dirty the tree, so the drive does not), and act on
165
+ `stop`:
166
+ - `milestone-gate`: with `accept`, go to "Milestone gate" step 1; with `revise`, its revise
167
+ path; without a reviewer, have the milestone reviewed first.
168
+ - `truth-touched`, `out-of-scope`, `check-touched`, `ratchet-broken`, `node-not-green`:
169
+ undo the attempt in a new commit (a truth line it committed goes with it). A completion it
170
+ recorded stays, so take that node through the node loop by hand until its checks are green
171
+ before driving on.
172
+ - `history-rewritten`: the attempt rewrote commits, which a new commit cannot undo. Find
173
+ the HEAD before the attempt in `git reflog`, check nothing after it needs keeping, and
174
+ reset the branch to it.
175
+ - `writer-left-dirty`, `dirty-tree`: clear any assume-unchanged or skip-worktree flag
176
+ (`git ls-files -v` shows them), undo any change to the repository's Git `config`,
177
+ `config.worktree` or `info/exclude`, then commit what belongs to the node and discard the
178
+ rest.
179
+ - `attempts-exhausted`, `writer-budget`: "Escalation" (stalled); the writers' logs are in
180
+ `.ultra/.runtime/drive/<run>/`.
181
+ - `review-exists`: keep the old review as `<milestone>-review-<n>.md`; `review-invalid`,
182
+ `reviewer-changed-tree`: fix the reviewer command and restore what it changed.
183
+ - `scope-missing`, `plan-gate`, `brief-over-budget`, `checks-not-green`, `blocked`: the
184
+ matching planner step.
185
+ - `drive-running`: another drive holds this tree; this one started nothing. Follow the
186
+ status table's first row. When `ubp status` shows no `drive`, the lock holds no live pid
187
+ (a drive killed while taking it): remove `.ultra/.runtime/drive.lock` and start the drive
188
+ again. Never remove it while its pid runs a drive.
189
+
190
+ ## Escalation (RESULT §3.2)
191
+
192
+ Before acting, name the layer the problem lives in. Never change a check to get past it.
193
+
194
+ | Finding | Layer | Decides | Action |
195
+ |---|---|---|---|
196
+ | the implementation is wrong | L4 | writer | retry inside the node, at most three attempts |
197
+ | a design or interface does not work | L2 | planner | ruling; change the design and plan; `ubp gate` |
198
+ | an acceptance is wrong | L1 | planner | add or modify with a ruling; edit spec and checks; `ubp gate` |
199
+ | two requirements conflict (both cannot hold) | L1 | Owner | stop and ask which holds; never leave a writer to pick; narrowing the other is a reduction |
200
+ | a requirement must be deleted or narrowed | L1 | Owner | stop and ask; act only on approval |
201
+ | the direction or success criteria are wrong | L0 | Owner | stop and ask |
202
+
203
+ When two repairs fail and both point at the same premise, test that premise before
204
+ choosing a layer.
205
+
206
+ ## Milestone gate
207
+
208
+ When `next` is `里程碑门`:
209
+
210
+ 1. `ubp check --all`. Every check covering a requirement of this milestone or of a closed
211
+ milestone, and every invariant, must be green; checks of later milestones may be red.
212
+ Then repeat it in a clean checkout of HEAD (`git worktree add --detach <temp> HEAD`,
213
+ install what the project needs, `ubp check --all --root <temp>`, then
214
+ `git worktree remove --force <temp>`): a fix that lives only in a file Git ignores or
215
+ hides passes here while HEAD lacks it. A check green here and red there is a stop: find
216
+ the file and commit it. Then `ubp retro` (see "Keeping it tidy").
217
+ 2. Whole-branch review. A reviewer who wrote none of the milestone's code reads the
218
+ milestone's diff (from the previous closure commit, or from the start), its requirements,
219
+ the plan-log changes, the rulings and the writers' handoffs since the previous closure.
220
+ Ask it to drive the product by hand and to run the checks against deliberately broken
221
+ copies of the code: a check that passes on a broken copy is an acceptance gap. The Owner's
222
+ rule (2026-11-02) is that a check that could be stronger never blocks, so every round uses
223
+ one bar: a finding blocks only when the product, as HEAD builds it, breaks a requirement's
224
+ `Done when` line or the Direction, or does something wrong that a person can reproduce
225
+ through its real interface. Wrong means it contradicts the text of the spec (a
226
+ requirement, the Interface or the Direction), loses or corrupts data, crashes, or opens a
227
+ security hole. An acceptance gap does not block once the reviewer has driven HEAD through
228
+ its real interface on the input the broken copy got wrong and seen it behave correctly:
229
+ it quotes what HEAD did, names the check that would close the gap under
230
+ `What must be said to the Owner`, and the verdict stays `accept`. The review,
231
+ `.ultra/records/milestones/<milestone>-review.md`, holds a first line `Reviewer: <who>`,
232
+ the findings that block (each naming the `Done when` line, the Direction or the
233
+ reproduction it rests on), a section `What must be said to the Owner` with everything
234
+ else, then exactly one line `Verdict: accept` (no finding blocks) or `Verdict: revise`.
235
+ Quote an earlier verdict only inside a code fence. On `revise`, keep that review as
236
+ `<milestone>-review-<n>.md`, triage every blocking finding with "Escalation" (a fix that
237
+ narrows a requirement goes to the Owner first), change the spec and the checks as
238
+ acceptance author, `ubp gate`, rework the stale nodes through the node loop, and review
239
+ again. A review after a `revise` also checks each blocking finding of that review and
240
+ looks for regressions.
241
+ 3. Demo for the Owner, in this order: what to try by hand (the journey in user terms), the
242
+ journey check's result and log path, the progress line, the plan changes since the
243
+ previous closure (`.ultra/ledger/plan-log.jsonl`), the rulings since then, the repeated
244
+ failure classes from `ubp retro` and what you changed for each, the count of `unplanned`
245
+ Owner touches, the verdict and which commits the accepting review read. Then list, defects
246
+ first, what the reviews put under `What must be said to the Owner` and what the writers'
247
+ handoffs (`.ultra/records/handoffs/`) say is unfinished, noticed and left unchanged, or
248
+ pinned by no check.
249
+ 4. Ask the Owner one question: let the milestone pass, or change direction. Their reply,
250
+ verbatim, is `--owner`. Never answer this by proxy while the step-3 list holds a defect:
251
+ fix it first, or ask the Owner. A defect you fix, or an item the Owner wants done now, is a
252
+ change handled under "Changes after 0→1"; the gate then starts again at step 1, with a
253
+ full review.
254
+ 5. `ubp milestone close <milestone> --owner "<words>" --review <review path>`, adding
255
+ `--proxy` when you answered for the Owner. Then commit `.ultra/`.
256
+
257
+ ## Changes after 0→1
258
+
259
+ An Owner message during the work, or a finding during it, is a difference in one layer.
260
+ Name the layer before touching any file, then follow its row. Every row ends with
261
+ `ubp gate` passing and a commit of `.ultra/`; the plan log then holds the diff, and
262
+ `ubp status` counts it in `本里程碑计划变更`.
263
+
264
+ | Difference | Layer | What you do | What the engine does |
265
+ |---|---|---|---|
266
+ | a new behavior | L1 add | spec block, a red check (commit it before code), a node; gate | new node `ready`; no other node changes state; every check is stale until `ubp check` (the new check file is code) |
267
+ | a behavior changes | L1 modify | edit the block, its checks; gate | only nodes covering it turn `stale`; brief a writer with the new `ubp context` |
268
+ | a behavior goes away or asks for less | L1 reduce | ask the Owner first (touch `reduction`); `ubp approve <milestone>/<id>… --owner "<words>"` (add `--proxy` when you answered for them); then edit | the gate refuses (`reduction-unapproved`) any dropped requirement, dropped check or narrowed check coverage without that record |
269
+ | how it is built changes | L2 | a ruling; edit the design, the plan (usually a new node, or new `depends`); gate | the new node runs; requirement texts are unchanged, so no other node turns stale |
270
+ | a shared convention changes (`## Interface`) | L2 | as above, plus edit the shared text | every node and check turns `stale` (`shared-changed`): rerun every check; a node whose checks are green again needs only `ubp node done` |
271
+ | direction or success criteria | L0 | stop and ask the Owner | — |
272
+
273
+ After any of these, the controller runs `ubp check` (every check is stale after any code
274
+ commit: the ratchet) and confirms that no requirement of the current or a closed milestone
275
+ went from green to red.
276
+
277
+ The engine sees removals, not meaning: rewording a requirement so it asks for less,
278
+ changing a check's `run` or `expect` so it proves less, or deleting a convention from the
279
+ shared text all pass the gate as modifications. Weakening a test inside a check's file never
280
+ reaches the gate or the plan log at all (a check's fingerprint covers only `run`,
281
+ `timeout_sec` and `expect`); it only makes checks stale like any code commit. Classify such an
282
+ edit as a reduction yourself and record the Owner's approval with `ubp approve` before making
283
+ it. An approval answers the plan as it stands: gate any other change of that milestone, or
284
+ close it, and the approval no longer counts, so approve, edit and gate in one go (approving
285
+ after a refused gate also works).
286
+
287
+ The engine does not know who approves: `ubp approve` without `--proxy` is accepted from
288
+ anyone. Only the controller runs it, only after the matching line in
289
+ `.ultra/records/owner-touches.md`, and with `--proxy` whenever that line says `proxy: yes`.
290
+
291
+ An L2 change re-opens no finished node: the engine has no per-module invalidation, only none
292
+ (a new node) or everything (`shared-changed`). The ratchet protects finished behavior; when
293
+ the new design makes a finished node's code wrong without failing a check, plan a node for
294
+ that change instead of editing the code inside another node's scope.
295
+
296
+ Interface details that concern one requirement go in that requirement's block, so changing
297
+ them stales only its nodes. A brief carries requirement text only: when the shared text
298
+ changed, quote the changed lines in the writer's mission.
299
+
300
+ ## Keeping it tidy (cleaner)
301
+
302
+ The ratchet keeps old behavior working. These three keep the code from decaying as it grows
303
+ (RESULT §3.7).
304
+
305
+ - **Invariants.** A rule the code must always keep (a file size limit, a forbidden import,
306
+ no npm dependency) is a check with `fix` and `covers: []`. `fix` says in one sentence how
307
+ to repair a violation, so the writer who meets it can act without asking. An invariant
308
+ belongs to no milestone; it blocks `node done` and `milestone close` while it is not
309
+ green, and `ubp check` prints its `fix` under a failure. Adding one is a ruling (L2), not
310
+ a plan change; break the code once and see it fail, as for any check. Removing one is a
311
+ reduction of what the project promises itself: log a ruling saying why.
312
+ - **Cleanup nodes.** A node with `"kind": "cleanup"` and `covers: []`, whose writer (the
313
+ cleaner) reads the code against the invariants, the Direction's meaning of elegance and
314
+ the rulings. It fixes small things inside its scope and turns anything bigger into a new
315
+ node with a ruling, never a large refactor. It completes only while every finished
316
+ requirement and every invariant stays green. With `"cleanup_every": K` in `plan.json`,
317
+ the gate requires one at the end of every milestone and after at most K other nodes.
318
+ - **Retro.** At every milestone gate, run `ubp retro` (it leaves out a check's red runs before
319
+ its first pass: test-first work is not a failure class; a test that turns red again because
320
+ a review added cases counts as a regression, since the engine cannot tell the two apart).
321
+ Each failure class seen twice or more becomes a change to the environment (an invariant, a
322
+ rule in the spec's interface, a helper, a ruling), not another one-off fix in the code; say
323
+ what you did in the demo. A
324
+ lesson about this method itself is a method candidate, never a direct edit of this file.
325
+
326
+ ## Parallel writers and the merge gate
327
+
328
+ The default is one writer. Run two in parallel only when the plan's frontier holds at least
329
+ two ready nodes whose scopes do not overlap and each is a substantial piece of work; reads,
330
+ reviews and test runs may run in parallel at any time.
331
+
332
+ - Each parallel writer gets its own branch and work tree (`git worktree add`), runs its
333
+ checks and `ubp node done` there, and commits its ledger lines with its code. A branch never
334
+ changes `spec.md`, `checks.json` or `plan.json`, and never approves or closes: the merge
335
+ refuses it (`truth-changed`); such a change is the planner's or yours, on the main line.
336
+ - Before merging: the project setup line `.ultra/ledger/*.jsonl merge=union` is committed in
337
+ `.gitattributes` (without it two writers' evidence conflicts); `.ultra/` is committed on
338
+ the main line (otherwise `dirty-tree`, naming the paths); and you have verified the
339
+ branch's commits as in Node loop step 4 (scope, no check file, no approval line). The merge
340
+ does not check scope or check scripts.
341
+ - Merge with `ubp merge <branch> --expect-head "$(git rev-parse HEAD)"`: a full commit id,
342
+ never the word `HEAD`. One merge at a time; a second is refused `merge-busy`. The engine
343
+ merges in a temporary work tree, refuses a branch that changes anything under `.ultra/`
344
+ except evidence and node lines, rulings and records (`truth-changed`), refuses a merged
345
+ tree that fails the plan gate (`merged-gate`, for example a malformed ruling), runs every
346
+ check there, and fast-forwards only when the finished work stayed green: every invariant,
347
+ every check of a closed milestone, every check of a node with a completion record (on the main
348
+ line or by the branch), and every check of the current milestone that passed before the merge.
349
+ The other writer's unfinished node only adds a `warning`; it never blocks.
350
+ - On refusal: `head-moved`, re-read HEAD and retry; `plan-gate`, run `ubp gate` on the main
351
+ line, commit `.ultra/`, retry; `nothing-to-merge`, the branch is already in; `merge-busy`
352
+ that persists while no merge runs, delete `.ultra/.runtime/merge.lock` and retry;
353
+ `merge-conflict`, the branch's writer resolves it on the branch (a conflict under
354
+ `.ultra/ledger/` means the `merge=union` line is missing); `truth-changed`, the branch must
355
+ drop that change (a plan change is yours, on the main line); `merged-gate`, the writer
356
+ fixes the ruling on the branch; `check-not-green` with `first bad commit …` or `the branch
357
+ marks <node> done`, brief that branch's writer again with it; `not green at HEAD before the
358
+ merge`, finished work is red on the main line, fix it there first (a requirement added to
359
+ a closed milestone is red until built: merge the branch that builds it first);
360
+ `fast-forward-failed`, the main tree changed during the merge, restore it, commit `.ultra/`
361
+ and retry. Exit 2 is
362
+ not a refusal: read its `Git failed: …` reason (identity, a hook, signing) and fix that.
363
+ Any other `warning` names a temporary tree the engine could not remove.
364
+ - The merged tree resolves modules from the main tree's installed dependencies: install a
365
+ dependency the branch adds on the main line before merging it.
366
+ - After each merge, run `ubp check --all` in the main tree (a branch's evidence lines are
367
+ not trusted until then) and commit `.ultra/` before the next merge.
368
+
369
+ ## Owner touches
370
+
371
+ Every question put to the Owner is one line in `.ultra/records/owner-touches.md`:
372
+
373
+ ```
374
+ - <YYYY-MM-DD> <touchpoint> · Q: <question> · A: <answer verbatim> · proxy: yes|no
375
+ ```
376
+
377
+ Touchpoints: `interview`, `milestone-gate`, `reduction`, `L0`, `delegation` (the Owner hands
378
+ the remaining touchpoints to you: answer them by proxy from then on, except step 4 of the
379
+ milestone gate while its list holds a defect), `unplanned`. A run that went as planned has
380
+ no `unplanned` line; report the count at every milestone gate. An
381
+ answer the assistant gave for the Owner (`proxy: yes`) is not Owner validation; say so
382
+ wherever it is reported.
383
+
384
+ ## Rulings
385
+
386
+ Every decision made without asking is one line in `.ultra/rulings.md`:
387
+
388
+ ```
389
+ - YYYY-MM-DD Lx 裁决:<decision> — 因为 <reason> — 如果判断错了,代价是 <cost>
390
+ ```
391
+
392
+ The plan gate reads it tolerantly: dashes, spaces and colons may differ and `如果判断错了` may
393
+ be left out, but a line without its date, layer, decision, reason or cost is refused.
394
+
395
+ The Owner reads this log at milestone gates instead of being asked along the way.
File without changes
@@ -1,135 +0,0 @@
1
- # Task {id}: {title}
2
-
3
- ## Context
4
-
5
- **What**: [what to build or change]
6
-
7
- **Why**: [business value, linked to a Persona and Scenario in specs/product.md]
8
-
9
- **Constraints**:
10
- - [constraint 1]
11
- - [constraint 2]
12
-
13
- ## Implementation
14
-
15
- **Layers touched**: [entry point / use case / domain / persistence]
16
-
17
- **Pattern**: [existing code to follow]
18
-
19
- **Tech Notes**: [framework or library specifics]
20
-
21
- **Earliest observable slice**: [the first real consumer -> real data path ->
22
- owner-visible observation, or `not applicable` with the concrete reason]
23
-
24
- **Fresh-session recovery**: [repository root and HEAD -> active Change -> matching
25
- ledger row -> this context and Resume Note -> exact safe resume command or path]
26
-
27
- ## Planned Path Inventory
28
-
29
- `MODIFY`:
30
-
31
- - `path/to/existing.ts`
32
-
33
- `CREATE`:
34
-
35
- - `path/to/file.ts`
36
-
37
- Any later addition, removal, or rename in this inventory or the Public Seams below is
38
- plan-critical and requires a rebuilt Execution Packet plus owner reapproval before
39
- implementation continues.
40
-
41
- ## Public Seams
42
-
43
- - `[entry point, schema, file contract, or other externally observable seam]`
44
-
45
- ## Narrow Verification
46
-
47
- - `exact command for the smallest relevant contract suite`
48
- - `[inspection, owner record, or external observation required by the typed criteria]`
49
-
50
- ## Acceptance Criteria
51
-
52
- <!-- The typed definition of done. Readers inject this section into agent context; keep
53
- every criterion observable and keep noise out. The ledger is the sole Status source. -->
54
-
55
- **Change Acceptance IDs**: [`AC-1`, `AC-3`, or `none` for task-local-only work]
56
-
57
- | ID | Criterion | Verification type | Required evidence |
58
- |---|---|---|---|
59
- | A-01 | [observable criterion] | `command` | exact command, cwd, exit code, raw evidence ref, and freshness identity |
60
- | A-02 | [observable criterion] | `inspection` | source/path, observed fact, and revision |
61
- | A-03 | [owner decision when genuinely required] | `owner-judgment` | durable owner statement or explicit disposition |
62
- | A-04 | [external fact when genuinely required] | `external-observation` | provider, run id, timestamp, raw evidence ref, and observation |
63
-
64
- ## Definition of Drift
65
-
66
- <!-- What would count as drifting from this task's intent? Catches scope creep early. -->
67
-
68
- - [e.g. "splitting this into two services" — out of scope unless the owner agrees]
69
- - [e.g. "adding a caching layer" — out of scope]
70
-
71
- ## Trace
72
-
73
- **Source**: `.ultra/specs/product.md#section-id`
74
-
75
- **First principles**: [`FP-1`, or every accepted principle this task relies on]
76
-
77
- **Serves**: [`NS-1`, or every accepted outcome this task causally advances]
78
-
79
- **Causal contribution**: [one task-local sentence connecting the planned seam to the
80
- listed outcome through the listed principles; reference IDs and do not copy North Star
81
- prose]
82
-
83
- **Hard constraints**: [`HC-1`, `HC-3`, or `none` — the accepted constraints this task
84
- could plausibly violate. Read them before the first edit and again before marking
85
- complete. Crossing one stops the work and goes to the owner, however good the argument.]
86
-
87
- **Decisions**: [relevant `.ultra/decisions/<id>.md` entries, or `none`]
88
-
89
- ## Change Log
90
-
91
- | Date | Classification | Change | Specs updated | Reason |
92
- |------|----------------|--------|---------------|--------|
93
- | {created_date} | — | Initial creation | — | Generated by ultra-plan |
94
-
95
- <!-- Classification is EXPANSION, CORRECTION, or REDUCTION. REDUCTION requires owner approval
96
- before the spec is touched. See PHILOSOPHY C5. -->
97
-
98
- ## Open Questions
99
-
100
- <!-- Question, its consequence, who owns it, and what evidence would resolve it. -->
101
-
102
- - _(none)_
103
-
104
- ## Resume Note
105
-
106
- <!-- Navigational state only: the current checkpoint, the next action a higher
107
- authority has already allowed, unresolved prerequisites, and the cheapest
108
- safe resume command or path. It cannot override current owner authority,
109
- approved scope/budget, task acceptance, or a validated Review verdict, it
110
- cannot promote P2/P3 findings into blockers, and it never requires a fresh
111
- zero-finding review after a current APPROVE. It never carries or re-issues
112
- an execution grant: continuing under a durable work-package grant requires
113
- the consuming Agent to re-verify the recorded grant itself. Overwrite it
114
- whenever work pauses. Say where to pick up, not what was done. When the
115
- pause is owner-facing, the note answers the checkpoint semantics: why,
116
- outcome, accepted boundary, delta, reality, decision needed, next bounded
117
- action, and not-done. -->
118
-
119
- _(not started)_
120
-
121
- ## Completion
122
-
123
- _Not completed._
124
-
125
- ## Task Review
126
-
127
- - Execution Packet state/digest/limitation: `not_run`
128
- - Review session identity and summary digest: `not_run`
129
- - Blocking findings with resolution/disposition/evidence refresh refs: `not_run`
130
- - Retention: retain the current strict review session until both aggregate Test and
131
- Deliver consume it. Premature loss requires a fresh Review and Test; never reconstruct
132
- the old receipt.
133
-
134
- ---
135
- *Generated by ultra-plan*
@@ -1 +0,0 @@
1
-
@@ -1 +0,0 @@
1
-
@@ -1,52 +0,0 @@
1
- # Project North Star
2
-
3
- > **Authority**: `ultra-research` is the first semantic writer. This placeholder is
4
- > owner-readable structure only; it is not an accepted direction, metric, or boundary.
5
- >
6
- > **Adoption**: Init creates this file with status `unresearched` and no semantic IDs.
7
- > Research replaces it only after evidence collection and explicit owner acceptance.
8
-
9
- ## Acceptance and Revision
10
-
11
- - Schema: `north-star-v2`
12
- - Status: `unresearched`
13
- - Revision: `none`
14
- - Owner acceptance source: `none`
15
- - Acceptance time: `not-recorded`
16
- - Supersedes: `none`
17
-
18
- ## Problem Reality
19
-
20
- - Reality: [NEEDS RESEARCH]
21
- - Evidence: [NEEDS RESEARCH]
22
- - Unknowns: [NEEDS RESEARCH]
23
-
24
- ## First-Principle Propositions
25
-
26
- [NEEDS RESEARCH: Research creates stable proposition IDs only after owner acceptance.]
27
-
28
- ## Value Causal Chain
29
-
30
- [NEEDS RESEARCH: map accepted principles through capability and behavior to outcomes.]
31
-
32
- ## North Star Outcomes
33
-
34
- [NEEDS RESEARCH: do not create an outcome ID or metric during Init.]
35
-
36
- ## Hard Constraints
37
-
38
- [NEEDS RESEARCH: do not create a constraint ID during Init.]
39
-
40
- ## Explicit Exclusions
41
-
42
- - [NEEDS RESEARCH]
43
-
44
- ## Uncertainties and Revisit Triggers
45
-
46
- - [NEEDS RESEARCH]
47
-
48
- ## Research Trace
49
-
50
- - Project Brief: `project-brief.md`
51
- - Research runs: none
52
- - Sources and decisions: none
@@ -1,28 +0,0 @@
1
- # Project Brief
2
-
3
- > **Authority**: raw owner intake captured by `ultra-init`. It preserves what the owner
4
- > initially asked for and the broad outline needed to begin research. It is not an
5
- > evidence-backed product baseline.
6
- >
7
- > **Lifecycle**: `ultra-research` reads this seed and promotes accepted conclusions into
8
- > the North Star, specifications, domain language, or decisions. It does not rewrite the
9
- > brief to make later conclusions look inevitable.
10
-
11
- ## One-line
12
-
13
- [NEEDS CLARIFICATION]
14
-
15
- ## Initial Outline
16
-
17
- - What it is: [NEEDS CLARIFICATION]
18
- - Broadly for whom or what: [NEEDS CLARIFICATION]
19
- - Intended result: [NEEDS CLARIFICATION]
20
- - Broad boundary: [NEEDS CLARIFICATION]
21
-
22
- ## Explicit Inputs
23
-
24
- - [NEEDS CLARIFICATION]
25
-
26
- ## Open Questions for Research
27
-
28
- - [NEEDS CLARIFICATION]
@@ -1 +0,0 @@
1
-