ultra-builder-pro-cli 0.18.0 → 0.20.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.
- package/CHANGELOG.md +54 -1
- package/README.md +16 -27
- package/adapters/_shared/interaction-contract.cjs +26 -4
- package/adapters/claude.js +3 -1
- package/adapters/kimi.js +4 -30
- package/adapters/opencode.js +50 -14
- package/commands/ultra-research.md +1 -1
- package/docs/AGENT-CONTEXT.md +23 -34
- package/docs/ARCHITECTURE.md +26 -12
- package/docs/DECISIONS.md +12 -8
- package/docs/LEGACY-CLI-CROSSWALK.md +9 -7
- package/docs/PLUGIN-ISOLATION-CONTRACT.md +54 -0
- package/docs/ROADMAP.md +5 -5
- package/docs/RUNTIME-COMPAT-MATRIX.md +26 -25
- package/docs/STATE-DB-ACCESS-POLICY.md +1 -1
- package/docs/WORKFLOW-LIFECYCLE.md +45 -25
- package/hooks/active_task_context.py +1 -1
- package/hooks/context_spine.py +1 -1
- package/hooks/health_check.py +19 -0
- package/hooks/pre_stop_check.py +1 -1
- package/hooks/workflow_checkpoint.py +1 -1
- package/hooks/workflow_context.py +1 -1
- package/hooks/workflow_resume.py +1 -1
- package/mcp-server/lib/decision-dialogue.cjs +84 -11
- package/mcp-server/lib/doctor.cjs +2 -1
- package/mcp-server/lib/state-db.cjs +143 -13
- package/mcp-server/lib/workflow-state.cjs +4 -4
- package/mcp-server/server.cjs +24 -8
- package/package.json +3 -4
- package/skills/ultra-change/SKILL.md +16 -8
- package/skills/ultra-init/SKILL.md +2 -1
- package/skills/ultra-plan/SKILL.md +20 -3
- package/skills/ultra-research/SKILL.md +25 -15
- package/skills/ultra-test/SKILL.md +5 -2
- package/skills/ultra-think/SKILL.md +2 -0
- package/skills/ultra-think/references/decision-dialogue.md +47 -11
- package/spec/cli-protocol.md +1 -0
- package/spec/mcp-tools.yaml +30 -3
- package/spec/schemas/state-db.sql +7 -4
- package/ultra-tools/cli.cjs +1 -1
- package/ultra-tools/commands/status.cjs +2 -1
- package/adapters/_shared/handbook.cjs +0 -569
- package/bin/handbook.js +0 -107
- package/docs/USER-HANDBOOK-CONTRACT.md +0 -120
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,56 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.20.0] — 2026-07-28
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
|
|
14
|
+
- Added schema 19 and `decision.complete` so settled normalized intent reaches a
|
|
15
|
+
terminal lifecycle state without fabricating a second user approval or an
|
|
16
|
+
artifact checkpoint. Existing settled schema-18 threads migrate safely.
|
|
17
|
+
|
|
18
|
+
### Changed
|
|
19
|
+
|
|
20
|
+
- Unified semantic selection across Claude Code, Codex, OpenCode, and Kimi Code
|
|
21
|
+
as `inspect -> suggest -> ask if unresolved -> normalize -> persist`, using
|
|
22
|
+
each host's native structured question surface with a direct-question
|
|
23
|
+
fallback.
|
|
24
|
+
- Made research coverage and planning posture owner-selected after model
|
|
25
|
+
recommendation while preserving autonomous fact finding, synthesis,
|
|
26
|
+
decomposition, and reversible implementation judgment.
|
|
27
|
+
- Stopped requiring a ceremonial decision checkpoint after every normalized
|
|
28
|
+
answer. Artifact checkpoints remain explicit digest-bound freshness gates.
|
|
29
|
+
- Made unanswered non-blocking follow-ups advisory instead of global workflow
|
|
30
|
+
gates; unanswered blocking choices and blocking deferrals still fail closed.
|
|
31
|
+
|
|
32
|
+
## [0.19.1] — 2026-07-26
|
|
33
|
+
|
|
34
|
+
### Fixed
|
|
35
|
+
|
|
36
|
+
- Made the four-host handbook-isolation release test hermetic so a clean CI
|
|
37
|
+
runner does not require the Codex CLI merely to prove that installation and
|
|
38
|
+
uninstallation preserve user-owned instruction files byte for byte.
|
|
39
|
+
|
|
40
|
+
## [0.19.0] — 2026-07-26
|
|
41
|
+
|
|
42
|
+
### Changed
|
|
43
|
+
|
|
44
|
+
- Made every public Ultra workflow explicitly activated. Claude Code and Kimi
|
|
45
|
+
Code disable model invocation, Codex keeps implicit invocation disabled, and
|
|
46
|
+
OpenCode commands load private plugin workflow assets instead of exposing
|
|
47
|
+
public workflows through its model skill catalog.
|
|
48
|
+
- Limited lifecycle context, health, checkpoint, stop, and subagent hooks to
|
|
49
|
+
DB-authoritative active workflows. Initialized idle projects retain only
|
|
50
|
+
generated-projection protection.
|
|
51
|
+
- Changed workflow handoff to return allowed transitions and a host-owned
|
|
52
|
+
recommendation without launching another public workflow.
|
|
53
|
+
|
|
54
|
+
### Removed
|
|
55
|
+
|
|
56
|
+
- Removed `ubp-handbook`, the shared handbook renderer, Kimi session bootstrap,
|
|
57
|
+
and every package path capable of creating or rewriting user-level
|
|
58
|
+
`CLAUDE.md` or `AGENTS.md` files.
|
|
59
|
+
|
|
10
60
|
## [0.18.0] — 2026-07-25
|
|
11
61
|
|
|
12
62
|
### Added
|
|
@@ -789,7 +839,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
789
839
|
skill manifest, CLI protocol + mapping table; 5 spec validators.
|
|
790
840
|
- **Phase 0 — skeleton**: multi-runtime installer scaffolding.
|
|
791
841
|
|
|
792
|
-
[Unreleased]: https://github.com/rocky2431/ultra-builder-pro-cli/compare/v0.
|
|
842
|
+
[Unreleased]: https://github.com/rocky2431/ultra-builder-pro-cli/compare/v0.20.0...HEAD
|
|
843
|
+
[0.20.0]: https://github.com/rocky2431/ultra-builder-pro-cli/compare/v0.19.1...v0.20.0
|
|
844
|
+
[0.19.1]: https://github.com/rocky2431/ultra-builder-pro-cli/compare/v0.19.0...v0.19.1
|
|
845
|
+
[0.19.0]: https://github.com/rocky2431/ultra-builder-pro-cli/compare/v0.18.0...v0.19.0
|
|
793
846
|
[0.18.0]: https://github.com/rocky2431/ultra-builder-pro-cli/compare/v0.17.1...v0.18.0
|
|
794
847
|
[0.17.1]: https://github.com/rocky2431/ultra-builder-pro-cli/compare/v0.17.0...v0.17.1
|
|
795
848
|
[0.17.0]: https://github.com/rocky2431/ultra-builder-pro-cli/compare/v0.16.0...v0.17.0
|
package/README.md
CHANGED
|
@@ -73,8 +73,8 @@ The responsibility split is deliberate:
|
|
|
73
73
|
|
|
74
74
|
| Owner | Responsibility |
|
|
75
75
|
|---|---|
|
|
76
|
-
| **User** | Product intent, material scope and trade-offs, destructive actions, publishing and deployment authorization |
|
|
77
|
-
| **Host model** | Fact-finding, synthesis, research
|
|
76
|
+
| **User** | Product intent, semantic route selection, material scope and trade-offs, risk acceptance, destructive actions, publishing and deployment authorization |
|
|
77
|
+
| **Host model** | Fact-finding, synthesis, research-coverage and route recommendations, reversible implementation decisions |
|
|
78
78
|
| **Ultra MCP** | Durable state, evidence references, digests, freshness, locks, valid transitions and hard recovery |
|
|
79
79
|
| **Host adapter** | Native Skill discovery, user questions, tool invocation, installation, and runtime wiring |
|
|
80
80
|
| **Hooks** | Fast lifecycle observation, current breadcrumb injection, and protection of generated projections |
|
|
@@ -155,24 +155,11 @@ npx --yes ultra-builder-pro-cli@latest --all --global --doctor --json
|
|
|
155
155
|
After installing or upgrading, start a new Claude Code, OpenCode, or Codex
|
|
156
156
|
session. In Kimi Code, run `/reload` or start a new session.
|
|
157
157
|
|
|
158
|
-
Plugin installation
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
npx --yes --package ultra-builder-pro-cli@latest \
|
|
164
|
-
ubp-handbook preview --runtime codex --full > /tmp/ubp-codex-handbook.md
|
|
165
|
-
# Inspect the preview, then copy the confirmation token printed to the terminal.
|
|
166
|
-
npx --yes --package ultra-builder-pro-cli@latest \
|
|
167
|
-
ubp-handbook apply --runtime codex --full \
|
|
168
|
-
--confirm "PASTE_64_CHARACTER_TOKEN_HERE"
|
|
169
|
-
```
|
|
170
|
-
|
|
171
|
-
Replace `codex` with `claude`, `opencode`, or `kimi` for the other hosts. The
|
|
172
|
-
apply command rejects a missing or stale preview token, creates a timestamped
|
|
173
|
-
backup, follows user-managed handbook symlinks, and preserves supported
|
|
174
|
-
marker-delimited content owned by other providers. Without `--full`, only the
|
|
175
|
-
small Ultra runtime block is merged.
|
|
158
|
+
Plugin installation, update, doctor, and uninstall never mutate durable user
|
|
159
|
+
instructions such as `CLAUDE.md` or `AGENTS.md`. Ultra policy stays in the plugin
|
|
160
|
+
and becomes active only after an explicit workflow invocation. Existing legacy
|
|
161
|
+
Ultra marker blocks in a user handbook are left untouched for the owner to review;
|
|
162
|
+
the plugin neither claims nor silently deletes user-authored content.
|
|
176
163
|
|
|
177
164
|
### Host invocation
|
|
178
165
|
|
|
@@ -202,7 +189,7 @@ Initialization:
|
|
|
202
189
|
- identifies the repository root and scope;
|
|
203
190
|
- classifies the repository as greenfield, brownfield, or migrated;
|
|
204
191
|
- initializes Git when needed;
|
|
205
|
-
- creates `.ultra/` and schema
|
|
192
|
+
- creates `.ultra/` and schema 19 project authority;
|
|
206
193
|
- verifies that the scaffold and database can be read back;
|
|
207
194
|
- completes without silently starting research, creating a commit, adding a
|
|
208
195
|
remote, or pushing anything.
|
|
@@ -244,9 +231,11 @@ product story. It builds a current-system baseline from:
|
|
|
244
231
|
- APIs, data, permissions, integrations, deployment, and recovery seams;
|
|
245
232
|
- known failures, documentation drift, technical debt, and unresolved unknowns.
|
|
246
233
|
|
|
247
|
-
During `ultra-research`, the host model
|
|
248
|
-
|
|
249
|
-
|
|
234
|
+
During `ultra-research`, the host model inspects current evidence and recommends
|
|
235
|
+
the smallest sufficient route. The owner selects, modifies, delegates, or
|
|
236
|
+
defers it through the host-native question surface unless the current request
|
|
237
|
+
already resolves the route. The normalized accepted coverage is then stored in
|
|
238
|
+
`.ultra/state.db`. Every included area receives one explicit disposition:
|
|
250
239
|
|
|
251
240
|
- `execute` — produce fresh evidence;
|
|
252
241
|
- `verify_existing` — validate an existing artifact;
|
|
@@ -256,7 +245,8 @@ disposition:
|
|
|
256
245
|
|
|
257
246
|
The catalog is not a mandatory document set or questionnaire. Omitted areas
|
|
258
247
|
create no workflow rows; an explicit exclusion is recorded only when retaining
|
|
259
|
-
that rationale is useful.
|
|
248
|
+
that rationale is useful. MCP validates state, evidence, and transitions; it
|
|
249
|
+
does not store or prove the preceding UI interaction.
|
|
260
250
|
|
|
261
251
|
Older projection-only Ultra projects are preserved and routed through a
|
|
262
252
|
backup-first migration or rebaseline. Use `ultra-doctor` when initialization
|
|
@@ -366,7 +356,6 @@ worker execution or verified auto-merge.
|
|
|
366
356
|
| `ultra-builder-pro-cli` / `ubp` | Install, update, uninstall, and diagnose host plugins |
|
|
367
357
|
| `ultra-tools` | Inspect and maintain project tasks, sessions, state, migration, and recovery |
|
|
368
358
|
| `ubp-orchestrator` | Execute current dependency waves or supervise configured workers |
|
|
369
|
-
| `ubp-handbook` | Preview or apply either the bounded Ultra block or the explicit full host-native handbook |
|
|
370
359
|
|
|
371
360
|
Useful read-only checks:
|
|
372
361
|
|
|
@@ -426,7 +415,7 @@ and `test:rest`.
|
|
|
426
415
|
| [Runtime Compatibility Matrix](./docs/RUNTIME-COMPAT-MATRIX.md) | Claude Code, OpenCode, Codex, and Kimi presentation details |
|
|
427
416
|
| [Legacy CLI Crosswalk](./docs/LEGACY-CLI-CROSSWALK.md) | What was preserved, strengthened, or replaced from the original Ultra Builder Pro |
|
|
428
417
|
| [Agent Context](./docs/AGENT-CONTEXT.md) | Context Manifest and host-agent execution contract |
|
|
429
|
-
| [
|
|
418
|
+
| [Plugin Isolation Contract](./docs/PLUGIN-ISOLATION-CONTRACT.md) | Plugin ownership, explicit activation, idle behavior, and user-instruction isolation |
|
|
430
419
|
| [State DB Access Policy](./docs/STATE-DB-ACCESS-POLICY.md) | Multi-process authority and write rules |
|
|
431
420
|
| [Roadmap](./docs/ROADMAP.md) | Current and historical delivery scope |
|
|
432
421
|
| [Changelog](./CHANGELOG.md) | Release history |
|
|
@@ -4,18 +4,22 @@ const SURFACES = Object.freeze({
|
|
|
4
4
|
claude: Object.freeze({
|
|
5
5
|
primary: 'AskUserQuestion',
|
|
6
6
|
fallback: 'direct_user_interaction',
|
|
7
|
+
availability: 'interactive_session',
|
|
7
8
|
}),
|
|
8
9
|
codex: Object.freeze({
|
|
9
10
|
primary: 'request_user_input',
|
|
10
11
|
fallback: 'direct_user_interaction',
|
|
12
|
+
availability: 'current_mode_exposes_tool',
|
|
11
13
|
}),
|
|
12
14
|
opencode: Object.freeze({
|
|
13
15
|
primary: 'question',
|
|
14
16
|
fallback: 'direct_user_interaction',
|
|
17
|
+
availability: 'question_permission_not_denied',
|
|
15
18
|
}),
|
|
16
19
|
kimi: Object.freeze({
|
|
17
|
-
primary: '
|
|
20
|
+
primary: 'AskUserQuestion',
|
|
18
21
|
fallback: 'direct_user_interaction',
|
|
22
|
+
availability: 'interactive_non_auto_mode',
|
|
19
23
|
}),
|
|
20
24
|
});
|
|
21
25
|
|
|
@@ -23,18 +27,21 @@ function interactionContract(runtime) {
|
|
|
23
27
|
const question = SURFACES[runtime];
|
|
24
28
|
if (!question) throw new Error(`unsupported interaction runtime: ${runtime}`);
|
|
25
29
|
return {
|
|
26
|
-
schema_version: '1.
|
|
30
|
+
schema_version: '1.1',
|
|
27
31
|
runtime,
|
|
28
32
|
authority: {
|
|
29
33
|
user: [
|
|
30
34
|
'product_intent',
|
|
31
35
|
'material_scope_and_tradeoffs',
|
|
36
|
+
'semantic_route_selection',
|
|
37
|
+
'risk_acceptance',
|
|
32
38
|
'destructive_or_external_effect_authorization',
|
|
33
39
|
],
|
|
34
40
|
host_model: [
|
|
35
41
|
'fact_finding_and_synthesis',
|
|
36
42
|
'reversible_implementation_judgment',
|
|
37
|
-
'
|
|
43
|
+
'semantic_route_recommendation',
|
|
44
|
+
'accepted_intent_normalization',
|
|
38
45
|
],
|
|
39
46
|
ultra_mcp: [
|
|
40
47
|
'durable_state_and_evidence_refs',
|
|
@@ -44,10 +51,25 @@ function interactionContract(runtime) {
|
|
|
44
51
|
},
|
|
45
52
|
interaction: {
|
|
46
53
|
question_surface: question,
|
|
54
|
+
semantic_selection_flow: [
|
|
55
|
+
'inspect',
|
|
56
|
+
'suggest',
|
|
57
|
+
'ask_if_unresolved',
|
|
58
|
+
'normalize',
|
|
59
|
+
'persist',
|
|
60
|
+
],
|
|
47
61
|
dependent_decisions: 'one_at_a_time',
|
|
48
62
|
independent_low_load_questions: { maximum: 3 },
|
|
49
63
|
explicit_current_intent: 'normalize_without_reconfirmation',
|
|
50
|
-
|
|
64
|
+
dismissed_question: 'remain_unanswered',
|
|
65
|
+
unavailable_native_surface: 'use_direct_interaction_if_permitted',
|
|
66
|
+
host_forbids_interaction: 'remain_unanswered',
|
|
67
|
+
},
|
|
68
|
+
persistence: {
|
|
69
|
+
accepted_intent: 'trust_as_current_authority',
|
|
70
|
+
user_interaction_proof: 'not_required',
|
|
71
|
+
raw_prompt_or_transcript: 'never_store',
|
|
72
|
+
pending_question: 'store_only_when_recovery_requires_it',
|
|
51
73
|
},
|
|
52
74
|
routing: {
|
|
53
75
|
semantic_recommendation_owner: 'host_model',
|
package/adapters/claude.js
CHANGED
|
@@ -68,10 +68,12 @@ function copySkills(repoRoot, target, names) {
|
|
|
68
68
|
'Claude Code Task workers using the installed review agent definitions',
|
|
69
69
|
);
|
|
70
70
|
}
|
|
71
|
+
const policy = skillPolicy(name);
|
|
71
72
|
return Buffer.from(serializeFrontmatter({
|
|
72
73
|
name,
|
|
73
74
|
description: fm.description,
|
|
74
|
-
'user-invocable':
|
|
75
|
+
'user-invocable': policy.userInvocable,
|
|
76
|
+
...(policy.userInvocable ? { 'disable-model-invocation': true } : {}),
|
|
75
77
|
}, adaptedBody));
|
|
76
78
|
},
|
|
77
79
|
});
|
package/adapters/kimi.js
CHANGED
|
@@ -20,6 +20,7 @@ const provenance = require('./_shared/provenance.cjs');
|
|
|
20
20
|
const {
|
|
21
21
|
CORE_PUBLIC_SKILLS,
|
|
22
22
|
WORKFLOW_HOOK_FILES,
|
|
23
|
+
skillPolicy,
|
|
23
24
|
skillsForRuntime,
|
|
24
25
|
} = require('./_shared/runtime-assets.cjs');
|
|
25
26
|
|
|
@@ -28,7 +29,6 @@ const MCP_SERVER_NAME = PLUGIN_ID;
|
|
|
28
29
|
const PROVENANCE_FILE = 'provenance.json';
|
|
29
30
|
const REGISTRY_RELATIVE = path.join('plugins', 'installed.json');
|
|
30
31
|
const MANAGED_RELATIVE = path.join('plugins', 'managed', PLUGIN_ID);
|
|
31
|
-
const BOOTSTRAP_SKILL = 'using-ultra-builder-pro';
|
|
32
32
|
|
|
33
33
|
function resolveTarget(ctx = {}) {
|
|
34
34
|
if (ctx.configDir) return path.resolve(ctx.configDir);
|
|
@@ -127,11 +127,13 @@ function transformSkill(buf, relPath, skillName) {
|
|
|
127
127
|
if (!relPath.endsWith('.md')) return buf;
|
|
128
128
|
const { fm, body } = parseFm(source);
|
|
129
129
|
if (!fm) return Buffer.from(kimiTextTransform(source, skillName), 'utf8');
|
|
130
|
+
const policy = skillPolicy(skillName);
|
|
130
131
|
const nativeFm = {
|
|
131
132
|
name: String(fm.name || skillName),
|
|
132
133
|
description: kimiTextTransform(fm.description || `${skillName} workflow`, skillName)
|
|
133
134
|
.replace(/\s+/g, ' ')
|
|
134
135
|
.trim(),
|
|
136
|
+
...(policy.userInvocable ? { disableModelInvocation: true } : {}),
|
|
135
137
|
};
|
|
136
138
|
return Buffer.from(serializeFm(nativeFm, kimiTextTransform(body, skillName)), 'utf8');
|
|
137
139
|
}
|
|
@@ -162,29 +164,6 @@ function copySkills(repoRoot, pluginRoot) {
|
|
|
162
164
|
});
|
|
163
165
|
installed.push(name);
|
|
164
166
|
}
|
|
165
|
-
const bootstrapRoot = path.join(pluginRoot, 'skills', BOOTSTRAP_SKILL);
|
|
166
|
-
ensureDir(bootstrapRoot);
|
|
167
|
-
writeAtomic(path.join(bootstrapRoot, 'SKILL.md'), `---
|
|
168
|
-
name: ${BOOTSTRAP_SKILL}
|
|
169
|
-
description: Bootstrap the Kimi-native Ultra Builder Pro runtime contract at session start.
|
|
170
|
-
---
|
|
171
|
-
|
|
172
|
-
# Ultra Builder Pro for Kimi Code
|
|
173
|
-
|
|
174
|
-
Kimi Code is the primary host and owns all edits, evidence, and final verification. Use the
|
|
175
|
-
namespaced \`/ultra-builder-pro:ultra-*\` commands or invoke the registered Ultra skills directly.
|
|
176
|
-
|
|
177
|
-
- \`.ultra/state.db\` is the only durable Ultra authority. JSON and Markdown under \`.ultra/\` are
|
|
178
|
-
projections or workflow artifacts and must never replace MCP state writes.
|
|
179
|
-
- Memory and code graph data belong to separately installed external providers. Ultra stores only
|
|
180
|
-
provider metadata references and never captures prompts, transcripts, or cross-session memory.
|
|
181
|
-
- Use Kimi \`TodoList\` for session coordination and Kimi \`Agent\` / \`AgentSwarm\` for bounded
|
|
182
|
-
workers. Bundled files under \`$KIMI_PLUGIN_ROOT/agents/\` are worker prompt templates.
|
|
183
|
-
- Before compaction, Ultra saves its workflow checkpoint. After compaction or recovery, inspect
|
|
184
|
-
\`.ultra/runtime/checkpoint.json\` and call the Ultra status/doctor MCP tools before continuing.
|
|
185
|
-
- If no Ultra workflow is active, the lifecycle hooks remain advisory except projection protection.
|
|
186
|
-
`);
|
|
187
|
-
installed.push(BOOTSTRAP_SKILL);
|
|
188
167
|
return installed;
|
|
189
168
|
}
|
|
190
169
|
|
|
@@ -280,7 +259,6 @@ function writeManifest(repoRoot, pluginRoot) {
|
|
|
280
259
|
homepage: pkg.homepage,
|
|
281
260
|
license: pkg.license || 'MIT',
|
|
282
261
|
skills: ['./skills'],
|
|
283
|
-
sessionStart: { skill: BOOTSTRAP_SKILL },
|
|
284
262
|
mcpServers: { [MCP_SERVER_NAME]: mcpManifest() },
|
|
285
263
|
hooks: buildHooksManifest(),
|
|
286
264
|
commands: ['./commands'],
|
|
@@ -351,9 +329,6 @@ function writePluginProvenance(repoRoot, target) {
|
|
|
351
329
|
mcp_launcher: { root: 'plugin', path: path.join('runtime', 'launch.cjs') },
|
|
352
330
|
hook_event_helper: { root: 'plugin', path: path.join('runtime', 'hook-event.cjs') },
|
|
353
331
|
hook_adapter: { root: 'plugin', path: path.join('hooks', 'adapters', 'kimi.py') },
|
|
354
|
-
session_bootstrap: {
|
|
355
|
-
root: 'plugin', path: path.join('skills', BOOTSTRAP_SKILL, 'SKILL.md'),
|
|
356
|
-
},
|
|
357
332
|
},
|
|
358
333
|
});
|
|
359
334
|
return { file, manifest };
|
|
@@ -444,7 +419,7 @@ function doctor(ctx = {}) {
|
|
|
444
419
|
&& manifest.skills.includes('./skills')
|
|
445
420
|
&& Array.isArray(manifest.commands)
|
|
446
421
|
&& manifest.commands.includes('./commands')
|
|
447
|
-
&& manifest.sessionStart
|
|
422
|
+
&& manifest.sessionStart === undefined;
|
|
448
423
|
const mcp = manifest.mcpServers?.[MCP_SERVER_NAME];
|
|
449
424
|
const expected = mcpManifest();
|
|
450
425
|
mcpOk = !!mcp
|
|
@@ -508,7 +483,6 @@ module.exports = {
|
|
|
508
483
|
name: 'kimi',
|
|
509
484
|
PLUGIN_ID,
|
|
510
485
|
MCP_SERVER_NAME,
|
|
511
|
-
BOOTSTRAP_SKILL,
|
|
512
486
|
buildHooksManifest,
|
|
513
487
|
kimiTextTransform,
|
|
514
488
|
resolveTarget,
|
package/adapters/opencode.js
CHANGED
|
@@ -38,6 +38,11 @@ const PLUGIN_MARKER = '// Managed by Ultra Builder Pro.';
|
|
|
38
38
|
const PROVENANCE_FILE = 'provenance.json';
|
|
39
39
|
const COMMAND_NAMES = CORE_PUBLIC_SKILLS;
|
|
40
40
|
|
|
41
|
+
function discoverableSkillNames() {
|
|
42
|
+
return skillsForRuntime('opencode')
|
|
43
|
+
.filter((name) => !CORE_PUBLIC_SKILLS.includes(name));
|
|
44
|
+
}
|
|
45
|
+
|
|
41
46
|
function resolveTarget(ctx = {}) {
|
|
42
47
|
if (ctx.configDir) return ctx.configDir;
|
|
43
48
|
if (ctx.scope === 'global') {
|
|
@@ -97,16 +102,26 @@ function openCodeTextTransform(input, assetName = '') {
|
|
|
97
102
|
return text;
|
|
98
103
|
}
|
|
99
104
|
|
|
100
|
-
function openCodeCommandTransform(buf, relPath, commandName) {
|
|
105
|
+
function openCodeCommandTransform(buf, relPath, commandName, workflowFile) {
|
|
101
106
|
if (!relPath.endsWith('.md')) return buf;
|
|
102
|
-
const { fm
|
|
103
|
-
if (!fm)
|
|
107
|
+
const { fm } = parseFm(buf.toString('utf8'));
|
|
108
|
+
if (!fm) throw new Error(`missing frontmatter in OpenCode command: ${commandName}`);
|
|
104
109
|
const nativeFm = {
|
|
105
110
|
description: openCodeTextTransform(fm.description || `${commandName} workflow`, commandName)
|
|
106
111
|
.replace(/\s+/g, ' ')
|
|
107
112
|
.trim(),
|
|
108
113
|
};
|
|
109
|
-
|
|
114
|
+
const body = [
|
|
115
|
+
`# Run ${commandName}`,
|
|
116
|
+
'',
|
|
117
|
+
`Read and follow \`${workflowFile}\` as the only workflow definition.`,
|
|
118
|
+
'This explicit command is the activation boundary; do not substitute a model-discovered',
|
|
119
|
+
'public skill or start another public Ultra workflow automatically.',
|
|
120
|
+
'',
|
|
121
|
+
'Arguments: $ARGUMENTS',
|
|
122
|
+
'',
|
|
123
|
+
].join('\n');
|
|
124
|
+
return Buffer.from(serializeFm(nativeFm, body), 'utf8');
|
|
110
125
|
}
|
|
111
126
|
|
|
112
127
|
function openCodeSkillAssetTransform(buf, relPath, skillName) {
|
|
@@ -229,7 +244,10 @@ function copyCommands(repoRoot, target) {
|
|
|
229
244
|
const file = `${name}.md`;
|
|
230
245
|
const source = path.join(repoRoot, 'commands', file);
|
|
231
246
|
if (!fs.existsSync(source)) throw new Error(`missing allowlisted OpenCode command: ${file}`);
|
|
232
|
-
const
|
|
247
|
+
const workflowFile = path.join(target, BUNDLE_DIR, 'workflows', name, 'SKILL.md');
|
|
248
|
+
const transformed = withManagedMarker(
|
|
249
|
+
openCodeCommandTransform(fs.readFileSync(source), file, name, workflowFile),
|
|
250
|
+
);
|
|
233
251
|
writeAtomic(path.join(output, file), transformed);
|
|
234
252
|
copied.push(file);
|
|
235
253
|
}
|
|
@@ -238,7 +256,7 @@ function copyCommands(repoRoot, target) {
|
|
|
238
256
|
|
|
239
257
|
function copySkills(repoRoot, target) {
|
|
240
258
|
const copied = [];
|
|
241
|
-
const names =
|
|
259
|
+
const names = discoverableSkillNames();
|
|
242
260
|
const skillsRoot = path.join(target, 'skills');
|
|
243
261
|
ensureDir(skillsRoot);
|
|
244
262
|
for (const entry of fs.readdirSync(skillsRoot, { withFileTypes: true })) {
|
|
@@ -262,6 +280,22 @@ function copySkills(repoRoot, target) {
|
|
|
262
280
|
return copied;
|
|
263
281
|
}
|
|
264
282
|
|
|
283
|
+
function copyPrivateWorkflows(repoRoot, bundleRoot) {
|
|
284
|
+
const copied = [];
|
|
285
|
+
const workflowsRoot = path.join(bundleRoot, 'workflows');
|
|
286
|
+
for (const name of CORE_PUBLIC_SKILLS) {
|
|
287
|
+
const source = path.join(repoRoot, 'skills', name);
|
|
288
|
+
if (!fs.existsSync(path.join(source, 'SKILL.md'))) {
|
|
289
|
+
throw new Error(`missing allowlisted OpenCode workflow: ${name}`);
|
|
290
|
+
}
|
|
291
|
+
const files = copyTree(source, path.join(workflowsRoot, name), {
|
|
292
|
+
transform: (buf, relPath) => openCodeSkillAssetTransform(buf, relPath, name),
|
|
293
|
+
});
|
|
294
|
+
copied.push(...files.map((rel) => path.join('workflows', name, rel)));
|
|
295
|
+
}
|
|
296
|
+
return copied;
|
|
297
|
+
}
|
|
298
|
+
|
|
265
299
|
function copyAgents(repoRoot, target) {
|
|
266
300
|
const sourceRoot = path.join(repoRoot, 'agents');
|
|
267
301
|
const output = path.join(target, 'agents');
|
|
@@ -279,7 +313,7 @@ function preflightAssets(repoRoot, target) {
|
|
|
279
313
|
for (const name of COMMAND_NAMES) {
|
|
280
314
|
assertManagedTextTarget(path.join(target, 'commands', `${name}.md`), 'command');
|
|
281
315
|
}
|
|
282
|
-
for (const name of
|
|
316
|
+
for (const name of discoverableSkillNames()) {
|
|
283
317
|
const destination = path.join(target, 'skills', name);
|
|
284
318
|
if (fs.existsSync(destination) && !isManaged(destination)) {
|
|
285
319
|
throw new Error(`refusing to replace unmanaged OpenCode skill: ${destination}`);
|
|
@@ -316,8 +350,8 @@ const BREADCRUMB_CLI = path.resolve(
|
|
|
316
350
|
function findUltraRoot(directory) {
|
|
317
351
|
let current = path.resolve(directory);
|
|
318
352
|
while (true) {
|
|
319
|
-
const
|
|
320
|
-
if (fs.existsSync(
|
|
353
|
+
const stateDb = path.join(current, ".ultra", "state.db");
|
|
354
|
+
if (fs.existsSync(stateDb) && fs.statSync(stateDb).isFile()) return current;
|
|
321
355
|
const parent = path.dirname(current);
|
|
322
356
|
if (parent === current) return null;
|
|
323
357
|
current = parent;
|
|
@@ -335,12 +369,13 @@ function readUltraContext(directory) {
|
|
|
335
369
|
timeout: 5000,
|
|
336
370
|
});
|
|
337
371
|
const value = JSON.parse(raw);
|
|
338
|
-
|
|
339
|
-
|
|
372
|
+
// A canonical breadcrumb is injectable only while DB authority proves an active workflow.
|
|
373
|
+
if (!value?.breadcrumb || !value.breadcrumb.workflow
|
|
374
|
+
|| typeof value.text !== "string" || !value.text) {
|
|
375
|
+
return { root, breadcrumb: null, text: null };
|
|
340
376
|
}
|
|
341
377
|
return { root, breadcrumb: value.breadcrumb, text: value.text };
|
|
342
|
-
} catch
|
|
343
|
-
process.stderr.write(\`[ultra-builder-pro] cannot read canonical breadcrumb: \${error.message}\\n\`);
|
|
378
|
+
} catch {
|
|
344
379
|
return { root, breadcrumb: null, text: null };
|
|
345
380
|
}
|
|
346
381
|
}
|
|
@@ -415,6 +450,7 @@ function install(ctx = {}) {
|
|
|
415
450
|
const bundleRoot = path.join(target, BUNDLE_DIR);
|
|
416
451
|
if (fs.existsSync(bundleRoot)) removeTree(bundleRoot);
|
|
417
452
|
ensureDir(bundleRoot);
|
|
453
|
+
report.copied.workflows = copyPrivateWorkflows(repoRoot, bundleRoot);
|
|
418
454
|
const runtime = buildMcpRuntime(repoRoot, bundleRoot, { runtime: 'opencode' });
|
|
419
455
|
markManaged(bundleRoot, { adapter: 'opencode', asset: 'runtime-bundle' });
|
|
420
456
|
const configFile = path.join(target, 'opencode.json');
|
|
@@ -433,7 +469,7 @@ function install(ctx = {}) {
|
|
|
433
469
|
const bundleAssets = provenance.assetRefsForTree('config', bundleRoot, {
|
|
434
470
|
exclude: [PROVENANCE_FILE],
|
|
435
471
|
}).map((asset) => ({ ...asset, path: path.join(BUNDLE_DIR, asset.path) }));
|
|
436
|
-
const skillMarkers =
|
|
472
|
+
const skillMarkers = discoverableSkillNames().map((name) => ({
|
|
437
473
|
root: 'config', path: path.join('skills', name, '.ubp-managed'),
|
|
438
474
|
}));
|
|
439
475
|
const provenanceFile = path.join(bundleRoot, PROVENANCE_FILE);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
description: Build evidence with
|
|
2
|
+
description: Build evidence with recommended, owner-selected semantic coverage and adaptive alignment
|
|
3
3
|
argument-hint: "[scope-or-question]"
|
|
4
4
|
workflow-ref: "@skills/ultra-research/SKILL.md"
|
|
5
5
|
---
|
package/docs/AGENT-CONTEXT.md
CHANGED
|
@@ -12,8 +12,8 @@ Ultra Builder Pro owns only:
|
|
|
12
12
|
`ultra-think`, plus the daily `ultra-change` and diagnostic `ultra-doctor`;
|
|
13
13
|
- four internal agent-only rule skills: `code-review-expert`, `security-rules`,
|
|
14
14
|
`integration-rules`, and `testing-rules`;
|
|
15
|
-
- the host-specific collaboration companions, `ultra-verify`, and
|
|
16
|
-
|
|
15
|
+
- the host-specific collaboration companions, `ultra-verify`, and host-native
|
|
16
|
+
explicit command or skill entry points;
|
|
17
17
|
- bounded review/debug agents, workflow-only hooks, MCP task state, and the
|
|
18
18
|
portable CLI/orchestrator.
|
|
19
19
|
|
|
@@ -44,7 +44,7 @@ reports are projections or workflow artifacts.
|
|
|
44
44
|
|
|
45
45
|
## 3. Live MCP and declared contracts
|
|
46
46
|
|
|
47
|
-
`spec/mcp-tools.yaml` declares and the bundled server registers
|
|
47
|
+
`spec/mcp-tools.yaml` declares and the bundled server registers 51 tools across
|
|
48
48
|
eight families:
|
|
49
49
|
|
|
50
50
|
| Family | Live tools |
|
|
@@ -53,15 +53,16 @@ eight families:
|
|
|
53
53
|
| `task.*` | create, update, list, get, switch_tag, delete, init_project, expand, parse_prd, dependency_topo, append_event, subscribe_events |
|
|
54
54
|
| `session.*` | spawn, close, get, list, admission_check, heartbeat, subscribe_events |
|
|
55
55
|
| `change.*` | create, update, get, list, context, breadcrumb, learning_propose, learning_resolve, converge, archive |
|
|
56
|
-
| `decision.*` | thread_start, get, list, open, resolve, delegate, defer, supersede, checkpoint |
|
|
56
|
+
| `decision.*` | thread_start, get, list, open, resolve, delegate, defer, supersede, complete, checkpoint |
|
|
57
57
|
| `workflow.*` | start, get, list, step, complete |
|
|
58
58
|
| `system.*` | doctor |
|
|
59
59
|
| `plan.*` | export, get |
|
|
60
60
|
|
|
61
61
|
Review, repository impact discovery, skill loading, and decision presentation remain
|
|
62
62
|
host-native capabilities rather than fake MCP contracts. MCP stores only normalized
|
|
63
|
-
decision authority
|
|
64
|
-
|
|
63
|
+
decision authority, pending-question recovery state, lifecycle completion, and optional
|
|
64
|
+
checkpoints; it never generates questions or retains prompts and transcripts. The
|
|
65
|
+
generated Codex capability map documents host replacements.
|
|
65
66
|
|
|
66
67
|
The complete write, transition, invalidation, and recovery contract lives in
|
|
67
68
|
[`WORKFLOW-LIFECYCLE.md`](./WORKFLOW-LIFECYCLE.md).
|
|
@@ -79,11 +80,13 @@ review, and deliver route back to the same thread instead of deciding for the ow
|
|
|
79
80
|
|
|
80
81
|
One partial unique index permits only one open item per thread. `decision.resolve`,
|
|
81
82
|
`decision.delegate`, and `decision.defer` preserve the source of authority;
|
|
82
|
-
`decision.supersede` preserves history when evidence or intent changes.
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
83
|
+
`decision.supersede` preserves history when evidence or intent changes.
|
|
84
|
+
`decision.complete` closes settled normalized state without manufacturing an approval
|
|
85
|
+
receipt. Prepare and confirm checkpointing remain optional and bind only a material
|
|
86
|
+
accepted cluster to current artifact digests when interruption recovery needs that
|
|
87
|
+
boundary. Status and breadcrumb return only the current question plus allowed and
|
|
88
|
+
mechanically required transitions, so recovery does not require replaying conversation
|
|
89
|
+
history.
|
|
87
90
|
|
|
88
91
|
## 5. Context Spine contract
|
|
89
92
|
|
|
@@ -191,31 +194,17 @@ Archive before prune; the confirmation token is intentionally required.
|
|
|
191
194
|
└── delivery/<workflow-id>.json
|
|
192
195
|
```
|
|
193
196
|
|
|
194
|
-
## 10.
|
|
197
|
+
## 10. Plugin and user-instruction isolation
|
|
195
198
|
|
|
196
|
-
General engineering doctrine
|
|
197
|
-
|
|
198
|
-
|
|
199
|
+
General engineering doctrine and long-term personal preferences live in each
|
|
200
|
+
host's durable `CLAUDE.md` or `AGENTS.md`. Ultra never writes those files. Its
|
|
201
|
+
workflow doctrine remains in plugin-owned skills and is loaded only through an
|
|
202
|
+
explicit public invocation.
|
|
199
203
|
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
Full mode replaces legacy unmarked prompt content with one complete host-native
|
|
206
|
-
engineering handbook:
|
|
207
|
-
|
|
208
|
-
```bash
|
|
209
|
-
ubp-handbook preview --runtime codex --full > /tmp/ubp-codex-handbook.md
|
|
210
|
-
ubp-handbook apply --runtime codex --full \
|
|
211
|
-
--confirm "PASTE_64_CHARACTER_TOKEN_HERE"
|
|
212
|
-
```
|
|
213
|
-
|
|
214
|
-
Supported runtime names are `claude`, `codex`, `opencode`, and `kimi`. The full
|
|
215
|
-
preview prints its content-bound confirmation token to stderr. Both apply modes
|
|
216
|
-
create a timestamped backup. Full mode preserves supported marker-delimited blocks
|
|
217
|
-
owned by other providers, follows handbook symlinks, and rejects missing or stale
|
|
218
|
-
confirmation. Plugin adapters never overwrite handbooks implicitly.
|
|
204
|
+
Installation and uninstall own only adapter-declared commands, skills, workers,
|
|
205
|
+
hooks, runtime assets, provenance, and host registration. Project authority is
|
|
206
|
+
created only by an explicit `ultra-init`, and uninstall never deletes `.ultra/`.
|
|
207
|
+
See [`PLUGIN-ISOLATION-CONTRACT.md`](./PLUGIN-ISOLATION-CONTRACT.md).
|
|
219
208
|
|
|
220
209
|
## 11. Verification
|
|
221
210
|
|