ultra-builder-pro-cli 5.0.1 → 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 +103 -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 +13 -32
  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 -316
  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
@@ -1,576 +0,0 @@
1
- #!/usr/bin/env node
2
- 'use strict';
3
-
4
- const crypto = require('node:crypto');
5
- const fs = require('node:fs');
6
- const path = require('node:path');
7
- const { execFileSync } = require('node:child_process');
8
-
9
- const MAX_SNAPSHOT_BYTES = 8 * 1024 * 1024;
10
- const SNAPSHOT_CHUNK_BYTES = 64 * 1024;
11
- const MAX_OBSERVATION_FILES = 256;
12
- const MAX_OBSERVATION_BYTES = 16 * 1024 * 1024;
13
- const GIT_TIMEOUT_MS = 5000;
14
- const GIT_MAX_OUTPUT_BYTES = 64 * 1024 * 1024;
15
- const PRODUCT_PATHSPEC = [
16
- '--', '.',
17
- ':(exclude).ultra/test-report.json',
18
- ':(exclude).ultra/evidence/**',
19
- ':(exclude).ultra/reviews/**',
20
- ':(exclude).ultra/.runtime/**',
21
- ':(exclude).ultra/progress/**',
22
- ':(exclude).ultra/changes/active/**',
23
- ':(exclude).ultra/changes/archive/**',
24
- ':(exclude).ultra/changes/abandoned/**',
25
- ];
26
-
27
- function git(cwd, args, encoding = 'utf8') {
28
- try {
29
- return execFileSync('git', args, {
30
- cwd,
31
- encoding,
32
- maxBuffer: GIT_MAX_OUTPUT_BYTES,
33
- stdio: ['ignore', 'pipe', 'pipe'],
34
- timeout: GIT_TIMEOUT_MS,
35
- });
36
- } catch (error) {
37
- const operation = args.slice(0, 2).join(' ');
38
- if (error && (error.code === 'ETIMEDOUT' || (error.killed && error.signal))) {
39
- throw new Error(
40
- `ULTRA_SNAPSHOT_GIT_TIMEOUT: Git ${JSON.stringify(operation)} exceeded the `
41
- + `${GIT_TIMEOUT_MS}ms physical observation limit. Restore a responsive repository `
42
- + 'and Git process, then retry worktree_digest.',
43
- );
44
- }
45
- if (error && error.code === 'ENOBUFS') {
46
- throw new Error(
47
- `ULTRA_SNAPSHOT_GIT_OUTPUT_LIMIT: Git ${JSON.stringify(operation)} exceeded the `
48
- + `${GIT_MAX_OUTPUT_BYTES}-byte output limit. Reduce or split the physical product `
49
- + 'observation, then retry worktree_digest.',
50
- );
51
- }
52
- const stderr = error && error.stderr
53
- ? Buffer.from(error.stderr).toString('utf8').trim().split('\n')[0]
54
- : 'Git returned an unknown failure';
55
- throw new Error(
56
- `ULTRA_SNAPSHOT_GIT_FAILED: Git ${JSON.stringify(operation)} failed (${stderr}). `
57
- + 'Repair the repository and Git operation, then retry worktree_digest.',
58
- );
59
- }
60
- }
61
-
62
- function optionsFromArgs(argv) {
63
- const options = { project: process.cwd(), changeId: null };
64
- for (let index = 0; index < argv.length; index += 2) {
65
- const flag = argv[index];
66
- const value = argv[index + 1];
67
- if (!value) throw new Error('usage: worktree_digest.cjs [--project <repository-root>] [--change-id <id>]');
68
- if (flag === '--project') options.project = path.resolve(value);
69
- else if (flag === '--change-id') options.changeId = value;
70
- else throw new Error('usage: worktree_digest.cjs [--project <repository-root>] [--change-id <id>]');
71
- }
72
- if (options.changeId && !/^[A-Za-z0-9][A-Za-z0-9._-]*$/.test(options.changeId)) {
73
- throw new Error(`invalid Change id: ${options.changeId}`);
74
- }
75
- return options;
76
- }
77
-
78
- function snapshotError(code, relative, observation) {
79
- return new Error(
80
- `${code}: cannot snapshot ${JSON.stringify(relative)}: ${observation}. `
81
- + 'Restore the repository path as an ordinary regular non-symlink file within the '
82
- + '8 MiB limit, then retry worktree_digest.',
83
- );
84
- }
85
-
86
- function repositoryPath(root, relative) {
87
- if (typeof relative !== 'string'
88
- || relative.length === 0
89
- || relative.includes('\0')
90
- || path.posix.isAbsolute(relative)
91
- || path.win32.isAbsolute(relative)) {
92
- throw snapshotError('ULTRA_SNAPSHOT_PATH_ESCAPE', String(relative), 'path is not repository-relative');
93
- }
94
- const parts = relative.split('/');
95
- if (parts.some((part) => part === '' || part === '.' || part === '..')
96
- || (path.sep === '\\' && parts.some((part) => part.includes('\\')))) {
97
- throw snapshotError('ULTRA_SNAPSHOT_PATH_ESCAPE', relative, 'path escapes its repository root');
98
- }
99
- const absolute = path.join(root, ...parts);
100
- const resolvedRelative = path.relative(root, absolute);
101
- if (resolvedRelative === ''
102
- || resolvedRelative === '..'
103
- || resolvedRelative.startsWith(`..${path.sep}`)
104
- || path.isAbsolute(resolvedRelative)) {
105
- throw snapshotError('ULTRA_SNAPSHOT_PATH_ESCAPE', relative, 'path escapes its repository root');
106
- }
107
- return { absolute, parts };
108
- }
109
-
110
- function lstatSnapshot(absolute, relative) {
111
- try {
112
- return fs.lstatSync(absolute, { bigint: true });
113
- } catch (error) {
114
- if (error && (error.code === 'ENOENT' || error.code === 'ENOTDIR')) {
115
- throw snapshotError('ULTRA_SNAPSHOT_MISSING', relative, 'path disappeared during observation');
116
- }
117
- throw snapshotError(
118
- 'ULTRA_SNAPSHOT_UNREADABLE',
119
- relative,
120
- `lstat failed with ${error && error.code ? error.code : 'an unknown error'}`,
121
- );
122
- }
123
- }
124
-
125
- function sameNode(left, right) {
126
- return left.dev === right.dev
127
- && left.ino === right.ino
128
- && left.mode === right.mode;
129
- }
130
-
131
- function sameFileVersion(left, right) {
132
- return sameNode(left, right)
133
- && left.size === right.size
134
- && left.mtimeNs === right.mtimeNs
135
- && left.ctimeNs === right.ctimeNs;
136
- }
137
-
138
- function walkSnapshotPath(root, relative) {
139
- const resolved = repositoryPath(root, relative);
140
- const parents = [];
141
- let current = root;
142
- const rootStat = lstatSnapshot(root, '.');
143
- if (rootStat.isSymbolicLink()) {
144
- throw snapshotError('ULTRA_SNAPSHOT_SYMLINK', relative, 'repository root is a symlink');
145
- }
146
- if (!rootStat.isDirectory()) {
147
- throw snapshotError('ULTRA_SNAPSHOT_NOT_DIRECTORY', relative, 'repository root is not a directory');
148
- }
149
- parents.push({ absolute: root, relative: '.', stat: rootStat });
150
-
151
- for (const part of resolved.parts.slice(0, -1)) {
152
- current = path.join(current, part);
153
- const observedRelative = path.relative(root, current) || '.';
154
- const stat = lstatSnapshot(current, observedRelative);
155
- if (stat.isSymbolicLink()) {
156
- throw snapshotError(
157
- 'ULTRA_SNAPSHOT_SYMLINK',
158
- relative,
159
- `parent ${JSON.stringify(observedRelative)} is a symlink`,
160
- );
161
- }
162
- if (!stat.isDirectory()) {
163
- throw snapshotError(
164
- 'ULTRA_SNAPSHOT_NOT_DIRECTORY',
165
- relative,
166
- `parent ${JSON.stringify(observedRelative)} is not a directory`,
167
- );
168
- }
169
- parents.push({ absolute: current, relative: observedRelative, stat });
170
- }
171
-
172
- const finalStat = lstatSnapshot(resolved.absolute, relative);
173
- if (finalStat.isSymbolicLink()) {
174
- throw snapshotError('ULTRA_SNAPSHOT_SYMLINK', relative, 'final entry is a symlink');
175
- }
176
- if (!finalStat.isFile()) {
177
- throw snapshotError('ULTRA_SNAPSHOT_NOT_REGULAR', relative, 'final entry is not a regular file');
178
- }
179
- if (finalStat.size > BigInt(MAX_SNAPSHOT_BYTES)) {
180
- throw snapshotError(
181
- 'ULTRA_SNAPSHOT_TOO_LARGE',
182
- relative,
183
- `regular file exceeds the ${MAX_SNAPSHOT_BYTES}-byte physical ceiling`,
184
- );
185
- }
186
- return {
187
- absolute: resolved.absolute,
188
- final: { absolute: resolved.absolute, relative, stat: finalStat },
189
- parents,
190
- };
191
- }
192
-
193
- function verifyFreshRewalk(root, relative, initial, phase) {
194
- let current;
195
- try {
196
- current = walkSnapshotPath(root, relative);
197
- } catch (error) {
198
- throw snapshotError(
199
- 'ULTRA_SNAPSHOT_REPLACED',
200
- relative,
201
- `${phase} rewalk no longer resolves the initial identities (${error.message})`,
202
- );
203
- }
204
- const parentsStable = current.parents.length === initial.parents.length
205
- && current.parents.every((entry, index) => sameNode(entry.stat, initial.parents[index].stat));
206
- if (!parentsStable || !sameFileVersion(current.final.stat, initial.final.stat)) {
207
- throw snapshotError(
208
- 'ULTRA_SNAPSHOT_REPLACED',
209
- relative,
210
- `${phase} rewalk observed a replaced root, parent, or final identity`,
211
- );
212
- }
213
- }
214
-
215
- function openSnapshotFile(absolute, relative) {
216
- const { O_NOFOLLOW, O_NONBLOCK, O_RDONLY } = fs.constants;
217
- if (![O_NOFOLLOW, O_NONBLOCK, O_RDONLY].every(Number.isInteger)) {
218
- throw snapshotError(
219
- 'ULTRA_SNAPSHOT_UNSUPPORTED',
220
- relative,
221
- 'this host cannot enforce O_NONBLOCK and O_NOFOLLOW',
222
- );
223
- }
224
- try {
225
- return fs.openSync(absolute, O_RDONLY | O_NONBLOCK | O_NOFOLLOW);
226
- } catch (error) {
227
- const observed = error && error.code ? error.code : 'an unknown error';
228
- if (['ELOOP', 'ENOENT', 'ENOTDIR', 'ENXIO'].includes(observed)) {
229
- throw snapshotError(
230
- 'ULTRA_SNAPSHOT_REPLACED',
231
- relative,
232
- `no-follow nonblocking open observed ${observed}`,
233
- );
234
- }
235
- throw snapshotError(
236
- 'ULTRA_SNAPSHOT_UNREADABLE',
237
- relative,
238
- `no-follow nonblocking open failed with ${observed}`,
239
- );
240
- }
241
- }
242
-
243
- function streamStableRepositoryFile(root, relative, consume, budget = null) {
244
- const initial = walkSnapshotPath(root, relative);
245
- if (budget) budget.reserve(relative, initial.final.stat.size);
246
- let descriptor;
247
- try {
248
- descriptor = openSnapshotFile(initial.absolute, relative);
249
- const opened = fs.fstatSync(descriptor, { bigint: true });
250
- if (!opened.isFile() || !sameFileVersion(opened, initial.final.stat)) {
251
- throw snapshotError(
252
- 'ULTRA_SNAPSHOT_REPLACED',
253
- relative,
254
- 'opened descriptor does not match the initial regular-file identity',
255
- );
256
- }
257
- verifyFreshRewalk(root, relative, initial, 'pre-read');
258
-
259
- const buffer = Buffer.allocUnsafe(SNAPSHOT_CHUNK_BYTES);
260
- let offset = 0;
261
- for (;;) {
262
- const remaining = MAX_SNAPSHOT_BYTES - offset;
263
- const requested = Math.min(buffer.length, remaining + 1);
264
- let bytesRead;
265
- try {
266
- bytesRead = fs.readSync(descriptor, buffer, 0, requested, offset);
267
- } catch (error) {
268
- throw snapshotError(
269
- 'ULTRA_SNAPSHOT_UNREADABLE',
270
- relative,
271
- `stream read failed with ${error && error.code ? error.code : 'an unknown error'}`,
272
- );
273
- }
274
- if (bytesRead === 0) break;
275
- offset += bytesRead;
276
- if (offset > MAX_SNAPSHOT_BYTES) {
277
- throw snapshotError(
278
- 'ULTRA_SNAPSHOT_TOO_LARGE',
279
- relative,
280
- `stream exceeded the ${MAX_SNAPSHOT_BYTES}-byte physical ceiling`,
281
- );
282
- }
283
- consume(buffer.subarray(0, bytesRead));
284
- }
285
-
286
- const finished = fs.fstatSync(descriptor, { bigint: true });
287
- if (!finished.isFile()
288
- || !sameFileVersion(finished, initial.final.stat)
289
- || BigInt(offset) !== finished.size) {
290
- throw snapshotError(
291
- 'ULTRA_SNAPSHOT_REPLACED',
292
- relative,
293
- 'file identity or byte extent changed during the streamed read',
294
- );
295
- }
296
- verifyFreshRewalk(root, relative, initial, 'post-read');
297
- return initial;
298
- } finally {
299
- if (descriptor !== undefined) fs.closeSync(descriptor);
300
- }
301
- }
302
-
303
- function resourceError(relative, nextFiles, nextBytes) {
304
- return new Error(
305
- `ULTRA_SNAPSHOT_RESOURCE_LIMIT: cannot snapshot ${JSON.stringify(relative)}: aggregate `
306
- + `product observation would reach ${nextFiles} files and ${nextBytes} bytes, above the `
307
- + `${MAX_OBSERVATION_FILES}-file or ${MAX_OBSERVATION_BYTES}-byte physical ceiling. `
308
- + 'Reduce or split the included physical product observation, then retry worktree_digest; '
309
- + 'this ceiling is not a semantic quality verdict.',
310
- );
311
- }
312
-
313
- function observationBudget() {
314
- let files = 0;
315
- let bytes = 0;
316
- return {
317
- reserve(relative, size) {
318
- const nextFiles = files + 1;
319
- const nextBytes = bytes + Number(size);
320
- if (nextFiles > MAX_OBSERVATION_FILES || nextBytes > MAX_OBSERVATION_BYTES) {
321
- throw resourceError(relative, nextFiles, nextBytes);
322
- }
323
- files = nextFiles;
324
- bytes = nextBytes;
325
- },
326
- };
327
- }
328
-
329
- function candidateExists(file) {
330
- try {
331
- fs.lstatSync(file);
332
- return true;
333
- } catch (error) {
334
- if (error && (error.code === 'ENOENT' || error.code === 'ENOTDIR')) return false;
335
- throw error;
336
- }
337
- }
338
-
339
- function intentSnapshot(root, changeId) {
340
- if (!changeId) return { change_id: null, intent_digest: null };
341
- const matches = ['active', 'archive', 'abandoned']
342
- .map((state) => path.join(root, '.ultra', 'changes', state, changeId, 'intent.md'))
343
- .filter(candidateExists);
344
- if (matches.length !== 1) {
345
- throw new Error(`expected exactly one intent.md for Change ${changeId}; found ${matches.length}`);
346
- }
347
- const intentHash = crypto.createHash('sha256');
348
- const relative = path.relative(root, matches[0]).split(path.sep).join('/');
349
- const snapshot = streamStableRepositoryFile(root, relative, (chunk) => intentHash.update(chunk));
350
- return {
351
- change_id: changeId,
352
- intent_digest: intentHash.digest('hex'),
353
- relative,
354
- identity: snapshotIdentity(snapshot),
355
- };
356
- }
357
-
358
- function snapshotIdentity(snapshot) {
359
- const statIdentity = (stat) => [
360
- stat.dev, stat.ino, stat.mode, stat.size, stat.mtimeNs, stat.ctimeNs,
361
- ].map((value) => value.toString()).join(':');
362
- return [
363
- ...snapshot.parents.map((entry) => statIdentity(entry.stat)),
364
- statIdentity(snapshot.final.stat),
365
- ].join('|');
366
- }
367
-
368
- function excluded(file) {
369
- return file === '.ultra/test-report.json'
370
- || /^\.ultra\/evidence(?:\/|$)/.test(file)
371
- || /^\.ultra\/(?:reviews|\.runtime|progress)(?:\/|$)/.test(file)
372
- || /^\.ultra\/changes\/(?:active|archive|abandoned)(?:\/|$)/.test(file);
373
- }
374
-
375
- function changedDuringObservation(observation) {
376
- return new Error(
377
- `ULTRA_SNAPSHOT_CHANGED_DURING_OBSERVATION: ${observation}. `
378
- + 'Finish or restore the concurrent repository change, then retry worktree_digest once; '
379
- + 'no digest was accepted.',
380
- );
381
- }
382
-
383
- function splitNul(buffer, label) {
384
- if (buffer.length === 0) return [];
385
- if (buffer[buffer.length - 1] !== 0) {
386
- throw new Error(
387
- `ULTRA_SNAPSHOT_GIT_FAILED: ${label} was not NUL terminated. `
388
- + 'Repair the Git observation, then retry worktree_digest.',
389
- );
390
- }
391
- const values = [];
392
- let start = 0;
393
- for (let index = 0; index < buffer.length; index += 1) {
394
- if (buffer[index] !== 0) continue;
395
- values.push(buffer.subarray(start, index));
396
- start = index + 1;
397
- }
398
- return values;
399
- }
400
-
401
- function decodeGitPath(bytes, label) {
402
- const relative = bytes.toString('utf8');
403
- if (!Buffer.from(relative, 'utf8').equals(bytes)) {
404
- throw snapshotError(
405
- 'ULTRA_SNAPSHOT_PATH_ENCODING',
406
- label,
407
- 'Git returned a path that is not valid UTF-8',
408
- );
409
- }
410
- return relative;
411
- }
412
-
413
- function trackedManifest(root, head) {
414
- const raw = git(root, [
415
- 'diff', '--raw', '-z', '--no-renames', '--abbrev=64', head, ...PRODUCT_PATHSPEC,
416
- ], 'buffer');
417
- const fields = splitNul(raw, 'tracked manifest');
418
- if (fields.length % 2 !== 0) {
419
- throw new Error(
420
- 'ULTRA_SNAPSHOT_GIT_FAILED: tracked manifest has an incomplete raw record. '
421
- + 'Repair the Git observation, then retry worktree_digest.',
422
- );
423
- }
424
- const files = [];
425
- for (let index = 0; index < fields.length; index += 2) {
426
- const header = fields[index].toString('ascii');
427
- const match = header.match(
428
- /^:([0-7]{6}) ([0-7]{6}) ([0-9a-f]+) ([0-9a-f]+) ([A-Z])(?:[0-9]+)?$/u,
429
- );
430
- if (!match) {
431
- throw new Error(
432
- `ULTRA_SNAPSHOT_GIT_FAILED: tracked manifest record ${JSON.stringify(header)} is invalid. `
433
- + 'Repair the Git observation, then retry worktree_digest.',
434
- );
435
- }
436
- const relative = decodeGitPath(fields[index + 1], 'tracked manifest path');
437
- files.push({
438
- path: relative,
439
- status: match[5],
440
- present: match[5] !== 'D',
441
- old_mode: match[1],
442
- new_mode: match[2],
443
- });
444
- }
445
- return { raw, files };
446
- }
447
-
448
- function untrackedManifest(root) {
449
- const raw = git(root, ['ls-files', '--others', '--exclude-standard', '-z'], 'buffer');
450
- const entries = splitNul(raw, 'untracked manifest')
451
- .map((bytes) => ({ bytes, path: decodeGitPath(bytes, 'untracked manifest path') }))
452
- .filter((entry) => !excluded(entry.path))
453
- .sort((left, right) => Buffer.compare(left.bytes, right.bytes));
454
- return {
455
- files: entries.map((entry) => entry.path),
456
- raw: Buffer.concat(entries.flatMap((entry) => [entry.bytes, Buffer.from([0])])),
457
- };
458
- }
459
-
460
- function exactDiff(root, head) {
461
- return git(root, [
462
- 'diff', '--binary', '--no-ext-diff', head, ...PRODUCT_PATHSPEC,
463
- ], 'buffer');
464
- }
465
-
466
- function verifyObservedPaths(root, records) {
467
- for (const record of records) {
468
- try {
469
- verifyFreshRewalk(root, record.relative, record.snapshot, 'final');
470
- } catch (error) {
471
- throw changedDuringObservation(
472
- `included path ${JSON.stringify(record.relative)} changed after its stable read (${error.message})`,
473
- );
474
- }
475
- }
476
- }
477
-
478
- function sameIntent(left, right) {
479
- return left.change_id === right.change_id
480
- && left.intent_digest === right.intent_digest
481
- && left.relative === right.relative
482
- && left.identity === right.identity;
483
- }
484
-
485
- function verifyExpectedObservation(root, expected) {
486
- const observedHead = git(root, ['rev-parse', 'HEAD']).trim();
487
- const observedTracked = trackedManifest(root, expected.head);
488
- const observedUntracked = untrackedManifest(root);
489
- const observedDiff = exactDiff(root, expected.head);
490
- if (observedHead !== expected.head
491
- || !observedTracked.raw.equals(expected.tracked.raw)
492
- || !observedUntracked.raw.equals(expected.untracked.raw)
493
- || !observedDiff.equals(expected.diff)) {
494
- throw changedDuringObservation(
495
- 'HEAD, the exact tracked manifest or diff, or the untracked manifest changed during capture',
496
- );
497
- }
498
-
499
- const observedIntent = intentSnapshot(root, expected.intent.change_id);
500
- if (!sameIntent(expected.intent, observedIntent)) {
501
- throw changedDuringObservation('the Change intent identity or bytes changed during capture');
502
- }
503
- verifyObservedPaths(root, expected.records);
504
- }
505
-
506
- function verifyClosingObservation(root, expected) {
507
- verifyExpectedObservation(root, expected);
508
- verifyExpectedObservation(root, expected);
509
- }
510
-
511
- function main(options) {
512
- const root = fs.realpathSync(git(options.project, ['rev-parse', '--show-toplevel']).trim());
513
- const head = git(root, ['rev-parse', 'HEAD']).trim();
514
- const tracked = trackedManifest(root, head);
515
- const untracked = untrackedManifest(root);
516
- const intent = intentSnapshot(root, options.changeId);
517
- const budget = observationBudget();
518
- const records = [];
519
-
520
- for (const file of tracked.files) {
521
- if (!file.present) {
522
- budget.reserve(file.path, 0n);
523
- continue;
524
- }
525
- const snapshot = streamStableRepositoryFile(root, file.path, () => {}, budget);
526
- records.push({ relative: file.path, snapshot });
527
- }
528
-
529
- const untrackedBytes = [];
530
- for (const file of untracked.files) {
531
- const chunks = [];
532
- const snapshot = streamStableRepositoryFile(
533
- root,
534
- file,
535
- (chunk) => chunks.push(Buffer.from(chunk)),
536
- budget,
537
- );
538
- records.push({ relative: file, snapshot });
539
- untrackedBytes.push(chunks);
540
- }
541
-
542
- const diff = exactDiff(root, head);
543
- const closingObservation = { diff, head, intent, records, tracked, untracked };
544
- verifyClosingObservation(root, closingObservation);
545
-
546
- const hash = crypto.createHash('sha256');
547
- hash.update('ultra-worktree-digest-v1\0').update(head).update('\0').update(diff);
548
- for (let index = 0; index < untracked.files.length; index += 1) {
549
- hash.update(untracked.files[index]).update('\0');
550
- for (const chunk of untrackedBytes[index]) hash.update(chunk);
551
- hash.update('\0');
552
- }
553
- return {
554
- $schema: 'ultra-worktree-digest-v1',
555
- change_id: intent.change_id,
556
- intent_digest: intent.intent_digest,
557
- head,
558
- dirty: diff.length > 0 || untracked.files.length > 0,
559
- diff_digest: hash.digest('hex'),
560
- untracked_files: untracked.files,
561
- };
562
- }
563
-
564
- if (require.main === module) {
565
- try {
566
- process.stdout.write(`${JSON.stringify(main(optionsFromArgs(process.argv.slice(2))), null, 2)}\n`);
567
- } catch (error) {
568
- process.stderr.write(`${error.message}\n`);
569
- process.exitCode = 1;
570
- }
571
- }
572
-
573
- // The product-subject pathspec and the stable file-snapshot primitive are the
574
- // single bounded mechanical definitions shared with the primary-transfer
575
- // validator, so receipt reads and digest subject bytes can never drift.
576
- module.exports = { PRODUCT_PATHSPEC, streamStableRepositoryFile };
@@ -1,56 +0,0 @@
1
- ---
2
- name: ultra-think
3
- description: Stress-test one consequential product, architecture, recovery, or scope decision and preserve the accepted result when it must outlive the session. Use when another skill has one evidence-backed trade-off whose answer could materially change accepted work.
4
- ---
5
-
6
- # Turn one consequential uncertainty into an evidence-backed decision
7
-
8
- Thinking sharpens one consequential decision; it does not map a research frontier or
9
- perform the implementation that follows.
10
- Persist only decisions that are hard to reverse, look surprising without context, and
11
- arose from a real trade-off. All three criteria must hold.
12
-
13
- ## Before you start
14
-
15
- 1. Resolve at most one active `change_id`, read `.ultra/tasks.json`, and if the decision
16
- is task-scoped read the matching current task's `context_file` and `## Resume Note`.
17
- 2. Read `CONTEXT.md`, relevant `.ultra/decisions/`, the active Change and its evidence.
18
- 3. State the one decision and the assumptions capable of changing its answer.
19
-
20
- ## Definition of done
21
-
22
- - Claims are labelled Fact, Inference or Speculation and cite their evidence.
23
- - The leading answer survived all four adversarial checks below.
24
- - The conclusion includes Confidence %, Key Assumptions and What would change my mind.
25
- - A qualifying durable decision is written once; a local reversible judgment is not.
26
-
27
- ## Run the adversarial protocol
28
-
29
- 1. **Steel Man**: build the strongest case for the option you expect to reject.
30
- 2. **Pre-Mortem**: assume the choice failed six months later and name the three most
31
- plausible causes.
32
- 3. **Sensitivity**: identify the assumption whose failure would reverse the answer.
33
- 4. **Second-Order**: describe the new constraints or failure modes created six to
34
- twelve months later.
35
-
36
- Give the owner one recommendation with the decisive evidence and what changes under
37
- each viable answer. Reuse an answer already explicit in the request.
38
-
39
- ## Write durable decisions
40
-
41
- Use `.ultra/decisions/<id>.md`: question, status, options and real trade-offs, accepted
42
- decision, owner, date, evidence, consequences, What would change my mind, and
43
- `supersedes` when applicable. An accepted file is append-only history: overturn it by
44
- writing a new decision that supersedes it.
45
-
46
- ## When the owner decides
47
-
48
- Only the owner accepts a durable decision or a REDUCTION. Reversible implementation
49
- details stay with the model. If the host cannot ask, keep `status: open`, record the
50
- missing answer and stop at that safe point.
51
-
52
- ## References
53
-
54
- - `references/autonomy-boundary.md` — read before changing accepted authority.
55
- - `references/interaction-boundary.md` — read when the host-facing decision needs one
56
- carefully framed question.
@@ -1,48 +0,0 @@
1
- # The autonomy boundary and the specification-change verdict
2
-
3
- Read this when an action is about to cross from "decide freely" into "surface to
4
- the owner". It is the operational form of PHILOSOPHY C5, Bounded Autonomy; the
5
- full constitution lives in the package's `docs/PHILOSOPHY.md`.
6
-
7
- ## Inside the boundary — decide and proceed
8
-
9
- Libraries, naming, file layout, internal abstractions, decomposition strategy,
10
- evidence interpretation, prioritization, final expression.
11
-
12
- ## Crossing the boundary — surface it
13
-
14
- Weakening a test assertion, editing the specification to match the
15
- implementation, shipping a feature flag that defaults off, replacing real
16
- persistence with an in-memory stand-in, reducing scope, and any external or
17
- irreversible effect.
18
-
19
- ## Classifying a specification change
20
-
21
- When the implementation and the specification disagree, classify before touching
22
- the specification — and classify by one question that can be checked against the
23
- file, never by intent:
24
-
25
- > **Does every commitment the specification already made still hold after this
26
- > change?**
27
-
28
- | Answer | Classification | Action |
29
- |---|---|---|
30
- | Yes, and it now commits to more | EXPANSION | write it, log it |
31
- | Yes, the commitment is unchanged but stated correctly | CORRECTION | write it, log it |
32
- | **No — at least one prior commitment no longer holds** | **REDUCTION** | **stop and ask the owner** |
33
-
34
- The classification follows from the outcome, never from the reason. A
35
- well-argued rationale does not convert a REDUCTION into a CORRECTION; the
36
- rationale goes into the question put to the owner.
37
-
38
- This matters because it is the exact mechanism by which specifications shrink
39
- silently. "The specification asked for offline mode, but the architecture makes
40
- it unreasonable, so the specification was wrong" reads as a CORRECTION and
41
- removes offline mode without anyone deciding to. Under the question above it is
42
- a REDUCTION, because a commitment stopped holding.
43
-
44
- ## Recording it
45
-
46
- A boundary crossing produces either an owner question, an entry in the active task
47
- context's `## Change Log`, or an accepted `.ultra/decisions/<id>.md` when the decision
48
- outlives that task. Silence and a second drift ledger are not outcomes.