@orkestrel/scaffold 0.0.73 → 0.0.75

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 (34) hide show
  1. package/dist/bin/main.js +75 -34
  2. package/dist/bin/main.js.map +1 -1
  3. package/dist/host/agents/skills/orkestrel-prove-journey/SKILL.md +212 -29
  4. package/dist/host/agents/skills/orkestrel-prove-journey/references/captures.md +40 -15
  5. package/dist/host/agents/skills/orkestrel-prove-journey/references/decide.md +34 -15
  6. package/dist/host/agents/skills/orkestrel-prove-journey/references/layer.md +248 -52
  7. package/dist/host/agents/skills/orkestrel-prove-journey/references/statechart.md +255 -49
  8. package/dist/host/agents/skills/orkestrel-prove-journey/references/styles.md +111 -23
  9. package/dist/host/agents/transports/codex.md +7 -0
  10. package/dist/host/claude/agents/orkestrel.md +2 -2
  11. package/dist/host/claude/rules/documentation.md +2 -0
  12. package/dist/host/claude/rules/tests.md +5 -3
  13. package/dist/host/claude/rules/workspace.md +26 -15
  14. package/dist/host/codex/config.toml +4 -7
  15. package/dist/host/guides/README.md +5 -0
  16. package/dist/host/guides/scaffold.md +104 -14
  17. package/dist/host/guides/test.md +744 -184
  18. package/dist/host/manifest.json +19 -19
  19. package/dist/host/tests/config.test.ts +159 -64
  20. package/dist/host/tests/policy.test.ts +11 -1
  21. package/dist/host/tests/setupPolicy.ts +571 -7
  22. package/dist/src/core/index.cjs +112 -18
  23. package/dist/src/core/index.cjs.map +1 -1
  24. package/dist/src/core/index.d.cts +19 -6
  25. package/dist/src/core/index.d.ts +19 -6
  26. package/dist/src/core/index.js +112 -19
  27. package/dist/src/core/index.js.map +1 -1
  28. package/dist/src/server/index.cjs +6 -4
  29. package/dist/src/server/index.cjs.map +1 -1
  30. package/dist/src/server/index.d.cts +9 -7
  31. package/dist/src/server/index.d.ts +9 -7
  32. package/dist/src/server/index.js +6 -4
  33. package/dist/src/server/index.js.map +1 -1
  34. package/package.json +2 -2
@@ -4,7 +4,7 @@ let _orkestrel_template = require("@orkestrel/template");
4
4
  let _orkestrel_emitter = require("@orkestrel/emitter");
5
5
  var package_default = {
6
6
  name: "@orkestrel/scaffold",
7
- version: "0.0.73",
7
+ version: "0.0.75",
8
8
  description: "Scaffold workspaces with commands: new, audit, repair, catalog, and overwrite.",
9
9
  keywords: [
10
10
  "audit",
@@ -102,7 +102,7 @@ var package_default = {
102
102
  "@orkestrel/guide": "^0.0.20",
103
103
  "@orkestrel/html": "^0.0.10",
104
104
  "@orkestrel/probe": "^0.0.16",
105
- "@orkestrel/test": "^0.0.16",
105
+ "@orkestrel/test": "^0.0.18",
106
106
  "@types/node": "^26.5.1",
107
107
  "@vitest/browser-playwright": "^4.1.11",
108
108
  "oxfmt": "^0.68.0",
@@ -435,6 +435,8 @@ var SERVICE_SETUP_PATH = "tests/setupService.ts";
435
435
  var SERVICE_TEST_INCLUDE = "tests/service/**/*.test.ts";
436
436
  /** Names the Vite wrapper whose presence makes a workspace `showcase`. */
437
437
  var SHOWCASE_CONFIG_PATH = "configs/app/vite.showcase.config.ts";
438
+ /** Names the Vite wrapper whose presence makes a workspace `journey`. */
439
+ var JOURNEY_CONFIG_PATH = "configs/app/vite.journey.config.ts";
438
440
  /** Matches the bare workspace name syntax: lowercase alphanumeric with hyphens, letter first. */
439
441
  var NAME_PATTERN = /^[a-z][a-z0-9-]*$/;
440
442
  /**
@@ -671,7 +673,7 @@ var CONFIG_TEMPLATES = Object.freeze({
671
673
  "exclude": ["node_modules", "dist", "tmp"]
672
674
  }
673
675
  `,
674
- vite: `import type { PluginOption, UserConfig } from 'vite'
676
+ vite: `{{journey}}import type { PluginOption, UserConfig } from 'vite'
675
677
  import { mergeConfig } from 'vite'
676
678
  {{imports}}import { defineConfig } from 'vitest/config'
677
679
  import manifest from './package.json' with { type: 'json' }
@@ -945,7 +947,7 @@ function isNamedPlugin(plugin: PluginOption): plugin is { name: string } {
945
947
  root: resolveWorkspacePath('.'),
946
948
  dir: resolveWorkspacePath('.'),
947
949
  include: ['tests/app/browser/**/*.test.ts'],
948
- setupFiles: ['./tests/setup.ts', './tests/setupBrowser.ts'],
950
+ {{journeyExclude}} setupFiles: ['./tests/setup.ts', './tests/setupBrowser.ts'],
949
951
  browser: {
950
952
  enabled: true,
951
953
  provider: playwright(browserOptions),
@@ -956,7 +958,32 @@ function isNamedPlugin(plugin: PluginOption): plugin is { name: string } {
956
958
  }
957
959
  return mergeOverride(project, override)
958
960
  }
959
- {{showcaseFactory}}`,
961
+ {{showcaseFactory}}{{journeyFactory}}`,
962
+ journey: `
963
+ // Replace the journey fields directly: merging would concatenate the ordinary include
964
+ // and retain the exclusion of the journey suite.
965
+ export function appJourney(
966
+ variant: JourneyVariant,
967
+ variants: readonly JourneyVariant[],
968
+ ): UserConfig {
969
+ const browser = appBrowser()
970
+ return {
971
+ ...browser,
972
+ test: {
973
+ ...browser.test,
974
+ name: { label: \`journey:\${variant.name}\`, color: 'green' },
975
+ include: ['tests/app/browser/integration.test.ts'],
976
+ exclude: [],
977
+ provide: { variant: variant.name, variants, capture },
978
+ browser: {
979
+ ...browser.test?.browser,
980
+ enabled: true,
981
+ viewport: { width: variant.width, height: variant.height },
982
+ },
983
+ },
984
+ }
985
+ }
986
+ `,
960
987
  showcase: `
961
988
  export function appShowcase(override?: UserConfig): UserConfig {
962
989
  const output = 'dist/showcase'
@@ -1068,6 +1095,7 @@ export function appShowcase(override?: UserConfig): UserConfig {
1068
1095
  test: {
1069
1096
  name: { label: 'setup', color: 'white' },
1070
1097
  include: ['tests/setup*.test.ts'],
1098
+ exclude: ['tests/setupBrowser.test.ts'],
1071
1099
  setupFiles: ['./tests/setup.ts'],
1072
1100
  environment: 'node',
1073
1101
  browser: { enabled: false },
@@ -1075,6 +1103,23 @@ export function appShowcase(override?: UserConfig): UserConfig {
1075
1103
  }
1076
1104
  return mergeOverride(project, override)
1077
1105
  }
1106
+ `,
1107
+ browser: `export function setupBrowser(override?: UserConfig): UserConfig {
1108
+ const project: UserConfig = {
1109
+ resolve,
1110
+ {{plugins}} test: {
1111
+ name: { label: 'setup:browser', color: 'blue' },
1112
+ include: ['tests/setupBrowser.test.ts'],
1113
+ setupFiles: ['./tests/setup.ts', './tests/setupBrowser.ts'],
1114
+ browser: {
1115
+ enabled: true,
1116
+ provider: playwright(browserOptions),
1117
+ instances: [{ browser: 'chromium', headless: true }],
1118
+ },
1119
+ },
1120
+ }
1121
+ return mergeOverride(project, override)
1122
+ }
1078
1123
  `,
1079
1124
  guides: `export function guides(override?: UserConfig): UserConfig {
1080
1125
  const project: UserConfig = {
@@ -1407,6 +1452,22 @@ export default defineConfig(appServer())
1407
1452
  import { appShowcase } from '../../vite.config.ts'
1408
1453
 
1409
1454
  export default defineConfig(appShowcase())
1455
+ `,
1456
+ journey: `import type { JourneyVariant } from '@orkestrel/test'
1457
+ import { defineConfig } from 'vitest/config'
1458
+ import { appJourney } from '../../vite.config.ts'
1459
+
1460
+ // Rename and extend these viewports for the application. Apply themes through its interface.
1461
+ const VARIANTS: readonly JourneyVariant[] = Object.freeze([
1462
+ { name: 'desktop', width: 1280, height: 800 },
1463
+ { name: 'compact', width: 390, height: 844 },
1464
+ ])
1465
+
1466
+ export default defineConfig({
1467
+ test: {
1468
+ projects: VARIANTS.map((variant) => () => appJourney(variant, VARIANTS)),
1469
+ },
1470
+ })
1410
1471
  `
1411
1472
  })
1412
1473
  }),
@@ -1669,7 +1730,7 @@ export function resolveSystemBrowser(
1669
1730
  }
1670
1731
 
1671
1732
  /**
1672
- * Resolves Playwright provider options for whatever browser this host can actually launch.
1733
+ * Resolves Playwright provider options for Chromium on this host.
1673
1734
  *
1674
1735
  * @param pinned - The executable path for Playwright's pinned Chromium revision, when it has one.
1675
1736
  * @param platform - The Node platform whose standard layouts this call probes.
@@ -1689,6 +1750,10 @@ export function resolveSystemBrowser(
1689
1750
  * as well and exists only as a last resort: Windows takes \`msedge\`, which ships with the OS and
1690
1751
  * never collides with a foreground Chrome.
1691
1752
  *
1753
+ * The resolver and the gate cover Chromium alone. Reopen engine selection when another
1754
+ * Playwright engine is installed and launches on the host with a \`captureFrame\` reading
1755
+ * back at its declared size, or when a journey or style divergence is recorded.
1756
+ *
1692
1757
  * @example
1693
1758
  * \`\`\`ts
1694
1759
  * resolveBrowser(resolvePinnedBrowser(), process.platform, process.env)
@@ -3247,14 +3312,15 @@ var isBlueprint = (0, _orkestrel_contract.recordOf)({
3247
3312
  engines: _orkestrel_contract.isString,
3248
3313
  overrides: (0, _orkestrel_contract.andOf)(isCollection, (0, _orkestrel_contract.arrayOf)(isOverride)),
3249
3314
  bin: _orkestrel_contract.isBoolean,
3250
- setup: _orkestrel_contract.isBoolean,
3315
+ setup: (0, _orkestrel_contract.andOf)(isCollection, (0, _orkestrel_contract.arrayOf)((0, _orkestrel_contract.literalOf)("node", "browser"))),
3251
3316
  guides: _orkestrel_contract.isBoolean,
3252
3317
  integration: _orkestrel_contract.isBoolean,
3253
3318
  conformance: _orkestrel_contract.isBoolean,
3254
3319
  service: _orkestrel_contract.isBoolean,
3255
3320
  vendors: (0, _orkestrel_contract.andOf)(isCollection, (0, _orkestrel_contract.arrayOf)(_orkestrel_contract.isString)),
3256
3321
  global: _orkestrel_contract.isBoolean,
3257
- showcase: _orkestrel_contract.isBoolean
3322
+ showcase: _orkestrel_contract.isBoolean,
3323
+ journey: _orkestrel_contract.isBoolean
3258
3324
  }, ["description"]);
3259
3325
  /**
3260
3326
  * Narrows a value to an {@link Artifact}.
@@ -4730,7 +4796,7 @@ function blueprintToDevDependencies(blueprint) {
4730
4796
  const merged = {
4731
4797
  ...BASE_DEV_DEPENDENCIES,
4732
4798
  ...blueprint.src.length > 0 || blueprint.bin ? DECLARATION_DEV_DEPENDENCIES : {},
4733
- ...blueprint.src.includes("browser") ? SOURCE_BROWSER_DEV_DEPENDENCIES : {},
4799
+ ...blueprint.src.includes("browser") || blueprint.setup.includes("browser") ? SOURCE_BROWSER_DEV_DEPENDENCIES : {},
4734
4800
  ...blueprint.app.length > 0 ? APP_DEV_DEPENDENCIES : {},
4735
4801
  ...blueprint.app.includes("browser") ? APP_BROWSER_DEV_DEPENDENCIES : {},
4736
4802
  ...blueprint.showcase && blueprint.app.includes("browser") ? SHOWCASE_DEV_DEPENDENCIES : {},
@@ -4809,9 +4875,11 @@ function blueprintToScripts(blueprint) {
4809
4875
  scripts.test = [
4810
4876
  ...compiles ? ["npm run test:src"] : [],
4811
4877
  ...blueprint.app.length > 0 ? ["npm run test:app"] : [],
4878
+ ...blueprint.journey && blueprint.app.includes("browser") ? ["npm run test:journey"] : [],
4812
4879
  "npm run test:policy",
4813
4880
  "npm run test:config",
4814
- ...blueprint.setup ? ["npm run test:setup"] : [],
4881
+ ...blueprint.setup.includes("node") ? ["npm run test:setup"] : [],
4882
+ ...blueprint.setup.includes("browser") ? ["npm run test:setup:browser"] : [],
4815
4883
  ...blueprint.guides ? ["npm run test:guides"] : [],
4816
4884
  ...blueprint.conformance ? ["npm run test:conformance"] : [],
4817
4885
  ...integrates ? ["npm run test:integration"] : [],
@@ -4832,7 +4900,9 @@ function blueprintToScripts(blueprint) {
4832
4900
  }
4833
4901
  scripts["test:policy"] = `${vitest} --project policy`;
4834
4902
  scripts["test:config"] = `${vitest} --project config`;
4835
- if (blueprint.setup) scripts["test:setup"] = `${vitest} --project setup`;
4903
+ if (blueprint.setup.includes("node")) scripts["test:setup"] = `${vitest} --project setup`;
4904
+ if (blueprint.setup.includes("browser")) scripts["test:setup:browser"] = `${vitest} --project setup:browser`;
4905
+ if (blueprint.journey && blueprint.app.includes("browser")) scripts["test:journey"] = `vitest run --config ${JOURNEY_CONFIG_PATH} --no-cache --reporter=dot`;
4836
4906
  if (blueprint.guides) scripts["test:guides"] = `node --experimental-strip-types ${GUIDES_TEST_PATH}`;
4837
4907
  if (blueprint.conformance) scripts["test:conformance"] = `${vitest} --project conformance`;
4838
4908
  scripts["test:probe"] = "vitest run --config vite.config.ts --no-cache --reporter=verbose --project probe";
@@ -5056,7 +5126,7 @@ function blueprintToManifest(blueprint) {
5056
5126
  function blueprintToMachinery(blueprint) {
5057
5127
  const hosted = blueprint.app.some((environment) => environment !== "core");
5058
5128
  return {
5059
- browser: blueprint.src.includes("browser") || blueprint.app.includes("browser"),
5129
+ browser: blueprint.src.includes("browser") || blueprint.app.includes("browser") || blueprint.setup.includes("browser"),
5060
5130
  vue: blueprint.app.includes("browser"),
5061
5131
  output: blueprint.src.length > 0 || blueprint.bin || hosted,
5062
5132
  showcase: blueprint.showcase && blueprint.app.includes("browser")
@@ -5196,7 +5266,11 @@ function blueprintToRootVite(blueprint) {
5196
5266
  }
5197
5267
  if (blueprint.app.includes("browser")) {
5198
5268
  const showcaseFactory = machinery.showcase ? CONFIG_TEMPLATES.factories.app.showcase : "";
5199
- factories.push((0, _orkestrel_template.fillTemplate)(CONFIG_TEMPLATES.factories.app.browser, { showcaseFactory }));
5269
+ factories.push((0, _orkestrel_template.fillTemplate)(CONFIG_TEMPLATES.factories.app.browser, {
5270
+ showcaseFactory,
5271
+ journeyFactory: blueprint.journey ? CONFIG_TEMPLATES.factories.app.journey : "",
5272
+ journeyExclude: blueprint.journey ? " exclude: ['tests/app/browser/integration.test.ts'],\n" : ""
5273
+ }));
5200
5274
  projects.push("appBrowser");
5201
5275
  }
5202
5276
  if (blueprint.app.includes("server")) {
@@ -5207,10 +5281,14 @@ function blueprintToRootVite(blueprint) {
5207
5281
  projects.push("policy");
5208
5282
  factories.push(CONFIG_TEMPLATES.factories.config);
5209
5283
  projects.push("config");
5210
- if (blueprint.setup) {
5284
+ if (blueprint.setup.includes("node")) {
5211
5285
  factories.push(CONFIG_TEMPLATES.factories.setup);
5212
5286
  projects.push("setup");
5213
5287
  }
5288
+ if (blueprint.setup.includes("browser")) {
5289
+ factories.push((0, _orkestrel_template.fillTemplate)(CONFIG_TEMPLATES.factories.browser, { plugins: machinery.vue ? " plugins: [vue()],\n" : "" }));
5290
+ projects.push("setupBrowser");
5291
+ }
5214
5292
  if (blueprint.guides) {
5215
5293
  factories.push(CONFIG_TEMPLATES.factories.guides);
5216
5294
  projects.push("guides");
@@ -5244,10 +5322,11 @@ ${projects.map((project) => `\t\t\t${project},`).join("\n")}
5244
5322
  "outputBoundary"
5245
5323
  ].filter((helper) => body.includes(helper));
5246
5324
  return (0, _orkestrel_template.fillTemplate)(CONFIG_TEMPLATES.root.vite, {
5325
+ journey: blueprint.journey && machinery.vue ? "import type { JourneyVariant } from '@orkestrel/test'\n" : "",
5247
5326
  imports: imports.length === 0 ? "" : `${imports.join("\n")}\n`,
5248
5327
  helpers: helpers.length === 0 ? "" : `import { ${helpers.join(", ")} } from './configs/helpers.js'\n`,
5249
5328
  browsers: machinery.browser ? "import { resolveBrowser, resolvePinnedBrowser } from './configs/browsers.js'\n" : "",
5250
- options: machinery.browser ? "const browserOptions = resolveBrowser(resolvePinnedBrowser(), process.platform, process.env)\n\n" : "",
5329
+ options: (machinery.browser ? "const browserOptions = resolveBrowser(resolvePinnedBrowser(), process.platform, process.env)\n\n" : "") + (blueprint.journey && machinery.vue ? "const capture = process.env.CAPTURE === '1'\n\n" : ""),
5251
5330
  factories: body,
5252
5331
  projects: projectRows
5253
5332
  });
@@ -5360,6 +5439,14 @@ ${paths.join("\n")}
5360
5439
  environment: "browser",
5361
5440
  content: CONFIG_TEMPLATES.vites.app.showcase
5362
5441
  });
5442
+ if (blueprint.journey && blueprint.app.includes("browser")) artifacts.push({
5443
+ path: JOURNEY_CONFIG_PATH,
5444
+ group: "configs",
5445
+ ownership: "birth",
5446
+ origin: "template",
5447
+ environment: "browser",
5448
+ content: CONFIG_TEMPLATES.vites.app.journey
5449
+ });
5363
5450
  return artifacts;
5364
5451
  }
5365
5452
  /**
@@ -5480,7 +5567,7 @@ function blueprintToTestArtifacts(blueprint) {
5480
5567
  origin: "template",
5481
5568
  content: ARTIFACT_TEMPLATES.tests.setup
5482
5569
  }];
5483
- if (blueprint.src.includes("browser") || blueprint.app.includes("browser")) artifacts.push({
5570
+ if (blueprintToMachinery(blueprint).browser) artifacts.push({
5484
5571
  path: "tests/setupBrowser.ts",
5485
5572
  group: "tests",
5486
5573
  ownership: "birth",
@@ -6529,6 +6616,11 @@ function blueprintToQuestions(blueprint) {
6529
6616
  message: "showcase projects a browser app, and this workspace declares none, so it emits nothing.",
6530
6617
  blocking: false
6531
6618
  });
6619
+ if (blueprint.journey && !blueprint.app.includes("browser")) questions.push({
6620
+ field: "journey",
6621
+ message: "journey projects a browser app, and this workspace declares none, so it emits nothing.",
6622
+ blocking: false
6623
+ });
6532
6624
  questions.push(...dependenciesToQuestions(blueprint.dependencies, "dependencies", DEPENDENCY_NAME_PATTERN, ORKESTREL_RANGE_PATTERN), ...dependenciesToQuestions(blueprint.peers.filter((peer) => peer.name.startsWith("@orkestrel/")), "peers", DEPENDENCY_NAME_PATTERN, ORKESTREL_RANGE_PATTERN), ...dependenciesToQuestions(blueprint.peers.filter((peer) => !peer.name.startsWith("@orkestrel/")), "peers", FOREIGN_NAME_PATTERN, FLOOR_RANGE_PATTERN), ...dependenciesToQuestions(blueprint.extras, "extras", FOREIGN_NAME_PATTERN, EXTRA_RANGE_PATTERN));
6533
6625
  const lists = [
6534
6626
  ["dependencies", blueprint.dependencies],
@@ -6736,14 +6828,15 @@ function createBlueprint(name, input) {
6736
6828
  engines: input?.engines ?? DEFAULT_ENGINES,
6737
6829
  overrides: input?.overrides ?? [],
6738
6830
  bin: input?.bin ?? false,
6739
- setup: input?.setup ?? false,
6831
+ setup: input?.setup ?? [],
6740
6832
  guides: input?.guides ?? false,
6741
6833
  integration: input?.integration ?? false,
6742
6834
  conformance: input?.conformance ?? false,
6743
6835
  service: input?.service ?? false,
6744
6836
  vendors: input?.vendors ?? [],
6745
6837
  global: input?.global ?? false,
6746
- showcase: input?.showcase ?? false
6838
+ showcase: input?.showcase ?? false,
6839
+ journey: input?.journey ?? false
6747
6840
  }));
6748
6841
  if (blueprint === void 0) throw new ScaffoldError("INVALID", "The filled record is not a blueprint.", { name });
6749
6842
  return blueprint;
@@ -7087,6 +7180,7 @@ exports.HOST_INVENTORY_PATH = HOST_INVENTORY_PATH;
7087
7180
  exports.HOST_PATHS = HOST_PATHS;
7088
7181
  exports.INTEGRATION_TEST_PATH = INTEGRATION_TEST_PATH;
7089
7182
  exports.INVALID_PATH_CHARACTER_PATTERN = INVALID_PATH_CHARACTER_PATTERN;
7183
+ exports.JOURNEY_CONFIG_PATH = JOURNEY_CONFIG_PATH;
7090
7184
  exports.MANIFEST_PATH = MANIFEST_PATH;
7091
7185
  exports.MAX_ARTIFACT_BYTES = MAX_ARTIFACT_BYTES;
7092
7186
  exports.MAX_ARTIFACT_HEX_LENGTH = MAX_ARTIFACT_HEX_LENGTH;