@orkestrel/scaffold 0.0.84 → 0.0.86
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/README.md +2 -2
- package/dist/agents/skills/orkestrel-publish/scripts/wave.js +16 -2
- package/dist/bin/main.js +172 -22
- package/dist/bin/main.js.map +1 -1
- package/dist/host/AGENTS.md +1 -1
- package/dist/host/agents/skills/orkestrel-publish/SKILL.md +6 -6
- package/dist/host/agents/skills/orkestrel-publish/references/wave.md +14 -2
- package/dist/host/agents/skills/orkestrel-publish/scripts/wave.ts +20 -7
- package/dist/host/claude/agents/orkestrel.md +1 -1
- package/dist/host/claude/rules/architecture.md +2 -2
- package/dist/host/claude/rules/styles.md +18 -9
- package/dist/host/claude/rules/workspace.md +1 -1
- package/dist/host/dotfiles/prettierignore +3 -0
- package/dist/host/guides/scaffold.md +32 -7
- package/dist/host/manifest.json +12 -12
- package/dist/host/tests/setupPolicy.ts +23 -7
- package/dist/src/core/index.cjs +181 -1
- package/dist/src/core/index.cjs.map +1 -1
- package/dist/src/core/index.d.cts +39 -0
- package/dist/src/core/index.d.ts +39 -0
- package/dist/src/core/index.js +181 -2
- package/dist/src/core/index.js.map +1 -1
- package/dist/src/server/index.cjs +31 -7
- package/dist/src/server/index.cjs.map +1 -1
- package/dist/src/server/index.d.cts +19 -6
- package/dist/src/server/index.d.ts +19 -6
- package/dist/src/server/index.js +32 -8
- package/dist/src/server/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -27,8 +27,8 @@ options, its defaults, and the exit codes.
|
|
|
27
27
|
and script regions.
|
|
28
28
|
- `catalog` rewrites the package table in the target's catalog agent file, and refetches the guide
|
|
29
29
|
mirrors.
|
|
30
|
-
- `overwrite` does everything `repair` and `catalog` do, then deletes what the plan does not own
|
|
31
|
-
re-declares the dependency ranges.
|
|
30
|
+
- `overwrite` does everything `repair` and `catalog` do, then deletes what the plan does not own,
|
|
31
|
+
re-declares the dependency ranges, and declares each planned dependency the manifest lacks.
|
|
32
32
|
|
|
33
33
|
## Library
|
|
34
34
|
|
|
@@ -89,9 +89,23 @@ function readReleases(text) {
|
|
|
89
89
|
function describeCommand(file, args) {
|
|
90
90
|
return [file === process.execPath ? 'node' : file, ...args].join(' ');
|
|
91
91
|
}
|
|
92
|
+
// A JSON verb writes its refusal envelope or its partial-run note on stdout, so the stderr tail
|
|
93
|
+
// alone reads empty for exactly the failures the operator needs named.
|
|
92
94
|
function describeFailure(result) {
|
|
93
95
|
if (result.status === 0)
|
|
94
96
|
return undefined;
|
|
97
|
+
const value = readJsonObject(result.stdout);
|
|
98
|
+
const error = value?.error;
|
|
99
|
+
if (typeof error === 'object' && error !== null && !Array.isArray(error)) {
|
|
100
|
+
const envelope = Object.fromEntries(Object.entries(error));
|
|
101
|
+
const code = readString(envelope, 'code');
|
|
102
|
+
const message = readString(envelope, 'message');
|
|
103
|
+
if (code !== undefined && message !== undefined)
|
|
104
|
+
return `${code}: ${message}`;
|
|
105
|
+
}
|
|
106
|
+
const note = readString(value, 'note');
|
|
107
|
+
if (note !== undefined)
|
|
108
|
+
return note;
|
|
95
109
|
return result.stderr
|
|
96
110
|
.trim()
|
|
97
111
|
.split(/\r\n|\n/)
|
|
@@ -214,12 +228,12 @@ function runCommit(runner) {
|
|
|
214
228
|
function runOverwrite(runner, scaffoldFile, scaffoldPrefix, offline) {
|
|
215
229
|
const written = runStep(runner, 'overwrite', scaffoldFile, [...scaffoldPrefix, 'overwrite', '--json', ...offline], runner.target);
|
|
216
230
|
if (runner.offline && written !== undefined && written.status === 1) {
|
|
217
|
-
const note = readString(readJsonObject(written.stdout)
|
|
231
|
+
const note = readString(readJsonObject(written.stdout), 'note');
|
|
218
232
|
if (note !== undefined && note.includes(OFFLINE_REFUSAL)) {
|
|
219
233
|
replaceLastStep(runner, 0, 'offline overwrite skipped the catalog step by design');
|
|
220
234
|
}
|
|
221
235
|
else {
|
|
222
|
-
replaceLastStep(runner, 1,
|
|
236
|
+
replaceLastStep(runner, 1, describeFailure(written));
|
|
223
237
|
}
|
|
224
238
|
}
|
|
225
239
|
if (!failed(runner)) {
|
package/dist/bin/main.js
CHANGED
|
@@ -10,7 +10,7 @@ import { normalize } from "node:path";
|
|
|
10
10
|
import { parseArgs } from "node:util";
|
|
11
11
|
var package_default = {
|
|
12
12
|
name: "@orkestrel/scaffold",
|
|
13
|
-
version: "0.0.
|
|
13
|
+
version: "0.0.86",
|
|
14
14
|
description: "Scaffold workspaces with commands: new, audit, repair, catalog, and overwrite.",
|
|
15
15
|
keywords: [
|
|
16
16
|
"audit",
|
|
@@ -322,8 +322,25 @@ var VERB_SUMMARY = Object.freeze({
|
|
|
322
322
|
audit: "report how the target compares to its plan, writing nothing",
|
|
323
323
|
repair: "write each planned path the target is missing or has let drift",
|
|
324
324
|
catalog: "regenerate the package table and refresh the guide mirrors",
|
|
325
|
-
overwrite: "do everything repair and catalog do, then delete what the plan does not own
|
|
325
|
+
overwrite: "do everything repair and catalog do, then delete what the plan does not own, re-declare the dependency ranges, and declare each planned dependency the manifest lacks"
|
|
326
326
|
});
|
|
327
|
+
/**
|
|
328
|
+
* Matches a module specifier that names a built sheet's CSS as raw text.
|
|
329
|
+
*
|
|
330
|
+
* @remarks
|
|
331
|
+
* The planned sheet test is the one birth-owned test whose text imports a built
|
|
332
|
+
* sheet, so this is what tells it apart from a face's entry test at the same
|
|
333
|
+
* `tests/src/<face>/index.test.ts` shape.
|
|
334
|
+
*/
|
|
335
|
+
var SHEET_IMPORT_PATTERN = /from\s+(['"])[^'"]*dist\/src\/[^'"]+\.css\?raw\1/u;
|
|
336
|
+
/**
|
|
337
|
+
* Matches each import declaration whose module specifier is root-relative, capturing the specifier.
|
|
338
|
+
*
|
|
339
|
+
* @remarks
|
|
340
|
+
* A root-relative specifier opens with one `/`. Oxlint's `import/no-absolute-path` rule
|
|
341
|
+
* refuses it, while a protocol-relative `//` specifier is outside this pattern.
|
|
342
|
+
*/
|
|
343
|
+
var ROOT_IMPORT_PATTERN = /^\s*import\s[^'"]*?(['"])(\/(?!\/)[^'"]*)\1/gmu;
|
|
327
344
|
//#endregion
|
|
328
345
|
//#region src/bin/errors.ts
|
|
329
346
|
/**
|
|
@@ -653,6 +670,89 @@ function manifestToWritableDependencies(manifest, blueprint) {
|
|
|
653
670
|
};
|
|
654
671
|
}
|
|
655
672
|
/**
|
|
673
|
+
* Reads the planned dependencies a target manifest declares in neither writable section.
|
|
674
|
+
*
|
|
675
|
+
* @param manifest - The target manifest text.
|
|
676
|
+
* @param blueprint - The workspace shape that supplies the planned dependencies.
|
|
677
|
+
* @returns The undeclared planned dependencies at their planned ranges, in name order, each in
|
|
678
|
+
* the list naming the section the plan assigns it.
|
|
679
|
+
*
|
|
680
|
+
* @remarks
|
|
681
|
+
* The plan declares its tooling under `devDependencies`, so every row lands in `development` and
|
|
682
|
+
* `runtime` stays empty: the blueprint's runtime packages are read from the manifest's own
|
|
683
|
+
* `dependencies`, so none of them is ever missing. A planned package either section declares is
|
|
684
|
+
* present, whatever its range. A manifest that is not an object, or whose sections are not
|
|
685
|
+
* objects, yields what its readable sections leave undeclared, and the caller's refusal of that
|
|
686
|
+
* malformed shape decides whether a write may follow.
|
|
687
|
+
*
|
|
688
|
+
* @example
|
|
689
|
+
* ```ts
|
|
690
|
+
* import { createBlueprint } from '@src/core'
|
|
691
|
+
* import { manifestToAdditions } from './helpers.js'
|
|
692
|
+
*
|
|
693
|
+
* const blueprint = createBlueprint('sample', { src: ['core'] })
|
|
694
|
+
* manifestToAdditions('{"devDependencies": {}}', blueprint).development.some(
|
|
695
|
+
* ({ name }) => name === 'typescript',
|
|
696
|
+
* ) // true
|
|
697
|
+
* ```
|
|
698
|
+
*/
|
|
699
|
+
function manifestToAdditions(manifest, blueprint) {
|
|
700
|
+
const parsed = parseJSON(manifest);
|
|
701
|
+
const runtime = isRecord(parsed) && isRecord(parsed.dependencies) ? parsed.dependencies : {};
|
|
702
|
+
const development = isRecord(parsed) && isRecord(parsed.devDependencies) ? parsed.devDependencies : {};
|
|
703
|
+
return {
|
|
704
|
+
runtime: [],
|
|
705
|
+
development: Object.entries(blueprintToDevDependencies(blueprint)).filter(([name]) => !Object.hasOwn(runtime, name) && !Object.hasOwn(development, name)).map(([name, range]) => ({
|
|
706
|
+
name,
|
|
707
|
+
range
|
|
708
|
+
}))
|
|
709
|
+
};
|
|
710
|
+
}
|
|
711
|
+
/**
|
|
712
|
+
* Reads the root-relative imports a target keeps in a planned birth-owned sheet test.
|
|
713
|
+
*
|
|
714
|
+
* @param artifact - The planned artifact at the path the target holds.
|
|
715
|
+
* @param present - The text the target holds at that path.
|
|
716
|
+
* @returns A non-blocking `tests` question naming the file and each root-relative specifier beside
|
|
717
|
+
* the relative specifier to write, or `undefined` when the artifact is not a birth-owned sheet
|
|
718
|
+
* test or the text imports nothing by a root-relative specifier.
|
|
719
|
+
*
|
|
720
|
+
* @remarks
|
|
721
|
+
* Birth ownership never rewrites a present file, so a target born before the sheet test imported
|
|
722
|
+
* the built sheet by a relative path keeps the root-relative import, and the content-owned lint
|
|
723
|
+
* configuration refuses it. The relative specifier climbs one `../` per directory of the
|
|
724
|
+
* artifact's path to the workspace root, which is the specifier the planned test itself imports.
|
|
725
|
+
*
|
|
726
|
+
* @example
|
|
727
|
+
* ```ts
|
|
728
|
+
* import { sheetTestToQuestion } from './helpers.js'
|
|
729
|
+
*
|
|
730
|
+
* const artifact = {
|
|
731
|
+
* path: 'tests/src/styles/index.test.ts',
|
|
732
|
+
* group: 'tests',
|
|
733
|
+
* ownership: 'birth',
|
|
734
|
+
* origin: 'template',
|
|
735
|
+
* content: "import sheet from '../../../dist/src/styles/index.css?raw'\n",
|
|
736
|
+
* } as const
|
|
737
|
+
* sheetTestToQuestion(artifact, "import sheet from '/dist/src/styles/index.css?raw'\n")?.field // 'tests'
|
|
738
|
+
* sheetTestToQuestion(artifact, artifact.content) // undefined
|
|
739
|
+
* ```
|
|
740
|
+
*/
|
|
741
|
+
function sheetTestToQuestion(artifact, present) {
|
|
742
|
+
if (artifact.origin === "host" || artifact.ownership !== "birth") return void 0;
|
|
743
|
+
if (!SHEET_IMPORT_PATTERN.test(artifact.content)) return void 0;
|
|
744
|
+
const root = "../".repeat(artifact.path.split("/").length - 1);
|
|
745
|
+
const replacements = [...present.matchAll(ROOT_IMPORT_PATTERN)].map((match) => `'${match[2] ?? ""}' with '${root}${(match[2] ?? "").slice(1)}'`);
|
|
746
|
+
if (replacements.length === 0) return void 0;
|
|
747
|
+
const single = replacements.length === 1;
|
|
748
|
+
return {
|
|
749
|
+
field: "tests",
|
|
750
|
+
message: `The birth-owned sheet test ${artifact.path} imports by ${single ? "a root-relative specifier" : "root-relative specifiers"}, which oxlint's import/no-absolute-path rule refuses under --deny-warnings. Replace ${replacements.join(" and ")}. Scaffold does not rewrite a birth-owned file.`,
|
|
751
|
+
blocking: false,
|
|
752
|
+
groups: ["tests"]
|
|
753
|
+
};
|
|
754
|
+
}
|
|
755
|
+
/**
|
|
656
756
|
* Reads the manifest scripts a writing verb may write.
|
|
657
757
|
*
|
|
658
758
|
* @param manifest - The target manifest text.
|
|
@@ -1517,11 +1617,14 @@ function selectionToPackages(selection) {
|
|
|
1517
1617
|
*
|
|
1518
1618
|
* @param first - The earlier result, which fixes the reported target.
|
|
1519
1619
|
* @param second - The later result.
|
|
1520
|
-
* @returns One result carrying both path lists, first's paths ahead of second's
|
|
1620
|
+
* @returns One result carrying both path lists, first's paths ahead of second's, each list
|
|
1621
|
+
* naming a path once.
|
|
1521
1622
|
*
|
|
1522
1623
|
* @remarks
|
|
1523
|
-
*
|
|
1524
|
-
*
|
|
1624
|
+
* Two calls can answer for one path: `overwrite` declares a missing dependency
|
|
1625
|
+
* and later rewrites the ranges in the same manifest, so each list keeps a path's
|
|
1626
|
+
* first entry. A path one call skipped and another wrote stays in both lists, as
|
|
1627
|
+
* the manifest a repair skips by birth and its range write rewrites does.
|
|
1525
1628
|
*
|
|
1526
1629
|
* @example
|
|
1527
1630
|
* ```ts
|
|
@@ -1536,9 +1639,9 @@ function selectionToPackages(selection) {
|
|
|
1536
1639
|
function mergeResults(first, second) {
|
|
1537
1640
|
return {
|
|
1538
1641
|
target: first.target,
|
|
1539
|
-
written: [...first.written, ...second.written],
|
|
1540
|
-
skipped: [...first.skipped, ...second.skipped],
|
|
1541
|
-
removed: [...first.removed, ...second.removed]
|
|
1642
|
+
written: [.../* @__PURE__ */ new Set([...first.written, ...second.written])],
|
|
1643
|
+
skipped: [.../* @__PURE__ */ new Set([...first.skipped, ...second.skipped])],
|
|
1644
|
+
removed: [.../* @__PURE__ */ new Set([...first.removed, ...second.removed])]
|
|
1542
1645
|
};
|
|
1543
1646
|
}
|
|
1544
1647
|
/**
|
|
@@ -1845,7 +1948,7 @@ var CLI = class {
|
|
|
1845
1948
|
const target = command.target ?? ".";
|
|
1846
1949
|
const groups = selectionToGroups(command.groups);
|
|
1847
1950
|
const blueprint = this.#derive(target);
|
|
1848
|
-
this.#assertTarget(target, blueprint, groups);
|
|
1951
|
+
this.#assertTarget(target, blueprint, groups, true);
|
|
1849
1952
|
const worktree = await this.#worktree(target);
|
|
1850
1953
|
if (worktree.dirty.length > 0 && command.dirty !== true) throw new ScaffoldError("TARGET", `The target at ${target} carries ${String(worktree.dirty.length)} uncommitted change${worktree.dirty.length === 1 ? "" : "s"}. Commit them, or pass --dirty to waive the refusal.`, {
|
|
1851
1954
|
target,
|
|
@@ -1866,23 +1969,42 @@ var CLI = class {
|
|
|
1866
1969
|
pins: manifestToWritableDependencies(this.#manifest(target), blueprint),
|
|
1867
1970
|
scripts: manifestToWritableScripts(this.#manifest(target), blueprint)
|
|
1868
1971
|
};
|
|
1869
|
-
const
|
|
1972
|
+
const additions = manifestToAdditions(this.#manifest(target), blueprint);
|
|
1973
|
+
const repaired = host.materializer.repair(plan, audit, target);
|
|
1974
|
+
const added = additions.runtime.length === 0 && additions.development.length === 0 ? void 0 : host.materializer.declare({
|
|
1975
|
+
pins: {
|
|
1976
|
+
runtime: [],
|
|
1977
|
+
development: []
|
|
1978
|
+
},
|
|
1979
|
+
scripts: [],
|
|
1980
|
+
additions
|
|
1981
|
+
}, target);
|
|
1982
|
+
const removed = host.materializer.remove(plan, audit, command.dirty === true ? {
|
|
1870
1983
|
tracked: worktree.tracked,
|
|
1871
1984
|
dirty: []
|
|
1872
|
-
} : worktree, target)
|
|
1985
|
+
} : worktree, target);
|
|
1986
|
+
const local = mergeResults(added === void 0 ? repaired : mergeResults(repaired, added), removed);
|
|
1873
1987
|
const remainder = command.offline === true ? await this.#declare(host.materializer, target, declared, host.baseline) : await this.#reconcile(host.materializer, target, declared, host.baseline, host.forced);
|
|
1874
1988
|
const [measured] = this.#survey(host.materializer, blueprint, target, groups);
|
|
1875
1989
|
const terminal = this.#appendQuestions(measured, target, blueprint, groups);
|
|
1876
1990
|
const outcome = {
|
|
1877
1991
|
...remainder,
|
|
1878
1992
|
...mergeResults(local, remainder),
|
|
1879
|
-
audit: terminal
|
|
1993
|
+
audit: terminal,
|
|
1994
|
+
additions
|
|
1880
1995
|
};
|
|
1881
1996
|
if (command.json === true) this.#report(outcome);
|
|
1882
1997
|
else {
|
|
1883
1998
|
this.#present(terminal);
|
|
1884
1999
|
this.#reportReplacements(audit, terminal);
|
|
1885
2000
|
this.#recount(outcome);
|
|
2001
|
+
for (const { section, dependencies } of [{
|
|
2002
|
+
section: "dependencies",
|
|
2003
|
+
dependencies: additions.runtime
|
|
2004
|
+
}, {
|
|
2005
|
+
section: "devDependencies",
|
|
2006
|
+
dependencies: additions.development
|
|
2007
|
+
}]) for (const { name, range } of dependencies) this.#say(`Declared ${JSON.stringify(name)}: ${JSON.stringify(range)} in ${section}. Run npm install to install it.`);
|
|
1886
2008
|
if (remainder.note !== void 0) this.#warn(remainder.note);
|
|
1887
2009
|
}
|
|
1888
2010
|
if (remainder.note !== void 0) return 1;
|
|
@@ -2341,9 +2463,32 @@ var CLI = class {
|
|
|
2341
2463
|
groups: ["manifest"]
|
|
2342
2464
|
};
|
|
2343
2465
|
}
|
|
2344
|
-
#dependencyQuestion(target, blueprint, writing = false) {
|
|
2466
|
+
#dependencyQuestion(target, blueprint, writing = false, declaring = false) {
|
|
2345
2467
|
const parsed = parseJSON(this.#manifest(target));
|
|
2346
2468
|
if (!isRecord(parsed)) return void 0;
|
|
2469
|
+
const dependencies = isRecord(parsed.dependencies) ? parsed.dependencies : {};
|
|
2470
|
+
const development = isRecord(parsed.devDependencies) ? parsed.devDependencies : {};
|
|
2471
|
+
const missing = Object.entries(blueprintToDevDependencies(blueprint)).filter(([name]) => !Object.hasOwn(dependencies, name) && !Object.hasOwn(development, name)).sort(([left], [right]) => left.localeCompare(right));
|
|
2472
|
+
const names = missing.map(([name]) => name);
|
|
2473
|
+
if (declaring && missing.length > 0) {
|
|
2474
|
+
const planned = `${names.length === 1 ? "the planned dependency" : "the planned dependencies"} ${names.join(", ")}`;
|
|
2475
|
+
if (parsed.devDependencies !== void 0 && !isRecord(parsed.devDependencies)) return {
|
|
2476
|
+
field: "dependencies",
|
|
2477
|
+
message: `The manifest at ${target} declares devDependencies as a value that is not an object, so overwrite cannot declare ${planned} in it. Replace it with an object in package.json before running overwrite.`,
|
|
2478
|
+
blocking: true,
|
|
2479
|
+
groups: ["configs", "tests"]
|
|
2480
|
+
};
|
|
2481
|
+
const entries = Object.entries(development).filter(([, value]) => !isString(value)).map(([name]) => JSON.stringify(name));
|
|
2482
|
+
if (entries.length > 0) {
|
|
2483
|
+
const single = entries.length === 1;
|
|
2484
|
+
return {
|
|
2485
|
+
field: "dependencies",
|
|
2486
|
+
message: `The manifest at ${target} declares the devDependencies ${single ? "entry" : "entries"} ${entries.join(", ")} as ${single ? "a value that is not a version string" : "values that are not version strings"}, so overwrite cannot declare ${planned} beside ${single ? "it" : "them"}. Replace ${single ? "it with a version range" : "them with version ranges"} in package.json before running overwrite.`,
|
|
2487
|
+
blocking: true,
|
|
2488
|
+
groups: ["configs", "tests"]
|
|
2489
|
+
};
|
|
2490
|
+
}
|
|
2491
|
+
}
|
|
2347
2492
|
const malformed = ["dependencies", "devDependencies"].filter((section) => parsed[section] !== void 0 && !isRecord(parsed[section]));
|
|
2348
2493
|
if (malformed.length > 0) return {
|
|
2349
2494
|
field: "dependencies",
|
|
@@ -2351,11 +2496,7 @@ var CLI = class {
|
|
|
2351
2496
|
blocking: false,
|
|
2352
2497
|
groups: ["configs", "tests"]
|
|
2353
2498
|
};
|
|
2354
|
-
|
|
2355
|
-
const development = isRecord(parsed.devDependencies) ? parsed.devDependencies : {};
|
|
2356
|
-
const missing = Object.entries(blueprintToDevDependencies(blueprint)).filter(([name]) => !Object.hasOwn(dependencies, name) && !Object.hasOwn(development, name)).sort(([left], [right]) => left.localeCompare(right));
|
|
2357
|
-
if (missing.length === 0) return void 0;
|
|
2358
|
-
const names = missing.map(([name]) => name);
|
|
2499
|
+
if (missing.length === 0 || declaring) return void 0;
|
|
2359
2500
|
const lines = missing.map(([name, range]) => `${JSON.stringify(name)}: ${JSON.stringify(range)},`);
|
|
2360
2501
|
return {
|
|
2361
2502
|
field: "dependencies",
|
|
@@ -2390,7 +2531,15 @@ var CLI = class {
|
|
|
2390
2531
|
groups: ["tests"]
|
|
2391
2532
|
};
|
|
2392
2533
|
}
|
|
2393
|
-
#
|
|
2534
|
+
#sheetQuestions(target, blueprint) {
|
|
2535
|
+
return blueprintToTestArtifacts(blueprint).flatMap((artifact) => {
|
|
2536
|
+
const path = resolveContainedPath(target, artifact.path);
|
|
2537
|
+
if (path === void 0 || !isExactCaseFile(path)) return [];
|
|
2538
|
+
const question = sheetTestToQuestion(artifact, readFileText(target, artifact.path) ?? "");
|
|
2539
|
+
return question === void 0 ? [] : [question];
|
|
2540
|
+
});
|
|
2541
|
+
}
|
|
2542
|
+
#targetQuestions(target, blueprint, groups, writing = false, declaring = false) {
|
|
2394
2543
|
const questions = [];
|
|
2395
2544
|
const browser = resolveContainedPath(target, "app/browser");
|
|
2396
2545
|
if (browser !== void 0 && listFiles(browser).some((path) => path.endsWith(".vue"))) questions.push({
|
|
@@ -2405,11 +2554,12 @@ var CLI = class {
|
|
|
2405
2554
|
}
|
|
2406
2555
|
const project = this.#projectQuestion(target, blueprint, writing);
|
|
2407
2556
|
if (project !== void 0) questions.push(project);
|
|
2408
|
-
const dependency = this.#dependencyQuestion(target, blueprint, writing);
|
|
2557
|
+
const dependency = this.#dependencyQuestion(target, blueprint, writing, declaring);
|
|
2409
2558
|
if (dependency !== void 0) questions.push(dependency);
|
|
2410
2559
|
if (!writing) {
|
|
2411
2560
|
const setup = this.#setupQuestion(target, blueprint);
|
|
2412
2561
|
if (setup !== void 0) questions.push(setup);
|
|
2562
|
+
questions.push(...this.#sheetQuestions(target, blueprint));
|
|
2413
2563
|
}
|
|
2414
2564
|
return questions.filter((question) => question.blocking || groups === void 0 || question.groups.some((group) => groups.includes(group))).map(({ field, message, blocking, candidates }) => ({
|
|
2415
2565
|
field,
|
|
@@ -2425,9 +2575,9 @@ var CLI = class {
|
|
|
2425
2575
|
questions: [...audit.questions, ...questions]
|
|
2426
2576
|
};
|
|
2427
2577
|
}
|
|
2428
|
-
#assertTarget(target, blueprint, groups) {
|
|
2578
|
+
#assertTarget(target, blueprint, groups, declaring = false) {
|
|
2429
2579
|
if (manifestToName(this.#manifest(target)) === PACKAGE_NAME) throw new ScaffoldError("TARGET", `The target at ${target} is the ${PACKAGE_NAME} package, whose canon the vendored host is staged from. Run repair and overwrite against a workspace that consumes it.`, { target });
|
|
2430
|
-
const questions = this.#targetQuestions(target, blueprint, groups, true);
|
|
2580
|
+
const questions = this.#targetQuestions(target, blueprint, groups, true, declaring);
|
|
2431
2581
|
if (questions.length === 0) return;
|
|
2432
2582
|
throw new ScaffoldError("TARGET", questions.map((question) => question.message).join(" "), { target });
|
|
2433
2583
|
}
|