@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
package/dist/bin/main.js CHANGED
@@ -1,7 +1,7 @@
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, MAX_MANIFEST_BYTES, MAX_PATH_LENGTH, SERVICE_SETUP_PATH, SHOWCASE_CONFIG_PATH, ScaffoldError, blueprintToDevDependencies, blueprintToRootVite, blueprintToScripts, blueprintToTestArtifacts, blueprintToWritableScripts, compareVersions, createBlueprint, extractRangeMajor, extractVersion, isFloorPath, isScaffoldError, manifestToDependencies, manifestToName, nameToGuide, replaceManifestScripts, replacePlanRanges } from "../src/core/index.js";
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, ScaffoldError, blueprintToConfigArtifacts, blueprintToDevDependencies, blueprintToRootVite, blueprintToScripts, blueprintToTestArtifacts, blueprintToWritableScripts, compareVersions, createBlueprint, extractRangeMajor, extractVersion, isFloorPath, isScaffoldError, manifestToDependencies, manifestToName, nameToGuide, 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";
@@ -836,16 +836,17 @@ function releasesToPins(releases, declared) {
836
836
  };
837
837
  }
838
838
  /**
839
- * Reads the literal Vitest projects and npm run scripts one shell command invokes.
839
+ * Reads the literal Vitest projects, configuration paths, and npm run scripts a shell command names.
840
840
  *
841
841
  * @param script - The manifest script text to read.
842
- * @returns The invoked projects and scripts, or `undefined` when the command
842
+ * @returns The named projects, configurations, and scripts, or `undefined` when the command
843
843
  * cannot be read literally.
844
844
  *
845
845
  * @remarks
846
846
  * Quotes group a token but do not hide the option, while shell expansions make
847
847
  * its value unresolved and therefore refuse the write that asked the question.
848
- * An unterminated quote, a trailing escape, and an unresolved `--project` value
848
+ * Configuration paths use `-c <path>`, `--config <path>`, or `--config=<path>`.
849
+ * An unterminated quote, a trailing escape, and an unresolved `--project`, `--config`, or `-c` value
849
850
  * all answer `undefined` rather than a partial reading.
850
851
  *
851
852
  * @example
@@ -853,7 +854,7 @@ function releasesToPins(releases, declared) {
853
854
  * import { scriptToInvocations } from './helpers.js'
854
855
  *
855
856
  * scriptToInvocations('vitest run --project src:core')
856
- * // { projects: ['src:core'], scripts: [] }
857
+ * // { projects: ['src:core'], configs: [], scripts: [] }
857
858
  * ```
858
859
  */
859
860
  function scriptToInvocations(script) {
@@ -931,6 +932,7 @@ function scriptToInvocations(script) {
931
932
  resolved
932
933
  });
933
934
  const projects = [];
935
+ const configs = [];
934
936
  const scripts = [];
935
937
  for (let index = 0; index < tokens.length; index += 1) {
936
938
  const token = tokens[index];
@@ -950,7 +952,7 @@ function scriptToInvocations(script) {
950
952
  index += 2;
951
953
  continue;
952
954
  }
953
- if (token.value === "--project") {
955
+ if (token.value === "--project" || token.value === "--config" || token.value === "-c") {
954
956
  const project = tokens[index + 1];
955
957
  if (project === void 0 || !project.resolved || project.value.length === 0 || [
956
958
  "&&",
@@ -961,20 +963,21 @@ function scriptToInvocations(script) {
961
963
  "(",
962
964
  ")"
963
965
  ].includes(project.value)) return void 0;
964
- projects.push(project.value);
966
+ (token.value === "--project" ? projects : configs).push(project.value);
965
967
  index += 1;
966
968
  continue;
967
969
  }
968
- if (token.value.startsWith("--project=")) {
969
- const project = token.value.slice(10);
970
+ if (token.value.startsWith("--project=") || token.value.startsWith("--config=")) {
971
+ const project = token.value.slice(token.value.indexOf("=") + 1);
970
972
  if (!token.resolved || project.length === 0) return void 0;
971
- projects.push(project);
973
+ (token.value.startsWith("--project=") ? projects : configs).push(project);
972
974
  continue;
973
975
  }
974
- if (!token.resolved && token.value.includes("--project")) return void 0;
976
+ if (!token.resolved && /--project|--config/.test(token.value)) return void 0;
975
977
  }
976
978
  return {
977
979
  projects,
980
+ configs,
978
981
  scripts
979
982
  };
980
983
  }
@@ -1343,11 +1346,13 @@ var CLI = class {
1343
1346
  }
1344
1347
  async #create(command) {
1345
1348
  const target = command.target ?? command.name;
1349
+ const app = selectionToEnvironments(command.app, "app");
1346
1350
  const blueprint = createBlueprint(command.name, {
1347
1351
  src: selectionToEnvironments(command.src, "src"),
1348
- app: selectionToEnvironments(command.app, "app"),
1352
+ app,
1353
+ journey: app.includes("browser"),
1349
1354
  bin: command.bin === true,
1350
- setup: false,
1355
+ setup: [],
1351
1356
  dependencies: selectionToPackages(command.dependencies).map((name) => ({
1352
1357
  name,
1353
1358
  range: "^0.0.0"
@@ -1847,22 +1852,26 @@ var CLI = class {
1847
1852
  const service = resolveContainedPath(target, SERVICE_SETUP_PATH);
1848
1853
  const global = resolveContainedPath(target, GLOBAL_SETUP_PATH);
1849
1854
  const showcase = resolveContainedPath(target, SHOWCASE_CONFIG_PATH);
1855
+ const journey = resolveContainedPath(target, JOURNEY_CONFIG_PATH);
1856
+ const setup = /* @__PURE__ */ new Set();
1857
+ if (tests !== void 0) for (const path of listFiles(tests)) {
1858
+ if (path.includes("/") || !path.startsWith("setup") || !path.endsWith(".test.ts")) continue;
1859
+ const proof = resolveContainedPath(tests, path);
1860
+ if (proof !== void 0 && isExactCaseFile(proof)) setup.add(path === "setupBrowser.test.ts" ? "browser" : "node");
1861
+ }
1850
1862
  return createBlueprint(declared.slice(declared.lastIndexOf("/") + 1), {
1851
1863
  src: targetToEnvironments(target, "src"),
1852
1864
  app: targetToEnvironments(target, "app"),
1853
1865
  dependencies: manifestToDependencies(manifest).runtime,
1854
1866
  bin: bin !== void 0 && isExactCaseFile(bin),
1855
- setup: tests !== void 0 && listFiles(tests).some((path) => {
1856
- if (path.includes("/") || !path.startsWith("setup") || !path.endsWith(".test.ts")) return false;
1857
- const proof = resolveContainedPath(tests, path);
1858
- return proof !== void 0 && isExactCaseFile(proof);
1859
- }),
1867
+ setup: [...setup],
1860
1868
  guides: guides !== void 0 && isExactCaseFile(guides),
1861
1869
  integration: integration !== void 0 && isExactCaseFile(integration),
1862
1870
  conformance: conformance !== void 0 && isExactCaseFile(conformance),
1863
1871
  service: service !== void 0 && isExactCaseFile(service),
1864
1872
  global: global !== void 0 && isExactCaseFile(global),
1865
- showcase: showcase !== void 0 && isExactCaseFile(showcase)
1873
+ showcase: showcase !== void 0 && isExactCaseFile(showcase),
1874
+ journey: journey !== void 0 && isExactCaseFile(journey)
1866
1875
  });
1867
1876
  }
1868
1877
  #projectQuestion(target, blueprint, writing = false) {
@@ -1897,6 +1906,26 @@ var CLI = class {
1897
1906
  blocking: false,
1898
1907
  groups: ["configs"]
1899
1908
  };
1909
+ if (!writing) {
1910
+ const paths = new Set(blueprintToConfigArtifacts(blueprint).map((artifact) => resolveContainedPath(target, artifact.path)));
1911
+ const configurations = [];
1912
+ for (const [name, script] of Object.entries(scripts)) {
1913
+ if (!name.startsWith("test:") || !isString(script) || !script.includes("vitest")) continue;
1914
+ const invoked = scriptToInvocations(script);
1915
+ if (invoked === void 0) continue;
1916
+ for (const config of invoked.configs) {
1917
+ const path = resolveContainedPath(target, config);
1918
+ if (path !== void 0 && (paths.has(path) || isExactCaseFile(path))) continue;
1919
+ configurations.push(`${name} --config ${config}`);
1920
+ }
1921
+ }
1922
+ if (configurations.length > 0) return {
1923
+ field: "projects",
1924
+ message: `The manifest at ${target} names a Vitest configuration the plan does not emit and the target does not hold: ${configurations.join(", ")}. Add the configuration, or remove the script that names it and its invocation from the test chain.`,
1925
+ blocking: false,
1926
+ groups: ["configs"]
1927
+ };
1928
+ }
1900
1929
  const expected = blueprintToScripts(blueprint);
1901
1930
  const expectedLines = /* @__PURE__ */ new Map();
1902
1931
  for (const [name, script] of Object.entries(expected)) {
@@ -1911,21 +1940,25 @@ var CLI = class {
1911
1940
  }
1912
1941
  }
1913
1942
  const reachable = /* @__PURE__ */ new Set();
1914
- const visited = /* @__PURE__ */ new Set();
1915
- const pending = [...gates];
1916
- while (pending.length > 0) {
1917
- const name = pending.shift();
1918
- if (name === void 0 || visited.has(name)) continue;
1919
- visited.add(name);
1920
- const script = scripts[name];
1921
- if (!isString(script)) continue;
1922
- const invoked = scriptToInvocations(script);
1923
- if (invoked === void 0) {
1924
- unresolved = true;
1925
- continue;
1943
+ const chains = /* @__PURE__ */ new Map();
1944
+ for (const gate of gates) {
1945
+ const visited = /* @__PURE__ */ new Set();
1946
+ chains.set(gate, visited);
1947
+ const pending = [gate];
1948
+ while (pending.length > 0) {
1949
+ const name = pending.shift();
1950
+ if (name === void 0 || visited.has(name)) continue;
1951
+ visited.add(name);
1952
+ const script = scripts[name];
1953
+ if (!isString(script)) continue;
1954
+ const invoked = scriptToInvocations(script);
1955
+ if (invoked === void 0) {
1956
+ unresolved = true;
1957
+ continue;
1958
+ }
1959
+ for (const project of invoked.projects) reachable.add(project);
1960
+ for (const called of invoked.scripts) if (!visited.has(called)) pending.push(called);
1926
1961
  }
1927
- for (const project of invoked.projects) reachable.add(project);
1928
- for (const called of invoked.scripts) if (!visited.has(called)) pending.push(called);
1929
1962
  }
1930
1963
  if (unresolved) return {
1931
1964
  field: "projects",
@@ -1934,7 +1967,15 @@ var CLI = class {
1934
1967
  groups: ["configs"]
1935
1968
  };
1936
1969
  const ungated = [...expectedLines].filter(([project]) => !reachable.has(project)).sort(([left], [right]) => left.localeCompare(right)).filter(([project]) => isString(scripts[`test:${project}`]));
1937
- if (ungated.length === 0) return void 0;
1970
+ if (ungated.length === 0) {
1971
+ if (!writing && expected["test:journey"] !== void 0 && !chains.get("test")?.has("test:journey")) return {
1972
+ field: "projects",
1973
+ message: `The manifest at ${target} does not invoke npm run test:journey from its test chain. Add npm run test:journey after npm run test:app.`,
1974
+ blocking: false,
1975
+ groups: ["configs"]
1976
+ };
1977
+ return;
1978
+ }
1938
1979
  const names = ungated.map(([project]) => project);
1939
1980
  const disk = parseJSON(text);
1940
1981
  const written = isRecord(disk) && isRecord(disk.scripts) ? disk.scripts : {};