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.
@@ -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 = spawnSync('git', ['rev-parse', 'HEAD'], {
96
- cwd: repoRoot, encoding: 'utf8', stdio: ['ignore', 'pipe', 'ignore'],
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: sourceCommit(repoRoot),
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: { repository, commit: commit || null },
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
- 'The apply command creates a timestamped backup before changing an existing file.',
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') runtime = args[++i];
31
- else if (args[i] === '--file') file = args[++i];
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
- return { action, runtime, file };
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 { action, runtime, file } = parse(process.argv);
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
- process.stdout.write(mergeHandbook(existing, runtime));
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
- process.stdout.write(JSON.stringify(applyHandbook({ runtime, file: target })) + '\n');
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 {
@@ -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 remains user-owned in `CLAUDE.md` or `AGENTS.md`.
197
- Ultra Builder Pro contributes one managed section only. Preview or apply it with:
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
- Supported runtime names are `claude`, `codex`, `opencode`, and `kimi`. Apply creates a
205
- timestamped backup, replaces only the marked block, and can migrate the old
206
- Codex `## Ultra Builder Pro Runtime Contract` section without touching the next
207
- user section. Plugin adapters themselves do not silently overwrite handbooks.
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
 
@@ -1,10 +1,8 @@
1
1
  # Ultra Builder Pro CLI — Architecture
2
2
 
3
- > Single-page entry point for reviewers and contributors. The detailed
4
- > roadmap and decision log live in [`docs/PLAN.zh-CN.md`](./PLAN.zh-CN.md);
5
- > this file freezes the architectural shape that the PLAN drives toward.
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 a disposition for each of the seventeen
147
- coverage areas and executes, verifies, or reuses only the evidence needed to converge
148
- the baseline.
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 validates those
374
- entry points, returning a non-zero degraded result for missing/corrupt
375
- provenance, content drift, or broken host wiring. This is separate from
376
- `system.doctor`, which diagnoses project state, projection, incidents, sessions,
377
- and backup-first workflow recovery.
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
- | Phase-by-phase work breakdown + decision log | [`docs/PLAN.zh-CN.md`](./PLAN.zh-CN.md) |
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 17 semantic areas as a coverage catalog with execute/verify/reuse/not-applicable/deferred dispositions | Preserved without questionnaire overload. Necessary reports, typed semantic records, source digests, and material decision checkpoints add durable evidence. |
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 17 coverage dispositions
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 17 coverage dispositions
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**. [`PLAN.zh-CN.md`](./PLAN.zh-CN.md) preserves the original
4
- > phase plan and decision history. Current executable contracts live in
5
- > `spec/`, `AGENT-CONTEXT.md`, and `RUNTIME-COMPAT-MATRIX.md`; those sources win
6
- > when historical plan text differs.
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**: `0.16.x`; every release is gated by `npm run verify:release`.
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 handed to cloud-mem/claude-mem | ✅ superseded by D50 boundary cleanup |
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 Spine v2 + breadcrumb + fresh-context budget + spec learning + two-axis review | ✅ done |
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 managed user-handbook sync
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
- ├── PLAN.zh-CN.md historical phase plan + decision log
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 managed CLAUDE.md / AGENTS.md boundary
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
- PLAN §13 lists Copilot / Cursor / Windsurf / 7 more runtimes, web
110
- dashboard / TUI, team-collab server, plugin
111
- marketplace.
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 Spine v2 / breadcrumb | FULL | FULL, same bundled read-only DB reader as every hook | FULL | FULL |
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
- | Read-only `ubp --doctor` | FULL | FULL | FULL | FULL |
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 host rendering, backup,
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
- > Phase 2.2 contract. Trace: PLAN §6 Phase 2.2, decisions D18 / D32 / D37,
4
- > risks R21 / R25.
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,