ultra-builder-pro-cli 0.10.0 → 0.12.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 (137) hide show
  1. package/.ultra-template/specs/architecture.md +54 -223
  2. package/.ultra-template/specs/discovery.md +34 -231
  3. package/.ultra-template/specs/product.md +44 -200
  4. package/.ultra-template/tasks/contexts/TEMPLATE.md +36 -0
  5. package/.ultra-template/tasks/tasks.json +6 -0
  6. package/CHANGELOG.md +86 -1
  7. package/README.md +21 -9
  8. package/adapters/_shared/codex-assets.cjs +24 -342
  9. package/adapters/_shared/handbook.cjs +4 -3
  10. package/adapters/_shared/runtime-assets.cjs +24 -0
  11. package/adapters/_shared/tests/handbook.test.cjs +4 -0
  12. package/adapters/_shared/tests/runtime-assets.test.cjs +11 -4
  13. package/adapters/claude.js +28 -5
  14. package/adapters/kimi.js +15 -138
  15. package/adapters/opencode.js +22 -49
  16. package/adapters/tests/claude.test.cjs +22 -8
  17. package/adapters/tests/codex.test.cjs +21 -8
  18. package/adapters/tests/kimi-hook.test.cjs +1 -1
  19. package/adapters/tests/kimi.test.cjs +11 -11
  20. package/adapters/tests/opencode.test.cjs +47 -8
  21. package/agents/code-reviewer.md +24 -85
  22. package/agents/debugger.md +30 -132
  23. package/agents/review-code.md +24 -104
  24. package/agents/review-comments.md +20 -83
  25. package/agents/review-coordinator.md +40 -137
  26. package/agents/review-design.md +21 -118
  27. package/agents/review-errors.md +22 -70
  28. package/agents/review-spec.md +36 -0
  29. package/agents/review-tests.md +20 -76
  30. package/agents/tdd-runner.md +26 -84
  31. package/commands/learn.md +5 -36
  32. package/commands/ultra-change.md +5 -43
  33. package/commands/ultra-deliver.md +4 -46
  34. package/commands/ultra-dev.md +4 -48
  35. package/commands/ultra-doctor.md +4 -30
  36. package/commands/ultra-init.md +5 -47
  37. package/commands/ultra-plan.md +5 -48
  38. package/commands/ultra-research.md +5 -54
  39. package/commands/ultra-status.md +5 -44
  40. package/commands/ultra-test.md +5 -45
  41. package/commands/ultra-think.md +5 -40
  42. package/docs/AGENT-CONTEXT.md +16 -8
  43. package/docs/ARCHITECTURE.md +32 -5
  44. package/docs/PLAN.zh-CN.md +8 -6
  45. package/docs/ROADMAP.md +5 -3
  46. package/docs/RUNTIME-COMPAT-MATRIX.md +8 -5
  47. package/docs/SKILL-AUTHORING.md +75 -0
  48. package/docs/STATE-DB-ACCESS-POLICY.md +17 -11
  49. package/docs/USER-HANDBOOK-CONTRACT.md +8 -5
  50. package/hooks/README.md +4 -3
  51. package/hooks/adapters/codex.py +1 -1
  52. package/hooks/adapters/kimi.py +1 -1
  53. package/hooks/context_spine.py +120 -16
  54. package/hooks/health_check.py +11 -0
  55. package/hooks/pre_stop_check.py +6 -5
  56. package/mcp-server/lib/baseline-workflow.cjs +415 -0
  57. package/mcp-server/lib/baseline-workflow.test.cjs +225 -0
  58. package/mcp-server/lib/change-workflow.cjs +24 -27
  59. package/mcp-server/lib/change-workflow.test.cjs +202 -6
  60. package/mcp-server/lib/context-spine.cjs +74 -9
  61. package/mcp-server/lib/context-spine.test.cjs +15 -0
  62. package/mcp-server/lib/doctor.cjs +14 -0
  63. package/mcp-server/lib/doctor.test.cjs +25 -1
  64. package/mcp-server/lib/init-project.cjs +49 -14
  65. package/mcp-server/lib/provider-refs.cjs +42 -0
  66. package/mcp-server/lib/spec-learning.test.cjs +5 -0
  67. package/mcp-server/lib/state-db.cjs +63 -4
  68. package/mcp-server/lib/state-db.test.cjs +8 -3
  69. package/mcp-server/server.cjs +48 -3
  70. package/mcp-server/tests/init-project.test.cjs +54 -8
  71. package/mcp-server/tests/server-contract.test.cjs +99 -2
  72. package/mcp-server/tests/state-db.test.cjs +11 -2
  73. package/package.json +3 -2
  74. package/skills/cc-collab/SKILL.md +16 -18
  75. package/skills/code-review-expert/SKILL.md +39 -114
  76. package/skills/code-review-expert/references/correctness-reliability.md +30 -0
  77. package/skills/code-review-expert/references/design-boundaries.md +26 -0
  78. package/skills/code-review-expert/references/removal-plan.md +17 -45
  79. package/skills/codex-collab/SKILL.md +23 -28
  80. package/skills/codex-collab/evals/evals.json +18 -23
  81. package/skills/integration-rules/SKILL.md +28 -67
  82. package/skills/learn/SKILL.md +46 -106
  83. package/skills/security-rules/SKILL.md +34 -56
  84. package/skills/testing-rules/SKILL.md +28 -52
  85. package/skills/ultra-change/SKILL.md +68 -114
  86. package/skills/ultra-deliver/SKILL.md +58 -86
  87. package/skills/ultra-dev/SKILL.md +46 -105
  88. package/skills/ultra-doctor/SKILL.md +45 -72
  89. package/skills/ultra-init/SKILL.md +62 -147
  90. package/skills/ultra-init/references/brownfield-adoption.md +65 -0
  91. package/skills/ultra-plan/SKILL.md +56 -89
  92. package/skills/ultra-research/SKILL.md +64 -152
  93. package/skills/ultra-research/references/architecture.md +38 -0
  94. package/skills/ultra-research/references/problem-product.md +39 -0
  95. package/skills/ultra-research/references/quality-delivery.md +34 -0
  96. package/skills/ultra-research/references/synthesis.md +38 -0
  97. package/skills/ultra-research/references/users-scope.md +40 -0
  98. package/skills/ultra-review/SKILL.md +54 -98
  99. package/skills/ultra-review/references/unified-schema.md +76 -101
  100. package/skills/ultra-review/scripts/review_wait.py +242 -77
  101. package/skills/ultra-status/SKILL.md +41 -56
  102. package/skills/ultra-test/SKILL.md +37 -72
  103. package/skills/ultra-think/SKILL.md +43 -102
  104. package/skills/ultra-verify/SKILL.md +44 -84
  105. package/skills/ultra-verify/evals/evals.json +24 -27
  106. package/spec/cli-protocol.md +4 -0
  107. package/spec/mcp-tools.yaml +223 -4
  108. package/spec/schemas/command-manifest.schema.json +7 -25
  109. package/spec/schemas/mcp-tools.schema.json +1 -1
  110. package/spec/schemas/skill-manifest.schema.json +9 -79
  111. package/spec/schemas/state-db.sql +33 -2
  112. package/ultra-tools/commands/status.cjs +20 -2
  113. package/ultra-tools/commands/task.cjs +4 -1
  114. package/ultra-tools/status-command.test.cjs +20 -0
  115. package/ultra-tools/system-command.test.cjs +5 -0
  116. package/skills/code-review-expert/references/code-quality-checklist.md +0 -112
  117. package/skills/code-review-expert/references/integration-checklist.md +0 -46
  118. package/skills/code-review-expert/references/security-checklist.md +0 -100
  119. package/skills/code-review-expert/references/solid-checklist.md +0 -65
  120. package/skills/ultra-research/steps/step-00-problem-validation.md +0 -154
  121. package/skills/ultra-research/steps/step-01-opportunity-discovery.md +0 -172
  122. package/skills/ultra-research/steps/step-02-market-assessment.md +0 -195
  123. package/skills/ultra-research/steps/step-03-competitive-landscape.md +0 -197
  124. package/skills/ultra-research/steps/step-04-product-strategy.md +0 -196
  125. package/skills/ultra-research/steps/step-05-assumptions-validation.md +0 -234
  126. package/skills/ultra-research/steps/step-10-user-personas.md +0 -169
  127. package/skills/ultra-research/steps/step-11-user-scenarios.md +0 -181
  128. package/skills/ultra-research/steps/step-20-user-stories.md +0 -156
  129. package/skills/ultra-research/steps/step-21-features-scope.md +0 -157
  130. package/skills/ultra-research/steps/step-22-success-metrics.md +0 -195
  131. package/skills/ultra-research/steps/step-30-architecture-context.md +0 -154
  132. package/skills/ultra-research/steps/step-31-solution-strategy.md +0 -172
  133. package/skills/ultra-research/steps/step-32-building-blocks.md +0 -188
  134. package/skills/ultra-research/steps/step-40-deployment.md +0 -123
  135. package/skills/ultra-research/steps/step-41-quality-risks.md +0 -135
  136. package/skills/ultra-research/steps/step-99-synthesis.md +0 -188
  137. package/skills/ultra-review/scripts/review_verdict_update.py +0 -99
@@ -8,8 +8,8 @@ const { spawnSync } = require('node:child_process');
8
8
  const yaml = require('js-yaml');
9
9
  const {
10
10
  CORE_PUBLIC_SKILLS,
11
- INTERNAL_AGENT_SKILLS,
12
11
  WORKFLOW_HOOK_FILES,
12
+ skillPolicy,
13
13
  skillsForRuntime,
14
14
  } = require('./runtime-assets.cjs');
15
15
 
@@ -69,7 +69,6 @@ const SKILL_REFERENCE_NAMES = Object.freeze([
69
69
  'ultra-review',
70
70
  'ultra-verify',
71
71
  ]);
72
- const INTERNAL_SKILLS = new Set(INTERNAL_AGENT_SKILLS);
73
72
  const CODEX_PRIMARY_SKILLS = new Set([...COMMAND_NAMES, 'ultra-review']);
74
73
  const TEXT_EXTENSIONS = new Set(['.md', '.json', '.py', '.sh', '.txt', '.yaml', '.yml']);
75
74
 
@@ -202,11 +201,7 @@ Model agreement never overrides failing tests or authoritative runtime evidence.
202
201
  Read the bundled references for mode-specific evidence and confidence guidance.
203
202
  */ }).match(/\/\*([\s\S]*?)\*\//)[1].trim();
204
203
  function titleCase(name) {
205
- const special = {
206
- 'ai-collab-base': 'AI Collaboration Base',
207
- 'cc-collab': 'Claude Code Collaboration',
208
- 'use-railway': 'Use Railway',
209
- };
204
+ const special = { 'cc-collab': 'Claude Code Collaboration' };
210
205
  if (special[name]) return special[name];
211
206
  return name.split('-').map((part) => part ? part[0].toUpperCase() + part.slice(1) : part).join(' ');
212
207
  }
@@ -221,276 +216,11 @@ function replaceSlashCommand(text, command, replacement) {
221
216
 
222
217
  function adaptCodexPrimaryText(input, skillName) {
223
218
  let text = String(input);
224
- text = text.replaceAll('mcp__claude-in-chrome__*', 'the available Codex browser verification tools');
225
- text = text.replaceAll('claude_md_rule', 'agents_md_rule');
226
- text = text.replaceAll('claude-opus-4-6', '<codex-model>');
227
- text = text.replaceAll('Claude', 'Codex');
228
- text = text.replaceAll('TaskCreate/TaskUpdate', 'the Codex plan tool');
229
- text = text.replaceAll('TaskCreate', 'the Codex plan tool');
230
- text = text.replaceAll('TaskUpdate', 'the Codex plan tool');
231
- text = text.replaceAll('TaskList', 'the current Codex plan');
232
- text = text.replaceAll('TaskOutput', 'verbose subagent transcript output');
233
- text = text.replaceAll('run_in_background: true', 'native parallel execution');
234
- text = text.replaceAll('Bash tool', '`exec_command`');
235
- text = text.replaceAll('Bash calls', '`exec_command` calls');
236
- text = text.replaceAll('Read tool', 'targeted file reads');
237
- text = text.replaceAll('Write tool', '`apply_patch`');
238
- text = text.replaceAll('`ask.question`', 'a direct user question');
239
- text = text.replaceAll('ask.question', 'ask the user directly');
240
- text = text.replaceAll('Playwright via Bash', 'Playwright through `exec_command`');
241
- text = text.replaceAll('mcp__context7__query-docs', 'official documentation lookup');
242
- text = text.replaceAll('mcp__exa__web_search_exa', 'verified web search');
243
- text = text.replaceAll('Context7 MCP', 'official primary documentation');
244
- text = text.replaceAll('Context7/Exa', 'official primary documentation and verified web search');
245
- text = text.replaceAll('Context7', 'official primary documentation');
246
- text = text.replaceAll('Exa MCP', 'verified web search');
247
- text = text.replaceAll('a direct user question (or runtime `ask the user directly`)', 'ask the user directly');
248
- text = text.replaceAll('a direct user question (fallback: `ask the user directly` / CLI menu)', 'ask the user directly');
249
- text = text.replaceAll('questions via ask the user directly.', 'questions directly to the user.');
250
- text = text.replaceAll('using `the Codex plan tool`', 'with the Codex plan tool');
251
- text = text.replaceAll("via the runtime's native the Codex plan tool", 'with the Codex plan tool when available');
252
- text = text.replaceAll('`the Codex plan tool` → `status: "in_progress"`', 'Mark the current Codex plan item `in_progress`');
253
- text = text.replaceAll('`the Codex plan tool` → `status: "completed"`', 'Mark the current Codex plan item `completed`');
254
- text = text.replaceAll('`the current Codex plan` → resume from last incomplete step', 'Resume from the first incomplete item in the current Codex plan');
255
- text = text.replaceAll('`the Codex plan tool`', 'the Codex plan tool');
256
-
257
- if (skillName === 'ultra-init') {
258
- text = text.replace(
259
- /MCP 不可达时回退[^。]*。/,
260
- 'MCP 不可达时只使用插件内置的可验证 CLI 初始化路径;不得手写投影文件。',
261
- );
262
- text = text.replace(
263
- /- \*\*无 Codex 独占依赖\*\*[::][\s\S]*?(?=\n- \*\*模板内置)/,
264
- '- **Codex-native boundary**: use the bundled `task.init_project` MCP tool; the plugin-local CLI below is only the verified initialization fallback.',
265
- );
266
- text = text.replace(
267
- /在调 `task\.init_project` 之前,调用方(Codex \/ CLI \/ SDK)需要先判断:/,
268
- '在调 `task.init_project` 之前,Codex 需要先判断:',
269
- );
270
- text = text.replace(
271
- /- 如果调用方是 Codex,可在此用 the Codex plan tool 跟踪 Step 0–4 的 session 内进度\n (这是 runtime 的 session-local 跟踪,不走 MCP)/,
272
- '- 多步初始化可用 Codex plan 跟踪;持久项目状态仍只通过 Ultra MCP 写入。',
273
- );
274
- text = text.replace(
275
- /交互渠道:[\s\S]*?(?=\n确认 4 个问题:)/,
276
- '交互渠道:直接向用户提问;不要调用未注册的人机交互 MCP tool。\n',
277
- );
278
- text = text.replace(
279
- /\*\*CLI 回退路径\*\*[\s\S]*?(?=\n\*\*错误处理\*\*)/,
280
- `**插件内置 CLI 回退路径**(只在 MCP 启动失败时使用):
281
-
282
- \`\`\`bash
283
- node ~/plugins/ultra-builder-pro/runtime/ultra-tools.cjs task init-project \\
284
- --target-dir "$TARGET" \\
285
- --project-name "$NAME" \\
286
- --project-type "$TYPE" \\
287
- --stack "$STACK"
288
- \`\`\`
289
-
290
- 该 CLI 与 MCP 使用同一模板和校验规则。不得改写 \`.ultra/tasks/tasks.json\` 来模拟成功。
291
- `,
292
- );
293
- text = text.replace(
294
- /## 调用方式(按 runtime)[\s\S]*?(?=\n## 输出锚点)/,
295
- '## Codex 调用方式\n\n在 Codex 中显式调用 `$ultra-builder-pro:ultra-init`,并在同一条任务消息中提供项目名、类型、技术栈或 git 约束。\n',
296
- );
297
- text = text.replace(
298
- /- \*\*不\*\*写入 state\.db(state\.db 由第一次 MCP 写操作或显式 `ultra-tools db init` 触发)/,
299
- '- **不**直接写入 state.db;它由第一次 Ultra MCP 状态写操作初始化。',
300
- );
301
- text = text.replaceAll('不再依赖 `~/.codex/.ultra-template/`', '不依赖任何用户目录模板');
302
- }
303
-
304
- if (skillName === 'ultra-plan') {
305
- text = text.replace(
306
- /Interactive prompt uses[\s\S]*?(?=\n\n\*\*Dual-scale effort)/,
307
- 'Ask the user directly in Codex and record the selected posture.',
308
- );
309
- text = text.replace(
310
- /\*\*CLI fallback\*\* \(per task\):[\s\S]*?(?=\nAfter each `task\.create`)/,
311
- '**Failure boundary**: if the bundled MCP cannot execute `task.create`, stop and report the MCP error. Do not write state.db or its JSON/Markdown projections directly.\n\n',
312
- );
313
- text = text.replace(
314
- /## MCP → CLI fallback matrix[\s\S]*?(?=\n## What this skill DOES NOT do)/,
315
- `## Codex runtime boundary
316
-
317
- - Ask scope and approval questions directly in the Codex conversation.
318
- - Persist tasks only through bundled MCP \`task.create\` or \`task.parse_prd\`.
319
- - If that MCP is unavailable, stop the state mutation with evidence; the legacy CLI does not
320
- implement task creation and is not a valid fallback.
321
- `,
322
- );
323
- }
324
-
325
- if (skillName === 'ultra-dev') {
326
- text = text.replace(
327
- /## Design decisions vs pre-Phase-3[\s\S]*?(?=\n## Prerequisites)/,
328
- `## Codex-native execution boundaries
329
-
330
- - Status changes use bundled MCP \`task.update\`; projected JSON and frontmatter are read-only.
331
- - Review uses \`$ultra-builder-pro:ultra-review\` and the installed native Codex custom agents.
332
- The active MCP server does not expose a server-side review worker.
333
- - Recovery uses the Codex plan plus \`.ultra/workflow-state.json\`, with the bundled compact hooks.
334
- The active MCP server does not expose a checkpoint tool, and no manual compact is required.
335
- `,
336
- );
337
- text = text.replaceAll(
338
- '**CLI fallback**: `ultra-tools task update <id> --status in_progress`.',
339
- '**Failure boundary**: if `task.update` is unavailable, stop; do not edit state.db or projections directly.',
340
- );
341
- text = text.replaceAll(
342
- '**CLI fallback**: `ultra-tools task update <id> --status completed`.',
343
- '**Failure boundary**: if `task.update` is unavailable, stop; do not mark the projection completed manually.',
344
- );
345
- text = text.replace(
346
- /\*\*Subagent isolation \(complexity ≥ 7\)\*\*:[\s\S]*?subagent returns summary\./,
347
- '**Subagent isolation (complexity ≥ 7)**: use a bounded installed Codex custom agent only when the Subagent Policy or this invoked workflow authorizes delegation; the parent retains decisions and verification.',
348
- );
349
- text = text.replace(
350
- /### Step 4\.4 — Pre-Review Checkpoint[\s\S]*?(?=\n### Step 4\.5)/,
351
- `### Step 4.4 — Pre-Review Checkpoint
352
-
353
- Atomically write \`.ultra/workflow-state.json\` with \`step=4.5\`,
354
- \`status=pre_review\`, the task id, branch, and timestamp. Mark the matching Codex plan item
355
- complete. The PreCompact/PostCompact hooks preserve and restore this checkpoint automatically;
356
- do not require the user to compact or call a nonexistent checkpoint tool.
357
- `,
358
- );
359
- text = text.replace(
360
- /### Step 4\.5 — Ultra Review \(MANDATORY\)[\s\S]*?(?=\n\*\*MAX_REVIEW_ITERATIONS)/,
361
- `### Step 4.5 — Ultra Review (MANDATORY)
362
-
363
- Invoke \`$ultra-builder-pro:ultra-review all\`. That skill selects and dispatches the installed
364
- native Codex review agents, waits on their structured files, and owns \`SUMMARY.json\`. Do not call
365
- an unregistered review MCP tool or shell out to another Codex process as a substitute.
366
-
367
- `,
368
- );
369
- text = text.replace(
370
- /## MCP → CLI fallback matrix[\s\S]*?(?=\n## What this skill DOES NOT do)/,
371
- `## Codex runtime boundary
372
-
373
- | Purpose | Authoritative Codex path |
374
- |---------|--------------------------|
375
- | Select/read/update task | bundled MCP \`task.list\`, \`task.get\`, \`task.update\` |
376
- | Pre-review recovery | Codex plan + \`.ultra/workflow-state.json\` + compact hooks |
377
- | Review | \`$ultra-builder-pro:ultra-review\` + native custom agents |
378
- | Human decision | ask the user directly |
379
-
380
- If a required task MCP operation fails, stop and report it; never fall back to direct database or
381
- projection writes.
382
- `,
383
- );
384
- text = text.replace(
385
- /- Does NOT assume `review\.run` or `session\.checkpoint` are wired — fallbacks are first-class/,
386
- '- Does NOT call unregistered review or checkpoint MCP tools.',
387
- );
388
- }
389
-
390
- if (skillName === 'ultra-test') {
391
- text = text.replace(
392
- /## MCP → CLI fallback matrix[\s\S]*?(?=\n## What this skill DOES NOT do)/,
393
- `## Codex runtime boundary
394
-
395
- - Read task completion through bundled MCP \`task.list\`.
396
- - Ask before risky auto-fixes directly in the Codex conversation.
397
- - If task state is unavailable, report the missing gate rather than trusting a projection alone.
398
- `,
399
- );
400
- }
401
-
402
- if (skillName === 'ultra-deliver') {
403
- text = text.replace(
404
- /## MCP → CLI fallback matrix[\s\S]*?(?=\n## What this skill DOES NOT do)/,
405
- `## Codex runtime boundary
406
-
407
- Ask the user directly before committing, tagging, pushing, or overriding the version bump. These are
408
- external repository mutations; never infer approval from a prior read-only or test request.
409
- `,
410
- );
411
- }
412
-
413
- if (skillName === 'ultra-status') {
414
- text = text.replace(
415
- /\*\*CLI fallback\*\*: `ultra-tools task list` \+ `ultra-tools session list`\./,
416
- '**Failure boundary**: if the bundled task/session MCP tools are unavailable, report those panels as unavailable; do not trust projections as authority.',
417
- );
418
- text = text.replace(
419
- /\*\*Output block\*\*:[\s\S]*?(?=\n## Single-task mode)/,
420
- `**Output block**: name the concrete next skill and use its namespaced Codex invocation, for
421
- example \`$ultra-builder-pro:ultra-dev\`. If a fresh context would help, recommend starting a new
422
- Codex task; do not emit a legacy slash-command placeholder.
423
-
424
- `,
425
- );
426
- text = text.replace(
427
- /## MCP → CLI fallback matrix[\s\S]*?(?=\n## Cost panel)/,
428
- `## Codex data paths
429
-
430
- | Purpose | Path |
431
- |---------|------|
432
- | List/detail tasks | bundled MCP \`task.list\` / \`task.get\` |
433
- | Cost panel | \`node ~/plugins/ultra-builder-pro/runtime/ultra-tools.cjs status --cost --json --since 7d\` |
434
-
435
- Task projections are not an authority fallback. If the MCP is unavailable, label the task panel
436
- unavailable while still reporting file and git evidence.
437
- `,
438
- );
439
- text = text.replaceAll(
440
- '`ultra-tools status --cost --json`',
441
- '`node ~/plugins/ultra-builder-pro/runtime/ultra-tools.cjs status --cost --json`',
442
- );
443
- }
444
-
445
- if (skillName === 'ultra-think') {
446
- text = text.replace(
447
- /Every factual claim about tech\/API\/best-practices must be verified via:[\s\S]*?(?=\n\nLabel each assertion:)/,
448
- `Every factual claim about technology, APIs, or current behavior must use the best available
449
- primary evidence in this order:
450
- - current repository or installed source;
451
- - official primary documentation;
452
- - web search when the fact may have changed or local evidence is insufficient.
453
- `,
454
- );
455
- text = text.replaceAll(
456
- 'docs via Context7/Exa',
457
- 'official primary documentation or verified web sources',
458
- );
459
- text = text.replace(
460
- /## MCP → CLI fallback matrix[\s\S]*?(?=\n## What this skill DOES NOT do)/,
461
- `## Codex interaction boundary
462
-
463
- Ask clarifying questions directly in the Codex conversation. This reasoning workflow is read-only
464
- and does not require an interactive MCP or legacy CLI menu.
465
- `,
466
- );
467
- }
468
-
469
219
  if (skillName === 'ultra-review') {
470
- text = text.replace(
471
- '# $ultra-builder-pro:ultra-review - Ultra Review System',
472
- `# $ultra-builder-pro:ultra-review - Ultra Review System
473
-
474
- ## Codex native worker contract
475
-
476
- Use the installed native Codex custom agents as bounded review workers. Dispatch independent
477
- workers concurrently, keep the current Codex task primary, and treat their JSON artifacts—not
478
- their conversational transcripts—as review evidence.`,
220
+ text = text.replaceAll(
221
+ "the current host's native bounded-worker mechanism",
222
+ 'native Codex custom agents installed for the selected review workers',
479
223
  );
480
- text = text.replaceAll('### Phase 3: Background Execution', '### Phase 3: Parallel Native Agent Execution');
481
- text = text.replaceAll('**Step 4b: Launch coordinator in background:**', '**Step 4b: Delegate coordination:**');
482
- text = text.replaceAll('in **background mode** (`native parallel execution`)', 'concurrently with native Codex subagent orchestration');
483
- text = text.replaceAll('using multiple native Codex subagent orchestration calls in a single message', 'using the installed native Codex custom agents');
484
- text = text.replaceAll('Set `native parallel execution` on every Task call.', 'Dispatch every selected custom agent concurrently and keep each delegated scope bounded.');
485
- text = text.replaceAll('NEVER call verbose subagent transcript output for any review agent', 'Do not copy verbose subagent transcripts into the parent context');
486
- text = text.replaceAll('Call `review_wait.py` IMMEDIATELY — do NOT process idle notifications', 'Use `review_wait.py` as the file-completion gate before synthesis');
487
- text = text.replaceAll('Ignore all agent idle/completion messages between launch and wait script return', 'Treat completion messages only as lifecycle evidence; findings still come from the JSON files');
488
- text = text.replaceAll('Launch review-coordinator with `native parallel execution`:', 'After reviewer completion, delegate coordination to the native `review-coordinator` agent:');
489
- text = text.replaceAll('Use Bash to block until all agents finish writing:', 'Run the waiter through `exec_command` with a short yield; if it returns a live session, poll in bounded intervals:');
490
- text = text.replaceAll('After launching background agents', 'After dispatching the review agents');
491
- text = text.replaceAll('The review agents write to files; you read from files.', 'The review agents write findings to files; the parent reads only the structured files and concise lifecycle acknowledgements.');
492
- text = text.replaceAll('The ONLY information path from agents is: wait script → Read SUMMARY.json', 'The authoritative finding path is: wait script → inspect SUMMARY.json');
493
- text = text.replaceAll('**Read SUMMARY.json**', '**Inspect SUMMARY.json**');
494
224
  }
495
225
 
496
226
  return text;
@@ -536,15 +266,6 @@ function adaptHostText(input, skillName = '') {
536
266
  text = text.replaceAll('~/.codex/skills', '~/plugins/ultra-builder-pro/skills');
537
267
  text = text.replaceAll('~/.claude/hooks', '~/plugins/ultra-builder-pro/hooks');
538
268
  text = text.replaceAll('~/.claude', '~/.codex');
539
- text = text.replaceAll('AskUserQuestion', 'ask the user directly');
540
- text = text.replaceAll('Claude runtime', 'Codex runtime');
541
- text = text.replaceAll('Claude-only', 'Codex-only');
542
- text = text.replaceAll('Claude Task tool', 'Codex native subagent orchestration');
543
- text = text.replaceAll('Claude `Task` tool', 'Codex native subagent orchestration');
544
- text = text.replaceAll('Claude: `Task`', 'Codex: native subagent orchestration');
545
- text = text.replaceAll('Task tool', 'native Codex subagent orchestration');
546
- text = text.replaceAll('`Task`/`ultra-tools subagent run`', 'native Codex subagent orchestration / `ultra-tools subagent run`');
547
- text = text.replaceAll('`Task` →', 'native Codex subagent orchestration →');
548
269
 
549
270
  for (const skill of SKILL_REFERENCE_NAMES) {
550
271
  text = replaceSlashCommand(text, skill, `$ultra-builder-pro:${skill}`);
@@ -555,52 +276,8 @@ function adaptHostText(input, skillName = '') {
555
276
  text = adaptCodexPrimaryText(text, skillName);
556
277
  }
557
278
 
558
- if (skillName === 'ai-collab-base') {
559
- text = text.replaceAll("Claude's", "Codex's");
560
- text = text.replaceAll('Claude-only', 'Codex-only');
561
- text = text.replaceAll('Claude ', 'Codex ');
562
- text = text.replaceAll('Claude\n', 'Codex\n');
563
- text = text.replaceAll('--approval-mode yolo', '--approval-mode plan');
564
- text = text.replaceAll('--yolo', '--approval-mode plan');
565
- text = text.replaceAll('Bash tool', '`exec_command`');
566
- text = text.replaceAll('Read tool', 'targeted file reads');
567
- text = text.replaceAll('Write tool', '`apply_patch`');
568
- }
569
-
570
279
  if (skillName === 'learn') {
571
- text = text.replaceAll(
572
- '~/plugins/ultra-builder-pro/skills/learned-<name>-unverified/SKILL.md',
573
- '~/.agents/skills/learned-<name>-unverified/SKILL.md',
574
- );
575
- text = text.replaceAll(
576
- '~/plugins/ultra-builder-pro/skills/learned-<pattern-slug>-unverified/SKILL.md',
577
- '~/.agents/skills/learned-<pattern-slug>-unverified/SKILL.md',
578
- );
579
- text = text.replaceAll(
580
- '~/plugins/ultra-builder-pro/skills/learned-<slug>-unverified/SKILL.md',
581
- '~/.agents/skills/learned-<slug>-unverified/SKILL.md',
582
- );
583
- text = text.replaceAll(
584
- '~/plugins/ultra-builder-pro/skills/learned/<name>_unverified.md',
585
- '~/.agents/skills/learned-<name>-unverified/SKILL.md',
586
- );
587
- text = text.replaceAll(
588
- '~/plugins/ultra-builder-pro/skills/learned/<pattern-slug>_unverified.md',
589
- '~/.agents/skills/learned-<pattern-slug>-unverified/SKILL.md',
590
- );
591
- text = text.replaceAll(
592
- '~/plugins/ultra-builder-pro/skills/learned/<slug>_unverified.md',
593
- '~/.agents/skills/learned-<slug>-unverified/SKILL.md',
594
- );
595
- text = text.replaceAll('append the `_unverified` suffix to the filename', 'append `-unverified` to the skill directory name');
596
- text = text.replaceAll('Never overwrite an existing unverified file', 'Never overwrite an existing learned skill directory');
597
- text = text.replaceAll('remove the `_unverified` suffix', 'rename the directory to remove `-unverified` and update the frontmatter name');
598
- text = text.replaceAll('(`pattern-slug-2_unverified.md`)', '(`learned-pattern-slug-2-unverified/`)');
599
- text = text.replaceAll('Anything the user already wrote in AGENTS.md or similar project instructions', 'Anything already captured in AGENTS.md or equivalent project instructions');
600
- text = text.replace(
601
- /## MCP → CLI fallback matrix[\s\S]*?(?=\n## What this skill DOES NOT do)/,
602
- '## Codex approval boundary\n\nAsk the user directly before writing a learned skill. No MCP or legacy CLI interaction layer is required.\n',
603
- );
280
+ text = text.replaceAll("current host's user skill directory", '`~/.agents/skills`');
604
281
  text += `\n\n## Codex packaging requirement\n\nEach learned pattern must be a valid skill directory, not a loose Markdown file. The generated\n\`SKILL.md\` must start with only \`name\` and \`description\` frontmatter. Also create\n\`agents/openai.yaml\` with \`policy.allow_implicit_invocation: false\`. A new Codex task is required\nbefore the learned skill appears in discovery.\n`;
605
282
  }
606
283
 
@@ -610,9 +287,9 @@ function adaptHostText(input, skillName = '') {
610
287
  function adaptedDescription(sourceDescription, targetName) {
611
288
  const special = {
612
289
  'cc-collab': 'Ask Claude Code for an independent read-only analysis while Codex owns verification and synthesis. Use only when the user explicitly requests CC or Claude Code collaboration.',
613
- 'ultra-verify': 'Run Codex-primary two-model verification with a read-only Claude Code advisor, then verify and synthesize the evidence.',
614
- 'ultra-dev': 'Execute one Ultra task with Codex-native TDD, persistent task.update state, workflow checkpoints, and the native Ultra review agents.',
615
- 'learn': 'Extract one reusable pattern from the current Codex task into a valid user skill, with explicit user approval before writing.',
290
+ 'ultra-verify': 'Run Codex-primary cross-model verification with a read-only Claude Code advisor. Use only when the user explicitly requests independent model verification.',
291
+ 'ultra-dev': 'Execute one authoritative Ultra task with Codex-native implementation, verification, and review. Use when a dependency-ready slice is ready for development.',
292
+ 'learn': 'Extract one verified reusable workflow from the current Codex task into a portable user skill. Use when the user explicitly asks to preserve the method.',
616
293
  };
617
294
  return special[targetName] || adaptHostText(String(sourceDescription || `${titleCase(targetName)} workflow for Codex.`), targetName)
618
295
  .replace(/\s+/g, ' ')
@@ -633,21 +310,26 @@ function buildSkillMarkdown(sourceText, sourceName, targetName) {
633
310
  }
634
311
 
635
312
  function buildOpenAiYaml(name, description) {
636
- const implicit = !(
637
- COMMAND_NAMES.includes(name)
638
- || INTERNAL_SKILLS.has(name)
639
- || name === 'cc-collab'
640
- || name.startsWith('ultra-')
641
- );
313
+ const policy = skillPolicy(name);
642
314
  const short = description.replace(/\s+/g, ' ').trim().slice(0, 63).replace(/[\s.,;:]+$/, '');
643
- return yaml.dump({
315
+ const metadata = {
644
316
  interface: {
645
317
  display_name: titleCase(name),
646
318
  short_description: short || `${titleCase(name)} for Codex`,
647
319
  default_prompt: `Use $ultra-builder-pro:${name} for this task and follow its workflow.`,
648
320
  },
649
- policy: { allow_implicit_invocation: implicit },
650
- }, { lineWidth: -1, noRefs: true });
321
+ policy: { allow_implicit_invocation: policy.allowImplicitInvocation },
322
+ };
323
+ if (policy.requiresUltraMcp) {
324
+ metadata.dependencies = {
325
+ tools: [{
326
+ type: 'mcp',
327
+ value: PLUGIN_NAME,
328
+ description: 'Ultra Builder Pro authoritative task and change runtime',
329
+ }],
330
+ };
331
+ }
332
+ return yaml.dump(metadata, { lineWidth: -1, noRefs: true });
651
333
  }
652
334
 
653
335
  function isTextFile(rel) {
@@ -718,7 +400,7 @@ function buildHooksManifest() {
718
400
  { hooks: [commandHook('workflow_resume.py', 10, 'Restoring Ultra workflow checkpoint')] },
719
401
  ],
720
402
  Stop: [
721
- { hooks: [commandHook('pre_stop_check.py', 5, 'Checking Ultra completion gates')] },
403
+ { hooks: [commandHook('pre_stop_check.py', 5, 'Reporting Ultra workflow position')] },
722
404
  ],
723
405
  SubagentStart: [
724
406
  { hooks: [commandHook('subagent_tracker.py', 5, 'Tracking Ultra subagent', 'start')] },
@@ -59,11 +59,12 @@ function renderHandbook(runtime) {
59
59
  `- Workflow entry points: ${value.invocation}.`,
60
60
  `- Collaboration boundary: ${value.collaboration}. The current host remains primary and owns final verification.`,
61
61
  `- Coordination boundary: ${value.coordination}.`,
62
- '- Authority: `.ultra/state.db` is the only durable Ultra authority for changes, tasks, sessions, events, incidents, projection state, telemetry, and review evidence. Generated JSON and Markdown are projections or workflow artifacts.',
63
- '- Context Spine boundary: `change.context` compiles role/gate readiness, bounded references, fresh-context budget, public seam, verification command, and one next action. Hooks inject only the DB-derived `change.breadcrumb`; stale or blocked context must be recompiled.',
62
+ '- Authority: `.ultra/state.db` is the only durable Ultra authority for baselines, changes, tasks, sessions, events, incidents, projection state, telemetry, and review evidence. Generated JSON and Markdown are projections or workflow artifacts.',
63
+ '- Baseline boundary: `task.init_project` detects greenfield or brownfield work; `baseline.start`, `baseline.record`, and `baseline.converge` adopt the project without rewriting application code. An incomplete baseline is advisory during active work but blocks change convergence; normal HEAD or tracked-spec drift from that change is reconciled and health-checked atomically at archive.',
64
+ '- Context Spine boundary: `change.context` compiles role/gate readiness, required references, a fresh-context budget, public seam, verification command, and one next action. File, token, and context-share budgets are advisory attention signals, not refusal gates. Hooks inject only the DB-derived `change.breadcrumb`; missing required evidence or stale execution context must be recompiled.',
64
65
  '- Specification learning boundary: stable implementation discoveries use approval-gated propose/approve-or-reject/apply transitions. Unresolved learning blocks convergence; review requires independent specification-fidelity and engineering-standards evidence.',
65
66
  '- Memory and graph boundary: Ultra Builder Pro does not capture prompts, transcripts, observations, summaries, cross-session memory, or code-graph content. Separately installed providers own that data; Ultra may store only their metadata references in a change context manifest.',
66
- '- Hook boundary: Ultra hooks observe workflow/change lifecycle only. Health/context may run when `.ultra/state.db` exists; projection protection is always authoritative, while edit/compact/stop/subagent enforcement remains active-workflow scoped. Generic command blocking and post-edit policy stay in user or repository governance.',
67
+ '- Hook boundary: Ultra hooks observe workflow/change lifecycle only. Health/context may run when `.ultra/state.db` exists; advisory warnings never reject work, and an incomplete workflow never traps session stop. Direct projection protection remains authoritative; compact and subagent recovery stays active-workflow scoped. Generic command blocking and post-edit policy stay in user or repository governance.',
67
68
  '- Installation boundary: `ubp --doctor` is the read-only authority for installed asset provenance, content hashes, and host entry-point wiring; `system.doctor` remains scoped to project state and workflow recovery.',
68
69
  '- Agent boundary: the bundled review and debugging agents are bounded workers. They use the current checkout and parent-supplied context, do not own private persistent state, and never replace the primary agent.',
69
70
  '- Package boundary: only the twelve Ultra workflows, four internal review-rule skills, host-specific collaboration companions, and the minimal host bootstrap belong to this plugin. General browser, deployment, discovery, and framework skills must be installed from their owners.',
@@ -38,6 +38,18 @@ const COLLAB_SKILLS_BY_RUNTIME = Object.freeze({
38
38
  kimi: Object.freeze(['cc-collab', 'codex-collab', 'ultra-verify']),
39
39
  });
40
40
 
41
+ const MCP_DEPENDENT_SKILLS = Object.freeze([
42
+ 'ultra-init',
43
+ 'ultra-change',
44
+ 'ultra-plan',
45
+ 'ultra-dev',
46
+ 'ultra-test',
47
+ 'ultra-review',
48
+ 'ultra-deliver',
49
+ 'ultra-status',
50
+ 'ultra-doctor',
51
+ ]);
52
+
41
53
  const RETIRED_SKILLS = Object.freeze([
42
54
  'agent-browser',
43
55
  'find-skills',
@@ -69,13 +81,25 @@ function isSupportedRuntime(runtime) {
69
81
  return SUPPORTED_RUNTIMES.includes(runtime);
70
82
  }
71
83
 
84
+ function skillPolicy(name) {
85
+ const packaged = SUPPORTED_RUNTIMES.some((runtime) => skillsForRuntime(runtime).includes(name));
86
+ if (!packaged) throw new Error(`unknown packaged Ultra skill: ${name}`);
87
+ return {
88
+ userInvocable: !INTERNAL_AGENT_SKILLS.includes(name),
89
+ allowImplicitInvocation: false,
90
+ requiresUltraMcp: MCP_DEPENDENT_SKILLS.includes(name),
91
+ };
92
+ }
93
+
72
94
  module.exports = {
73
95
  CORE_PUBLIC_SKILLS,
74
96
  INTERNAL_AGENT_SKILLS,
75
97
  SUPPORTED_RUNTIMES,
76
98
  COLLAB_SKILLS_BY_RUNTIME,
99
+ MCP_DEPENDENT_SKILLS,
77
100
  RETIRED_SKILLS,
78
101
  WORKFLOW_HOOK_FILES,
79
102
  isSupportedRuntime,
103
+ skillPolicy,
80
104
  skillsForRuntime,
81
105
  };
@@ -34,6 +34,10 @@ test('renders one common contract with host-native invocation syntax', () => {
34
34
  assert.match(rendered, /ultra-doctor/);
35
35
  assert.match(rendered, /metadata references/);
36
36
  assert.match(rendered, /Context Spine boundary/);
37
+ assert.match(rendered, /budgets are advisory attention signals/);
38
+ assert.match(rendered, /blocks change convergence/);
39
+ assert.match(rendered, /health-checked atomically at archive/);
40
+ assert.match(rendered, /never traps session stop/);
37
41
  assert.match(rendered, /change\.breadcrumb/);
38
42
  assert.match(rendered, /Specification learning boundary/);
39
43
  assert.doesNotMatch(rendered, /\.ultra\/memory|memory\.retain|memory\.recall/);
@@ -11,8 +11,10 @@ const {
11
11
  INTERNAL_AGENT_SKILLS,
12
12
  SUPPORTED_RUNTIMES,
13
13
  COLLAB_SKILLS_BY_RUNTIME,
14
+ MCP_DEPENDENT_SKILLS,
14
15
  RETIRED_SKILLS,
15
16
  WORKFLOW_HOOK_FILES,
17
+ skillPolicy,
16
18
  skillsForRuntime,
17
19
  } = require('../runtime-assets.cjs');
18
20
 
@@ -74,10 +76,15 @@ test('runtime asset manifest exposes only Ultra-owned core and internal skills',
74
76
  }
75
77
  });
76
78
 
77
- test('code-review-expert and rule skills are internal, never implicitly exposed', () => {
78
- const codexAssets = fs.readFileSync(path.join(REPO_ROOT, 'adapters', '_shared', 'codex-assets.cjs'), 'utf8');
79
- assert.match(codexAssets, /const INTERNAL_SKILLS = new Set\(INTERNAL_AGENT_SKILLS\)/);
80
- assert.match(codexAssets, /INTERNAL_SKILLS\.has\(name\)/);
79
+ test('host invocation and MCP metadata live outside source SKILL frontmatter', () => {
80
+ const all = new Set(SUPPORTED_RUNTIMES.flatMap((runtime) => skillsForRuntime(runtime)));
81
+ for (const name of all) {
82
+ const policy = skillPolicy(name);
83
+ assert.equal(policy.allowImplicitInvocation, false, name);
84
+ assert.equal(policy.userInvocable, !INTERNAL_AGENT_SKILLS.includes(name), name);
85
+ assert.equal(policy.requiresUltraMcp, MCP_DEPENDENT_SKILLS.includes(name), name);
86
+ }
87
+ assert.throws(() => skillPolicy('not-packaged'), /unknown packaged Ultra skill/);
81
88
  });
82
89
 
83
90
  test('workflow hook allowlist contains no memory, prompt capture, or generic policy hook', () => {
@@ -15,10 +15,12 @@ const {
15
15
  writeAtomic,
16
16
  } = require('./_shared/file-ops.cjs');
17
17
  const { buildMcpRuntime } = require('./_shared/codex-assets.cjs');
18
+ const { parse: parseFrontmatter, serialize: serializeFrontmatter } = require('./_shared/frontmatter.cjs');
18
19
  const provenance = require('./_shared/provenance.cjs');
19
20
  const {
20
21
  CORE_PUBLIC_SKILLS,
21
22
  WORKFLOW_HOOK_FILES,
23
+ skillPolicy,
22
24
  skillsForRuntime,
23
25
  } = require('./_shared/runtime-assets.cjs');
24
26
 
@@ -46,12 +48,33 @@ function resolveRepoRoot(ctx = {}) {
46
48
  return ctx.repoRoot || path.resolve(__dirname, '..');
47
49
  }
48
50
 
49
- function copyNamedDirectories(repoRoot, target, parent, names) {
51
+ function copySkills(repoRoot, target, names) {
50
52
  const copied = [];
51
53
  for (const name of names) {
52
- const source = path.join(repoRoot, parent, name);
53
- if (!fs.existsSync(source)) throw new Error(`missing allowlisted Claude asset: ${parent}/${name}`);
54
- const files = copyTree(source, path.join(target, parent, name));
54
+ const source = path.join(repoRoot, 'skills', name);
55
+ if (!fs.existsSync(source)) throw new Error(`missing allowlisted Claude skill: ${name}`);
56
+ const files = copyTree(source, path.join(target, 'skills', name), {
57
+ transform(buf, rel) {
58
+ if (rel !== 'SKILL.md') return buf;
59
+ const { fm, body } = parseFrontmatter(buf.toString('utf8'));
60
+ if (!fm) throw new Error(`missing frontmatter in Claude skill: ${name}`);
61
+ let adaptedBody = body;
62
+ if (name === 'learn') {
63
+ adaptedBody = adaptedBody.replaceAll("current host's user skill directory", '`~/.claude/skills`');
64
+ }
65
+ if (name === 'ultra-review') {
66
+ adaptedBody = adaptedBody.replaceAll(
67
+ "the current host's native bounded-worker mechanism",
68
+ 'Claude Code Task workers using the installed review agent definitions',
69
+ );
70
+ }
71
+ return Buffer.from(serializeFrontmatter({
72
+ name,
73
+ description: fm.description,
74
+ 'user-invocable': skillPolicy(name).userInvocable,
75
+ }, adaptedBody));
76
+ },
77
+ });
55
78
  copied.push(...files.map((rel) => path.join(name, rel)));
56
79
  }
57
80
  return copied;
@@ -126,7 +149,7 @@ function install(ctx = {}) {
126
149
 
127
150
  const report = { target, copied: {}, config: { updated: false } };
128
151
  report.copied.commands = copyCommands(repoRoot, target);
129
- report.copied.skills = copyNamedDirectories(repoRoot, target, 'skills', skillsForRuntime('claude'));
152
+ report.copied.skills = copySkills(repoRoot, target, skillsForRuntime('claude'));
130
153
  report.copied.agents = copyTree(path.join(repoRoot, 'agents'), path.join(target, 'agents'));
131
154
 
132
155
  ensureDir(path.join(target, 'hooks'));