@orkestrel/scaffold 0.0.81 → 0.0.82

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.
Files changed (35) hide show
  1. package/dist/bin/main.js +167 -13
  2. package/dist/bin/main.js.map +1 -1
  3. package/dist/host/AGENTS.md +5 -3
  4. package/dist/host/agents/skills/orkestrel-harden/references/centralization.md +2 -2
  5. package/dist/host/agents/skills/orkestrel-journey/SKILL.md +41 -38
  6. package/dist/host/agents/skills/orkestrel-journey/references/captures.md +3 -3
  7. package/dist/host/agents/skills/orkestrel-journey/references/decide.md +3 -3
  8. package/dist/host/agents/skills/orkestrel-journey/references/layer.md +5 -5
  9. package/dist/host/agents/skills/orkestrel-journey/references/statechart.md +3 -3
  10. package/dist/host/agents/skills/orkestrel-journey/references/styles.md +9 -9
  11. package/dist/host/claude/rules/application.md +20 -6
  12. package/dist/host/claude/rules/architecture.md +2 -2
  13. package/dist/host/claude/rules/browser.md +9 -0
  14. package/dist/host/claude/rules/documentation.md +2 -1
  15. package/dist/host/claude/rules/styles.md +35 -12
  16. package/dist/host/claude/rules/tests.md +15 -10
  17. package/dist/host/claude/rules/workspace.md +128 -98
  18. package/dist/host/claude/skills/orkestrel-journey/SKILL.md +1 -1
  19. package/dist/host/configs/helpers.ts +157 -9
  20. package/dist/host/configs/policy.ts +64 -61
  21. package/dist/host/dotfiles/oxlintrc.json +132 -16
  22. package/dist/host/dotfiles/prettierignore +1 -1
  23. package/dist/host/guides/README.md +9 -5
  24. package/dist/host/guides/scaffold.md +475 -115
  25. package/dist/host/manifest.json +26 -26
  26. package/dist/host/tests/config.test.ts +996 -39
  27. package/dist/host/tests/policy.test.ts +11 -0
  28. package/dist/host/tests/setupPolicy.ts +396 -22
  29. package/dist/src/core/index.cjs +1261 -159
  30. package/dist/src/core/index.cjs.map +1 -1
  31. package/dist/src/core/index.d.cts +297 -35
  32. package/dist/src/core/index.d.ts +297 -35
  33. package/dist/src/core/index.js +1241 -160
  34. package/dist/src/core/index.js.map +1 -1
  35. package/package.json +1 -1
package/dist/bin/main.js CHANGED
@@ -1,10 +1,12 @@
1
1
  #!/usr/bin/env node
2
2
  import { align, renderTable, strip, stripControls, width } from "@orkestrel/console";
3
3
  import { attempt, isArray, isError, isInstance, isRecord, isString, parseJSON } from "@orkestrel/contract";
4
- import { BIN_ENTRY_PATH, CATALOG_AGENT_PATH, CONFORMANCE_TEST_PATH, Compiler, DEPENDENCY_NAME_PATTERN, ENVIRONMENTS, GLOBAL_SETUP_PATH, GROUPS, GUIDES_TEST_PATH, HOST_PATHS, INTEGRATION_TEST_PATH, JOURNEY_CONFIG_PATH, MAX_MANIFEST_BYTES, MAX_PATH_LENGTH, SERVICE_SETUP_PATH, SHOWCASE_CONFIG_PATH, SKILLS_CONFIG_PATH, ScaffoldError, blueprintToConfigArtifacts, blueprintToDevDependencies, blueprintToRootVite, blueprintToScripts, blueprintToTestArtifacts, blueprintToWritableScripts, compareVersions, createBlueprint, extractRangeMajor, extractVersion, isFloorPath, isScaffoldError, manifestToDependencies, manifestToName, nameToGuide, replaceManifestScripts, replacePlanRanges } from "../src/core/index.js";
4
+ import { AXES, BIN_ENTRY_PATH, CATALOG_AGENT_PATH, CONFORMANCE_TEST_PATH, Compiler, DEPENDENCY_NAME_PATTERN, ENVIRONMENTS, FRAMEWORKS, GLOBAL_SETUP_PATH, GROUPS, GUIDES_TEST_PATH, HOST_PATHS, INTEGRATION_TEST_PATH, JOURNEY_CONFIG_PATH, MAX_MANIFEST_BYTES, MAX_PATH_LENGTH, RESERVED_SHEET_NAMES, SERVICE_SETUP_PATH, SHEET_ENTRY_NAME, SHOWCASE_CONFIG_PATH, SHOWCASE_PAGES_PATH, SKILLS_CONFIG_PATH, STYLES_ENTRY_PATH, ScaffoldError, THEMES_BARREL_PATH, THEMES_ENTRY_PATH, blueprintToConfigArtifacts, blueprintToDevDependencies, blueprintToFaces, blueprintToProjects, blueprintToScripts, blueprintToSheets, blueprintToTestArtifacts, blueprintToWritableScripts, compareVersions, createBlueprint, extractRangeMajor, extractVersion, isFloorPath, isScaffoldError, isSheetName, manifestToDependencies, manifestToName, nameToGuide, parseExtension, replaceManifestScripts, replacePlanRanges } from "../src/core/index.js";
5
5
  import { MAX_INVENTORY_PATHS, Materializer, Upstream, filesToHost, isExactCaseFile, isPhysicalDirectory, isWorktree, listFiles, readFileText, readHostFloor, readHostManifest, readSnapshot, resolveContainedPath } from "../src/server/index.js";
6
6
  import { createMarkdown, flattenText, isTableNode } from "@orkestrel/markdown";
7
7
  import { createSession } from "@orkestrel/process/server";
8
+ import { readdirSync } from "node:fs";
9
+ import { normalize } from "node:path";
8
10
  import { parseArgs } from "node:util";
9
11
  //#region src/bin/constants.ts
10
12
  /**
@@ -82,6 +84,13 @@ var COMMAND_OPTIONS = Object.freeze({
82
84
  src: Object.freeze({ type: "string" }),
83
85
  app: Object.freeze({ type: "string" }),
84
86
  bin: Object.freeze({ type: "boolean" }),
87
+ styles: Object.freeze({ type: "boolean" }),
88
+ themes: Object.freeze({ type: "boolean" }),
89
+ showcase: Object.freeze({ type: "boolean" }),
90
+ extend: Object.freeze({
91
+ type: "string",
92
+ multiple: true
93
+ }),
85
94
  deps: Object.freeze({ type: "string" }),
86
95
  groups: Object.freeze({ type: "string" }),
87
96
  all: Object.freeze({ type: "boolean" }),
@@ -106,6 +115,10 @@ var OPTION_SUMMARY = Object.freeze({
106
115
  "--src <list>": "the published library environments to build: core, browser, server",
107
116
  "--app <list>": "the private application environments to build: core, browser, server",
108
117
  "--bin": "scaffold a command-line executable at src/bin/main.ts",
118
+ "--styles": "select the base styles surface",
119
+ "--themes": "select themes; requires --styles",
120
+ "--showcase": "select the showcase; requires --app browser",
121
+ "--extend <list>": "select surface:name extensions on the selected surfaces",
109
122
  "--deps <list>": "the @orkestrel/* packages the workspace depends on",
110
123
  "--groups <list>": "the artifact groups to cover; every group when absent",
111
124
  "--all": "fetch a guide for every package the organization publishes, not the declared ones alone",
@@ -131,6 +144,10 @@ var VERB_OPTIONS = Object.freeze({
131
144
  "--src <list>",
132
145
  "--app <list>",
133
146
  "--bin",
147
+ "--styles",
148
+ "--themes",
149
+ "--showcase",
150
+ "--extend <list>",
134
151
  "--deps <list>",
135
152
  "--offline",
136
153
  "--from <path>",
@@ -383,6 +400,9 @@ function argvToCommand(argv) {
383
400
  const target = isString(values.target) ? values.target : void 0;
384
401
  const json = values.json === true;
385
402
  const [from] = paths;
403
+ const extensions = isArray(values.extend) ? values.extend.filter(isString) : [];
404
+ if (extensions.length > 1) throw new UsageError("'new' takes --extend once; combine entries in one list.");
405
+ const [extension] = extensions;
386
406
  const location = target === void 0 ? {} : { target };
387
407
  const source = from === void 0 ? {} : { from };
388
408
  const selection = isString(values.groups) ? { groups: values.groups } : {};
@@ -398,6 +418,10 @@ function argvToCommand(argv) {
398
418
  ...src === void 0 ? {} : { src },
399
419
  ...app === void 0 ? {} : { app },
400
420
  ...bin ? { bin } : {},
421
+ ...values.styles === true ? { styles: true } : {},
422
+ ...values.themes === true ? { themes: true } : {},
423
+ ...values.showcase === true ? { showcase: true } : {},
424
+ ...extension === void 0 ? {} : { extensions: extension },
401
425
  ...offline ? { offline } : {},
402
426
  ...dependencies === void 0 ? {} : { dependencies }
403
427
  };
@@ -888,6 +912,7 @@ function releasesToPins(releases, declared) {
888
912
  * Reads the literal Vitest projects, configuration paths, and npm run scripts a shell command names.
889
913
  *
890
914
  * @param script - The manifest script text to read.
915
+ * @param wrappers - Planned wrapper paths mapped to the face projects they run.
891
916
  * @returns The named projects, configurations, and scripts, or `undefined` when the command
892
917
  * cannot be read literally.
893
918
  *
@@ -906,7 +931,7 @@ function releasesToPins(releases, declared) {
906
931
  * // { projects: ['src:core'], configs: [], scripts: [] }
907
932
  * ```
908
933
  */
909
- function scriptToInvocations(script) {
934
+ function scriptToInvocations(script, wrappers = /* @__PURE__ */ new Map()) {
910
935
  const tokens = [];
911
936
  let value = "";
912
937
  let resolved = true;
@@ -983,9 +1008,19 @@ function scriptToInvocations(script) {
983
1008
  const projects = [];
984
1009
  const configs = [];
985
1010
  const scripts = [];
1011
+ const configurations = new Map([...wrappers].map(([path, project]) => [normalize(path), project]));
1012
+ let testing = false;
986
1013
  for (let index = 0; index < tokens.length; index += 1) {
987
1014
  const token = tokens[index];
988
1015
  if (token === void 0) return void 0;
1016
+ if (index === 0 || [
1017
+ "&&",
1018
+ "||",
1019
+ ";",
1020
+ "|",
1021
+ "&",
1022
+ "("
1023
+ ].includes(tokens[index - 1]?.value ?? "")) testing = token.resolved && token.value === "vitest" && tokens[index + 1]?.value === "run";
989
1024
  if (token.value === "npm" && tokens[index + 1]?.value === "run") {
990
1025
  const name = tokens[index + 2];
991
1026
  if (name === void 0 || !name.resolved || name.value.length === 0 || [
@@ -1012,14 +1047,20 @@ function scriptToInvocations(script) {
1012
1047
  "(",
1013
1048
  ")"
1014
1049
  ].includes(project.value)) return void 0;
1015
- (token.value === "--project" ? projects : configs).push(project.value);
1050
+ const names = token.value === "--project" ? projects : configs;
1051
+ names.push(project.value);
1052
+ const face = testing && names === configs ? configurations.get(normalize(project.value)) : void 0;
1053
+ if (face !== void 0) projects.push(face);
1016
1054
  index += 1;
1017
1055
  continue;
1018
1056
  }
1019
1057
  if (token.value.startsWith("--project=") || token.value.startsWith("--config=")) {
1020
1058
  const project = token.value.slice(token.value.indexOf("=") + 1);
1021
1059
  if (!token.resolved || project.length === 0) return void 0;
1022
- (token.value.startsWith("--project=") ? projects : configs).push(project);
1060
+ const names = token.value.startsWith("--project=") ? projects : configs;
1061
+ names.push(project);
1062
+ const face = testing && names === configs ? configurations.get(normalize(project)) : void 0;
1063
+ if (face !== void 0) projects.push(face);
1023
1064
  continue;
1024
1065
  }
1025
1066
  if (!token.resolved && /--project|--config/.test(token.value)) return void 0;
@@ -1055,6 +1096,96 @@ function targetToEnvironments(target, axis) {
1055
1096
  });
1056
1097
  }
1057
1098
  /**
1099
+ * Reads the styles, themes, and showcase markers a target physically holds.
1100
+ * @param target - The target directory.
1101
+ * @returns The independent structural facts, false when their markers are absent.
1102
+ */
1103
+ function targetToFacts(target) {
1104
+ const styles = resolveContainedPath(target, STYLES_ENTRY_PATH);
1105
+ const themes = resolveContainedPath(target, THEMES_ENTRY_PATH);
1106
+ const barrel = resolveContainedPath(target, THEMES_BARREL_PATH);
1107
+ const wrapper = resolveContainedPath(target, SHOWCASE_CONFIG_PATH);
1108
+ const pages = resolveContainedPath(target, SHOWCASE_PAGES_PATH);
1109
+ return {
1110
+ styles: styles !== void 0 && isExactCaseFile(styles),
1111
+ themes: themes !== void 0 && isExactCaseFile(themes) && barrel !== void 0 && isExactCaseFile(barrel),
1112
+ showcase: wrapper !== void 0 && isExactCaseFile(wrapper) || pages !== void 0 && isPhysicalDirectory(pages)
1113
+ };
1114
+ }
1115
+ /**
1116
+ * Reads browser faces and named sheet marker pairs from a target.
1117
+ * @param target - The target directory.
1118
+ * @returns Browser extensions in framework order followed by sheets in code-unit order.
1119
+ * @throws `ScaffoldError` when sheet markers name an invalid or case-colliding face, or the directory cannot be read.
1120
+ */
1121
+ function targetToExtensions(target) {
1122
+ const extensions = [];
1123
+ for (const name of FRAMEWORKS) {
1124
+ const axes = AXES.filter((axis) => {
1125
+ const path = resolveContainedPath(target, `${axis}/${name}`);
1126
+ return path !== void 0 && isPhysicalDirectory(path);
1127
+ });
1128
+ if (axes.length > 0) extensions.push({
1129
+ surface: "browser",
1130
+ name,
1131
+ axes
1132
+ });
1133
+ }
1134
+ const source = resolveContainedPath(target, "src");
1135
+ if (source === void 0 || !isPhysicalDirectory(source)) return extensions;
1136
+ const entries = readdirSync(source, { withFileTypes: true });
1137
+ if (entries.length > MAX_INVENTORY_PATHS) throw new ScaffoldError("TARGET", "The source directory exceeds the inventory limit.");
1138
+ const names = [];
1139
+ const seen = /* @__PURE__ */ new Set();
1140
+ for (const entry of entries) {
1141
+ if (!entry.isDirectory() || RESERVED_SHEET_NAMES.includes(entry.name)) continue;
1142
+ const sheet = resolveContainedPath(target, `src/${entry.name}/index.scss`);
1143
+ const marker = resolveContainedPath(target, `src/${entry.name}/${SHEET_ENTRY_NAME}`);
1144
+ if (sheet === void 0 || marker === void 0 || !isExactCaseFile(sheet) || !isExactCaseFile(marker)) continue;
1145
+ const folded = entry.name.toLowerCase();
1146
+ if (seen.has(folded)) throw new ScaffoldError("TARGET", `Case-colliding sheet face '${entry.name}'.`);
1147
+ seen.add(folded);
1148
+ names.push(entry.name);
1149
+ }
1150
+ for (const name of names.sort()) {
1151
+ if (!isSheetName(name)) throw new ScaffoldError("TARGET", `Invalid sheet face '${name}'.`);
1152
+ extensions.push({
1153
+ surface: "styles",
1154
+ name
1155
+ });
1156
+ }
1157
+ return extensions;
1158
+ }
1159
+ /**
1160
+ * Reads a creation extension list and assigns its selected browser axes.
1161
+ * @param selection - The comma-separated `surface:name` entries, or no selection.
1162
+ * @param axes - The axes selecting a browser environment.
1163
+ * @param styles - If `true`, admits stylesheet extensions; if `false`, refuses them.
1164
+ * @returns The validated extensions in selection order.
1165
+ * @throws `UsageError` when an entry is malformed, repeated, unsupported, or lacks its surface.
1166
+ */
1167
+ function selectionToExtensions(selection, axes, styles) {
1168
+ if (selection === void 0) return [];
1169
+ const extensions = [];
1170
+ const seen = /* @__PURE__ */ new Set();
1171
+ for (const entry of selection.split(",")) {
1172
+ const extension = parseExtension(entry);
1173
+ if (extension === void 0 || seen.has(entry)) throw new UsageError(`'--extend' refuses '${entry}': use distinct supported surface:name entries.`);
1174
+ seen.add(entry);
1175
+ if (extension.surface === "browser") {
1176
+ if (axes.length === 0) throw new UsageError("A browser extension requires browser in --src or --app.");
1177
+ extensions.push({
1178
+ ...extension,
1179
+ axes
1180
+ });
1181
+ } else {
1182
+ if (!styles) throw new UsageError("A styles extension requires --styles.");
1183
+ extensions.push(extension);
1184
+ }
1185
+ }
1186
+ return extensions;
1187
+ }
1188
+ /**
1058
1189
  * Reads the packages a target's catalog table listed before this run.
1059
1190
  *
1060
1191
  * @param target - The target or raw checkout directory, or a verified value host.
@@ -1396,9 +1527,17 @@ var CLI = class {
1396
1527
  async #create(command) {
1397
1528
  const target = command.target ?? command.name;
1398
1529
  const app = selectionToEnvironments(command.app, "app");
1530
+ const src = selectionToEnvironments(command.src, "src");
1531
+ if (command.themes === true && command.styles !== true) throw new UsageError("--themes requires --styles.");
1532
+ if (command.showcase === true && !app.includes("browser")) throw new UsageError("--showcase requires --app browser.");
1533
+ const axes = AXES.filter((axis) => (axis === "src" ? src : app).includes("browser"));
1399
1534
  const blueprint = createBlueprint(command.name, {
1400
- src: selectionToEnvironments(command.src, "src"),
1535
+ src,
1401
1536
  app,
1537
+ extensions: selectionToExtensions(command.extensions, axes, command.styles === true),
1538
+ styles: command.styles === true,
1539
+ themes: command.themes === true,
1540
+ showcase: command.showcase === true,
1402
1541
  journey: app.includes("browser"),
1403
1542
  bin: command.bin === true,
1404
1543
  setup: [],
@@ -1900,16 +2039,17 @@ var CLI = class {
1900
2039
  const conformance = resolveContainedPath(target, CONFORMANCE_TEST_PATH);
1901
2040
  const service = resolveContainedPath(target, SERVICE_SETUP_PATH);
1902
2041
  const global = resolveContainedPath(target, GLOBAL_SETUP_PATH);
1903
- const showcase = resolveContainedPath(target, SHOWCASE_CONFIG_PATH);
1904
2042
  const journey = resolveContainedPath(target, JOURNEY_CONFIG_PATH);
1905
2043
  const skills = resolveContainedPath(target, SKILLS_CONFIG_PATH);
1906
2044
  const setup = /* @__PURE__ */ new Set();
1907
2045
  if (tests !== void 0) for (const path of listFiles(tests)) {
1908
2046
  if (path.includes("/") || !path.startsWith("setup") || !path.endsWith(".test.ts")) continue;
1909
2047
  const proof = resolveContainedPath(tests, path);
1910
- if (proof !== void 0 && isExactCaseFile(proof)) setup.add(path === "setupBrowser.test.ts" ? "browser" : "node");
2048
+ if (proof !== void 0 && isExactCaseFile(proof)) setup.add(path === "setupBrowser.test.ts" || path === "setupStyles.test.ts" ? "browser" : "node");
1911
2049
  }
1912
2050
  return createBlueprint(declared.slice(declared.lastIndexOf("/") + 1), {
2051
+ ...targetToFacts(target),
2052
+ extensions: targetToExtensions(target),
1913
2053
  src: targetToEnvironments(target, "src"),
1914
2054
  app: targetToEnvironments(target, "app"),
1915
2055
  dependencies: manifestToDependencies(manifest).runtime,
@@ -1920,7 +2060,6 @@ var CLI = class {
1920
2060
  conformance: conformance !== void 0 && isExactCaseFile(conformance),
1921
2061
  service: service !== void 0 && isExactCaseFile(service),
1922
2062
  global: global !== void 0 && isExactCaseFile(global),
1923
- showcase: showcase !== void 0 && isExactCaseFile(showcase),
1924
2063
  journey: journey !== void 0 && isExactCaseFile(journey),
1925
2064
  skills: skills !== void 0 && isExactCaseFile(skills)
1926
2065
  });
@@ -1929,7 +2068,7 @@ var CLI = class {
1929
2068
  const text = this.#manifest(target);
1930
2069
  const writable = writing ? manifestToWritableScripts(text, blueprint) : blueprintToWritableScripts(blueprint);
1931
2070
  const manifest = replaceManifestScripts(text, writable) ?? text;
1932
- const planned = blueprintToRootVite(blueprint);
2071
+ const planned = new Set(blueprintToProjects(blueprint));
1933
2072
  const parsed = parseJSON(manifest);
1934
2073
  const scripts = isRecord(parsed) && isRecord(parsed.scripts) ? parsed.scripts : {};
1935
2074
  const gates = !isRecord(parsed) || parsed.private !== true ? ["test", "prepublishOnly"] : ["test"];
@@ -1943,7 +2082,7 @@ var CLI = class {
1943
2082
  unresolved = true;
1944
2083
  continue;
1945
2084
  }
1946
- for (const project of invoked.projects) if (!planned.includes(`name: { label: '${project}',`)) absent.add(project);
2085
+ for (const project of invoked.projects) if (!planned.has(project)) absent.add(project);
1947
2086
  }
1948
2087
  const projects = [...absent].sort();
1949
2088
  if (unresolved) return {
@@ -1991,6 +2130,14 @@ var CLI = class {
1991
2130
  if (command !== void 0) expectedLines.set(project, `"${direct}": ${JSON.stringify(command)},`);
1992
2131
  }
1993
2132
  }
2133
+ const faces = /* @__PURE__ */ new Set([...blueprintToSheets(blueprint).map((name) => `src:${name}`), ...blueprintToFaces(blueprint).flatMap(({ name, axes }) => axes.map((axis) => `${axis}:${name}`))]);
2134
+ const wrappers = /* @__PURE__ */ new Map();
2135
+ for (const artifact of blueprintToConfigArtifacts(blueprint)) {
2136
+ const match = /^configs\/(src|app)\/vite\.([^.]+)\.config\.ts$/u.exec(artifact.path);
2137
+ if (match === null) continue;
2138
+ const project = `${match[1]}:${match[2]}`;
2139
+ if (faces.has(project)) wrappers.set(artifact.path, project);
2140
+ }
1994
2141
  const reachable = /* @__PURE__ */ new Set();
1995
2142
  const chains = /* @__PURE__ */ new Map();
1996
2143
  for (const gate of gates) {
@@ -2003,7 +2150,7 @@ var CLI = class {
2003
2150
  visited.add(name);
2004
2151
  const script = scripts[name];
2005
2152
  if (!isString(script)) continue;
2006
- const invoked = scriptToInvocations(script);
2153
+ const invoked = scriptToInvocations(script, wrappers);
2007
2154
  if (invoked === void 0) {
2008
2155
  unresolved = true;
2009
2156
  continue;
@@ -2102,7 +2249,7 @@ var CLI = class {
2102
2249
  if (proofs.has(`${path.slice(0, -3)}.test.ts`)) return false;
2103
2250
  if (resolveContainedPath(tests, path) === void 0) return false;
2104
2251
  const content = (readFileText(tests, path) ?? "").trim();
2105
- return content !== "" && content !== (seeds.get(`tests/${path}`) ?? "");
2252
+ return /^export /m.test(content) && content !== (seeds.get(`tests/${path}`) ?? "");
2106
2253
  }).sort();
2107
2254
  if (modules.length === 0) return void 0;
2108
2255
  const single = modules.length === 1;
@@ -2118,6 +2265,13 @@ var CLI = class {
2118
2265
  }
2119
2266
  #targetQuestions(target, blueprint, groups, writing = false) {
2120
2267
  const questions = [];
2268
+ const browser = resolveContainedPath(target, "app/browser");
2269
+ if (browser !== void 0 && listFiles(browser).some((path) => path.endsWith(".vue"))) questions.push({
2270
+ field: "extensions",
2271
+ message: "Move Vue components from app/browser to app/vue before regenerating this workspace.",
2272
+ blocking: writing,
2273
+ groups: []
2274
+ });
2121
2275
  if (!writing) {
2122
2276
  const script = this.#scriptQuestion(target, blueprint);
2123
2277
  if (script !== void 0) questions.push(script);
@@ -2130,7 +2284,7 @@ var CLI = class {
2130
2284
  const setup = this.#setupQuestion(target, blueprint);
2131
2285
  if (setup !== void 0) questions.push(setup);
2132
2286
  }
2133
- return questions.filter((question) => groups === void 0 || question.groups.some((group) => groups.includes(group))).map(({ field, message, blocking, candidates }) => ({
2287
+ return questions.filter((question) => question.blocking || groups === void 0 || question.groups.some((group) => groups.includes(group))).map(({ field, message, blocking, candidates }) => ({
2134
2288
  field,
2135
2289
  message,
2136
2290
  blocking,