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,15 @@
1
+ ---
2
+ name: ultra-delegate-read-only
3
+ description: Execute one bounded Ultra delegation without file writes, shell commands, web access, MCP tools, or subagents.
4
+ tools:
5
+ - Read
6
+ - Grep
7
+ - Glob
8
+ subagents: []
9
+ ---
10
+
11
+ ${base_prompt}
12
+
13
+ Follow the supplied immutable delegation instruction. Do not modify files, execute
14
+ commands, access external services, dispatch subagents, or widen scope. Return the
15
+ requested strict JSON object as the final response.
@@ -0,0 +1,17 @@
1
+ ---
2
+ name: ultra-delegate-write
3
+ description: Execute one bounded Ultra delegation with file tools only and without shell commands, web access, MCP tools, or subagents.
4
+ tools:
5
+ - Read
6
+ - Write
7
+ - Edit
8
+ - Grep
9
+ - Glob
10
+ subagents: []
11
+ ---
12
+
13
+ ${base_prompt}
14
+
15
+ Follow the supplied immutable delegation instruction. Use file tools only inside the
16
+ declared worktree roots. Do not execute commands, access external services, dispatch
17
+ subagents, or widen scope. Return the requested strict JSON object as the final response.
@@ -120,9 +120,18 @@ const UBP_SENTINEL_FILE = '.ubp-managed';
120
120
  // ownership before deleting (P1 #3).
121
121
  function markManaged(dir, meta = {}) {
122
122
  ensureDir(dir);
123
- writeAtomic(path.join(dir, UBP_SENTINEL_FILE), JSON.stringify({
123
+ let previous = {};
124
+ const sentinel = path.join(dir, UBP_SENTINEL_FILE);
125
+ if (fs.existsSync(sentinel)) {
126
+ try {
127
+ const parsed = JSON.parse(fs.readFileSync(sentinel, 'utf8'));
128
+ if (parsed?.source === 'ubp') previous = parsed;
129
+ } catch {}
130
+ }
131
+ writeAtomic(sentinel, JSON.stringify({
132
+ ...previous,
124
133
  source: 'ubp',
125
- installed_at: new Date().toISOString(),
134
+ installed_at: previous.installed_at || new Date().toISOString(),
126
135
  ...meta,
127
136
  }, null, 2) + '\n');
128
137
  }
@@ -131,6 +140,68 @@ function isManaged(dir) {
131
140
  return fs.existsSync(path.join(dir, UBP_SENTINEL_FILE));
132
141
  }
133
142
 
143
+ function managedMetadata(dir) {
144
+ const sentinel = path.join(dir, UBP_SENTINEL_FILE);
145
+ if (!fs.existsSync(sentinel)) return null;
146
+ const value = JSON.parse(fs.readFileSync(sentinel, 'utf8'));
147
+ if (!value || typeof value !== 'object' || Array.isArray(value)) {
148
+ throw new Error(`invalid managed marker: ${sentinel}`);
149
+ }
150
+ if (value.source === undefined && Object.keys(value).length === 0) return {};
151
+ if (value.source !== 'ubp') throw new Error(`invalid managed marker: ${sentinel}`);
152
+ return value;
153
+ }
154
+
155
+ function normalizeOwnedRelative(value) {
156
+ if (value === '.') return '.';
157
+ if (typeof value !== 'string' || !value || path.isAbsolute(value)) {
158
+ throw new Error(`owned cleanup path must be relative: ${String(value)}`);
159
+ }
160
+ const normalized = path.normalize(value);
161
+ if (
162
+ normalized !== value
163
+ || normalized === '.'
164
+ || normalized === '..'
165
+ || normalized.startsWith(`..${path.sep}`)
166
+ ) {
167
+ throw new Error(`owned cleanup path escapes its root: ${value}`);
168
+ }
169
+ return normalized;
170
+ }
171
+
172
+ function captureAbsent(root, relatives) {
173
+ const absoluteRoot = path.resolve(root);
174
+ return [...new Set(relatives.map(normalizeOwnedRelative))]
175
+ .filter((relative) => !fs.existsSync(relative === '.' ? absoluteRoot : path.join(absoluteRoot, relative)));
176
+ }
177
+
178
+ function pruneCreatedEmpty(root, relatives) {
179
+ const absoluteRoot = path.resolve(root);
180
+ const ordered = [...new Set((relatives || []).map(normalizeOwnedRelative))]
181
+ .sort((a, b) => {
182
+ const depth = (value) => (value === '.' ? 0 : value.split(path.sep).length);
183
+ return depth(b) - depth(a);
184
+ });
185
+ const removed = [];
186
+ for (const relative of ordered) {
187
+ const target = relative === '.' ? absoluteRoot : path.resolve(absoluteRoot, relative);
188
+ if (target !== absoluteRoot && !target.startsWith(`${absoluteRoot}${path.sep}`)) {
189
+ throw new Error(`owned cleanup path escapes its root: ${relative}`);
190
+ }
191
+ if (!fs.existsSync(target)) continue;
192
+ const stat = fs.lstatSync(target);
193
+ if (stat.isSymbolicLink()) continue;
194
+ if (stat.isDirectory() && fs.readdirSync(target).length === 0) {
195
+ fs.rmdirSync(target);
196
+ removed.push(relative);
197
+ } else if (stat.isFile() && stat.size === 0) {
198
+ fs.unlinkSync(target);
199
+ removed.push(relative);
200
+ }
201
+ }
202
+ return removed;
203
+ }
204
+
134
205
  function copyFlatByExt(srcDir, dstDir, ext) {
135
206
  if (!fs.existsSync(srcDir)) return [];
136
207
  const files = fs.readdirSync(srcDir).filter((f) => f.endsWith(ext));
@@ -152,5 +223,8 @@ module.exports = {
152
223
  removeTree,
153
224
  markManaged,
154
225
  isManaged,
226
+ managedMetadata,
227
+ captureAbsent,
228
+ pruneCreatedEmpty,
155
229
  copyFlatByExt,
156
230
  };
@@ -0,0 +1,97 @@
1
+ 'use strict';
2
+
3
+ const path = require('node:path');
4
+
5
+ const KIMI_PROFILE_ROOT = path.join(__dirname, 'delegate-profiles');
6
+
7
+ function opencodePermission(writableRoots) {
8
+ const edit = { '*': 'deny' };
9
+ for (const root of writableRoots) {
10
+ if (root === '.') edit['*'] = 'allow';
11
+ else edit[`${root}/**`] = 'allow';
12
+ }
13
+ return JSON.stringify({
14
+ share: 'disabled',
15
+ permission: {
16
+ '*': 'deny',
17
+ read: 'allow',
18
+ glob: 'allow',
19
+ grep: 'allow',
20
+ list: 'allow',
21
+ lsp: 'allow',
22
+ edit,
23
+ external_directory: 'deny',
24
+ bash: 'deny',
25
+ task: 'deny',
26
+ webfetch: 'deny',
27
+ websearch: 'deny',
28
+ question: 'deny',
29
+ skill: 'deny',
30
+ },
31
+ });
32
+ }
33
+
34
+ const PROFILES = Object.freeze({
35
+ claude: Object.freeze({
36
+ binary: 'claude',
37
+ delegateArgv: (prompt, _cwd, options) => [
38
+ '-p', prompt,
39
+ '--permission-mode', options.readOnly ? 'plan' : 'acceptEdits',
40
+ '--no-session-persistence',
41
+ '--output-format', 'json',
42
+ '--json-schema', options.schemaJson,
43
+ '--tools', options.readOnly ? 'Read,Grep,Glob' : 'Read,Write,Edit,Grep,Glob',
44
+ ],
45
+ }),
46
+ codex: Object.freeze({
47
+ binary: 'codex',
48
+ delegateArgv: (prompt, cwd, options) => [
49
+ 'exec', '--ephemeral', '--ignore-user-config',
50
+ '--sandbox', options.readOnly ? 'read-only' : 'workspace-write',
51
+ '--cd', cwd,
52
+ '--config', 'sandbox_workspace_write.network_access=false',
53
+ '--output-schema', options.schemaFile,
54
+ '--output-last-message', options.hostOutput,
55
+ '--json', prompt,
56
+ ],
57
+ }),
58
+ opencode: Object.freeze({
59
+ binary: 'opencode',
60
+ delegateArgv: (prompt, cwd) => [
61
+ 'run', '--dir', cwd, '--format', 'json', '--auto', prompt,
62
+ ],
63
+ delegateEnv: (options) => ({
64
+ OPENCODE_CONFIG_CONTENT: opencodePermission(options.writableRoots),
65
+ }),
66
+ }),
67
+ kimi: Object.freeze({
68
+ binary: 'kimi',
69
+ delegateArgv: (prompt, _cwd, options) => [
70
+ '-p', prompt,
71
+ '--output-format', 'stream-json',
72
+ '--agent-file', path.join(
73
+ KIMI_PROFILE_ROOT,
74
+ options.readOnly ? 'kimi-read-only.md' : 'kimi-write.md',
75
+ ),
76
+ ],
77
+ }),
78
+ grok: Object.freeze({
79
+ binary: 'grok',
80
+ delegateArgv: (prompt, cwd, options) => [
81
+ '--cwd', cwd, '--single', prompt,
82
+ '--permission-mode', options.readOnly ? 'plan' : 'acceptEdits',
83
+ '--sandbox', options.readOnly ? 'read-only' : 'workspace',
84
+ '--no-memory', '--no-subagents', '--disable-web-search',
85
+ '--json-schema', options.schemaJson,
86
+ '--output-format', 'json',
87
+ ],
88
+ }),
89
+ });
90
+
91
+ function hostProfile(runtime) {
92
+ const profile = PROFILES[runtime];
93
+ if (!profile) throw new Error(`unsupported delegate host: ${runtime}`);
94
+ return profile;
95
+ }
96
+
97
+ module.exports = { PROFILES, hostProfile, opencodePermission };
@@ -0,0 +1,204 @@
1
+ 'use strict';
2
+
3
+ const fs = require('node:fs');
4
+ const path = require('node:path');
5
+ const crypto = require('node:crypto');
6
+
7
+ const {
8
+ copyTree,
9
+ ensureDir,
10
+ isManaged,
11
+ markManaged,
12
+ removeTree,
13
+ writeAtomic,
14
+ } = require('./file-ops.cjs');
15
+ const { parse, serialize } = require('./frontmatter.cjs');
16
+ const provenance = require('./provenance.cjs');
17
+ const {
18
+ MODEL_INVOKED_SKILLS,
19
+ WORKFLOW_HOOK_FILES,
20
+ skillPolicy,
21
+ skillsForRuntime,
22
+ } = require('./runtime-assets.cjs');
23
+
24
+ const PROVENANCE_FILE = 'provenance.json';
25
+
26
+ function titleCase(name) {
27
+ return name.split('-').map((part) => part.charAt(0).toUpperCase() + part.slice(1)).join(' ');
28
+ }
29
+
30
+ function skillFrontmatter(runtime, name, fm) {
31
+ const base = { name, description: String(fm.description || '') };
32
+ const policy = skillPolicy(name);
33
+ if (runtime === 'claude' || runtime === 'grok') {
34
+ return {
35
+ ...base,
36
+ 'user-invocable': policy.userInvocable,
37
+ ...(policy.userInvocable ? { 'disable-model-invocation': true } : {}),
38
+ };
39
+ }
40
+ if (runtime === 'kimi') {
41
+ return {
42
+ ...base,
43
+ ...(policy.userInvocable ? { disableModelInvocation: true } : {}),
44
+ };
45
+ }
46
+ return base;
47
+ }
48
+
49
+ function codexMetadata(name, description) {
50
+ const short = String(description).replace(/\s+/g, ' ').trim().slice(0, 64).replace(/[\s.,;:]+$/, '');
51
+ return [
52
+ 'interface:',
53
+ ` display_name: ${JSON.stringify(titleCase(name))}`,
54
+ ` short_description: ${JSON.stringify(short || titleCase(name))}`,
55
+ ` default_prompt: ${JSON.stringify(`Use $ultra-builder-pro:${name} and follow its workflow.`)}`,
56
+ 'policy:',
57
+ ` allow_implicit_invocation: ${MODEL_INVOKED_SKILLS.includes(name) ? 'true' : 'false'}`,
58
+ '',
59
+ ].join('\n');
60
+ }
61
+
62
+ function copySkills({ runtime, repoRoot, skillRoot }) {
63
+ const installed = [];
64
+ for (const name of skillsForRuntime(runtime)) {
65
+ const source = path.join(repoRoot, 'skills', name);
66
+ if (!fs.existsSync(path.join(source, 'SKILL.md'))) {
67
+ throw new Error(`missing allowlisted ${runtime} skill: ${name}`);
68
+ }
69
+ const target = path.join(skillRoot, name);
70
+ copyTree(source, target, {
71
+ transform(buffer, relative) {
72
+ if (relative !== 'SKILL.md') return buffer;
73
+ const { fm, body } = parse(buffer.toString('utf8'));
74
+ if (!fm) throw new Error(`missing frontmatter in ${name}`);
75
+ return Buffer.from(serialize(skillFrontmatter(runtime, name, fm), body));
76
+ },
77
+ });
78
+ if (name === 'ultra-init') {
79
+ const template = path.join(repoRoot, '.ultra-template');
80
+ if (!fs.existsSync(template)) throw new Error('missing canonical .ultra-template');
81
+ copyTree(template, path.join(target, 'assets', 'project-template'));
82
+ }
83
+ if (runtime === 'codex') {
84
+ const { fm } = parse(fs.readFileSync(path.join(source, 'SKILL.md'), 'utf8'));
85
+ writeAtomic(
86
+ path.join(target, 'agents', 'openai.yaml'),
87
+ codexMetadata(name, fm.description),
88
+ );
89
+ }
90
+ installed.push(name);
91
+ }
92
+ return installed;
93
+ }
94
+
95
+ function copyHooks({ runtime, repoRoot, hookRoot, hooksManifest }) {
96
+ ensureDir(hookRoot);
97
+ for (const name of [...WORKFLOW_HOOK_FILES, '_common.py']) {
98
+ const source = path.join(repoRoot, 'hooks', name);
99
+ if (!fs.existsSync(source)) throw new Error(`missing allowlisted hook: ${name}`);
100
+ fs.copyFileSync(source, path.join(hookRoot, name));
101
+ }
102
+ if (['codex', 'kimi', 'grok'].includes(runtime)) {
103
+ ensureDir(path.join(hookRoot, 'adapters'));
104
+ fs.copyFileSync(
105
+ path.join(repoRoot, 'hooks', 'adapters', `${runtime}.py`),
106
+ path.join(hookRoot, 'adapters', `${runtime}.py`),
107
+ );
108
+ }
109
+ writeAtomic(path.join(hookRoot, 'hooks.json'), `${JSON.stringify(hooksManifest, null, 2)}\n`);
110
+ return [...WORKFLOW_HOOK_FILES];
111
+ }
112
+
113
+ function writePluginProvenance({ adapter, repoRoot, stagingRoot, publishedRoot, contracts = {} }) {
114
+ const source = provenance.packageSource(repoRoot);
115
+ return provenance.writeProvenance({
116
+ file: path.join(stagingRoot, PROVENANCE_FILE),
117
+ adapter,
118
+ ...source,
119
+ roots: { plugin: publishedRoot },
120
+ assetRoots: { plugin: stagingRoot },
121
+ assets: provenance.assetRefsForTree('plugin', stagingRoot, {
122
+ exclude: ['.ubp-managed', PROVENANCE_FILE],
123
+ }),
124
+ contracts,
125
+ });
126
+ }
127
+
128
+ function publishManagedTrees(entries) {
129
+ const transaction = [];
130
+ for (const { source, target, label } of entries) {
131
+ if (fs.existsSync(target) && !isManaged(target)) {
132
+ throw new Error(`refusing to replace unmanaged ${label}: ${target}`);
133
+ }
134
+ ensureDir(path.dirname(target));
135
+ }
136
+ try {
137
+ for (const { source, target } of entries) {
138
+ const backup = `${target}.ubp-backup-${crypto.randomUUID()}`;
139
+ if (fs.existsSync(target)) fs.renameSync(target, backup);
140
+ fs.renameSync(source, target);
141
+ transaction.push({ target, backup });
142
+ }
143
+ for (const { backup } of transaction) {
144
+ if (fs.existsSync(backup)) removeTree(backup);
145
+ }
146
+ } catch (error) {
147
+ for (const { target, backup } of transaction.reverse()) {
148
+ if (fs.existsSync(target)) removeTree(target);
149
+ if (fs.existsSync(backup)) fs.renameSync(backup, target);
150
+ }
151
+ throw error;
152
+ }
153
+ }
154
+
155
+ function inspectPlugin({ adapter, repoRoot, pluginRoot, skillRoot, hookRoot, manifestFile }) {
156
+ const source = provenance.packageSource(repoRoot);
157
+ const report = provenance.inspectProvenance({
158
+ file: path.join(pluginRoot, PROVENANCE_FILE),
159
+ expectedAdapter: adapter,
160
+ expectedPackageVersion: source.packageInfo.version,
161
+ });
162
+ const issue = (code, details = {}) => report.issues.push({ code, ...details });
163
+ if (!fs.existsSync(manifestFile)) issue('PLUGIN_MANIFEST_MISSING', { path: manifestFile });
164
+ for (const name of skillsForRuntime(adapter)) {
165
+ if (!fs.existsSync(path.join(skillRoot, name, 'SKILL.md'))) {
166
+ issue('SKILL_MISSING', { skill: name });
167
+ }
168
+ }
169
+ for (const name of [...WORKFLOW_HOOK_FILES, '_common.py']) {
170
+ if (!fs.existsSync(path.join(hookRoot, name))) issue('HOOK_MISSING', { hook: name });
171
+ }
172
+ for (const retired of ['commands', 'agents', 'runtime', '.mcp.json']) {
173
+ if (fs.existsSync(path.join(pluginRoot, retired))) issue('RETIRED_ASSET_PRESENT', { path: retired });
174
+ }
175
+ report.checks.skill_inventory = {
176
+ status: report.issues.some((entry) => entry.code === 'SKILL_MISSING') ? 'fail' : 'pass',
177
+ };
178
+ report.checks.hook_inventory = {
179
+ status: report.issues.some((entry) => entry.code === 'HOOK_MISSING') ? 'fail' : 'pass',
180
+ };
181
+ report.checks.plugin_manifest = {
182
+ status: fs.existsSync(manifestFile) ? 'pass' : 'fail',
183
+ };
184
+ report.status = report.issues.length === 0 ? 'healthy' : 'degraded';
185
+ return report;
186
+ }
187
+
188
+ function removeManaged(target, label) {
189
+ if (!fs.existsSync(target)) return false;
190
+ if (!isManaged(target)) throw new Error(`refusing to remove unmanaged ${label}: ${target}`);
191
+ removeTree(target);
192
+ return true;
193
+ }
194
+
195
+ module.exports = {
196
+ PROVENANCE_FILE,
197
+ copySkills,
198
+ copyHooks,
199
+ inspectPlugin,
200
+ markManaged,
201
+ publishManagedTrees,
202
+ removeManaged,
203
+ writePluginProvenance,
204
+ };
@@ -1,109 +1,47 @@
1
1
  'use strict';
2
2
 
3
3
  /**
4
- * Canonical Ultra Builder Pro package boundary.
4
+ * Canonical v0.26 package boundary.
5
5
  *
6
- * Adapters must build from this allowlist. A new directory under skills/ or
7
- * hooks/ is not packaged until it is deliberately classified here.
6
+ * Skills carry semantic workflow. Hooks are optional acceleration and safety.
7
+ * There is no prompt projection, worker registry, MCP kernel, or runtime daemon.
8
8
  */
9
9
 
10
- const CORE_PUBLIC_SKILLS = Object.freeze([
10
+ const USER_INVOKED_SKILLS = Object.freeze([
11
11
  'ultra-init',
12
12
  'ultra-research',
13
+ 'ultra-change',
13
14
  'ultra-plan',
14
15
  'ultra-dev',
15
16
  'ultra-test',
16
- 'ultra-review',
17
17
  'ultra-deliver',
18
- 'ultra-status',
19
- 'ultra-think',
20
- 'ultra-change',
21
- 'ultra-doctor',
18
+ 'ultra-delegate',
22
19
  ]);
23
20
 
24
- const PUBLIC_CAPABILITY_MODES = Object.freeze({
25
- 'ultra-init': 'setup',
26
- 'ultra-research': 'workflow',
27
- 'ultra-plan': 'workflow',
28
- 'ultra-dev': 'workflow',
29
- 'ultra-test': 'workflow',
30
- 'ultra-review': 'workflow',
31
- 'ultra-deliver': 'workflow',
32
- 'ultra-status': 'read_only',
33
- 'ultra-think': 'reasoning',
34
- 'ultra-change': 'workflow',
35
- 'ultra-doctor': 'diagnostic',
36
- });
37
-
38
- const PUBLIC_CAPABILITY_GRAPH = Object.freeze(Object.fromEntries(
39
- CORE_PUBLIC_SKILLS.map((name) => [
40
- name,
41
- Object.freeze({
42
- mode: PUBLIC_CAPABILITY_MODES[name],
43
- activation: 'explicit_only',
44
- next_capability_source: 'host_model_from_ultra_context',
45
- recommendation_owner: 'host_model',
46
- selection_owner: 'user',
47
- automatic_invocation: false,
48
- }),
49
- ]),
50
- ));
51
-
52
- const INTERNAL_AGENT_SKILLS = Object.freeze([
53
- 'code-review-expert',
54
- 'security-rules',
55
- 'integration-rules',
56
- 'testing-rules',
21
+ const MODEL_INVOKED_SKILLS = Object.freeze([
22
+ 'ultra-grilling',
23
+ 'ultra-domain-modeling',
24
+ 'ultra-tdd',
25
+ 'ultra-review',
26
+ 'ultra-think',
57
27
  ]);
58
28
 
29
+ const ROUTER_SKILLS = Object.freeze(['ultra-status']);
59
30
  const SUPPORTED_RUNTIMES = Object.freeze(['claude', 'opencode', 'codex', 'kimi', 'grok']);
60
31
 
61
- const COLLAB_SKILLS_BY_RUNTIME = Object.freeze({
62
- claude: Object.freeze(['codex-collab', 'ultra-verify']),
63
- codex: Object.freeze(['cc-collab', 'ultra-verify']),
64
- opencode: Object.freeze(['cc-collab', 'codex-collab', 'ultra-verify']),
65
- kimi: Object.freeze(['cc-collab', 'codex-collab', 'ultra-verify']),
66
- grok: Object.freeze(['cc-collab', 'codex-collab', 'ultra-verify']),
67
- });
68
-
69
- const MCP_DEPENDENT_SKILLS = Object.freeze([
70
- 'ultra-init',
71
- 'ultra-research',
72
- 'ultra-change',
73
- 'ultra-plan',
74
- 'ultra-dev',
75
- 'ultra-test',
76
- 'ultra-review',
77
- 'ultra-deliver',
78
- 'ultra-status',
79
- 'ultra-doctor',
80
- ]);
81
-
82
32
  const WORKFLOW_HOOK_FILES = Object.freeze([
83
- 'active_task_context.py',
84
- 'context_envelope.py',
85
- 'health_check.py',
86
- 'pre_stop_check.py',
87
- 'runtime_paths.py',
88
- 'subagent_tracker.py',
89
- 'workflow_checkpoint.py',
90
- 'workflow_context.py',
91
- 'workflow_resume.py',
92
- ]);
93
-
94
- const RUNTIME_WORKER_FILES = Object.freeze([
95
- 'session-close-journal-worker.cjs',
96
- 'doctor-backup-worker.cjs',
97
- ]);
98
-
99
- const RUNTIME_SUPPORT_FILES = Object.freeze([
100
- 'archive-mutation-worker.py',
33
+ 'session_context.py',
34
+ 'mid_workflow_recall.py',
35
+ 'compact_context.py',
36
+ 'post_edit_guard.py',
37
+ 'block_dangerous_commands.py',
101
38
  ]);
102
39
 
103
40
  function skillsForRuntime(runtime) {
104
- const collab = COLLAB_SKILLS_BY_RUNTIME[runtime];
105
- if (!collab) throw new Error(`unsupported Ultra runtime: ${runtime}`);
106
- return [...CORE_PUBLIC_SKILLS, ...INTERNAL_AGENT_SKILLS, ...collab];
41
+ if (!SUPPORTED_RUNTIMES.includes(runtime)) {
42
+ throw new Error(`unsupported Ultra runtime: ${runtime}`);
43
+ }
44
+ return [...USER_INVOKED_SKILLS, ...MODEL_INVOKED_SKILLS, ...ROUTER_SKILLS];
107
45
  }
108
46
 
109
47
  function isSupportedRuntime(runtime) {
@@ -111,25 +49,22 @@ function isSupportedRuntime(runtime) {
111
49
  }
112
50
 
113
51
  function skillPolicy(name) {
114
- const packaged = SUPPORTED_RUNTIMES.some((runtime) => skillsForRuntime(runtime).includes(name));
115
- if (!packaged) throw new Error(`unknown packaged Ultra skill: ${name}`);
52
+ if (!skillsForRuntime(SUPPORTED_RUNTIMES[0]).includes(name)) {
53
+ throw new Error(`unknown packaged Ultra skill: ${name}`);
54
+ }
55
+ const modelInvoked = MODEL_INVOKED_SKILLS.includes(name);
116
56
  return {
117
- userInvocable: !INTERNAL_AGENT_SKILLS.includes(name),
118
- allowImplicitInvocation: false,
119
- requiresUltraMcp: MCP_DEPENDENT_SKILLS.includes(name),
57
+ userInvocable: !modelInvoked,
58
+ allowImplicitInvocation: modelInvoked,
120
59
  };
121
60
  }
122
61
 
123
62
  module.exports = {
124
- CORE_PUBLIC_SKILLS,
125
- PUBLIC_CAPABILITY_GRAPH,
126
- INTERNAL_AGENT_SKILLS,
63
+ USER_INVOKED_SKILLS,
64
+ MODEL_INVOKED_SKILLS,
65
+ ROUTER_SKILLS,
127
66
  SUPPORTED_RUNTIMES,
128
- COLLAB_SKILLS_BY_RUNTIME,
129
- MCP_DEPENDENT_SKILLS,
130
- RUNTIME_SUPPORT_FILES,
131
67
  WORKFLOW_HOOK_FILES,
132
- RUNTIME_WORKER_FILES,
133
68
  isSupportedRuntime,
134
69
  skillPolicy,
135
70
  skillsForRuntime,