@orkestrel/scaffold 0.0.20 → 0.0.22

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 (69) hide show
  1. package/dist/bin/scaffold.js +385 -148
  2. package/dist/bin/scaffold.js.map +1 -1
  3. package/dist/host/AGENTS.md +61 -42
  4. package/dist/host/CLAUDE.md +39 -387
  5. package/dist/host/agents/orchestration.md +454 -0
  6. package/dist/host/agents/skills/enterprise-bootstrap/SKILL.md +25 -7
  7. package/dist/host/agents/skills/orkestrel-align-packages/SKILL.md +2 -2
  8. package/dist/host/agents/skills/orkestrel-build-application/SKILL.md +42 -31
  9. package/dist/host/agents/skills/orkestrel-build-application/references/application.md +129 -0
  10. package/dist/host/agents/skills/orkestrel-debrief/SKILL.md +3 -3
  11. package/dist/host/agents/skills/orkestrel-debrief/references/field-testing.md +4 -4
  12. package/dist/host/agents/skills/orkestrel-debrief/references/instruction-audit.md +12 -0
  13. package/dist/host/agents/skills/orkestrel-falsify/SKILL.md +167 -0
  14. package/dist/host/agents/skills/orkestrel-falsify/references/brief.md +98 -0
  15. package/dist/host/agents/skills/orkestrel-falsify/references/reconcile.md +148 -0
  16. package/dist/host/agents/skills/orkestrel-harden-package/SKILL.md +4 -2
  17. package/dist/host/agents/skills/orkestrel-harden-package/references/centralization.md +5 -5
  18. package/dist/host/agents/skills/orkestrel-harden-package/references/research.md +2 -0
  19. package/dist/host/agents/skills/orkestrel-polish-surface/SKILL.md +11 -6
  20. package/dist/host/claude/agents/analyst.md +59 -0
  21. package/dist/host/claude/agents/application.md +1 -1
  22. package/dist/host/claude/agents/builder.md +1 -1
  23. package/dist/host/claude/agents/checker.md +5 -1
  24. package/dist/host/claude/agents/codex.md +120 -87
  25. package/dist/host/claude/agents/grok.md +44 -32
  26. package/dist/host/claude/agents/implementer.md +1 -1
  27. package/dist/host/claude/agents/orkestrel.md +3 -3
  28. package/dist/host/claude/agents/planner.md +9 -3
  29. package/dist/host/claude/agents/researcher.md +6 -5
  30. package/dist/host/claude/agents/reviewer.md +17 -6
  31. package/dist/host/claude/agents/scout.md +7 -4
  32. package/dist/host/claude/agents/verifier.md +1 -1
  33. package/dist/host/claude/rules/application.md +17 -16
  34. package/dist/host/claude/rules/architecture.md +41 -22
  35. package/dist/host/claude/rules/documentation.md +2 -1
  36. package/dist/host/claude/rules/names.md +7 -6
  37. package/dist/host/claude/rules/quality.md +71 -14
  38. package/dist/host/claude/rules/styles.md +1 -1
  39. package/dist/host/claude/rules/tests.md +18 -2
  40. package/dist/host/claude/rules/typescript.md +1 -1
  41. package/dist/host/claude/rules/workspace.md +6 -3
  42. package/dist/host/claude/settings.json +2 -0
  43. package/dist/host/claude/skills/orkestrel-falsify/SKILL.md +10 -0
  44. package/dist/host/codex/agents/analyst.toml +15 -2
  45. package/dist/host/codex/agents/checker.toml +1 -1
  46. package/dist/host/codex/agents/grok.toml +2 -1
  47. package/dist/host/codex/agents/opus.toml +1 -1
  48. package/dist/host/codex/agents/planner.toml +1 -1
  49. package/dist/host/codex/agents/researcher.toml +2 -2
  50. package/dist/host/codex/agents/reviewer.toml +4 -2
  51. package/dist/host/codex/agents/scout.toml +2 -2
  52. package/dist/host/codex/config.toml +23 -64
  53. package/dist/host/cursor/rules/orchestration.mdc +33 -0
  54. package/dist/host/guides/src/scaffold.md +419 -150
  55. package/dist/host/manifest.json +47 -1
  56. package/dist/host/tests/setupPolicy.ts +130 -12
  57. package/dist/src/core/index.cjs +2059 -913
  58. package/dist/src/core/index.cjs.map +1 -1
  59. package/dist/src/core/index.d.cts +202 -47
  60. package/dist/src/core/index.d.ts +202 -47
  61. package/dist/src/core/index.js +2050 -914
  62. package/dist/src/core/index.js.map +1 -1
  63. package/dist/src/server/index.cjs +83 -33
  64. package/dist/src/server/index.cjs.map +1 -1
  65. package/dist/src/server/index.d.cts +32 -16
  66. package/dist/src/server/index.d.ts +32 -16
  67. package/dist/src/server/index.js +84 -35
  68. package/dist/src/server/index.js.map +1 -1
  69. package/package.json +7 -5
@@ -41,12 +41,18 @@ export declare function alignTable(header: readonly string[], rows: readonly (re
41
41
  /** Additional development dependencies required by a private Vue browser application. */
42
42
  export declare const APP_BROWSER_DEV_DEPENDENCIES: Readonly<Record<string, string>>;
43
43
 
44
+ /** Baseline development dependency required by every private application environment. */
45
+ export declare const APP_DEV_DEPENDENCIES: Readonly<Record<string, string>>;
46
+
44
47
  /**
45
48
  * The per-environment application matrix: thin config artifacts, Vitest project
46
49
  * label, and executable entry where the environment produces a runtime bundle.
47
50
  */
48
51
  export declare const APP_MATRIX: Readonly<Record<Environment, AppDefinition>>;
49
52
 
53
+ /** Additional development dependencies required by a private server application. */
54
+ export declare const APP_SERVER_DEV_DEPENDENCIES: Readonly<Record<string, string>>;
55
+
50
56
  /** The deterministic config, test-project, and runtime-entry settings for one application environment. */
51
57
  export declare interface AppDefinition {
52
58
  readonly configs: readonly string[];
@@ -58,9 +64,16 @@ export declare interface AppDefinition {
58
64
  * Draft the application source artifacts for every selected app environment.
59
65
  *
60
66
  * @param spec - The blueprint carrying the application environment set.
67
+ * @remarks
68
+ * Two conditional shapes layer over the per-environment set. The health contract —
69
+ * record, route constants, guard, and the one unknown-to-typed read — is declared by
70
+ * `app/server` while the server alone reads it and RELOCATES to `app/core` the moment
71
+ * the browser reads it too, because a contract two hosts share belongs to neither of
72
+ * them. The showcase entry pair, its seeder, and its factory appear only for a
73
+ * blueprint that declares the physical showcase wrapper alongside `app/browser`.
61
74
  * @returns Complete, runnable app/core, app/browser, and app/server artifacts.
62
75
  */
63
- export declare function applicationArtifacts(spec: Blueprint): readonly Artifact[];
76
+ export declare function applicationArtifacts(spec: Pick<Blueprint, 'name' | 'app' | 'showcase'>): readonly Artifact[];
64
77
 
65
78
  /**
66
79
  * Build the root Vite/Vitest configuration for a workspace that includes
@@ -164,8 +177,8 @@ export declare function artifactShape(): UnionShape<readonly [ ObjectShape<{
164
177
  *
165
178
  * @remarks
166
179
  * A `Compiler.audit` over a gate-failing blueprint sets `complete: false` with
167
- * the gate's `questions` and zero findings, while `diffPlan` over an existing
168
- * plan is always `complete: true`.
180
+ * the gate's `questions` and zero findings. `diffPlan` over an existing plan
181
+ * is always complete; a host artifact without `hex` is presence-owned.
169
182
  */
170
183
  export declare interface Audit {
171
184
  readonly findings: readonly Finding[];
@@ -255,8 +268,8 @@ export declare interface Blueprint {
255
268
  readonly bin: boolean;
256
269
  /** Structural: `true` only for a repo that ships `tests/integration` — a slow, opt-in proof project over the repo's own built output, outside the default run, never by name. */
257
270
  readonly integration: boolean;
258
- /** Structural: `true` only for a repo that ships `tests/service` a slow, opt-in proof project against a foreign running process, outside the default run, never by name. Derivation requires `tests/setupService.ts` and `scripts/service.sh` beside it and fails `TARGET` otherwise. */
259
- readonly service: boolean;
271
+ /** Structural vendor names derived from non-empty `tests/service/<name>` directories, sorted in code-unit order. Each vendor owns `tests/service/<name>/setup.ts`; the workspace owns `scripts/service.sh`. */
272
+ readonly services: readonly string[];
260
273
  /** Structural: `true` only for a repo that carries the physical, exact-case `tests/setupGlobal.ts` module — integration and `srcBrowser` projects consume that shared global setup only under their own additional structural conditions. */
261
274
  readonly global: boolean;
262
275
  /** Structural: `true` only for a repo that carries the physical, exact-case `configs/app/vite.showcase.config.ts` regular file; valid only with `app/browser`. */
@@ -271,8 +284,8 @@ export declare interface Blueprint {
271
284
  * @remarks
272
285
  * `version` / `engines` default `DEFAULT_VERSION` / `DEFAULT_ENGINES`,
273
286
  * `src` defaults `['core']`, and `app` / `keywords` / `dependencies` /
274
- * `peers` / `extras` / `overrides` default `[]`, and `bin` / `integration` /
275
- * `service` / `global` / `showcase` default `false`. `description` is OMITTED entirely
287
+ * `peers` / `extras` / `overrides` / `services` default `[]`, and `bin` /
288
+ * `integration` / `global` / `showcase` default `false`. `description` is OMITTED entirely
276
289
  * when absent, so the result round-trips the exact-record `Blueprint` guard.
277
290
  * @returns A complete `Blueprint`.
278
291
  *
@@ -329,7 +342,7 @@ export declare function blueprintShape(): ObjectShape<{
329
342
  }, false>>;
330
343
  bin: BooleanShape;
331
344
  integration: BooleanShape;
332
- service: BooleanShape;
345
+ services: ArrayShape<StringShape>;
333
346
  global: BooleanShape;
334
347
  showcase: BooleanShape;
335
348
  }, false>;
@@ -341,7 +354,11 @@ export declare function blueprintShape(): ObjectShape<{
341
354
  * @remarks
342
355
  * Published source environments receive the canonical entity/type/factory/constant
343
356
  * inventory. Application environments receive their exact public declaration kinds,
344
- * including parsers, guards, handlers, errors, and runners where present.
357
+ * including parsers, guards, handlers, errors, and runners where present. Two groups
358
+ * move rather than duplicate: the health contract is declared against `app/server`
359
+ * while the server alone reads it and against `app/core` once the browser reads it
360
+ * too, and the showcase seed, factory, and root-view identity appear only for a
361
+ * blueprint whose showcase accompanies `app/browser`.
345
362
  * @returns The declared `Member[]`, one set per environment.
346
363
  *
347
364
  * @example
@@ -381,6 +398,17 @@ export declare type BuildFormat = 'es' | 'cjs';
381
398
  */
382
399
  export declare function bytesToHex(bytes: Uint8Array): string;
383
400
 
401
+ /**
402
+ * The catalog agent file whose bounded marker region the catalog operation alone owns.
403
+ *
404
+ * @remarks
405
+ * Vendored like every other host artifact, but presence-owned after hydration:
406
+ * `diffPlan` compares this one path by presence, so a consumer restores it while
407
+ * absent and never replaces its bytes — not from an audit, not from a repair, and
408
+ * not under `replace`.
409
+ */
410
+ export declare const CATALOG_AGENT_PATH = ".claude/agents/orkestrel.md";
411
+
384
412
  /**
385
413
  * One fleet package's catalog row — the `orkestrel` agent's package-catalog
386
414
  * section, derived rather than hand-maintained.
@@ -422,7 +450,7 @@ export declare function catalogNames(text: string): readonly string[];
422
450
 
423
451
  /**
424
452
  * Project a fleet package catalog into a markdown table — the block
425
- * `.claude/agents/orkestrel.md`'s catalog markers wrap.
453
+ * `CATALOG_AGENT_PATH`'s catalog markers wrap.
426
454
  *
427
455
  * @param entries - The catalog rows to render.
428
456
  * @remarks
@@ -647,6 +675,18 @@ export declare function computeHash(text: string): string;
647
675
  */
648
676
  export declare function configArtifacts(spec: Blueprint): readonly Artifact[];
649
677
 
678
+ /**
679
+ * Build the standalone Node-only root-configuration Vitest project.
680
+ *
681
+ * @returns The emitted `config` project definition.
682
+ *
683
+ * @example
684
+ * ```ts
685
+ * configViteProject().includes("label: 'config'") // true
686
+ * ```
687
+ */
688
+ export declare function configViteProject(): string;
689
+
650
690
  /** Constant-declaration token kept out of template literals consumed by parity scans. */
651
691
  export declare const CONST_KEYWORD = "const";
652
692
 
@@ -876,13 +916,14 @@ export declare function coreViteConfig(): string;
876
916
  * @param plan - The plan whose artifacts are the source of truth.
877
917
  * @param current - The target's current content, keyed by artifact-relative path.
878
918
  * @remarks
879
- * Audit semantics are per-origin. A `host`-origin artifact is audited by
880
- * PRESENCE only `missing` or `aligned`, never `stale` UNLESS it has been
881
- * hydrated with its real host bytes (`hydratePlan`'s `content`), in which case
882
- * it is content-compared exactly like a `computed` artifact and CAN be
883
- * `stale`. `hydratePlan` expands directory-shaped host artifacts into
884
- * content-bearing file artifacts; only an unresolved degrade-path host
885
- * artifact stays presence-only. A `computed` artifact is content-aware canon —
919
+ * Audit semantics are per-origin. A `host`-origin artifact with canonical
920
+ * `hex` is content-compared exactly like a `computed` artifact and CAN be
921
+ * `stale`. A host artifact without canonical bytes is presence-owned:
922
+ * present is `aligned`, absent is `missing`. `CATALOG_AGENT_PATH` remains
923
+ * presence-owned after hydration because the catalog operation alone owns its
924
+ * bounded marker region. `hydratePlan` expands directory-shaped host artifacts
925
+ * into byte-aware file artifacts; only an intentional dependency-guide pointer
926
+ * may remain without `hex`. A `computed` artifact is content-aware canon —
886
927
  * `missing` / `aligned` / `stale` — and gates the audit like any drifted
887
928
  * finding. A `template`-origin artifact is BIRTH-ONLY and AUDIT-EXEMPT: it is
888
929
  * always reported `aligned`, regardless of whether the target has it at all
@@ -1202,6 +1243,32 @@ export declare function coreViteConfig(): string;
1202
1243
  */
1203
1244
  export declare function guideUsage(spec: Blueprint, pascal: string): string;
1204
1245
 
1246
+ /**
1247
+ * Determine whether an application blueprint spans the shared browser/server boundary.
1248
+ *
1249
+ * @param spec - The blueprint to inspect.
1250
+ * @returns True only when app/core, app/browser, and app/server are all selected.
1251
+ *
1252
+ * @example
1253
+ * ```ts
1254
+ * hasApplicationBoundary(blueprint('application', { app: ['core', 'browser', 'server'] }))
1255
+ * ```
1256
+ */
1257
+ export declare function hasApplicationBoundary(spec: Pick<Blueprint, 'app'>): boolean;
1258
+
1259
+ /**
1260
+ * Determine whether an application blueprint emits its browser showcase.
1261
+ *
1262
+ * @param spec - The blueprint to inspect.
1263
+ * @returns True only when showcase intent accompanies app/browser.
1264
+ *
1265
+ * @example
1266
+ * ```ts
1267
+ * hasApplicationShowcase(blueprint('application', { app: ['browser'], showcase: true }))
1268
+ * ```
1269
+ */
1270
+ export declare function hasApplicationShowcase(spec: Pick<Blueprint, 'app' | 'showcase'>): boolean;
1271
+
1205
1272
  /**
1206
1273
  * Whether a structurally valid blueprint selects at least one source or app environment.
1207
1274
  *
@@ -1262,15 +1329,23 @@ export declare function coreViteConfig(): string;
1262
1329
  * The byte-copied host artifact paths, frozen.
1263
1330
  *
1264
1331
  * @remarks
1265
- * The root docs (`AGENTS.md` / `CLAUDE.md`), `LICENSE`, `.agents`, `.claude`, `.codex`,
1266
- * the four SessionStart hook scripts (`scripts/deps.sh` / `scripts/cursor.sh` /
1267
- * `scripts/codex.sh` / `scripts/ollama.sh`), the repository coding-law policy module,
1268
- * the line's seven byte-identical root dotfiles, and the two guides-grouped
1269
- * mirror candidates: the line-wide dev-tooling guide
1270
- * (`guides/src/guide.md`) and the scaffold bin's own self-guide
1271
- * (`guides/src/scaffold.md`). `stageHost` vendors both; each plan carries the
1272
- * subset selected by `selectHostPaths`, omitting the target blueprint's own
1273
- * guide.
1332
+ * The root docs (`AGENTS.md` / `CLAUDE.md`), `LICENSE`, the canonical
1333
+ * orchestration contract (`.agents/orchestration.md`) every harness bridge
1334
+ * points at, `.agents`, `.claude`, `.codex`, `.cursor`, the four SessionStart
1335
+ * hook scripts (`scripts/deps.sh` / `scripts/cursor.sh` / `scripts/codex.sh` /
1336
+ * `scripts/ollama.sh`), the repository coding-law policy module, the line's
1337
+ * seven byte-identical root dotfiles, and the two guides-grouped mirror
1338
+ * candidates: the line-wide dev-tooling guide (`guides/src/guide.md`) and the
1339
+ * scaffold bin's own self-guide (`guides/src/scaffold.md`). `stageHost` vendors
1340
+ * both; each plan carries the subset selected by `selectHostPaths`, omitting the
1341
+ * target blueprint's own guide.
1342
+ *
1343
+ * Three harness bridges point at `.agents/orchestration.md` and carry only their
1344
+ * own harness's specifics: `CLAUDE.md`, `.codex/config.toml`, and
1345
+ * `.cursor/rules`. They are meaningless without the contract they reference, but
1346
+ * they do not share a `Group` — `hostGroup` keeps `CLAUDE.md` in `docs` with the
1347
+ * other root documents, so a plan selecting `orchestration` carries two of the
1348
+ * three and a plan selecting `docs` carries the third.
1274
1349
  */
1275
1350
  export declare const HOST_PATHS: readonly string[];
1276
1351
 
@@ -1292,10 +1367,26 @@ export declare function coreViteConfig(): string;
1292
1367
  * @example
1293
1368
  * ```ts
1294
1369
  * hostGroup('AGENTS.md') // 'docs'
1295
- * hostGroup('.agents') // 'orchestration'
1296
- * hostGroup('.claude') // 'orchestration'
1297
- * hostGroup('.codex') // 'orchestration'
1370
+ * hostGroup('.agents/orchestration.md') // 'orchestration'
1371
+ * hostGroup('.claude/rules') // 'orchestration'
1372
+ * hostGroup('.cursor/rules') // 'orchestration'
1373
+ * hostGroup('.mcp.json') // 'orchestration'
1374
+ * hostGroup('.oxlintrc.json') // 'configs'
1298
1375
  * ```
1376
+ *
1377
+ * @remarks
1378
+ * Takes a `HOST_PATHS` entry, so every example above is one. A bare directory
1379
+ * name is not: `ORCHESTRATION_PATH_PREFIXES` entries carry a trailing slash, so
1380
+ * `hostGroup('.cursor')` is `configs`, and no vendored entry has that form.
1381
+ *
1382
+ * Below the `docs` branch the split is by what a path governs rather than where
1383
+ * it sits, which is why both MCP registrations — `.mcp.json` and
1384
+ * `.cursor/mcp.json` — group with the harness bridges instead of with the root
1385
+ * dotfiles beside them. The `docs` branch is checked first and is deliberately
1386
+ * positional: `AGENTS.md`, `CLAUDE.md`, and `LICENSE` are the root documents, and
1387
+ * `CLAUDE.md` stays there as a root document even though it is also a harness
1388
+ * bridge. A plan selecting `orchestration` therefore carries two of the three
1389
+ * bridges; a plan selecting `docs` carries the third.
1299
1390
  */
1300
1391
  export declare function hostGroup(path: string): Group;
1301
1392
 
@@ -1307,10 +1398,12 @@ export declare function coreViteConfig(): string;
1307
1398
  *
1308
1399
  * @param path - The target-relative path to classify.
1309
1400
  * @remarks
1310
- * Ordered prefix match — `src/`, `tests/`, `guides/`, `docs/`, `configs/`,
1311
- * then `.agents/`, `.claude/`, `.codex/`, `.github/`, and `scripts/` as
1312
- * `'orchestration'`, then the two manifest files by exact name. Anything else
1313
- * (a root-level, prefix-less file) falls through to `'configs'`.
1401
+ * Ordered prefix match — `src/`, `tests/`, `guides/`, `docs/`, `configs/`, then
1402
+ * `matchesOrchestrationPath`, which owns the orchestration membership rule for
1403
+ * this function and for `hostGroup` alike, then the two manifest files by exact
1404
+ * name. Anything left falls through to `'configs'`. Read the rule at
1405
+ * `matchesOrchestrationPath` rather than here; one rule with two descriptions
1406
+ * drifts exactly as fast as one rule with two implementations.
1314
1407
  * @returns The inferred `Group` for `path`.
1315
1408
  *
1316
1409
  * @example
@@ -1510,6 +1603,23 @@ export declare function coreViteConfig(): string;
1510
1603
  */
1511
1604
  export declare function manifestToName(manifest: string): string | undefined;
1512
1605
 
1606
+ /**
1607
+ * Test whether a path instructs or wires an agent rather than the toolchain.
1608
+ *
1609
+ * @param path - The portable path to classify.
1610
+ * @returns `true` when the path is agent orchestration.
1611
+ *
1612
+ * @example
1613
+ * ```ts
1614
+ * import { matchesOrchestrationPath } from '@orkestrel/scaffold'
1615
+ *
1616
+ * matchesOrchestrationPath('.cursor/rules/orchestration.mdc') // true
1617
+ * matchesOrchestrationPath('.mcp.json') // true
1618
+ * matchesOrchestrationPath('.oxlintrc.json') // false
1619
+ * ```
1620
+ */
1621
+ export declare function matchesOrchestrationPath(path: string): boolean;
1622
+
1513
1623
  /** Maximum byte size accepted for one scaffold artifact. */
1514
1624
  export declare const MAX_ARTIFACT_BYTES = 5242880;
1515
1625
 
@@ -1595,6 +1705,27 @@ export declare function coreViteConfig(): string;
1595
1705
  /** The package-name RegExp — lowercase alphanumeric-with-hyphens, letter-first. */
1596
1706
  export declare const NAME_PATTERN: RegExp;
1597
1707
 
1708
+ /**
1709
+ * The exact root filenames that wire an agent bench rather than the toolchain, frozen.
1710
+ *
1711
+ * @remarks
1712
+ * `.mcp.json` registers MCP servers for the harness. It sits among the root
1713
+ * dotfiles but governs agents, so it groups with the harness bridges.
1714
+ */
1715
+ export declare const ORCHESTRATION_PATH_NAMES: readonly string[];
1716
+
1717
+ /**
1718
+ * The path prefixes whose contents instruct or wire an agent, frozen.
1719
+ *
1720
+ * @remarks
1721
+ * Group classification splits by what a path governs, not by where it sits:
1722
+ * anything under these prefixes is `orchestration`, and everything else that is
1723
+ * not source, tests, guides, docs, or a manifest is `configs`. Both classifiers
1724
+ * — `inferGroup` for a foreign target path and `hostGroup` for a `HOST_PATHS`
1725
+ * entry — read this one list, so a new harness directory is admitted once.
1726
+ */
1727
+ export declare const ORCHESTRATION_PATH_PREFIXES: readonly string[];
1728
+
1598
1729
  /**
1599
1730
  * How an `Artifact`'s content is produced: `host` byte-copied from the vendored
1600
1731
  * data root, `template` filled from a frozen `TemplateDefinition` by
@@ -2048,7 +2179,7 @@ export declare function coreViteConfig(): string;
2048
2179
  }, false>>;
2049
2180
  bin: BooleanShape;
2050
2181
  integration: BooleanShape;
2051
- service: BooleanShape;
2182
+ services: ArrayShape<StringShape>;
2052
2183
  global: BooleanShape;
2053
2184
  showcase: BooleanShape;
2054
2185
  }, false>;
@@ -2196,6 +2327,28 @@ export declare function coreViteConfig(): string;
2196
2327
  */
2197
2328
  export declare function renderObject(entry: Readonly<Record<string, unknown>>, indent: string): string;
2198
2329
 
2330
+ /**
2331
+ * Render a single-quoted TypeScript string array literal through `oxfmt`'s
2332
+ * inline-or-broken rule — inline when the rendered width fits
2333
+ * `JSON_PRINT_WIDTH`, one item per line with a trailing comma on every line
2334
+ * (including the last) otherwise, matching `.oxfmtrc.json`'s
2335
+ * `trailingComma: "all"` for non-JSON files.
2336
+ *
2337
+ * @param entries - The array's string elements, in order.
2338
+ * @param indent - The current indentation prefix.
2339
+ * @param prefix - The text already emitted on this line before the array.
2340
+ * @param suffix - The text that will follow the array on this line.
2341
+ * @returns The rendered array fragment (no trailing newline).
2342
+ *
2343
+ * @example
2344
+ * ```ts
2345
+ * import { renderStringArray } from '@orkestrel/scaffold'
2346
+ *
2347
+ * renderStringArray(['app', 'guides', 'tests'], '', '', '') // "['app', 'guides', 'tests']"
2348
+ * ```
2349
+ */
2350
+ export declare function renderStringArray(entries: readonly string[], indent: string, prefix: string, suffix: string): string;
2351
+
2199
2352
  /**
2200
2353
  * Render one JSON value through `formatJson`'s dispatch — arrays via
2201
2354
  * `renderArray`, objects via `renderObject`, everything else via
@@ -2267,7 +2420,7 @@ export declare function coreViteConfig(): string;
2267
2420
  *
2268
2421
  * @param src - The declared `Environment[]`.
2269
2422
  * @param facts - Optional structural facts. `bin` appends the standalone executable
2270
- * build-and-test project; `integration` and `service` append their standalone
2423
+ * build-and-test project; `integration` and `services` append their standalone
2271
2424
  * proof projects; `global` wires the shared global-setup module.
2272
2425
  * @returns The root `vite.config.ts` file content, newline-terminated.
2273
2426
  *
@@ -2279,7 +2432,7 @@ export declare function coreViteConfig(): string;
2279
2432
  export declare function rootViteConfig(src: readonly Environment[], facts?: ViteFacts): string;
2280
2433
 
2281
2434
  /** The devDependency range generated packages pin `@orkestrel/scaffold` at. */
2282
- export declare const SCAFFOLD_RANGE = "^0.0.20";
2435
+ export declare const SCAFFOLD_RANGE = "^0.0.22";
2283
2436
 
2284
2437
  /**
2285
2438
  * Carries a `ScaffoldErrorCode` + optional `context` (AGENTS §12).
@@ -2351,20 +2504,21 @@ export declare function coreViteConfig(): string;
2351
2504
  */
2352
2505
  export declare function serializeTypeScriptString(value: string): string;
2353
2506
 
2354
- /** The consumer-owned live-service provisioner expected only by service workspaces. */
2507
+ /** The birth-only provisioner skeleton retained by workspaces with declared service vendors. */
2355
2508
  export declare const SERVICE_SCRIPT_PATH = "scripts/service.sh";
2356
2509
 
2357
2510
  /**
2358
- * Build the standalone Node-only live-service proof project.
2511
+ * Build one standalone Node-only live-service vendor proof project.
2359
2512
  *
2360
- * @returns The emitted `service` project definition.
2513
+ * @param name - The bounded vendor directory name.
2514
+ * @returns The emitted `service:<name>` project definition.
2361
2515
  *
2362
2516
  * @example
2363
2517
  * ```ts
2364
- * serviceViteProject().includes("label: 'service'") // true
2518
+ * serviceViteProject('claude').includes("label: 'service:claude'") // true
2365
2519
  * ```
2366
2520
  */
2367
- export declare function serviceViteProject(): string;
2521
+ export declare function serviceViteProject(name: string): string;
2368
2522
 
2369
2523
  /** Immutable official actions/setup-node v6.4.0 commit used by generated CI. */
2370
2524
  export declare const SETUP_NODE_ACTION_SHA = "48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e";
@@ -2431,7 +2585,7 @@ export declare function coreViteConfig(): string;
2431
2585
  * factory per environment (AGENTS §5's per-environment centralized-file pattern), so
2432
2586
  * every environment gets the same uniform stub shape.
2433
2587
  *
2434
- * @param spec - The `Blueprint` to derive source stubs from.
2588
+ * @param spec - The blueprint carrying the declared source environment set.
2435
2589
  * @param pascal - The package's PascalCase entity name.
2436
2590
  * @returns The `source` group's `Artifact[]`.
2437
2591
  *
@@ -2440,7 +2594,7 @@ export declare function coreViteConfig(): string;
2440
2594
  * sourceArtifacts(blueprint('router'), 'Router').length // 4
2441
2595
  * ```
2442
2596
  */
2443
- export declare function sourceArtifacts(spec: Blueprint, pascal: string): readonly Artifact[];
2597
+ export declare function sourceArtifacts(spec: Pick<Blueprint, 'src'>, pascal: string): readonly Artifact[];
2444
2598
 
2445
2599
  /**
2446
2600
  * Split one rendered GFM table row into its trimmed cell strings.
@@ -2755,7 +2909,8 @@ export declare function coreViteConfig(): string;
2755
2909
  * Optional structural facts consumed by a generated root Vite configuration.
2756
2910
  *
2757
2911
  * @remarks
2758
- * `bin`, `integration`, and `service` select their matching projects.
2912
+ * `bin` and `integration` select their matching projects. `services` is the
2913
+ * sorted list of vendor projects derived from `tests/service/<name>` directories.
2759
2914
  * `global` records the physical `tests/setupGlobal.ts` module and wires it
2760
2915
  * into every selected project that consumes that shared setup. `showcase`
2761
2916
  * records the physical app showcase wrapper and selects its browser machinery.
@@ -2763,7 +2918,7 @@ export declare function coreViteConfig(): string;
2763
2918
  export declare interface ViteFacts {
2764
2919
  readonly bin?: boolean;
2765
2920
  readonly integration?: boolean;
2766
- readonly service?: boolean;
2921
+ readonly services?: readonly string[];
2767
2922
  readonly global?: boolean;
2768
2923
  readonly showcase?: boolean;
2769
2924
  }
@@ -2841,7 +2996,7 @@ export declare function coreViteConfig(): string;
2841
2996
  * Render the one ordered proof and structural-axis project definition block.
2842
2997
  *
2843
2998
  * @param facts - Optional structural facts.
2844
- * @returns Policy, guides, then selected axis project definitions, separated by one blank line.
2999
+ * @returns Policy, config, guides, then selected axis project definitions, separated by one blank line.
2845
3000
  *
2846
3001
  * @example
2847
3002
  * ```ts
@@ -2868,7 +3023,7 @@ export declare function coreViteConfig(): string;
2868
3023
  * @example
2869
3024
  * ```ts
2870
3025
  * viteProjectRegistrations(['core'], [], { integration: true })
2871
- * // [{ project: 'srcCore' }, { project: 'policy' }, { project: 'guides' }, { project: 'integration' }]
3026
+ * // [{ project: 'srcCore' }, { project: 'policy' }, { project: 'config' }, { project: 'guides' }, { project: 'integration' }]
2872
3027
  * ```
2873
3028
  */
2874
3029
  export declare function viteProjectRegistrations(src: readonly Environment[], app?: readonly Environment[], facts?: ViteFacts): readonly ViteProjectRegistration[];