@orkestrel/scaffold 0.0.44 → 0.0.45

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 (66) hide show
  1. package/README.md +10 -10
  2. package/dist/bin/main.js +31 -31
  3. package/dist/bin/main.js.map +1 -1
  4. package/dist/host/AGENTS.md +7 -2
  5. package/dist/host/agents/orchestration.md +232 -56
  6. package/dist/host/agents/skills/enterprise-bootstrap/SKILL.md +7 -7
  7. package/dist/host/agents/skills/enterprise-bootstrap/references/bootstrap-reference.md +11 -9
  8. package/dist/host/agents/skills/enterprise-bootstrap/references/components.md +3 -3
  9. package/dist/host/agents/skills/enterprise-bootstrap/references/frontend-design.md +3 -3
  10. package/dist/host/agents/skills/enterprise-bootstrap/references/utilities.md +1 -1
  11. package/dist/host/agents/skills/orkestrel-align-packages/SKILL.md +1 -1
  12. package/dist/host/agents/skills/orkestrel-build-application/SKILL.md +2 -2
  13. package/dist/host/agents/skills/orkestrel-debrief/SKILL.md +1 -1
  14. package/dist/host/agents/skills/orkestrel-debrief/references/field-testing.md +2 -2
  15. package/dist/host/agents/skills/orkestrel-debrief/references/instruction-audit.md +8 -8
  16. package/dist/host/agents/skills/orkestrel-falsify/SKILL.md +16 -14
  17. package/dist/host/agents/skills/orkestrel-falsify/references/brief.md +3 -3
  18. package/dist/host/agents/skills/orkestrel-falsify/references/reconcile.md +14 -14
  19. package/dist/host/agents/skills/orkestrel-harden-package/SKILL.md +1 -1
  20. package/dist/host/agents/skills/orkestrel-human-journey/SKILL.md +3 -3
  21. package/dist/host/agents/skills/orkestrel-human-journey/references/captures.md +3 -3
  22. package/dist/host/agents/skills/orkestrel-human-journey/references/layer.md +3 -3
  23. package/dist/host/agents/skills/orkestrel-polish-surface/SKILL.md +3 -3
  24. package/dist/host/claude/agents/analyst.md +2 -2
  25. package/dist/host/claude/agents/checker.md +2 -2
  26. package/dist/host/claude/agents/codex.md +5 -5
  27. package/dist/host/claude/agents/orkestrel.md +9 -8
  28. package/dist/host/claude/agents/planner.md +1 -1
  29. package/dist/host/claude/agents/researcher.md +2 -2
  30. package/dist/host/claude/agents/reviewer.md +1 -1
  31. package/dist/host/claude/agents/scout.md +2 -2
  32. package/dist/host/claude/agents/sol.md +3 -3
  33. package/dist/host/claude/agents/verifier.md +8 -0
  34. package/dist/host/claude/rules/application.md +7 -7
  35. package/dist/host/claude/rules/architecture.md +6 -6
  36. package/dist/host/claude/rules/documentation.md +1 -0
  37. package/dist/host/claude/rules/patterns.md +3 -3
  38. package/dist/host/claude/rules/quality.md +3 -3
  39. package/dist/host/claude/rules/tests.md +9 -2
  40. package/dist/host/claude/rules/workspace.md +7 -7
  41. package/dist/host/claude/rules/writing.md +12 -2
  42. package/dist/host/codex/agents/planner.toml +1 -1
  43. package/dist/host/configs/helpers.ts +21 -1
  44. package/dist/host/cursor/rules/orchestration.mdc +1 -1
  45. package/dist/host/dotfiles/gitignore +4 -1
  46. package/dist/host/guides/scaffold.md +134 -119
  47. package/dist/host/scripts/codex.sh +0 -0
  48. package/dist/host/scripts/cursor.sh +0 -0
  49. package/dist/host/scripts/deps.sh +0 -0
  50. package/dist/host/scripts/ollama.sh +0 -0
  51. package/dist/host/tests/config.test.ts +40 -1
  52. package/dist/host/tests/policy.test.ts +2 -2
  53. package/dist/host/tests/setupPolicy.ts +8 -5
  54. package/dist/src/core/index.cjs +143 -149
  55. package/dist/src/core/index.cjs.map +1 -1
  56. package/dist/src/core/index.d.cts +1624 -1643
  57. package/dist/src/core/index.d.ts +1624 -1643
  58. package/dist/src/core/index.js +144 -149
  59. package/dist/src/core/index.js.map +1 -1
  60. package/dist/src/server/index.cjs +82 -97
  61. package/dist/src/server/index.cjs.map +1 -1
  62. package/dist/src/server/index.d.cts +1844 -1871
  63. package/dist/src/server/index.d.ts +1844 -1871
  64. package/dist/src/server/index.js +83 -96
  65. package/dist/src/server/index.js.map +1 -1
  66. package/package.json +3 -3
package/README.md CHANGED
@@ -13,7 +13,7 @@ a workspace from it, report how a workspace differs from it, and write the diffe
13
13
  npm install --save-dev @orkestrel/scaffold
14
14
  ```
15
15
 
16
- The executable needs Node 22.12 or newer. Run it without installing anything:
16
+ The executable needs Node 22.12 or later. Run it without installing anything:
17
17
 
18
18
  ```sh
19
19
  npx @orkestrel/scaffold --help
@@ -21,7 +21,7 @@ npx @orkestrel/scaffold --help
21
21
 
22
22
  ## Verbs
23
23
 
24
- Five verbs. Authority is the verb's: every verb except `audit` writes when it is typed, and no
24
+ Authority is the verb's: every verb except `audit` writes when it is typed, and no
25
25
  option grants a write. Exit codes are `0` clean, `1` drift or failure, and `2` usage error.
26
26
 
27
27
  `--target <path>` points any verb at another directory; the working directory is the default.
@@ -74,20 +74,20 @@ Reads the organization's published package list, rewrites the marker-bounded tab
74
74
  npx scaffold overwrite --dirty
75
75
  ```
76
76
 
77
- Everything `repair` and `catalog` do, plus the two steps only this verb carries: it deletes tracked
77
+ Everything `repair` and `catalog` do, plus the steps only this verb carries: it deletes tracked
78
78
  files the plan does not own, and it rewrites the `@orkestrel/*` ranges in the manifest to the
79
79
  registry's latest releases. It needs a git repository, and it refuses a tree carrying uncommitted
80
80
  changes unless `--dirty` waives that refusal.
81
81
 
82
82
  ## Library
83
83
 
84
- Two entry points, split by host. `@orkestrel/scaffold` is host-independent: it compiles, gates, and
84
+ The entry points split by host. `@orkestrel/scaffold` is host-independent: it compiles, gates, and
85
85
  compares.
86
86
 
87
87
  ```ts
88
- import { createBlueprint, createCompiler } from '@orkestrel/scaffold'
88
+ import { Compiler, createBlueprint } from '@orkestrel/scaffold'
89
89
 
90
- const compiler = createCompiler()
90
+ const compiler = new Compiler()
91
91
  const scaffolding = compiler.compile(createBlueprint('router', { src: ['core', 'server'] }))
92
92
 
93
93
  scaffolding.plan?.artifacts // every planned file, in group order
@@ -95,21 +95,21 @@ scaffolding.questions // the advice the compile could not settle
95
95
  compiler.destroy()
96
96
  ```
97
97
 
98
- A plan says the workspace can be built. It does not say the workspace should be created: a caller
98
+ A plan says the workspace can be built. It does not decide whether to create it: a caller
99
99
  creating a fresh workspace refuses on any question beside the plan, blocking or not, exactly as
100
100
  `new` does. [`guides/scaffold.md`](guides/scaffold.md) states that rule and what it covers.
101
101
 
102
102
  `@orkestrel/scaffold/server` is Node-only and holds everything that touches the filesystem or the
103
- network: `createMaterializer` writes a plan into a target, `createUpstream` reads the registry and
103
+ network: `Materializer` writes a plan into a target, `Upstream` reads the registry and
104
104
  the guide host, and `WriteTransaction` stages and swaps a set of files with rollback.
105
105
 
106
106
  ```ts
107
107
  import type { Plan } from '@orkestrel/scaffold'
108
- import { createMaterializer } from '@orkestrel/scaffold/server'
108
+ import { Materializer } from '@orkestrel/scaffold/server'
109
109
 
110
110
  declare const plan: Plan
111
111
 
112
- const materializer = createMaterializer()
112
+ const materializer = new Materializer()
113
113
  const result = materializer.materialize(plan, './packages/router')
114
114
 
115
115
  result.written // every path created
package/dist/bin/main.js CHANGED
@@ -2,9 +2,9 @@
2
2
  import { align, renderTable, strip, stripControls, width } from "@orkestrel/console";
3
3
  import { attempt, isRecord, isString, parseJSON } from "@orkestrel/contract";
4
4
  import { createMarkdown, flattenText, isTableNode } from "@orkestrel/markdown";
5
- import { runSync } from "@orkestrel/process/server";
6
- import { BIN_ENTRY_PATH, CATALOG_AGENT_PATH, CONFORMANCE_TEST_PATH, DEPENDENCY_NAME_PATTERN, DISTRIBUTION_TEST_PATH, ENVIRONMENTS, GLOBAL_SETUP_PATH, GROUPS, GUIDES_TEST_PATH, INTEGRATION_TEST_PATH, MAX_MANIFEST_BYTES, SERVICE_SETUP_PATH, SHOWCASE_CONFIG_PATH, ScaffoldError, blueprintToDevDependencies, blueprintToRootVite, blueprintToScripts, createBlueprint, createCompiler, isScaffoldError, manifestToDependencies, manifestToName, nameToGuide } from "../src/core/index.js";
7
- import { createMaterializer, createUpstream, isExactCaseFile, isPhysicalDirectory, isRepository, listFiles, readFileText, readSnapshot, resolveContainedPath } from "../src/server/index.js";
5
+ import { executeSync } from "@orkestrel/process/server";
6
+ import { BIN_ENTRY_PATH, CATALOG_AGENT_PATH, CONFORMANCE_TEST_PATH, Compiler, DEPENDENCY_NAME_PATTERN, DISTRIBUTION_TEST_PATH, ENVIRONMENTS, GLOBAL_SETUP_PATH, GROUPS, GUIDES_TEST_PATH, INTEGRATION_TEST_PATH, MAX_MANIFEST_BYTES, SERVICE_SETUP_PATH, SHOWCASE_CONFIG_PATH, ScaffoldError, blueprintToDevDependencies, blueprintToRootVite, blueprintToScripts, createBlueprint, isScaffoldError, manifestToDependencies, manifestToName, nameToGuide } from "../src/core/index.js";
7
+ import { Materializer, Upstream, isExactCaseFile, isPhysicalDirectory, isRepository, listFiles, readFileText, readSnapshot, resolveContainedPath } from "../src/server/index.js";
8
8
  import { parseArgs } from "node:util";
9
9
  //#region src/bin/constants.ts
10
10
  /**
@@ -17,12 +17,12 @@ import { parseArgs } from "node:util";
17
17
  */
18
18
  var EXECUTABLE_NAME = "scaffold";
19
19
  /**
20
- * The five {@link Verb} values in usage order, frozen.
20
+ * The {@link Verb} values in usage order, frozen.
21
21
  *
22
22
  * @remarks
23
23
  * The order the type declares them in, which is also the order usage lists them:
24
24
  * the verb that creates a workspace, then the one that only reads it, then the
25
- * three that write to one that already exists, widest last.
25
+ * ones that write to one that already exists, widest last.
26
26
  */
27
27
  var VERBS = Object.freeze([
28
28
  "new",
@@ -35,7 +35,7 @@ var VERBS = Object.freeze([
35
35
  * What each exit code means, frozen.
36
36
  *
37
37
  * @remarks
38
- * Keyed by the three code constants rather than by literals, so the usage block
38
+ * Keyed by the code constants rather than by literals, so the usage block
39
39
  * cannot document a code the executable does not return.
40
40
  */
41
41
  var EXIT_SUMMARY = Object.freeze({
@@ -62,7 +62,7 @@ var FAILED_MESSAGE = "The command failed for an unrecognized reason";
62
62
  *
63
63
  * @remarks
64
64
  * The workspace name is the only positional argument any verb takes, so it is
65
- * one value rather than a per-verb table with four holes in it.
65
+ * one value rather than a per-verb table with holes in it.
66
66
  */
67
67
  var NAME_ARGUMENT = "<name>";
68
68
  /**
@@ -107,7 +107,7 @@ var OPTION_SUMMARY = Object.freeze({
107
107
  "--bin": "scaffold a command-line executable at src/bin/main.ts",
108
108
  "--deps <list>": "the @orkestrel/* packages the workspace depends on",
109
109
  "--groups <list>": "the artifact groups to cover; every group when absent",
110
- "--all": "fetch a guide for every package the organization publishes, not just the declared ones",
110
+ "--all": "fetch a guide for every package the organization publishes, not the declared ones alone",
111
111
  "--dirty": "delete from a tree carrying uncommitted changes",
112
112
  "--from <path>": "read the data root from a local path instead of the bundled one; catalog alone accepts it more than once",
113
113
  "--target <path>": "the directory the verb operates on; the working directory when absent",
@@ -178,7 +178,7 @@ var VERB_SUMMARY = Object.freeze({
178
178
  * The error raised when a command line is not a command.
179
179
  *
180
180
  * @remarks
181
- * Distinct from `ScaffoldError` because the two answer different questions and
181
+ * Distinct from `ScaffoldError` because they answer different questions and
182
182
  * exit differently: a `ScaffoldError` says the package could not serve a
183
183
  * well-formed request and exits `1`, while this says there was no request to
184
184
  * serve and exits `2`. Folding a usage error into `INVALID` would report a
@@ -240,7 +240,7 @@ function isUsageError(value) {
240
240
  * @remarks
241
241
  * One token serves both readers: a person reads the value placeholder and the
242
242
  * parser reads the name in front of it. Deriving the name means a documented
243
- * option and an accepted option cannot be two different lists.
243
+ * option and an accepted option cannot be separate lists.
244
244
  *
245
245
  * @example
246
246
  * ```ts
@@ -283,9 +283,9 @@ function verbToSyntax(verb) {
283
283
  * @remarks
284
284
  * Returned as lines because the executable writes through a handler that takes
285
285
  * one line, so the caller never has to split a block back apart. The glossary is
286
- * printed once for every verb rather than repeated per verb, since seven of the
287
- * nine options are shared and a reader comparing two verbs wants the difference,
288
- * not the repetition.
286
+ * printed once for every verb rather than repeated per verb, because
287
+ * `--from <path>`, `--target <path>`, and `--json` are shared by every verb and
288
+ * a reader comparing two verbs wants the difference, not the repetition.
289
289
  */
290
290
  function renderUsage() {
291
291
  const summaries = Object.entries(OPTION_SUMMARY);
@@ -312,10 +312,10 @@ function renderUsage() {
312
312
  * @remarks
313
313
  * The one place untrusted argument text becomes a domain value, and it stays one
314
314
  * function because the command union admits no partial command to hand on: every
315
- * refusal has to happen before the value exists. It refuses in four ways, each
315
+ * refusal has to happen before the value exists. It refuses in these ways, each
316
316
  * naming what was wrong — a word that is not a verb, a word that is not an
317
317
  * option, an option this verb does not take, and an argument this verb does not
318
- * take. `node:util` decides the second and this decides the rest, so an unknown
318
+ * take. `node:util` decides the unknown option and this decides the rest, so an unknown
319
319
  * option is reported by the parser that found it rather than re-derived here.
320
320
  *
321
321
  * A request for usage is not a command and never reaches this: the caller
@@ -441,7 +441,7 @@ function auditToExit(audit) {
441
441
  *
442
442
  * @remarks
443
443
  * A blocking question means the gate produced no plan, so the target was not
444
- * compared and no finding count is reported. Otherwise the three grounds
444
+ * compared and no finding count is reported. Otherwise the grounds
445
445
  * describe what this run did. `bytes` means content-owned
446
446
  * bytes were observed, `existence` means presence or absence alone decided the
447
447
  * finding, and `nothing` means a birth-owned path was not examined. Foreign
@@ -524,8 +524,8 @@ function errorToEnvelope(error) {
524
524
  * upstream reader is built the same way but from the options, because no
525
525
  * command line names an endpoint: a terminal caller means the published
526
526
  * registry and the published guide host, and only the process driving the
527
- * executable can mean anything else. That is the seam that makes the three
528
- * verbs which read the network provable without one.
527
+ * executable can mean anything else. That is the seam that makes the verbs
528
+ * which read the network provable without one.
529
529
  *
530
530
  * @example
531
531
  * ```ts
@@ -543,7 +543,7 @@ var CLI = class CLI {
543
543
  #diagnostic;
544
544
  #upstream;
545
545
  /**
546
- * Construct the executable over the two destinations it writes to.
546
+ * Construct the executable over the destinations it writes to.
547
547
  *
548
548
  * @param options - The report and diagnostic handlers and the upstream
549
549
  * endpoints; the process streams and the published endpoints when absent.
@@ -605,7 +605,7 @@ var CLI = class CLI {
605
605
  dependencies: await this.#resolve(this.#packages(command.dependencies))
606
606
  });
607
607
  const plan = this.#compile(blueprint);
608
- const materializer = createMaterializer(command.from === void 0 ? void 0 : { host: command.from });
608
+ const materializer = new Materializer(command.from === void 0 ? void 0 : { host: command.from });
609
609
  try {
610
610
  const result = materializer.materialize(plan, target);
611
611
  if (command.json === true) this.#report(result);
@@ -622,7 +622,7 @@ var CLI = class CLI {
622
622
  const target = command.target ?? ".";
623
623
  const blueprint = this.#derive(target);
624
624
  const questions = this.#targetQuestions(target, blueprint);
625
- const materializer = createMaterializer(command.from === void 0 ? void 0 : { host: command.from });
625
+ const materializer = new Materializer(command.from === void 0 ? void 0 : { host: command.from });
626
626
  try {
627
627
  const [measured] = this.#survey(materializer, blueprint, target, this.#groups(command.groups));
628
628
  const audit = questions.length === 0 ? measured : {
@@ -641,7 +641,7 @@ var CLI = class CLI {
641
641
  const groups = this.#groups(command.groups);
642
642
  const blueprint = this.#derive(target);
643
643
  this.#assertTarget(target, blueprint);
644
- const materializer = createMaterializer(command.from === void 0 ? void 0 : { host: command.from });
644
+ const materializer = new Materializer(command.from === void 0 ? void 0 : { host: command.from });
645
645
  try {
646
646
  const [audit, plan] = this.#survey(materializer, blueprint, target, groups);
647
647
  if (plan === void 0) {
@@ -672,7 +672,7 @@ var CLI = class CLI {
672
672
  if (extra.length > 0) this.#warn(`Read the data root from ${String(host)}. The other ${String(extra.length)} local root${extra.length === 1 ? "" : "s"} named by --from reach nothing this run does.`);
673
673
  const previous = this.#previous(target);
674
674
  const fetched = await this.#fetch(target, command.all === true);
675
- const materializer = createMaterializer(host === void 0 ? void 0 : { host });
675
+ const materializer = new Materializer(host === void 0 ? void 0 : { host });
676
676
  let result;
677
677
  try {
678
678
  result = this.#publish(materializer, target, fetched.entries, fetched.mirrors);
@@ -699,7 +699,7 @@ var CLI = class CLI {
699
699
  target,
700
700
  dirty: repository.dirty.length
701
701
  });
702
- const materializer = createMaterializer(command.from === void 0 ? void 0 : { host: command.from });
702
+ const materializer = new Materializer(command.from === void 0 ? void 0 : { host: command.from });
703
703
  try {
704
704
  const [audit, plan] = this.#survey(materializer, blueprint, target, groups);
705
705
  if (plan === void 0) {
@@ -708,7 +708,7 @@ var CLI = class CLI {
708
708
  return 1;
709
709
  }
710
710
  const repaired = materializer.repair(plan, audit, target);
711
- const removed = materializer.remove(audit, command.dirty === true ? {
711
+ const removed = materializer.remove(plan, audit, command.dirty === true ? {
712
712
  tracked: repository.tracked,
713
713
  dirty: []
714
714
  } : repository, target);
@@ -760,7 +760,7 @@ var CLI = class CLI {
760
760
  }
761
761
  }
762
762
  async #lookup(declared) {
763
- const upstream = createUpstream(this.#upstream);
763
+ const upstream = new Upstream(this.#upstream);
764
764
  try {
765
765
  return await upstream.lookup(declared);
766
766
  } finally {
@@ -771,7 +771,7 @@ var CLI = class CLI {
771
771
  const manifest = this.#manifest(target);
772
772
  const own = manifestToName(manifest);
773
773
  const declared = manifestToDependencies(manifest).map((dependency) => dependency.name);
774
- const upstream = createUpstream(this.#upstream);
774
+ const upstream = new Upstream(this.#upstream);
775
775
  try {
776
776
  const entries = await upstream.catalog();
777
777
  const names = (all ? entries.map((entry) => entry.name) : declared).filter((name) => name !== own);
@@ -795,7 +795,7 @@ var CLI = class CLI {
795
795
  return pinned;
796
796
  }
797
797
  #compile(blueprint, groups) {
798
- const compiler = createCompiler();
798
+ const compiler = new Compiler();
799
799
  try {
800
800
  const scaffolding = compiler.compile(blueprint, groups);
801
801
  if (scaffolding.plan !== void 0 && scaffolding.questions.length === 0) return scaffolding.plan;
@@ -805,7 +805,7 @@ var CLI = class CLI {
805
805
  }
806
806
  }
807
807
  #survey(materializer, blueprint, target, groups) {
808
- const compiler = createCompiler();
808
+ const compiler = new Compiler();
809
809
  try {
810
810
  const scaffolding = compiler.compile(blueprint, groups);
811
811
  if (scaffolding.plan === void 0) return [compiler.audit(blueprint, {}, groups), void 0];
@@ -1133,7 +1133,7 @@ var CLI = class CLI {
1133
1133
  return state;
1134
1134
  }
1135
1135
  #inventory(target, args) {
1136
- const result = runSync({
1136
+ const result = executeSync({
1137
1137
  file: "git",
1138
1138
  arguments: [...args]
1139
1139
  }, {
@@ -1167,7 +1167,7 @@ var CLI = class CLI {
1167
1167
  }
1168
1168
  async #resolve(names) {
1169
1169
  if (names.length === 0) return [];
1170
- const upstream = createUpstream(this.#upstream);
1170
+ const upstream = new Upstream(this.#upstream);
1171
1171
  let releases;
1172
1172
  try {
1173
1173
  releases = await upstream.lookup(names.map((name) => ({