coding-agent-harness 1.0.2 → 1.0.4
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 +25 -0
- package/CONTRIBUTING.md +98 -0
- package/README.md +211 -86
- package/README.zh-CN.md +54 -34
- package/SKILL.md +25 -18
- package/docs-release/README.md +9 -5
- package/docs-release/architecture/overview.md +17 -5
- package/docs-release/architecture/overview.zh-CN.md +9 -5
- package/docs-release/assets/dashboard-overview.png +0 -0
- package/docs-release/guides/agent-installation.en-US.md +31 -8
- package/docs-release/guides/agent-installation.md +34 -9
- package/docs-release/guides/contributing.md +100 -0
- package/docs-release/guides/contributing.zh-CN.md +99 -0
- package/docs-release/guides/document-audience-and-surfaces.en-US.md +3 -2
- package/docs-release/guides/document-audience-and-surfaces.md +3 -2
- package/docs-release/guides/full-legacy-migration-subagent-strategy.md +2 -2
- package/docs-release/guides/full-legacy-migration-subagent-strategy.zh-CN.md +2 -2
- package/docs-release/guides/legacy-migration-agent-prompt.md +0 -11
- package/docs-release/guides/legacy-migration-agent-prompt.zh-CN.md +0 -11
- package/docs-release/guides/migration-playbook.en-US.md +14 -15
- package/docs-release/guides/migration-playbook.md +14 -15
- package/docs-release/guides/parent-control-repository-pattern.en-US.md +7 -5
- package/docs-release/guides/parent-control-repository-pattern.md +7 -5
- package/docs-release/guides/preset-development.md +214 -0
- package/docs-release/guides/repository-operating-models.en-US.md +5 -4
- package/docs-release/guides/repository-operating-models.md +5 -4
- package/docs-release/guides/task-state-machine.en-US.md +207 -0
- package/docs-release/guides/task-state-machine.md +214 -0
- package/docs-release/intl/en-US.md +1 -1
- package/docs-release/intl/zh-CN.md +1 -1
- package/examples/minimal-project/docs/09-PLANNING/TASKS/demo-task/findings.md +7 -0
- package/package.json +8 -3
- package/presets/legacy-migration/checks/preset-check.mjs +3 -0
- package/presets/legacy-migration/preset.yaml +134 -0
- package/presets/legacy-migration/scripts/plan-work-queue.mjs +4 -0
- package/presets/legacy-migration/scripts/scaffold-task-contracts.mjs +4 -0
- package/presets/legacy-migration/templates/execution_strategy.append.md +18 -0
- package/presets/legacy-migration/templates/findings.seed.md +17 -0
- package/presets/legacy-migration/templates/review.seed.md +12 -0
- package/presets/legacy-migration/templates/task_plan.append.md +9 -0
- package/presets/legacy-migration/templates/visual_map.append.md +12 -0
- package/presets/legacy-migration/workbench/dashboard-panels.yaml +2 -0
- package/presets/legacy-migration/workbench/migration-queue.schema.json +23 -0
- package/presets/lesson-sedimentation/preset.yaml +23 -0
- package/presets/lesson-sedimentation/templates/prompt.md +23 -0
- package/presets/module/preset.yaml +25 -0
- package/presets/module/templates/execution_strategy.append.md +8 -0
- package/presets/module/templates/task_plan.append.md +17 -0
- package/presets/standard-task/preset.yaml +31 -0
- package/presets/standard-task/templates/task_plan.append.md +7 -0
- package/references/adversarial-review-standard.md +2 -2
- package/references/agents-md-pattern.md +2 -2
- package/references/delivery-operating-model-standard.md +3 -3
- package/references/docs-directory-standard.md +6 -7
- package/references/harness-ledger.md +53 -96
- package/references/lessons-governance.md +88 -93
- package/references/module-parallel-standard.md +14 -14
- package/references/planning-loop.md +12 -6
- package/references/pull-request-standard.md +118 -0
- package/references/repo-governance-standard.md +11 -2
- package/references/review-routing-standard.md +7 -1
- package/references/ssot-governance.md +67 -59
- package/references/taskr-gap-analysis.md +600 -0
- package/references/walkthrough-closeout.md +7 -7
- package/scripts/check-harness.mjs +40 -301
- package/scripts/commands/dashboard-command.mjs +67 -0
- package/scripts/commands/migration-command.mjs +96 -0
- package/scripts/commands/preset-command.mjs +73 -0
- package/scripts/commands/task-command.mjs +327 -0
- package/scripts/harness.mjs +55 -260
- package/scripts/lib/capability-registry.mjs +66 -8
- package/scripts/lib/check-module-parallel.mjs +237 -0
- package/scripts/lib/check-profiles.mjs +61 -153
- package/scripts/lib/check-task-contracts.mjs +47 -0
- package/scripts/lib/core-shared.mjs +10 -0
- package/scripts/lib/dashboard-data.mjs +29 -6
- package/scripts/lib/dashboard-workbench.mjs +52 -12
- package/scripts/lib/dashboard-writer.mjs +14 -2
- package/scripts/lib/git-status-summary.mjs +46 -0
- package/scripts/lib/governance-index-generator.mjs +174 -0
- package/scripts/lib/governance-sync.mjs +514 -0
- package/scripts/lib/governance-table-boundary.mjs +175 -0
- package/scripts/lib/harness-core.mjs +5 -0
- package/scripts/lib/lesson-maintenance.mjs +36 -29
- package/scripts/lib/migration-support.mjs +1 -1
- package/scripts/lib/preset-audit-contracts.mjs +37 -0
- package/scripts/lib/preset-engine.mjs +497 -0
- package/scripts/lib/preset-registry.mjs +627 -0
- package/scripts/lib/preset-resource-contracts.mjs +83 -0
- package/scripts/lib/review-confirm-git-gate.mjs +248 -0
- package/scripts/lib/status-dashboard-renderer.mjs +102 -0
- package/scripts/lib/subagent-authorization-audit.mjs +196 -0
- package/scripts/lib/task-completion-consistency.mjs +16 -0
- package/scripts/lib/task-index.mjs +93 -0
- package/scripts/lib/task-lesson-candidates.mjs +242 -0
- package/scripts/lib/task-lesson-sedimentation.mjs +326 -0
- package/scripts/lib/task-lifecycle/review-confirm.mjs +101 -0
- package/scripts/lib/task-lifecycle/review-gates.mjs +70 -0
- package/scripts/lib/task-lifecycle/text-utils.mjs +24 -0
- package/scripts/lib/task-lifecycle.mjs +297 -403
- package/scripts/lib/task-review-model.mjs +469 -0
- package/scripts/lib/task-scanner.mjs +130 -236
- package/scripts/lib/task-tombstone-commands.mjs +140 -0
- package/scripts/postinstall.mjs +14 -0
- package/skills/preset-creator/SKILL.md +179 -0
- package/skills/preset-creator/references/complex-task-skeleton/README.md +31 -0
- package/skills/preset-creator/references/complex-task-skeleton/artifacts/INDEX.md +12 -0
- package/skills/preset-creator/references/complex-task-skeleton/brief.md +32 -0
- package/skills/preset-creator/references/complex-task-skeleton/execution_strategy.md +71 -0
- package/skills/preset-creator/references/complex-task-skeleton/findings.md +24 -0
- package/skills/preset-creator/references/complex-task-skeleton/lesson_candidates.md +70 -0
- package/skills/preset-creator/references/complex-task-skeleton/long-running-task-contract.md +76 -0
- package/skills/preset-creator/references/complex-task-skeleton/progress.md +33 -0
- package/skills/preset-creator/references/complex-task-skeleton/references/INDEX.md +13 -0
- package/skills/preset-creator/references/complex-task-skeleton/review.md +107 -0
- package/skills/preset-creator/references/complex-task-skeleton/task_plan.md +111 -0
- package/skills/preset-creator/references/complex-task-skeleton/visual_map.md +50 -0
- package/skills/preset-creator/references/preset-package-skeleton.md +296 -0
- package/templates/AGENTS.md.template +19 -15
- package/templates/dashboard/assets/app-src/00-state.js +1 -0
- package/templates/dashboard/assets/app-src/10-router.js +2 -1
- package/templates/dashboard/assets/app-src/20-overview.js +11 -5
- package/templates/dashboard/assets/app-src/30-tasks.js +92 -246
- package/templates/dashboard/assets/app-src/35-task-detail.js +246 -0
- package/templates/dashboard/assets/app-src/45-review.js +241 -22
- package/templates/dashboard/assets/app-src/50-migration.js +24 -10
- package/templates/dashboard/assets/app-src/90-bindings.js +171 -29
- package/templates/dashboard/assets/app.css +698 -156
- package/templates/dashboard/assets/app.css.manifest.json +9 -0
- package/templates/dashboard/assets/app.js +662 -91
- package/templates/dashboard/assets/app.manifest.json +1 -0
- package/templates/dashboard/assets/css-src/00-foundation.css +342 -0
- package/templates/dashboard/assets/css-src/10-panels-flow.css +236 -0
- package/templates/dashboard/assets/css-src/20-briefs-controls.css +398 -0
- package/templates/dashboard/assets/css-src/30-task-index.css +739 -0
- package/templates/dashboard/assets/css-src/35-review-workspace.css +507 -0
- package/templates/dashboard/assets/css-src/40-detail-modules-migration.css +427 -0
- package/templates/dashboard/assets/css-src/50-responsive-overrides.css +551 -0
- package/templates/dashboard/assets/i18n.js +123 -21
- package/templates/ledger/Harness-Ledger.md +13 -25
- package/templates/lessons/lesson-arch-process-change.md +1 -1
- package/templates/lessons/lesson-new-doc.md +1 -1
- package/templates/lessons/lesson-ref-change.md +1 -1
- package/templates/planning/execution_strategy.md +31 -0
- package/templates/planning/lesson_candidates.md +18 -6
- package/templates/planning/optional/artifacts/INDEX.md +3 -3
- package/templates/planning/optional/references/INDEX.md +3 -3
- package/templates/planning/review.md +59 -0
- package/templates/planning/task_plan.md +36 -13
- package/templates/reference/execution-workflow-standard.md +4 -3
- package/templates/reference/pull-request-standard.md +80 -0
- package/templates/reference/repo-governance-standard.md +7 -6
- package/templates/reference/review-routing-standard.md +6 -0
- package/templates/reference/walkthrough-standard.md +2 -1
- package/templates/verifier/verifier-output.md +1 -1
- package/templates-zh-CN/AGENTS.md.template +20 -16
- package/templates-zh-CN/ledger/Harness-Ledger.md +17 -40
- package/templates-zh-CN/planning/execution_strategy.md +30 -0
- package/templates-zh-CN/planning/lesson_candidates.md +18 -6
- package/templates-zh-CN/planning/review.md +59 -1
- package/templates-zh-CN/planning/task_plan.md +30 -10
- package/templates-zh-CN/reference/adversarial-review-standard.md +1 -1
- package/templates-zh-CN/reference/docs-library-standard.md +1 -1
- package/templates-zh-CN/reference/execution-workflow-standard.md +4 -3
- package/templates-zh-CN/reference/harness-ledger-standard.md +2 -2
- package/templates-zh-CN/reference/pull-request-standard.md +106 -0
- package/templates-zh-CN/reference/repo-governance-standard.md +4 -3
- package/templates-zh-CN/reference/review-routing-standard.md +8 -1
- package/templates-zh-CN/reference/walkthrough-standard.md +3 -2
- package/templates-zh-CN/walkthrough/Closeout-SSoT.md +1 -1
- package/docs-release/assets/dashboard-overview-en.png +0 -0
- package/scripts/smoke-dashboard.mjs +0 -92
- package/scripts/test-harness.mjs +0 -1395
- package/templates/ssot/Feature-SSoT.md +0 -43
- package/templates/ssot/Lessons-SSoT.md +0 -44
- package/templates-zh-CN/ssot/Feature-SSoT.md +0 -49
- package/templates-zh-CN/ssot/Lessons-SSoT.md +0 -49
package/scripts/harness.mjs
CHANGED
|
@@ -6,26 +6,19 @@ import path from "node:path";
|
|
|
6
6
|
import { createInterface } from "node:readline/promises";
|
|
7
7
|
import {
|
|
8
8
|
addCapability,
|
|
9
|
-
buildMigrationPlan,
|
|
10
9
|
buildStatus,
|
|
11
|
-
confirmTaskReview,
|
|
12
|
-
createTask,
|
|
13
10
|
doctorUserSkill,
|
|
14
11
|
installUserSkill,
|
|
15
|
-
listLifecycleTasks,
|
|
16
12
|
normalizeLocale,
|
|
17
|
-
|
|
18
|
-
runMigration,
|
|
13
|
+
rebuildGovernanceIndexes,
|
|
19
14
|
serveDashboardWorkbench,
|
|
20
15
|
validateSourcePackageBoundary,
|
|
21
|
-
updateModuleStep,
|
|
22
|
-
updateTaskPhase,
|
|
23
|
-
updateTaskLifecycle,
|
|
24
|
-
verifyMigrationSession,
|
|
25
|
-
writeDashboardFolder,
|
|
26
|
-
writeDashboardSingleFile,
|
|
27
16
|
writeInitFiles,
|
|
28
17
|
} from "./lib/harness-core.mjs";
|
|
18
|
+
import { runDashboardCommand } from "./commands/dashboard-command.mjs";
|
|
19
|
+
import { runMigrationCommand } from "./commands/migration-command.mjs";
|
|
20
|
+
import { runPresetCommand } from "./commands/preset-command.mjs";
|
|
21
|
+
import { runTaskCommand } from "./commands/task-command.mjs";
|
|
29
22
|
|
|
30
23
|
const args = process.argv.slice(2);
|
|
31
24
|
const command = args.shift() || "help";
|
|
@@ -96,22 +89,47 @@ Usage:
|
|
|
96
89
|
harness migrate-plan [--json] [--limit n] [target]
|
|
97
90
|
harness migrate-run [--locale zh-CN|en-US] [--assume-locale] [--allow-dirty] [--plan-only] [--out-dir folder] [--session-dir folder] [target]
|
|
98
91
|
harness migrate-verify [--json] [--full-cutover] <session.json>
|
|
99
|
-
harness
|
|
92
|
+
harness governance rebuild [--dry-run] [--archive] [--apply] [target]
|
|
93
|
+
harness preset list [--json] [target]
|
|
94
|
+
harness preset inspect <id> [--json] [target]
|
|
95
|
+
harness preset check <id> [--json] [target]
|
|
96
|
+
harness preset install <path-or-builtin-id> [--project] [--force] [--json] [target]
|
|
97
|
+
harness preset seed [--project] [--force] [--dry-run] [--json] [target]
|
|
98
|
+
harness preset uninstall <id> [--project] [--json] [target]
|
|
99
|
+
harness new-task <task-id> [--module key] [--budget simple|standard|complex] [--preset id] [--from-session session.json] [--long-running] [--title title] [--locale zh-CN|en-US] [--dry-run] [target]
|
|
100
100
|
harness task-start <task-id> [--message text] [target]
|
|
101
101
|
harness task-phase <task-id> <phase-id> [--state done] [--completion 100] [--evidence present] [target]
|
|
102
102
|
harness task-log <task-id> --message text [--evidence type:PATH:summary] [target]
|
|
103
103
|
harness task-block <task-id> [--message text] [target]
|
|
104
104
|
harness task-review <task-id> [--message text] [target]
|
|
105
105
|
harness review-confirm <task-id> --confirm task-id [--reviewer name] [--message text] [target]
|
|
106
|
-
harness lesson-promote <task-id> <candidate-id> [--dry-run] [target]
|
|
106
|
+
harness lesson-promote <task-id> <candidate-id> [--dry-run|--apply] [target]
|
|
107
|
+
harness lesson-sediment <task-id> <candidate-id> [--dry-run] [--title title] [target]
|
|
107
108
|
harness task-complete <task-id> [--message text] [target]
|
|
108
|
-
harness task-list [--json] [--state state] [--module key] [target]
|
|
109
|
+
harness task-list [--json] [--state state] [--module key] [--queue queue] [--preset id] [--review status] [--lesson status] [--missing-materials] [--search text] [target]
|
|
110
|
+
harness task-index [--json] [target]
|
|
111
|
+
harness task-supersede <old-task-id> --by <new-task-id> [--reason text] [target]
|
|
112
|
+
harness task-delete <task-id> --soft [--reason text] [target]
|
|
113
|
+
harness task-archive <task-id> [--reason text] [target]
|
|
114
|
+
harness task-reopen <task-id> [--reason text] [target]
|
|
109
115
|
harness module-step <module-key> <step-id> [--state done|in-progress|blocked] [target]
|
|
110
|
-
harness install-user [--agent codex|claude|gemini|openclaw|agents|all] [--home dir] [--dry-run] [--force] [--yes]
|
|
116
|
+
harness install-user [--agent codex|claude|gemini|openclaw|agents|all] [--home dir] [--dry-run] [--force] [--skip-presets] [--yes]
|
|
111
117
|
harness doctor-user [--agent codex|claude|gemini|openclaw|agents|all] [--home dir]
|
|
112
118
|
|
|
113
119
|
If init runs in an interactive terminal and --locale is omitted, it asks for a
|
|
114
120
|
language. Non-interactive init defaults to en-US.
|
|
121
|
+
|
|
122
|
+
Preset discovery:
|
|
123
|
+
Project presets live in <target>/.coding-agent-harness/presets/<preset-id>/.
|
|
124
|
+
User presets live in ~/.coding-agent-harness/presets/<preset-id>/.
|
|
125
|
+
Harness discovers project presets first when a target is supplied, then user
|
|
126
|
+
presets, then bundled package presets under presets/<preset-id>/.
|
|
127
|
+
"harness init" seeds bundled presets into the target project. "harness
|
|
128
|
+
install-user" and npm postinstall seed bundled presets into the user root.
|
|
129
|
+
Use "harness preset seed" to repair or re-run preset seeding.
|
|
130
|
+
Use "harness preset list --json" to see available presets, their source,
|
|
131
|
+
purpose, compatible budgets, and manifest path. Use "harness preset inspect
|
|
132
|
+
<id> --json" for the full preset manifest summary.
|
|
115
133
|
`);
|
|
116
134
|
}
|
|
117
135
|
|
|
@@ -123,6 +141,8 @@ function exitWithReport(report) {
|
|
|
123
141
|
|
|
124
142
|
if (command === "help" || command === "--help" || command === "-h") {
|
|
125
143
|
printHelp();
|
|
144
|
+
} else if (args[0] === "help" || args.includes("--help") || args.includes("-h")) {
|
|
145
|
+
printHelp();
|
|
126
146
|
} else if (command === "check") {
|
|
127
147
|
const profile = takeOption("--profile", "target-project");
|
|
128
148
|
const strict = takeFlag("--strict");
|
|
@@ -166,8 +186,9 @@ if (command === "help" || command === "--help" || command === "-h") {
|
|
|
166
186
|
const port = takeOption("--port", "0");
|
|
167
187
|
const localeOverride = takeOption("--locale", "");
|
|
168
188
|
const target = targetArg();
|
|
189
|
+
const usesDefaultOutDir = !outDir;
|
|
169
190
|
const dashboardOutDir = outDir || defaultDevOutDir(target);
|
|
170
|
-
const opts = localeOverride ? { localeOverride } : {};
|
|
191
|
+
const opts = { ...(localeOverride ? { localeOverride } : {}), recoverGeneratedDashboard: usesDefaultOutDir };
|
|
171
192
|
try {
|
|
172
193
|
await serveDashboardWorkbench(dashboardOutDir, target, { ...opts, host, port, autoRefresh: true, open, label: "harness dev" });
|
|
173
194
|
} catch (error) {
|
|
@@ -175,63 +196,7 @@ if (command === "help" || command === "--help" || command === "-h") {
|
|
|
175
196
|
process.exit(1);
|
|
176
197
|
}
|
|
177
198
|
} else if (command === "dashboard") {
|
|
178
|
-
|
|
179
|
-
const workbench = takeFlag("--workbench");
|
|
180
|
-
const out = takeOption("--out", "harness-dashboard.html");
|
|
181
|
-
const outDir = takeOption("--out-dir", "");
|
|
182
|
-
const host = takeOption("--host", "127.0.0.1");
|
|
183
|
-
const port = takeOption("--port", "0");
|
|
184
|
-
const localeOverride = takeOption("--locale", "");
|
|
185
|
-
const opts = localeOverride ? { localeOverride } : {};
|
|
186
|
-
if (workbench) {
|
|
187
|
-
if (!outDir) {
|
|
188
|
-
console.error("dashboard --workbench requires --out-dir so regenerated data has a stable folder");
|
|
189
|
-
process.exit(2);
|
|
190
|
-
}
|
|
191
|
-
try {
|
|
192
|
-
await serveDashboardWorkbench(outDir, targetArg(), { ...opts, host, port });
|
|
193
|
-
} catch (error) {
|
|
194
|
-
console.error(error.message);
|
|
195
|
-
process.exit(1);
|
|
196
|
-
}
|
|
197
|
-
}
|
|
198
|
-
if (watch) {
|
|
199
|
-
if (!outDir) {
|
|
200
|
-
console.error("dashboard --watch requires --out-dir so updates are written to a stable folder");
|
|
201
|
-
process.exit(2);
|
|
202
|
-
}
|
|
203
|
-
const target = targetArg();
|
|
204
|
-
const docsRoot = path.basename(path.resolve(target)) === "docs" ? path.resolve(target) : path.join(path.resolve(target), "docs");
|
|
205
|
-
const regenerate = () => {
|
|
206
|
-
try {
|
|
207
|
-
console.log(writeDashboardFolder(outDir, target, opts));
|
|
208
|
-
console.log(`dashboard regenerated: ${new Date().toISOString()}`);
|
|
209
|
-
} catch (error) {
|
|
210
|
-
console.error(`dashboard regeneration failed: ${error.message}`);
|
|
211
|
-
}
|
|
212
|
-
};
|
|
213
|
-
regenerate();
|
|
214
|
-
let timer = null;
|
|
215
|
-
const watcher = fs.watch(docsRoot, { recursive: true }, () => {
|
|
216
|
-
clearTimeout(timer);
|
|
217
|
-
timer = setTimeout(regenerate, 300);
|
|
218
|
-
});
|
|
219
|
-
const close = () => {
|
|
220
|
-
watcher.close();
|
|
221
|
-
clearTimeout(timer);
|
|
222
|
-
process.exit(0);
|
|
223
|
-
};
|
|
224
|
-
process.on("SIGINT", close);
|
|
225
|
-
process.on("SIGTERM", close);
|
|
226
|
-
console.log(`watching ${docsRoot}`);
|
|
227
|
-
await new Promise(() => {});
|
|
228
|
-
}
|
|
229
|
-
if (outDir) {
|
|
230
|
-
console.log(writeDashboardFolder(outDir, targetArg(), opts));
|
|
231
|
-
} else {
|
|
232
|
-
console.log(writeDashboardSingleFile(out, targetArg(), opts));
|
|
233
|
-
}
|
|
234
|
-
process.exit(0);
|
|
199
|
+
await runDashboardCommand({ takeFlag, takeOption, targetArg });
|
|
235
200
|
} else if (command === "init") {
|
|
236
201
|
const dryRun = takeFlag("--dry-run");
|
|
237
202
|
const addNpmScripts = takeFlag("--add-npm-scripts");
|
|
@@ -239,7 +204,7 @@ if (command === "help" || command === "--help" || command === "-h") {
|
|
|
239
204
|
const capabilities = takeOption("--capabilities", "core").split(",").map((item) => item.trim()).filter(Boolean);
|
|
240
205
|
try {
|
|
241
206
|
const result = writeInitFiles(targetArg(), capabilities, { dryRun, locale, addNpmScripts });
|
|
242
|
-
console.log(JSON.stringify({ dryRun, locale: result.locale, capabilities: result.capabilities, changes: result.changes, nextCommands: result.nextCommands, report: result.report }, null, 2));
|
|
207
|
+
console.log(JSON.stringify({ dryRun, locale: result.locale, capabilities: result.capabilities, changes: result.changes, presetSeed: result.presetSeed, nextCommands: result.nextCommands, report: result.report }, null, 2));
|
|
243
208
|
} catch (error) {
|
|
244
209
|
console.error(error.message);
|
|
245
210
|
process.exit(1);
|
|
@@ -259,202 +224,32 @@ if (command === "help" || command === "--help" || command === "-h") {
|
|
|
259
224
|
console.error(error.message);
|
|
260
225
|
process.exit(1);
|
|
261
226
|
}
|
|
262
|
-
} else if (
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
console.log(JSON.stringify(plan, null, 2));
|
|
269
|
-
} else {
|
|
270
|
-
console.log(`Migration Plan: ${plan.target}`);
|
|
271
|
-
console.log(`mode: ${plan.mode}`);
|
|
272
|
-
console.log(`warnings: ${plan.summary.warnings}`);
|
|
273
|
-
console.log(`task actions: ${plan.summary.taskActions}`);
|
|
274
|
-
console.log(`visual map actions: ${plan.summary.visualMapActions}`);
|
|
275
|
-
console.log(`legacy visual-only tasks: ${plan.summary.legacyVisualOnly}`);
|
|
276
|
-
console.log(`weak briefs: ${plan.summary.weakBrief}`);
|
|
277
|
-
console.log(`unknown classifications: ${plan.summary.unknownClassification}`);
|
|
278
|
-
console.log(`full cutover eligible: ${plan.summary.fullCutoverEligible ? "yes" : "no"}`);
|
|
279
|
-
console.log(`review actions: ${plan.summary.reviewSchemaGaps}`);
|
|
280
|
-
console.log(`legacy actions: ${plan.summary.legacyReferenceGaps}`);
|
|
281
|
-
console.log(`legacy residuals: ${plan.summary.legacyResiduals}`);
|
|
282
|
-
console.log(`recommended capabilities: ${plan.summary.recommendedCapabilities.join(", ") || "none"}`);
|
|
283
|
-
console.log("\nPhases:");
|
|
284
|
-
for (const phase of plan.phases) console.log(`- ${phase.id}: ${phase.title}`);
|
|
285
|
-
console.log("\nTop task actions:");
|
|
286
|
-
for (const action of plan.taskActions) console.log(`- ${action.taskId}: add ${action.files.join(", ")}`);
|
|
287
|
-
console.log("\nTop review actions:");
|
|
288
|
-
for (const action of plan.reviewActions) console.log(`- ${action.path}: add ${action.missing.join(", ")}`);
|
|
289
|
-
console.log("\nTop legacy residuals:");
|
|
290
|
-
for (const action of plan.legacyResiduals) console.log(`- ${action.taskId}: ${action.missing} (${action.reason})`);
|
|
291
|
-
console.log("\nNext commands:");
|
|
292
|
-
for (const next of plan.nextCommands) console.log(`- ${next}`);
|
|
293
|
-
}
|
|
294
|
-
} catch (error) {
|
|
295
|
-
console.error(error.message);
|
|
296
|
-
process.exit(1);
|
|
297
|
-
}
|
|
298
|
-
} else if (command === "migrate-run") {
|
|
299
|
-
const locale = takeOption("--locale", "");
|
|
300
|
-
const assumeLocale = takeFlag("--assume-locale");
|
|
301
|
-
const allowDirty = takeFlag("--allow-dirty");
|
|
302
|
-
const planOnly = takeFlag("--plan-only");
|
|
303
|
-
const outDir = takeOption("--out-dir", "");
|
|
304
|
-
const sessionDir = takeOption("--session-dir", "");
|
|
305
|
-
try {
|
|
306
|
-
console.log(
|
|
307
|
-
JSON.stringify(
|
|
308
|
-
runMigration(targetArg(), {
|
|
309
|
-
locale,
|
|
310
|
-
assumeLocale,
|
|
311
|
-
allowDirty,
|
|
312
|
-
planOnly,
|
|
313
|
-
outDir,
|
|
314
|
-
sessionDir,
|
|
315
|
-
}),
|
|
316
|
-
null,
|
|
317
|
-
2,
|
|
318
|
-
),
|
|
319
|
-
);
|
|
320
|
-
} catch (error) {
|
|
321
|
-
console.error(error.message);
|
|
322
|
-
process.exit(1);
|
|
323
|
-
}
|
|
324
|
-
} else if (command === "migrate-verify") {
|
|
325
|
-
const json = takeFlag("--json");
|
|
326
|
-
const fullCutover = takeFlag("--full-cutover");
|
|
327
|
-
const sessionPath = args.shift();
|
|
328
|
-
if (!sessionPath) {
|
|
329
|
-
console.error("Missing session.json path");
|
|
227
|
+
} else if (["migrate-plan", "migrate-run", "migrate-verify"].includes(command)) {
|
|
228
|
+
runMigrationCommand(command, { args, takeFlag, takeOption, targetArg });
|
|
229
|
+
} else if (command === "governance") {
|
|
230
|
+
const subcommand = args.shift() || "";
|
|
231
|
+
if (subcommand !== "rebuild") {
|
|
232
|
+
console.error(`Unknown governance subcommand: ${subcommand || "(missing)"}`);
|
|
330
233
|
process.exit(2);
|
|
331
234
|
}
|
|
332
|
-
const result = verifyMigrationSession(sessionPath, { fullCutover });
|
|
333
|
-
if (json) {
|
|
334
|
-
console.log(JSON.stringify(result, null, 2));
|
|
335
|
-
} else {
|
|
336
|
-
for (const failure of result.failures) console.error(`Failure: ${failure}`);
|
|
337
|
-
for (const warning of result.warnings) console.log(`Warning: ${warning}`);
|
|
338
|
-
console.log(`Migration verify ${result.status}: ${result.sessionPath}`);
|
|
339
|
-
}
|
|
340
|
-
process.exit(result.status === "pass" ? 0 : 1);
|
|
341
|
-
} else if (command === "new-task") {
|
|
342
235
|
const dryRun = takeFlag("--dry-run");
|
|
343
|
-
const
|
|
344
|
-
const
|
|
345
|
-
const moduleKey = takeOption("--module", "");
|
|
346
|
-
const budget = takeOption("--budget", "standard");
|
|
347
|
-
const preset = takeOption("--preset", "");
|
|
348
|
-
const fromSession = takeOption("--from-session", "");
|
|
349
|
-
const longRunning = takeFlag("--long-running");
|
|
350
|
-
const taskId = args.shift() || (fromSession ? "harness-v1-migration" : "");
|
|
351
|
-
if (!taskId) {
|
|
352
|
-
console.error("Missing task id");
|
|
353
|
-
process.exit(2);
|
|
354
|
-
}
|
|
355
|
-
try {
|
|
356
|
-
console.log(JSON.stringify(createTask(targetArg(), taskId, { title, locale, dryRun, moduleKey, budget, longRunning, preset, fromSession }), null, 2));
|
|
357
|
-
} catch (error) {
|
|
358
|
-
console.error(error.message);
|
|
359
|
-
process.exit(1);
|
|
360
|
-
}
|
|
361
|
-
} else if (command === "task-phase") {
|
|
362
|
-
const state = takeOption("--state", "");
|
|
363
|
-
const completion = takeOption("--completion", "");
|
|
364
|
-
const evidenceStatus = takeOption("--evidence", "");
|
|
365
|
-
const taskId = args.shift();
|
|
366
|
-
const phaseId = args.shift();
|
|
367
|
-
if (!taskId || !phaseId) {
|
|
368
|
-
console.error("Missing task id or phase id");
|
|
369
|
-
process.exit(2);
|
|
370
|
-
}
|
|
371
|
-
try {
|
|
372
|
-
console.log(JSON.stringify(updateTaskPhase(targetArg(), taskId, phaseId, { state, completion, evidenceStatus }), null, 2));
|
|
373
|
-
} catch (error) {
|
|
374
|
-
console.error(error.message);
|
|
375
|
-
process.exit(1);
|
|
376
|
-
}
|
|
377
|
-
} else if (["task-start", "task-log", "task-block", "task-review", "task-complete"].includes(command)) {
|
|
378
|
-
const message = takeOption("--message", "");
|
|
379
|
-
const evidence = takeOption("--evidence", "");
|
|
380
|
-
const taskId = args.shift();
|
|
381
|
-
if (!taskId) {
|
|
382
|
-
console.error("Missing task id");
|
|
383
|
-
process.exit(2);
|
|
384
|
-
}
|
|
385
|
-
const lifecycle = {
|
|
386
|
-
"task-start": { event: "task-start", state: "in_progress" },
|
|
387
|
-
"task-log": { event: "task-log", state: "" },
|
|
388
|
-
"task-block": { event: "task-block", state: "blocked" },
|
|
389
|
-
"task-review": { event: "task-review", state: "review" },
|
|
390
|
-
"task-complete": { event: "task-complete", state: "done" },
|
|
391
|
-
}[command];
|
|
392
|
-
try {
|
|
393
|
-
console.log(JSON.stringify(updateTaskLifecycle(targetArg(), taskId, { ...lifecycle, message, evidence }), null, 2));
|
|
394
|
-
} catch (error) {
|
|
395
|
-
console.error(error.message);
|
|
396
|
-
process.exit(1);
|
|
397
|
-
}
|
|
398
|
-
} else if (command === "review-confirm") {
|
|
399
|
-
const reviewer = takeOption("--reviewer", "Human Reviewer");
|
|
400
|
-
const message = takeOption("--message", "");
|
|
401
|
-
const evidence = takeOption("--evidence", "");
|
|
402
|
-
const confirmText = takeOption("--confirm", "");
|
|
403
|
-
const taskId = args.shift();
|
|
404
|
-
if (!taskId) {
|
|
405
|
-
console.error("Missing task id");
|
|
406
|
-
process.exit(2);
|
|
407
|
-
}
|
|
408
|
-
try {
|
|
409
|
-
console.log(JSON.stringify(confirmTaskReview(targetArg(), taskId, { reviewer, message, evidence, confirmText }), null, 2));
|
|
410
|
-
} catch (error) {
|
|
411
|
-
console.error(error.message);
|
|
412
|
-
process.exit(1);
|
|
413
|
-
}
|
|
414
|
-
} else if (command === "lesson-promote") {
|
|
415
|
-
const dryRun = takeFlag("--dry-run");
|
|
416
|
-
const taskId = args.shift();
|
|
417
|
-
const candidateId = args.shift();
|
|
418
|
-
if (!taskId || !candidateId) {
|
|
419
|
-
console.error("Missing task id or candidate id");
|
|
420
|
-
process.exit(2);
|
|
421
|
-
}
|
|
422
|
-
try {
|
|
423
|
-
console.log(JSON.stringify(promoteLessonCandidate(targetArg(), taskId, candidateId, { dryRun }), null, 2));
|
|
424
|
-
} catch (error) {
|
|
425
|
-
console.error(error.message);
|
|
426
|
-
process.exit(1);
|
|
427
|
-
}
|
|
428
|
-
} else if (command === "task-list") {
|
|
429
|
-
const json = takeFlag("--json");
|
|
430
|
-
const state = takeOption("--state", "");
|
|
431
|
-
const moduleKey = takeOption("--module", "");
|
|
432
|
-
const result = listLifecycleTasks(targetArg(), { state, moduleKey });
|
|
433
|
-
if (json) {
|
|
434
|
-
console.log(JSON.stringify(result, null, 2));
|
|
435
|
-
} else {
|
|
436
|
-
for (const task of result.tasks) {
|
|
437
|
-
console.log(`${task.id}\t${task.state}\t${task.completion}%\t${task.title}`);
|
|
438
|
-
}
|
|
439
|
-
}
|
|
440
|
-
} else if (command === "module-step") {
|
|
441
|
-
const state = takeOption("--state", "done");
|
|
442
|
-
const moduleKey = args.shift();
|
|
443
|
-
const stepId = args.shift();
|
|
444
|
-
if (!moduleKey || !stepId) {
|
|
445
|
-
console.error("Missing module key or step id");
|
|
446
|
-
process.exit(2);
|
|
447
|
-
}
|
|
236
|
+
const archive = takeFlag("--archive");
|
|
237
|
+
const apply = takeFlag("--apply");
|
|
448
238
|
try {
|
|
449
|
-
console.log(JSON.stringify(
|
|
239
|
+
console.log(JSON.stringify(rebuildGovernanceIndexes(targetArg(), { dryRun, archive, apply }), null, 2));
|
|
450
240
|
} catch (error) {
|
|
451
241
|
console.error(error.message);
|
|
452
242
|
process.exit(1);
|
|
453
243
|
}
|
|
244
|
+
} else if (command === "preset") {
|
|
245
|
+
runPresetCommand({ args, takeFlag, targetArg });
|
|
246
|
+
} else if (["new-task", "task-phase", "task-start", "task-log", "task-block", "task-review", "task-complete", "review-confirm", "lesson-promote", "lesson-sediment", "task-list", "task-index", "task-supersede", "task-delete", "task-archive", "task-reopen", "module-step"].includes(command)) {
|
|
247
|
+
runTaskCommand(command, { args, takeFlag, takeOption, targetArg });
|
|
454
248
|
} else if (command === "install-user") {
|
|
455
249
|
const dryRun = takeFlag("--dry-run");
|
|
456
250
|
const force = takeFlag("--force");
|
|
457
251
|
const yes = takeFlag("--yes") || takeFlag("-y");
|
|
252
|
+
const skipPresets = takeFlag("--skip-presets");
|
|
458
253
|
takeFlag("--global");
|
|
459
254
|
const agent = takeOption("--agent", "codex");
|
|
460
255
|
const home = takeOption("--home", "");
|
|
@@ -463,7 +258,7 @@ if (command === "help" || command === "--help" || command === "-h") {
|
|
|
463
258
|
process.exit(2);
|
|
464
259
|
}
|
|
465
260
|
try {
|
|
466
|
-
console.log(JSON.stringify(installUserSkill({ agent, home, dryRun, force }), null, 2));
|
|
261
|
+
console.log(JSON.stringify(installUserSkill({ agent, home, dryRun, force, seedPresets: !skipPresets }), null, 2));
|
|
467
262
|
} catch (error) {
|
|
468
263
|
console.error(error.message);
|
|
469
264
|
process.exit(1);
|
|
@@ -14,7 +14,9 @@ import {
|
|
|
14
14
|
walkFiles,
|
|
15
15
|
normalizeLocale,
|
|
16
16
|
localizedTemplateSource,
|
|
17
|
+
userPresetRootForHome,
|
|
17
18
|
} from "./core-shared.mjs";
|
|
19
|
+
import { listBundledPresetIds, seedBundledPresets } from "./preset-registry.mjs";
|
|
18
20
|
|
|
19
21
|
export const capabilityDefinitions = {
|
|
20
22
|
core: {
|
|
@@ -124,12 +126,53 @@ export function validateSourcePackageBoundary(targetInput = ".") {
|
|
|
124
126
|
.split("\0")
|
|
125
127
|
.filter(Boolean)
|
|
126
128
|
.filter((file) => file === "AGENTS.md" || file === "CLAUDE.md" || file === "docs" || file.startsWith("docs/") || file === ".harness-private" || file.startsWith(".harness-private/"));
|
|
129
|
+
const tracked = spawnSync("git", ["-C", root, "ls-files", "-z", "--", "harness-dashboard.html"], { encoding: "utf8" });
|
|
130
|
+
const generatedRootDashboard = tracked.status === 0
|
|
131
|
+
? tracked.stdout.split("\0").filter(Boolean)
|
|
132
|
+
.filter((file) => fs.existsSync(path.join(root, file)))
|
|
133
|
+
: [];
|
|
134
|
+
const internalScripts = ["scripts/test-harness.mjs", "scripts/smoke-dashboard.mjs"]
|
|
135
|
+
.filter((file) => fs.existsSync(path.join(root, file)));
|
|
136
|
+
const dashboardAppDrift = validateDashboardAppAssembly(root);
|
|
137
|
+
const dashboardCssDrift = validateDashboardAssetAssembly(root, "app.css.manifest.json", "app.css", "dashboard assets/app.css does not match css-src manifest assembly");
|
|
127
138
|
return {
|
|
128
|
-
failures:
|
|
129
|
-
|
|
139
|
+
failures: [
|
|
140
|
+
...localOnly.map((file) => `private local-only file staged: ${file}`),
|
|
141
|
+
...generatedRootDashboard.map((file) => `generated dashboard file tracked in source root: ${file}`),
|
|
142
|
+
...internalScripts.map((file) => `internal test/smoke file in publishable scripts directory: ${file}`),
|
|
143
|
+
...dashboardAppDrift,
|
|
144
|
+
...dashboardCssDrift,
|
|
145
|
+
],
|
|
146
|
+
warnings: tracked.status === 0 ? [] : [`could not inspect tracked generated dashboard files: ${tracked.stderr.trim() || tracked.status}`],
|
|
130
147
|
};
|
|
131
148
|
}
|
|
132
149
|
|
|
150
|
+
function validateDashboardAppAssembly(root) {
|
|
151
|
+
return validateDashboardAssetAssembly(root, "app.manifest.json", "app.js", "dashboard assets/app.js does not match app-src manifest assembly");
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
function validateDashboardAssetAssembly(root, manifestName, assetName, driftMessage) {
|
|
155
|
+
const assetsDir = path.join(root, "templates/dashboard/assets");
|
|
156
|
+
const manifestPath = path.join(assetsDir, manifestName);
|
|
157
|
+
const assetPath = path.join(assetsDir, assetName);
|
|
158
|
+
if (!fs.existsSync(manifestPath) || !fs.existsSync(assetPath)) return [];
|
|
159
|
+
try {
|
|
160
|
+
const manifest = JSON.parse(fs.readFileSync(manifestPath, "utf8"));
|
|
161
|
+
if (!Array.isArray(manifest) || manifest.length === 0) {
|
|
162
|
+
return [`dashboard asset manifest must list source files: ${manifestName}`];
|
|
163
|
+
}
|
|
164
|
+
const assembled = `${manifest.map((relativePath) => {
|
|
165
|
+
const source = path.join(assetsDir, relativePath);
|
|
166
|
+
if (!fs.existsSync(source)) throw new Error(`missing ${relativePath}`);
|
|
167
|
+
return fs.readFileSync(source, "utf8").trimEnd();
|
|
168
|
+
}).join("\n\n")}\n`;
|
|
169
|
+
const trackedAsset = fs.readFileSync(assetPath, "utf8");
|
|
170
|
+
return trackedAsset === assembled ? [] : [driftMessage];
|
|
171
|
+
} catch (error) {
|
|
172
|
+
return [`could not validate dashboard asset assembly (${assetName}): ${error.message}`];
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
|
|
133
176
|
export function detectCapabilities(target) {
|
|
134
177
|
const detected = new Set(["core"]);
|
|
135
178
|
if (existsInDocs(target, "09-PLANNING/Module-Registry.md")) detected.add("module-parallel");
|
|
@@ -164,6 +207,7 @@ export function buildInstallReport({ target, locale, capabilities, changes, dryR
|
|
|
164
207
|
agentInstructions: [
|
|
165
208
|
"Agents must choose locale during Decide and pass --locale zh-CN|en-US explicitly in non-interactive installs.",
|
|
166
209
|
"Use core for every install; add optional capabilities only when their selectWhen rule is true.",
|
|
210
|
+
"Bundled presets are seeded during init; use harness preset list --json before choosing task presets.",
|
|
167
211
|
"After scaffold, run Configure before marking capabilities configured or verified.",
|
|
168
212
|
"Run harness check/status/dashboard and record residuals before delivery.",
|
|
169
213
|
],
|
|
@@ -209,6 +253,7 @@ function skillPackageEntries() {
|
|
|
209
253
|
"references",
|
|
210
254
|
"templates",
|
|
211
255
|
"templates-zh-CN",
|
|
256
|
+
"presets",
|
|
212
257
|
"scripts",
|
|
213
258
|
"docs-release",
|
|
214
259
|
"examples",
|
|
@@ -246,7 +291,7 @@ function copySkillPackage(targetRoot, { dryRun = false, force = false } = {}) {
|
|
|
246
291
|
return changes;
|
|
247
292
|
}
|
|
248
293
|
|
|
249
|
-
export function installUserSkill({ agent = "codex", home = "", dryRun = false, force = false } = {}) {
|
|
294
|
+
export function installUserSkill({ agent = "codex", home = "", dryRun = false, force = false, seedPresets = true } = {}) {
|
|
250
295
|
const agents = normalizeUserAgent(agent);
|
|
251
296
|
const targets = agents.map((targetAgent) => {
|
|
252
297
|
const target = targetForUserAgent(targetAgent, home);
|
|
@@ -260,8 +305,11 @@ export function installUserSkill({ agent = "codex", home = "", dryRun = false, f
|
|
|
260
305
|
skipped: changes.filter((change) => change.action === "skip-existing").length,
|
|
261
306
|
};
|
|
262
307
|
});
|
|
263
|
-
const
|
|
264
|
-
const
|
|
308
|
+
const presetSeed = seedPresets ? seedBundledPresets({ scope: "user", home, dryRun, force }) : null;
|
|
309
|
+
const changed = targets.some((target) => target.created > 0 || target.overwritten > 0) || (presetSeed && (presetSeed.created > 0 || presetSeed.overwritten > 0));
|
|
310
|
+
const onlySkipped =
|
|
311
|
+
targets.every((target) => target.created === 0 && target.overwritten === 0 && target.skipped > 0) &&
|
|
312
|
+
(!presetSeed || presetSeed.presets.every((preset) => preset.action === "skip-existing"));
|
|
265
313
|
return {
|
|
266
314
|
operation: "install-user",
|
|
267
315
|
status: dryRun ? "dry-run" : changed ? "installed" : onlySkipped ? "already-present" : "no-op",
|
|
@@ -269,6 +317,7 @@ export function installUserSkill({ agent = "codex", home = "", dryRun = false, f
|
|
|
269
317
|
force,
|
|
270
318
|
version: packageVersion(),
|
|
271
319
|
source: repoRoot,
|
|
320
|
+
presets: presetSeed,
|
|
272
321
|
targets,
|
|
273
322
|
};
|
|
274
323
|
}
|
|
@@ -301,6 +350,7 @@ export function doctorUserSkill({ agent = "codex", home = "" } = {}) {
|
|
|
301
350
|
"references",
|
|
302
351
|
"templates",
|
|
303
352
|
"templates-zh-CN",
|
|
353
|
+
"presets",
|
|
304
354
|
"scripts/harness.mjs",
|
|
305
355
|
"docs-release/guides/agent-installation.md",
|
|
306
356
|
];
|
|
@@ -315,12 +365,20 @@ export function doctorUserSkill({ agent = "codex", home = "" } = {}) {
|
|
|
315
365
|
missing,
|
|
316
366
|
};
|
|
317
367
|
});
|
|
368
|
+
const presetRoot = userPresetRootForHome(home);
|
|
369
|
+
const missingPresets = listBundledPresetIds().filter((id) => !fs.existsSync(path.join(presetRoot, id, "preset.yaml")));
|
|
370
|
+
const presets = {
|
|
371
|
+
root: presetRoot,
|
|
372
|
+
status: missingPresets.length === 0 ? "pass" : "fail",
|
|
373
|
+
missing: missingPresets,
|
|
374
|
+
};
|
|
318
375
|
const harnessCommand = commandOnPath("harness");
|
|
319
376
|
return {
|
|
320
377
|
operation: "doctor-user",
|
|
321
|
-
status: targets.every((target) => target.status === "pass") ? "pass" : "fail",
|
|
378
|
+
status: targets.every((target) => target.status === "pass") && presets.status === "pass" ? "pass" : "fail",
|
|
322
379
|
version: packageVersion(),
|
|
323
380
|
harnessCommand: harnessCommand || null,
|
|
381
|
+
presets,
|
|
324
382
|
targets,
|
|
325
383
|
};
|
|
326
384
|
}
|
|
@@ -399,7 +457,6 @@ export function plannedInitFiles(capabilities = ["core"], { locale = "en-US" } =
|
|
|
399
457
|
["docs/09-PLANNING/TASKS/_task-template/review.md", "templates/planning/review.md"],
|
|
400
458
|
["docs/05-TEST-QA/Regression-SSoT.md", "templates/ssot/Regression-SSoT.md"],
|
|
401
459
|
["docs/05-TEST-QA/Cadence-Ledger.md", "templates/regression/Cadence-Ledger.md"],
|
|
402
|
-
["docs/01-GOVERNANCE/Lessons-SSoT.md", "templates/ssot/Lessons-SSoT.md"],
|
|
403
460
|
["docs/10-WALKTHROUGH/_walkthrough-template.md", "templates/walkthrough/walkthrough-template.md"],
|
|
404
461
|
["docs/10-WALKTHROUGH/Closeout-SSoT.md", "templates/walkthrough/Closeout-SSoT.md"],
|
|
405
462
|
["docs/11-REFERENCE/external-source-intake-standard.md", "templates/reference/external-source-intake-standard.md"],
|
|
@@ -464,8 +521,9 @@ export function writeInitFiles(targetInput, capabilities, { dryRun = true, local
|
|
|
464
521
|
const registryPath = path.join(target.projectRoot, ".harness-capabilities.json");
|
|
465
522
|
if (!fs.existsSync(registryPath)) fs.writeFileSync(registryPath, `${JSON.stringify(registry, null, 2)}\n`);
|
|
466
523
|
}
|
|
524
|
+
const presetSeed = seedBundledPresets({ scope: "project", targetInput: target.projectRoot, dryRun });
|
|
467
525
|
const report = buildInstallReport({ target, locale: normalizedLocale, capabilities: normalizedCapabilities, changes, dryRun, operation: "init" });
|
|
468
|
-
return { target, capabilities: normalizedCapabilities, locale: normalizedLocale, changes, nextCommands: initNextCommands(), report };
|
|
526
|
+
return { target, capabilities: normalizedCapabilities, locale: normalizedLocale, changes, presetSeed, nextCommands: initNextCommands(), report };
|
|
469
527
|
}
|
|
470
528
|
|
|
471
529
|
function initNextCommands() {
|