ultra-builder-pro-cli 0.17.0 → 0.18.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/.ultra-template/reports/templates/delivery-report.json +17 -0
- package/.ultra-template/reports/templates/test-report.json +18 -0
- package/CHANGELOG.md +56 -6
- package/README.md +394 -261
- package/adapters/_shared/codex-assets.cjs +24 -16
- package/adapters/_shared/file-ops.cjs +40 -3
- package/adapters/_shared/handbook.cjs +418 -5
- package/adapters/_shared/provenance.cjs +90 -6
- package/adapters/_shared/runtime-assets.cjs +0 -11
- package/bin/handbook.js +61 -8
- package/docs/AGENT-CONTEXT.md +17 -6
- package/docs/ARCHITECTURE.md +13 -14
- package/docs/DECISIONS.md +75 -0
- package/docs/LEGACY-CLI-CROSSWALK.md +3 -3
- package/docs/ROADMAP.md +14 -13
- package/docs/RUNTIME-COMPAT-MATRIX.md +14 -6
- package/docs/STATE-DB-ACCESS-POLICY.md +2 -2
- package/docs/USER-HANDBOOK-CONTRACT.md +76 -37
- package/docs/WORKFLOW-LIFECYCLE.md +12 -10
- package/mcp-server/lib/workflow-state.cjs +67 -54
- package/orchestrator/dispatch-rules.cjs +1 -1
- package/package.json +2 -2
- package/skills/ultra-research/SKILL.md +7 -4
- package/spec/cli-protocol.md +4 -4
- package/spec/mcp-tools.yaml +6 -6
- package/spec/schemas/context-file.v4.5.schema.json +1 -1
- package/spec/schemas/mcp-tools.schema.json +3 -3
- package/spec/schemas/state-db.sql +3 -3
- package/spec/schemas/tasks.v4.5.schema.json +1 -1
- package/docs/PLAN.zh-CN.md +0 -1696
|
@@ -90,15 +90,76 @@ function digestEntries(entries) {
|
|
|
90
90
|
return hash.digest('hex');
|
|
91
91
|
}
|
|
92
92
|
|
|
93
|
+
function runGit(repoRoot, args, encoding = 'utf8') {
|
|
94
|
+
const result = spawnSync('git', args, {
|
|
95
|
+
cwd: repoRoot,
|
|
96
|
+
encoding,
|
|
97
|
+
stdio: ['ignore', 'pipe', 'ignore'],
|
|
98
|
+
maxBuffer: 64 * 1024 * 1024,
|
|
99
|
+
});
|
|
100
|
+
return result.status === 0 ? result.stdout : null;
|
|
101
|
+
}
|
|
102
|
+
|
|
93
103
|
function sourceCommit(repoRoot) {
|
|
94
104
|
if (!fs.existsSync(path.join(repoRoot, '.git'))) return null;
|
|
95
|
-
const result =
|
|
96
|
-
|
|
97
|
-
});
|
|
98
|
-
const value = result.status === 0 ? result.stdout.trim() : '';
|
|
105
|
+
const result = runGit(repoRoot, ['rev-parse', 'HEAD']);
|
|
106
|
+
const value = typeof result === 'string' ? result.trim() : '';
|
|
99
107
|
return /^[0-9a-f]{40,64}$/i.test(value) ? value : null;
|
|
100
108
|
}
|
|
101
109
|
|
|
110
|
+
function sourceWorktreeState(repoRoot, commit) {
|
|
111
|
+
if (!fs.existsSync(path.join(repoRoot, '.git'))) {
|
|
112
|
+
return { sourceDirty: null, sourceWorktreeDigest: null };
|
|
113
|
+
}
|
|
114
|
+
const status = runGit(
|
|
115
|
+
repoRoot, ['status', '--porcelain=v1', '-z', '--untracked-files=all', '--', '.'], null,
|
|
116
|
+
);
|
|
117
|
+
if (!Buffer.isBuffer(status)) {
|
|
118
|
+
return { sourceDirty: null, sourceWorktreeDigest: null };
|
|
119
|
+
}
|
|
120
|
+
const trackedDiff = commit
|
|
121
|
+
? runGit(repoRoot, ['diff', '--binary', 'HEAD', '--', '.'], null)
|
|
122
|
+
: runGit(repoRoot, ['diff', '--binary', '--cached', '--', '.'], null);
|
|
123
|
+
const unstagedDiff = commit
|
|
124
|
+
? Buffer.alloc(0)
|
|
125
|
+
: runGit(repoRoot, ['diff', '--binary', '--', '.'], null);
|
|
126
|
+
const untrackedOutput = runGit(
|
|
127
|
+
repoRoot, ['ls-files', '--others', '--exclude-standard', '-z', '--', '.'],
|
|
128
|
+
);
|
|
129
|
+
if (!Buffer.isBuffer(trackedDiff) || !Buffer.isBuffer(unstagedDiff)
|
|
130
|
+
|| typeof untrackedOutput !== 'string') {
|
|
131
|
+
return { sourceDirty: null, sourceWorktreeDigest: null };
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
const hash = crypto.createHash(DIGEST_ALGORITHM);
|
|
135
|
+
hash.update('ultra-source-worktree-v1\0');
|
|
136
|
+
hash.update(commit || 'unborn');
|
|
137
|
+
hash.update('\0');
|
|
138
|
+
hash.update(status);
|
|
139
|
+
hash.update('\0');
|
|
140
|
+
hash.update(trackedDiff);
|
|
141
|
+
hash.update('\0');
|
|
142
|
+
hash.update(unstagedDiff);
|
|
143
|
+
hash.update('\0');
|
|
144
|
+
const untrackedPaths = untrackedOutput.split('\0').filter(Boolean).sort();
|
|
145
|
+
for (const relative of untrackedPaths) {
|
|
146
|
+
const target = path.resolve(repoRoot, relative);
|
|
147
|
+
if (target !== repoRoot && !target.startsWith(`${path.resolve(repoRoot)}${path.sep}`)) {
|
|
148
|
+
return { sourceDirty: null, sourceWorktreeDigest: null };
|
|
149
|
+
}
|
|
150
|
+
const stat = fs.lstatSync(target);
|
|
151
|
+
hash.update(relative);
|
|
152
|
+
hash.update('\0');
|
|
153
|
+
if (stat.isSymbolicLink()) hash.update(fs.readlinkSync(target));
|
|
154
|
+
else if (stat.isFile()) hash.update(fs.readFileSync(target));
|
|
155
|
+
hash.update('\0');
|
|
156
|
+
}
|
|
157
|
+
return {
|
|
158
|
+
sourceDirty: status.length > 0,
|
|
159
|
+
sourceWorktreeDigest: hash.digest('hex'),
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
|
|
102
163
|
function repositoryUrl(pkg) {
|
|
103
164
|
if (typeof pkg.repository === 'string') return pkg.repository;
|
|
104
165
|
if (pkg.repository && typeof pkg.repository.url === 'string') return pkg.repository.url;
|
|
@@ -107,10 +168,12 @@ function repositoryUrl(pkg) {
|
|
|
107
168
|
|
|
108
169
|
function packageSource(repoRoot) {
|
|
109
170
|
const pkg = JSON.parse(fs.readFileSync(path.join(repoRoot, 'package.json'), 'utf8'));
|
|
171
|
+
const commit = sourceCommit(repoRoot);
|
|
110
172
|
return {
|
|
111
173
|
packageInfo: { name: pkg.name, version: pkg.version },
|
|
112
174
|
repository: repositoryUrl(pkg),
|
|
113
|
-
sourceCommit:
|
|
175
|
+
sourceCommit: commit,
|
|
176
|
+
...sourceWorktreeState(repoRoot, commit),
|
|
114
177
|
};
|
|
115
178
|
}
|
|
116
179
|
|
|
@@ -123,11 +186,18 @@ function assetRefsForTree(rootName, root, { exclude = [] } = {}) {
|
|
|
123
186
|
|
|
124
187
|
function writeProvenance({
|
|
125
188
|
file, adapter, packageInfo, repository, sourceCommit: commit = null,
|
|
189
|
+
sourceDirty: dirty = null, sourceWorktreeDigest: worktreeDigest = null,
|
|
126
190
|
roots: inputRoots, assets: inputAssets, contracts: inputContracts = {},
|
|
127
191
|
}) {
|
|
128
192
|
if (!file || !adapter || !packageInfo?.name || !packageInfo?.version || !repository) {
|
|
129
193
|
throw new Error('provenance file, adapter, package, version, and repository are required');
|
|
130
194
|
}
|
|
195
|
+
if (dirty !== null && typeof dirty !== 'boolean') {
|
|
196
|
+
throw new Error('provenance source dirty state must be a boolean or null');
|
|
197
|
+
}
|
|
198
|
+
if (worktreeDigest !== null && !/^[0-9a-f]{64}$/i.test(worktreeDigest)) {
|
|
199
|
+
throw new Error('provenance source worktree digest must be a SHA-256 digest or null');
|
|
200
|
+
}
|
|
131
201
|
const roots = normalizeRoots(inputRoots);
|
|
132
202
|
const refs = normalizeAssetRefs(inputAssets, roots);
|
|
133
203
|
const assets = refs.map((ref) => {
|
|
@@ -145,7 +215,12 @@ function writeProvenance({
|
|
|
145
215
|
schema_version: SCHEMA_VERSION,
|
|
146
216
|
adapter,
|
|
147
217
|
package: { name: packageInfo.name, version: packageInfo.version },
|
|
148
|
-
source: {
|
|
218
|
+
source: {
|
|
219
|
+
repository,
|
|
220
|
+
commit: commit || null,
|
|
221
|
+
dirty,
|
|
222
|
+
worktree_digest: worktreeDigest,
|
|
223
|
+
},
|
|
149
224
|
installed_at: new Date().toISOString(),
|
|
150
225
|
roots,
|
|
151
226
|
content: { algorithm: DIGEST_ALGORITHM, digest: digestEntries(assets) },
|
|
@@ -188,6 +263,15 @@ function inspectProvenance({ file, expectedAdapter = null, expectedPackageVersio
|
|
|
188
263
|
if (!manifest.package?.name || !manifest.package?.version || !manifest.source?.repository) {
|
|
189
264
|
throw new Error('package and source metadata required');
|
|
190
265
|
}
|
|
266
|
+
if (manifest.source.dirty !== undefined && manifest.source.dirty !== null
|
|
267
|
+
&& typeof manifest.source.dirty !== 'boolean') {
|
|
268
|
+
throw new Error('source dirty state must be a boolean or null');
|
|
269
|
+
}
|
|
270
|
+
if (manifest.source.worktree_digest !== undefined
|
|
271
|
+
&& manifest.source.worktree_digest !== null
|
|
272
|
+
&& !/^[0-9a-f]{64}$/i.test(manifest.source.worktree_digest)) {
|
|
273
|
+
throw new Error('source worktree digest must be a SHA-256 digest or null');
|
|
274
|
+
}
|
|
191
275
|
} catch (error) {
|
|
192
276
|
return invalidReport(
|
|
193
277
|
manifestPath, 'degraded', issue('PROVENANCE_INVALID', { message: error.message }), expectedAdapter,
|
|
@@ -51,16 +51,6 @@ const MCP_DEPENDENT_SKILLS = Object.freeze([
|
|
|
51
51
|
'ultra-doctor',
|
|
52
52
|
]);
|
|
53
53
|
|
|
54
|
-
const RETIRED_SKILLS = Object.freeze([
|
|
55
|
-
'agent-browser',
|
|
56
|
-
'find-skills',
|
|
57
|
-
'recall',
|
|
58
|
-
'use-railway',
|
|
59
|
-
'vercel-composition-patterns',
|
|
60
|
-
'vercel-react-best-practices',
|
|
61
|
-
'vercel-react-native-skills',
|
|
62
|
-
]);
|
|
63
|
-
|
|
64
54
|
const WORKFLOW_HOOK_FILES = Object.freeze([
|
|
65
55
|
'active_task_context.py',
|
|
66
56
|
'context_spine.py',
|
|
@@ -98,7 +88,6 @@ module.exports = {
|
|
|
98
88
|
SUPPORTED_RUNTIMES,
|
|
99
89
|
COLLAB_SKILLS_BY_RUNTIME,
|
|
100
90
|
MCP_DEPENDENT_SKILLS,
|
|
101
|
-
RETIRED_SKILLS,
|
|
102
91
|
WORKFLOW_HOOK_FILES,
|
|
103
92
|
isSupportedRuntime,
|
|
104
93
|
skillPolicy,
|
package/bin/handbook.js
CHANGED
|
@@ -7,17 +7,23 @@ const path = require('node:path');
|
|
|
7
7
|
|
|
8
8
|
const {
|
|
9
9
|
applyHandbook,
|
|
10
|
+
applyFullHandbook,
|
|
10
11
|
mergeHandbook,
|
|
12
|
+
previewFullHandbook,
|
|
11
13
|
resolveHandbookFile,
|
|
12
14
|
} = require('../adapters/_shared/handbook.cjs');
|
|
13
15
|
|
|
14
16
|
function usage() {
|
|
15
17
|
return [
|
|
16
18
|
'Usage:',
|
|
17
|
-
' ubp-handbook preview --runtime <claude|codex|opencode|kimi> [--file <path>]',
|
|
19
|
+
' ubp-handbook preview --runtime <claude|codex|opencode|kimi> [--file <path>] [--full]',
|
|
18
20
|
' ubp-handbook apply --runtime <claude|codex|opencode|kimi> [--file <path>]',
|
|
21
|
+
' ubp-handbook apply --runtime <claude|codex|opencode|kimi> [--file <path>] --full --confirm <token>',
|
|
19
22
|
'',
|
|
20
|
-
'
|
|
23
|
+
'Default mode merges only the Ultra runtime contract.',
|
|
24
|
+
'Full mode replaces legacy unmarked prompt content with the complete host-native handbook,',
|
|
25
|
+
'preserves other provider-managed marker blocks, and creates a timestamped backup.',
|
|
26
|
+
'A full preview prints the target content to stdout and its apply confirmation token to stderr.',
|
|
21
27
|
].join('\n');
|
|
22
28
|
}
|
|
23
29
|
|
|
@@ -26,24 +32,71 @@ function parse(argv) {
|
|
|
26
32
|
const action = args.shift();
|
|
27
33
|
let runtime = null;
|
|
28
34
|
let file = null;
|
|
35
|
+
let full = false;
|
|
36
|
+
let confirmation = null;
|
|
37
|
+
function valueFor(flag, index) {
|
|
38
|
+
const value = args[index + 1];
|
|
39
|
+
if (!value || value.startsWith('--')) throw new Error(`${flag} requires a value`);
|
|
40
|
+
return value;
|
|
41
|
+
}
|
|
29
42
|
for (let i = 0; i < args.length; i++) {
|
|
30
|
-
if (args[i] === '--runtime')
|
|
31
|
-
|
|
43
|
+
if (args[i] === '--runtime') {
|
|
44
|
+
runtime = valueFor('--runtime', i);
|
|
45
|
+
i += 1;
|
|
46
|
+
} else if (args[i] === '--file') {
|
|
47
|
+
file = valueFor('--file', i);
|
|
48
|
+
i += 1;
|
|
49
|
+
}
|
|
50
|
+
else if (args[i] === '--full') full = true;
|
|
51
|
+
else if (args[i] === '--confirm') {
|
|
52
|
+
confirmation = valueFor('--confirm', i);
|
|
53
|
+
i += 1;
|
|
54
|
+
}
|
|
32
55
|
else throw new Error(`unknown argument: ${args[i]}`);
|
|
33
56
|
}
|
|
34
57
|
if (!['preview', 'apply'].includes(action) || !runtime) throw new Error(usage());
|
|
35
|
-
|
|
58
|
+
if (!['claude', 'codex', 'opencode', 'kimi'].includes(runtime)) {
|
|
59
|
+
throw new Error(`unsupported handbook runtime: ${runtime}`);
|
|
60
|
+
}
|
|
61
|
+
if (action === 'apply' && full && !confirmation) {
|
|
62
|
+
throw new Error('full handbook apply requires --confirm <token> from a current full preview');
|
|
63
|
+
}
|
|
64
|
+
if (confirmation && (action !== 'apply' || !full)) {
|
|
65
|
+
throw new Error('--confirm is valid only with apply --full');
|
|
66
|
+
}
|
|
67
|
+
return {
|
|
68
|
+
action,
|
|
69
|
+
runtime,
|
|
70
|
+
file,
|
|
71
|
+
full,
|
|
72
|
+
confirmation,
|
|
73
|
+
};
|
|
36
74
|
}
|
|
37
75
|
|
|
38
76
|
function main() {
|
|
39
|
-
const {
|
|
77
|
+
const {
|
|
78
|
+
action,
|
|
79
|
+
runtime,
|
|
80
|
+
file,
|
|
81
|
+
full,
|
|
82
|
+
confirmation,
|
|
83
|
+
} = parse(process.argv);
|
|
40
84
|
const target = path.resolve(file || resolveHandbookFile(runtime, { homeDir: os.homedir() }));
|
|
41
85
|
if (action === 'preview') {
|
|
42
86
|
const existing = fs.existsSync(target) ? fs.readFileSync(target, 'utf8') : '';
|
|
43
|
-
|
|
87
|
+
if (full) {
|
|
88
|
+
const preview = previewFullHandbook({ runtime, file: target });
|
|
89
|
+
process.stdout.write(preview.content);
|
|
90
|
+
process.stderr.write(`Full apply confirmation: ${preview.confirmation}\n`);
|
|
91
|
+
} else {
|
|
92
|
+
process.stdout.write(mergeHandbook(existing, runtime));
|
|
93
|
+
}
|
|
44
94
|
return;
|
|
45
95
|
}
|
|
46
|
-
|
|
96
|
+
const result = full
|
|
97
|
+
? applyFullHandbook({ runtime, file: target, confirmation })
|
|
98
|
+
: applyHandbook({ runtime, file: target });
|
|
99
|
+
process.stdout.write(JSON.stringify(result) + '\n');
|
|
47
100
|
}
|
|
48
101
|
|
|
49
102
|
try {
|
package/docs/AGENT-CONTEXT.md
CHANGED
|
@@ -193,18 +193,29 @@ Archive before prune; the confirmation token is intentionally required.
|
|
|
193
193
|
|
|
194
194
|
## 10. User handbook integration
|
|
195
195
|
|
|
196
|
-
General engineering doctrine
|
|
197
|
-
Ultra Builder Pro
|
|
196
|
+
General engineering doctrine lives in the host's durable `CLAUDE.md` or `AGENTS.md`.
|
|
197
|
+
Ultra Builder Pro supports two explicit operations. Default mode updates only the
|
|
198
|
+
bounded runtime contract:
|
|
198
199
|
|
|
199
200
|
```bash
|
|
200
201
|
ubp-handbook preview --runtime codex
|
|
201
202
|
ubp-handbook apply --runtime codex
|
|
202
203
|
```
|
|
203
204
|
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
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.
|
|
208
219
|
|
|
209
220
|
## 11. Verification
|
|
210
221
|
|
package/docs/ARCHITECTURE.md
CHANGED
|
@@ -1,10 +1,8 @@
|
|
|
1
1
|
# Ultra Builder Pro CLI — Architecture
|
|
2
2
|
|
|
3
|
-
> Single-page entry point for reviewers and contributors.
|
|
4
|
-
>
|
|
5
|
-
>
|
|
6
|
-
>
|
|
7
|
-
> Trace: PLAN §4, decisions D12 / D13 / D18 / D20 / D29 / D32 / D33.
|
|
3
|
+
> Single-page entry point for reviewers and contributors. Current authority and
|
|
4
|
+
> package boundaries live in [`docs/DECISIONS.md`](./DECISIONS.md); executable
|
|
5
|
+
> behavior remains defined by source, schemas, and tests.
|
|
8
6
|
|
|
9
7
|
## 1. One sentence
|
|
10
8
|
|
|
@@ -143,9 +141,9 @@ same authoritative state shape without rewriting application code.
|
|
|
143
141
|
|
|
144
142
|
Initialization completes after local authority, classification, Git/scaffold setup,
|
|
145
143
|
and read-back verification. It does not start or complete research. An explicit
|
|
146
|
-
`ultra-research` invocation then records
|
|
147
|
-
|
|
148
|
-
|
|
144
|
+
`ultra-research` invocation then records the model-selected semantic coverage and
|
|
145
|
+
executes, verifies, or reuses only the evidence needed to converge the baseline.
|
|
146
|
+
Omitted catalog areas create no workflow row.
|
|
149
147
|
|
|
150
148
|
Auto initialization preserves an existing Git repository and HEAD. When Git is absent,
|
|
151
149
|
it initializes `main`, adds the symlink-safe `.ultra` rule to `.gitignore`, and persists
|
|
@@ -370,11 +368,12 @@ host-specific plugin, MCP, hook, launcher, and runtime contracts expected at
|
|
|
370
368
|
that install scope. It never attributes a package to an enclosing consumer
|
|
371
369
|
repository commit.
|
|
372
370
|
|
|
373
|
-
`ubp --doctor [--json]` is read-only: it recomputes hashes and
|
|
374
|
-
entry points, returning a non-zero degraded result for
|
|
375
|
-
provenance, content drift, or broken host wiring.
|
|
376
|
-
`system.doctor`, which
|
|
377
|
-
and backup-first
|
|
371
|
+
`ubp --all --global --doctor [--json]` is read-only: it recomputes hashes and
|
|
372
|
+
validates those entry points, returning a non-zero degraded result for
|
|
373
|
+
missing/corrupt provenance, content drift, or broken host wiring. A single host
|
|
374
|
+
can be selected instead of `--all`. This is separate from `system.doctor`, which
|
|
375
|
+
diagnoses project state, projection, incidents, sessions, and backup-first
|
|
376
|
+
workflow recovery.
|
|
378
377
|
|
|
379
378
|
## 8. Two timelines — rule layer vs execution layer
|
|
380
379
|
|
|
@@ -412,7 +411,7 @@ shippable; downstream slip never blocks an earlier release.
|
|
|
412
411
|
| How do CLI subcommands map to MCP tools? | [`spec/cli-protocol.md`](../spec/cli-protocol.md) |
|
|
413
412
|
| Exact SQLite schema? | [`spec/schemas/state-db.sql`](../spec/schemas/state-db.sql) |
|
|
414
413
|
| What does a tasks.json look like after projection? | [`spec/fixtures/valid/tasks.v4.5.json`](../spec/fixtures/valid/tasks.v4.5.json) |
|
|
415
|
-
|
|
|
414
|
+
| Current authority and package decisions | [`docs/DECISIONS.md`](./DECISIONS.md) |
|
|
416
415
|
| When does each workflow write, invalidate, and converge state? | [`docs/WORKFLOW-LIFECYCLE.md`](./WORKFLOW-LIFECYCLE.md) |
|
|
417
416
|
|
|
418
417
|
## 10. Verifying the architecture
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
# Ultra Builder Pro decision contract
|
|
2
|
+
|
|
3
|
+
This document records the current product and authority boundaries that apply to
|
|
4
|
+
the distributed package. Executable behavior remains defined by source,
|
|
5
|
+
`spec/mcp-tools.yaml`, and `spec/schemas/state-db.sql`; `package.json` is the
|
|
6
|
+
release-version authority.
|
|
7
|
+
|
|
8
|
+
## Authority split
|
|
9
|
+
|
|
10
|
+
| Layer | Owns | Must not own |
|
|
11
|
+
|---|---|---|
|
|
12
|
+
| User intent | Goals, acceptance, non-goals, material product trade-offs, risk acceptance, and authorization for irreversible or external effects | Facts that the current checkout or runtime can establish directly |
|
|
13
|
+
| Host model | Classification, investigation, research coverage, solution design, task decomposition, context, test and review strategy, documentation impact, and next-action recommendations | Fabricated evidence, bypassed authorization, or durable lifecycle state |
|
|
14
|
+
| Ultra MCP | IDs, state, digests, provenance, freshness, locks, leases, transactions, recovery, and legal state transitions | Product direction, a fixed research route, technology selection, or business decisions |
|
|
15
|
+
| Host adapter | Native Skill discovery, user-question surfaces, tool invocation, installation, and runtime wiring | A second project-state authority |
|
|
16
|
+
| Hook | Lifecycle observation, compact DB-derived context, recovery hints, and generated-projection protection | Ordinary development blocking or semantic route selection |
|
|
17
|
+
|
|
18
|
+
`.ultra/state.db` is the only durable Ultra lifecycle authority. Generated JSON
|
|
19
|
+
and Markdown are projections or evidence artifacts. Prompt text, chat history,
|
|
20
|
+
external memory, and code-graph payloads are not Ultra authority.
|
|
21
|
+
|
|
22
|
+
## Research coverage
|
|
23
|
+
|
|
24
|
+
The research references form an optional semantic catalog. The host model
|
|
25
|
+
selects only the areas justified by the current goal and evidence, records an
|
|
26
|
+
evidence-based selection reason, and always includes synthesis. Omitted catalog
|
|
27
|
+
areas create no workflow rows. An explicit `not_applicable` or accepted
|
|
28
|
+
`deferred` entry is recorded only when preserving that exclusion is useful.
|
|
29
|
+
|
|
30
|
+
MCP validates generic invariants: selected identifiers must exist, dispositions
|
|
31
|
+
must be legal, reused or excluded evidence must be referenced, synthesis must be
|
|
32
|
+
active, and at least one non-synthesis area must be applicable. MCP does not
|
|
33
|
+
choose the coverage set.
|
|
34
|
+
|
|
35
|
+
## Lifecycle boundaries
|
|
36
|
+
|
|
37
|
+
- `ultra-init` classifies and initializes local project authority. It does not
|
|
38
|
+
perform product research or start another workflow.
|
|
39
|
+
- `ultra-research` establishes or refreshes evidence and converges a baseline
|
|
40
|
+
only after the required user decisions and local Git authority exist.
|
|
41
|
+
- `ultra-change` owns post-baseline product deltas. Research, planning,
|
|
42
|
+
development, testing, review, and delivery remain separately invocable
|
|
43
|
+
capabilities with DB-enforced prerequisites.
|
|
44
|
+
- `ultra-deliver` converges local Ultra evidence. Commit, push, publish, deploy,
|
|
45
|
+
messaging, and other external effects remain separately authorized host
|
|
46
|
+
actions.
|
|
47
|
+
|
|
48
|
+
## Package boundary
|
|
49
|
+
|
|
50
|
+
The package contains the public Ultra workflows, internal review-rule Skills,
|
|
51
|
+
host-specific collaboration companions, MCP runtime, adapters, lifecycle hooks,
|
|
52
|
+
and minimal project bootstrap. General browser, deployment, framework,
|
|
53
|
+
discovery, memory, and graph capabilities remain owned by their separately
|
|
54
|
+
installed providers. Ultra stores only bounded provider metadata references.
|
|
55
|
+
|
|
56
|
+
## Installation provenance
|
|
57
|
+
|
|
58
|
+
Each host installation records package identity, repository, source commit when
|
|
59
|
+
available, installed-asset hashes, and contract targets. A local source checkout
|
|
60
|
+
also records whether it was dirty and a deterministic worktree digest. An npm
|
|
61
|
+
installation has no package-local Git repository and records those source
|
|
62
|
+
checkout fields as `null`; it never inherits an enclosing consumer repository.
|
|
63
|
+
|
|
64
|
+
Installation and project diagnostics are read-only unless an explicit repair or
|
|
65
|
+
install action is requested. No local workflow completion authorizes a remote,
|
|
66
|
+
release, deployment, or destructive effect.
|
|
67
|
+
|
|
68
|
+
## Current source map
|
|
69
|
+
|
|
70
|
+
- Runtime architecture: [`ARCHITECTURE.md`](./ARCHITECTURE.md)
|
|
71
|
+
- Workflow state and invalidation: [`WORKFLOW-LIFECYCLE.md`](./WORKFLOW-LIFECYCLE.md)
|
|
72
|
+
- Host compatibility: [`RUNTIME-COMPAT-MATRIX.md`](./RUNTIME-COMPAT-MATRIX.md)
|
|
73
|
+
- User handbook projection: [`USER-HANDBOOK-CONTRACT.md`](./USER-HANDBOOK-CONTRACT.md)
|
|
74
|
+
- MCP interface: [`../spec/mcp-tools.yaml`](../spec/mcp-tools.yaml)
|
|
75
|
+
- Database contract: [`../spec/schemas/state-db.sql`](../spec/schemas/state-db.sql)
|
|
@@ -24,7 +24,7 @@ contract and adds stronger authority, recovery, or portability.
|
|
|
24
24
|
| Original capability | Current implementation | Compatibility result |
|
|
25
25
|
|---|---|---|
|
|
26
26
|
| Init gathers project facts, creates Ultra files, and establishes Git | `task.init_project` performs deterministic classification, scaffold, schema, Git bootstrap, read-back verification, and then stops | Preserved and strengthened. Init has its own completion boundary and never starts research implicitly. |
|
|
27
|
-
| Complete product and architecture research | `ultra-research` retains the
|
|
27
|
+
| Complete product and architecture research | `ultra-research` retains the semantic reference catalog while the model selects only applicable areas and records execute/verify/reuse/not-applicable/deferred dispositions as needed | Preserved without questionnaire overload. Necessary reports, typed semantic records, source digests, and material decision checkpoints add durable evidence. |
|
|
28
28
|
| Planning converts accepted research into executable work with dependencies | `ultra-plan` persists complete change-owned task contracts and an exact dependency graph | Preserved and strengthened with topology, acceptance coverage, public seams, verification commands, and plan digests. |
|
|
29
29
|
| Development uses isolated Git work, TDD, verification, review, commit, and integration | `ultra-dev`, `session.*`, and the session runner create real worktrees and retain task/review/commit evidence | Preserved and strengthened. Process exit cannot complete a task; uncommitted or unintegrated worktrees cannot be deleted. |
|
|
30
30
|
| Test checks wiring, acceptance, regression, build, performance, security, and failures | `ultra-test` emits a change-bound immutable report covering each applicable dimension | Preserved and strengthened with HEAD, context, task-set, and report-digest validation. |
|
|
@@ -83,7 +83,7 @@ task.init_project
|
|
|
83
83
|
-> greenfield classification
|
|
84
84
|
-> Git bootstrap when absent
|
|
85
85
|
-> init read-back and completion
|
|
86
|
-
-> explicit full research with
|
|
86
|
+
-> explicit full research with model-selected coverage
|
|
87
87
|
-> selected execute/verify/reuse work and synthesis
|
|
88
88
|
-> owner-authorized local checkpoint commit when Git is unborn
|
|
89
89
|
-> baseline.record
|
|
@@ -99,7 +99,7 @@ task.init_project
|
|
|
99
99
|
-> brownfield classification and selected scope
|
|
100
100
|
-> preserve current Git HEAD and dirty-state evidence
|
|
101
101
|
-> init read-back and completion
|
|
102
|
-
-> explicit adoption research with
|
|
102
|
+
-> explicit adoption research with model-selected coverage
|
|
103
103
|
-> characterization verification + known-red/gap ledger
|
|
104
104
|
-> baseline.record + owner approval
|
|
105
105
|
-> baseline.converge
|
package/docs/ROADMAP.md
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
# ultra-builder-pro-cli — Roadmap
|
|
2
2
|
|
|
3
|
-
> **Current roadmap**. [`
|
|
4
|
-
>
|
|
5
|
-
> `
|
|
6
|
-
> when
|
|
3
|
+
> **Current roadmap**. [`DECISIONS.md`](./DECISIONS.md) defines the current
|
|
4
|
+
> authority and package boundaries. Executable contracts live in `spec/`,
|
|
5
|
+
> `AGENT-CONTEXT.md`, and `RUNTIME-COMPAT-MATRIX.md`; source and contract tests
|
|
6
|
+
> win when roadmap text drifts.
|
|
7
7
|
|
|
8
8
|
**Goal**: distribute the Ultra Builder Pro engineering loop as native Claude
|
|
9
9
|
Code, OpenCode, Codex, and Kimi Code plugins, and run it with isolated sessions
|
|
@@ -13,7 +13,8 @@ sharing one authoritative workflow store.
|
|
|
13
13
|
|
|
14
14
|
**Distribution channels (v1.0)**: npm · Homebrew · pip.
|
|
15
15
|
|
|
16
|
-
**Release line**: `
|
|
16
|
+
**Release line**: the `package.json` version; every release is gated by
|
|
17
|
+
`npm run verify:release`.
|
|
17
18
|
|
|
18
19
|
---
|
|
19
20
|
|
|
@@ -39,11 +40,11 @@ sharing one authoritative workflow store.
|
|
|
39
40
|
| 5 | Recovery + staleness + auto-routing | ✅ done (D43) → v0.2 |
|
|
40
41
|
| 6 | Monitoring + telemetry | ✅ done (D44) → v0.2 |
|
|
41
42
|
| 4.6b | Full conformance suite | ✅ done (D45) — 20 conformance + 21 resolveTarget tests |
|
|
42
|
-
| 7 | tagged tasks + skill mining; retired Ultra memory
|
|
43
|
+
| 7 | tagged tasks + skill mining; retired Ultra memory delegated to external providers | ✅ superseded by the package-boundary cleanup |
|
|
43
44
|
| 8A | Plan automation (parse / topo / expand + artifact + human gate) | ✅ done (D47, `a932cb8`) → v0.3 |
|
|
44
45
|
| 8B | Execution automation (dispatch / parallel worktree / merge) | ✅ done (D48, `8224159`) — **v0.3 ready** |
|
|
45
46
|
| 8C | Continuous change packets + context compiler + convergence + doctor | ✅ done (D52) |
|
|
46
|
-
| 10 | Context
|
|
47
|
+
| 10 | Context Manifest v3 + breadcrumb + fresh-context budget + spec learning + two-axis review | ✅ done |
|
|
47
48
|
| 11 | Greenfield/brownfield baseline adoption + advisory context budgets + convergence gate | ✅ done |
|
|
48
49
|
| 12 | Repository evidence snapshots + gap ledger + migration re-adoption + incident governance | ✅ done |
|
|
49
50
|
| 13 | Durable init-to-delivery workflows + task execution contracts + immutable stage evidence | ✅ done |
|
|
@@ -79,16 +80,16 @@ ultra-tools/ ← CLI fallback, migration, and diagnostics
|
|
|
79
80
|
└── legacy-memory.cjs (explicit inspect/archive/confirmed prune)
|
|
80
81
|
|
|
81
82
|
bin/install.js ← multi-runtime installer
|
|
82
|
-
bin/handbook.js ← explicit
|
|
83
|
+
bin/handbook.js ← explicit bounded or full host-native handbook sync
|
|
83
84
|
adapters/ ← native Claude/OpenCode/Codex plugin builders
|
|
84
85
|
skills/ ← allowlisted Ultra workflows, internal rules, and collab companions
|
|
85
86
|
hooks/ ← 7 executable workflow hooks + shared Context Spine helper; OpenCode uses native JavaScript hooks
|
|
86
87
|
docs/
|
|
87
|
-
├──
|
|
88
|
+
├── DECISIONS.md current authority and package boundaries
|
|
88
89
|
├── ARCHITECTURE.md Phase 1 single-page entry point
|
|
89
90
|
├── WORKFLOW-LIFECYCLE.md baseline classification + DB transition contract
|
|
90
91
|
├── AGENT-CONTEXT.md Phase 3 canonical runtime context contract
|
|
91
|
-
├── USER-HANDBOOK-CONTRACT.md
|
|
92
|
+
├── USER-HANDBOOK-CONTRACT.md bounded/full CLAUDE.md / AGENTS.md contract
|
|
92
93
|
├── RUNTIME-COMPAT-MATRIX.md Phase 4 runtime capability matrix
|
|
93
94
|
├── STATE-DB-ACCESS-POLICY.md Phase 2 multi-process write contract
|
|
94
95
|
├── COMMIT-HASH-BACKFILL.md Phase 2.8 two-commit completion flow
|
|
@@ -106,6 +107,6 @@ npm audit
|
|
|
106
107
|
|
|
107
108
|
## Out of scope for v1.0 (deferred)
|
|
108
109
|
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
110
|
+
Additional runtimes, a web dashboard or TUI, a team-collaboration server, and
|
|
111
|
+
an independent plugin marketplace remain deferred until a current product
|
|
112
|
+
decision brings them into scope.
|
|
@@ -73,7 +73,7 @@ they do not deny edits or stop active incident work.
|
|
|
73
73
|
| stdio MCP registration | plugin `.mcp.json` | `opencode.json` local MCP entry | plugin `.mcp.json` | plugin `mcpServers` entry |
|
|
74
74
|
| Live/declared contracts | 50 | 50 | 50 | 50 |
|
|
75
75
|
| Greenfield/brownfield baseline adoption | FULL | FULL | FULL | FULL |
|
|
76
|
-
| Context
|
|
76
|
+
| Context Manifest v3 / breadcrumb | FULL | FULL, same bundled read-only DB reader as every hook | FULL | FULL |
|
|
77
77
|
| Approval-gated spec learning | FULL | FULL | FULL | FULL |
|
|
78
78
|
| Host-native review/discovery/ask | native | native | documented in `codex-capability-map.json` | native Kimi tools and workers |
|
|
79
79
|
| Durable authority | project `.ultra/state.db` | project `.ultra/state.db` | project `.ultra/state.db` | project `.ultra/state.db` |
|
|
@@ -95,12 +95,14 @@ cannot be established. On POSIX it intentionally uses `env node` because Kimi
|
|
|
95
95
|
|---|---|---|---|---|
|
|
96
96
|
| Durable user file | `~/.claude/CLAUDE.md` | `~/.config/opencode/AGENTS.md` | `~/.codex/AGENTS.md` | `~/.kimi-code/AGENTS.md` |
|
|
97
97
|
| Automatic overwrite by plugin install | no | no | no | no |
|
|
98
|
-
| Explicit managed-block sync | `ubp-handbook --runtime claude` | `ubp-handbook --runtime opencode` | `ubp-handbook --runtime codex` | `ubp-handbook --runtime kimi` |
|
|
98
|
+
| Explicit managed-block sync | `ubp-handbook apply --runtime claude` | `ubp-handbook apply --runtime opencode` | `ubp-handbook apply --runtime codex` | `ubp-handbook apply --runtime kimi` |
|
|
99
|
+
| Explicit complete-handbook convergence | `--full --confirm TOKEN` | `--full --confirm TOKEN` | `--full --confirm TOKEN` | `--full --confirm TOKEN` |
|
|
99
100
|
| Backup before change | FULL | FULL | FULL | FULL |
|
|
100
101
|
|
|
101
102
|
The Kimi plugin installer does not edit `~/.kimi-code/config.toml`. Handbook
|
|
102
103
|
sync remains a separate, previewable action so user policy and plugin mechanics
|
|
103
|
-
do not become one irreversible mutation.
|
|
104
|
+
do not become one irreversible mutation. Full mode is a semantic host rendering,
|
|
105
|
+
not a product-name or path substitution.
|
|
104
106
|
|
|
105
107
|
## 6. Install, update, and uninstall
|
|
106
108
|
|
|
@@ -113,9 +115,15 @@ do not become one irreversible mutation.
|
|
|
113
115
|
| Preserves unrelated config | FULL | FULL | FULL | FULL, including `config.toml` and unrelated registry records |
|
|
114
116
|
| Uninstall ownership guard | managed plugin root | sentinels + owned MCP entry | managed root/manifest/agent headers | managed root + exact registry record |
|
|
115
117
|
| Normalized install provenance | FULL | FULL | FULL | FULL |
|
|
116
|
-
|
|
|
118
|
+
| Local-source dirty state and worktree digest | FULL | FULL | FULL | FULL |
|
|
119
|
+
| Read-only `ubp --all --global --doctor` | FULL | FULL | FULL | FULL |
|
|
117
120
|
| Asset-content and host-contract drift detection | FULL | FULL | FULL | FULL |
|
|
118
121
|
|
|
122
|
+
Package-local Git provenance never falls through to an enclosing consumer
|
|
123
|
+
repository. Source installs record commit, dirty state, and a deterministic
|
|
124
|
+
worktree digest; registry installs record unavailable checkout fields as
|
|
125
|
+
`null`.
|
|
126
|
+
|
|
119
127
|
Kimi's global managed root is
|
|
120
128
|
`~/.kimi-code/plugins/managed/ultra-builder-pro`; its only registry mutation is
|
|
121
129
|
the owned `ultra-builder-pro` entry in `~/.kimi-code/plugins/installed.json`.
|
|
@@ -143,8 +151,8 @@ records. Uninstall refuses an unmanaged or conflicting root.
|
|
|
143
151
|
skills and generic/memory hooks from re-entering a package.
|
|
144
152
|
- `tests/retired-runtime.test.cjs` prevents retired runtime code or prompt text
|
|
145
153
|
from re-entering active product surfaces.
|
|
146
|
-
- `adapters/_shared/tests/handbook.test.cjs` verifies
|
|
147
|
-
migration, and idempotency.
|
|
154
|
+
- `adapters/_shared/tests/handbook.test.cjs` verifies bounded and full host
|
|
155
|
+
rendering, external-provider block preservation, backup, migration, and idempotency.
|
|
148
156
|
- `adapters/_shared/tests/provenance.test.cjs` verifies normalized manifests,
|
|
149
157
|
content hashes, source attribution, corruption handling, and contract drift.
|
|
150
158
|
- `tests/install.test.cjs` verifies healthy four-host doctor output and
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# `.ultra/state.db` access policy
|
|
2
2
|
|
|
3
|
-
>
|
|
4
|
-
>
|
|
3
|
+
> Multi-process access contract. Current authority is defined by
|
|
4
|
+
> [`DECISIONS.md`](./DECISIONS.md) and the live database schema.
|
|
5
5
|
|
|
6
6
|
`.ultra/state.db` is the only authoritative state store for baselines, changes,
|
|
7
7
|
decision threads/items, tasks, workflow runs/steps, events, sessions, incidents,
|