@orkestrel/scaffold 0.0.30 → 0.0.32
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.
- package/dist/bin/main.js +144 -23
- package/dist/bin/main.js.map +1 -1
- package/dist/host/agents/orchestration.md +48 -6
- package/dist/host/agents/skills/orkestrel-falsify/SKILL.md +12 -0
- package/dist/host/claude/agents/codex.md +10 -0
- package/dist/host/claude/agents/grok.md +19 -8
- package/dist/host/claude/rules/architecture.md +25 -0
- package/dist/host/claude/rules/documentation.md +2 -1
- package/dist/host/claude/rules/tests.md +58 -21
- package/dist/host/claude/rules/workspace.md +25 -20
- package/dist/host/dotfiles/oxlintrc.json +1 -0
- package/dist/host/guides/scaffold.md +142 -67
- package/dist/host/tests/config.test.ts +45 -17
- package/dist/host/tests/policy.test.ts +254 -2
- package/dist/host/tests/setupPolicy.ts +297 -34
- package/dist/src/core/index.cjs +176 -179
- package/dist/src/core/index.cjs.map +1 -1
- package/dist/src/core/index.d.cts +90 -33
- package/dist/src/core/index.d.ts +90 -33
- package/dist/src/core/index.js +171 -180
- package/dist/src/core/index.js.map +1 -1
- package/dist/src/server/index.cjs +13 -1
- package/dist/src/server/index.cjs.map +1 -1
- package/dist/src/server/index.js +14 -2
- package/dist/src/server/index.js.map +1 -1
- package/package.json +6 -5
|
@@ -95,7 +95,7 @@ export declare const ARTIFACT_TEMPLATES: Readonly<{
|
|
|
95
95
|
global: "export function setup(): void {}\n";
|
|
96
96
|
entry: "import * as entry from {{specifier}}\nimport { describe, expect, it } from 'vitest'\n\ndescribe({{label}}, () => {\n\tit('has no starter exports', () => {\n\t\texpect(Object.keys(entry)).toStrictEqual([])\n\t})\n})\n";
|
|
97
97
|
bin: "import { describe, expect, it } from 'vitest'\n\ndescribe('bin entry', () => {\n\tit('has no starter exports', async () => {\n{{import}}\n\t\texpect(Object.keys(entry)).toStrictEqual([])\n\t})\n})\n";
|
|
98
|
-
integration: "
|
|
98
|
+
integration: "{{imports}}import { describe, expect, it } from 'vitest'\n\ndescribe('workspace integration', () => {\n\tit('loads every selected public barrel together as a composition seed', () => {\n\t\t// Replace this empty-barrel seed with one observable flow that passes one\n\t\t// environment's public result into another.\n\t\t{{actual}}{{expected}})\n\t})\n})\n";
|
|
99
99
|
}>;
|
|
100
100
|
docs: Readonly<{
|
|
101
101
|
readme: "# {{package}}\n\n{{description}}\n\n## Development\n\n```sh\nnpm install\nnpm test\n```\n";
|
|
@@ -235,15 +235,14 @@ export declare const BIN_ENTRY_PATH = "src/bin/main.ts";
|
|
|
235
235
|
* application-only, and mixed workspaces are all first class. `dependencies`
|
|
236
236
|
* and `peers` are runtime `@orkestrel/*` packages; `extras` are
|
|
237
237
|
* package-specific development dependencies and may carry any valid npm name.
|
|
238
|
-
* `bin`, `
|
|
239
|
-
* `showcase` are structural facts: each is set only
|
|
240
|
-
* physically ships the directory or exact-case file that
|
|
241
|
-
* because of the workspace's name and never because a sibling
|
|
242
|
-
*
|
|
243
|
-
* `
|
|
244
|
-
*
|
|
245
|
-
*
|
|
246
|
-
* completes.
|
|
238
|
+
* `bin`, `guides`, `distribution`, `integration`, `conformance`, `service`,
|
|
239
|
+
* `vendors`, `global`, and `showcase` are structural facts: each is set only
|
|
240
|
+
* when the workspace physically ships the directory or exact-case file that
|
|
241
|
+
* defines it, never because of the workspace's name and never because a sibling
|
|
242
|
+
* fact is set.
|
|
243
|
+
* `showcase` projects only a browser `app`. The gate answers an absent browser
|
|
244
|
+
* axis with a non-blocking question, so a caller that set the flag learns it
|
|
245
|
+
* emitted nothing and the compile still completes.
|
|
247
246
|
*
|
|
248
247
|
* `service` says the workspace runs a live-service Vitest project over
|
|
249
248
|
* `tests/service`, and it alone registers that project. `vendors` names each
|
|
@@ -265,6 +264,8 @@ export declare interface Blueprint {
|
|
|
265
264
|
readonly engines: string;
|
|
266
265
|
readonly overrides: readonly Override[];
|
|
267
266
|
readonly bin: boolean;
|
|
267
|
+
readonly guides: boolean;
|
|
268
|
+
readonly distribution: boolean;
|
|
268
269
|
readonly integration: boolean;
|
|
269
270
|
readonly conformance: boolean;
|
|
270
271
|
readonly service: boolean;
|
|
@@ -438,12 +439,19 @@ export declare function blueprintToOrchestrationArtifacts(blueprint: Blueprint):
|
|
|
438
439
|
*
|
|
439
440
|
* A question blocks when it describes a workspace this package cannot generate.
|
|
440
441
|
* Three do not, because each describes a workspace it can describe honestly and
|
|
441
|
-
* should not create: a published axis of several environments without core,
|
|
442
|
-
* manifest names a core build the workspace never runs
|
|
443
|
-
* whose required axis is absent, which emits nothing
|
|
444
|
-
*
|
|
445
|
-
*
|
|
446
|
-
*
|
|
442
|
+
* should not create: a published axis of several environments without core,
|
|
443
|
+
* whose manifest names a core build the workspace never runs; a showcase flag
|
|
444
|
+
* whose required browser axis is absent, which emits nothing; and an
|
|
445
|
+
* integration flag over fewer than two environments, whose seed does emit and
|
|
446
|
+
* has nothing to compose across. Blocking any of them closed the gate for every
|
|
447
|
+
* verb. The verbs that read an existing workspace need the plan the gate
|
|
448
|
+
* refused. The caller that chooses the shape refuses the advisory; the callers
|
|
449
|
+
* that read one report it.
|
|
450
|
+
*
|
|
451
|
+
* The integration advisory counts both axes together, because the proof it
|
|
452
|
+
* seeds spans environments rather than published ones: an application of two
|
|
453
|
+
* environments composes, and a package publishing one does not. Reading either
|
|
454
|
+
* axis alone withdrew the proof from a workspace that does compose.
|
|
447
455
|
*
|
|
448
456
|
* An environment question carries `ENVIRONMENTS` as its candidates, so a caller
|
|
449
457
|
* reads the accepted values from the question instead of from the documentation.
|
|
@@ -511,12 +519,13 @@ export declare function blueprintToRootVite(blueprint: Blueprint): string;
|
|
|
511
519
|
* proofs every workspace can pass before it has a public API, and one build per
|
|
512
520
|
* target that actually builds.
|
|
513
521
|
*
|
|
514
|
-
* A
|
|
515
|
-
*
|
|
516
|
-
*
|
|
517
|
-
*
|
|
518
|
-
*
|
|
519
|
-
*
|
|
522
|
+
* A publishing workspace isolates distribution and live-service proofs from
|
|
523
|
+
* `test` and runs them from `prepublishOnly` instead. A private workspace has
|
|
524
|
+
* no publish lifecycle, so it omits distribution and runs a live-service proof
|
|
525
|
+
* from `test`. Integration and conformance stay in `test` because they neither
|
|
526
|
+
* pack nor install the workspace and drive no external service. A conformance
|
|
527
|
+
* run may start a server, but it starts its own and reaches it over loopback,
|
|
528
|
+
* so the run stays hermetic.
|
|
520
529
|
*
|
|
521
530
|
* The configuration paths interpolated here are the same ones `SRC_MATRIX` and
|
|
522
531
|
* `APP_MATRIX` list as each environment's configuration files, so a rename in
|
|
@@ -562,15 +571,14 @@ export declare function blueprintToSourceArtifacts(blueprint: Blueprint): readon
|
|
|
562
571
|
* Compile every artifact in the `tests` group that is not vendored from the host.
|
|
563
572
|
*
|
|
564
573
|
* @param blueprint - The workspace specification.
|
|
565
|
-
* @returns Shared setup modules, axis tests, and the optional
|
|
574
|
+
* @returns Shared setup modules, axis tests, and the optional integration seed.
|
|
566
575
|
*
|
|
567
576
|
* @remarks
|
|
568
577
|
* `tests/setupPolicy.ts`, `tests/policy.test.ts`, and `tests/config.test.ts` are
|
|
569
578
|
* fleet-invariant host artifacts and therefore do not appear here. A guide
|
|
570
579
|
* proof is not emitted while the workspace intentionally has empty barrels and
|
|
571
|
-
* no package guide. The
|
|
572
|
-
*
|
|
573
|
-
* flag.
|
|
580
|
+
* no package guide. The integration seed follows its structural flag and loads
|
|
581
|
+
* every selected environment through its public barrel.
|
|
574
582
|
*
|
|
575
583
|
* The conformance proof is not emitted either, for the reason the guide proof
|
|
576
584
|
* is not: it names an official artifact only the package knows, so a generated
|
|
@@ -1026,18 +1034,18 @@ export declare class Compiler implements CompilerInterface {
|
|
|
1026
1034
|
export declare const CONFIG_TEMPLATES: Readonly<{
|
|
1027
1035
|
root: Readonly<{
|
|
1028
1036
|
tsconfig: "{\n\t\"compilerOptions\": {\n\t\t\"target\": \"ESNext\",\n\t\t\"module\": \"ESNext\",\n\t\t\"moduleResolution\": \"bundler\",\n\t\t\"allowImportingTsExtensions\": true,\n\t\t\"lib\": [\"ESNext\", \"DOM\", \"DOM.Iterable\"],\n\t\t\"types\": [\"node\", \"vite/client\", \"vitest/globals\"],\n\t\t\"moduleDetection\": \"force\",\n\t\t\"resolveJsonModule\": true,\n\t\t\"strict\": true,\n\t\t\"verbatimModuleSyntax\": true,\n\t\t\"noUncheckedIndexedAccess\": true,\n\t\t\"noUncheckedSideEffectImports\": true,\n\t\t\"exactOptionalPropertyTypes\": true,\n\t\t\"noUnusedLocals\": true,\n\t\t\"noUnusedParameters\": true,\n\t\t\"noImplicitOverride\": true,\n\t\t\"noFallthroughCasesInSwitch\": true,\n\t\t\"forceConsistentCasingInFileNames\": true,\n\t\t\"skipLibCheck\": true,\n\t\t\"noEmit\": true,\n\t\t\"paths\": {\n{{paths}}\n\t\t}\n\t},\n\t\"exclude\": [\"node_modules\", \"dist\", \"tmp\"]\n}\n";
|
|
1029
|
-
vite: "import type { {{viteTypes}} } from 'vite'\n{{imports}}import { defineConfig, mergeConfig } from 'vitest/config'\nimport tsconfig from './tsconfig.json' with { type: 'json' }\n{{helpers}}{{browsers}}import {
|
|
1037
|
+
vite: "import type { {{viteTypes}} } from 'vite'\n{{imports}}import { defineConfig, mergeConfig } from 'vitest/config'\nimport tsconfig from './tsconfig.json' with { type: 'json' }\n{{helpers}}{{browsers}}import { fileURLToPath, URL } from 'node:url'\n\n{{options}}export function resolveWorkspacePath(relativePath: string): string {\n\treturn fileURLToPath(new URL(relativePath, import.meta.url))\n}\n\nconst resolve = {\n\talias: Object.entries(tsconfig.compilerOptions.paths).reduce((aliases, [key, values]) => {\n\t\tconst [path] = values\n\t\tif (path === undefined) throw new Error('tsconfig path alias ' + key + ' has no target')\n\t\treturn Object.assign(aliases, { [key]: resolveWorkspacePath(path) })\n\t}, {}),\n}\n\n{{factories}}export default defineConfig({\n\tresolve,\n\ttest: {\n{{projects}}\n\t},\n})\n";
|
|
1030
1038
|
}>;
|
|
1031
1039
|
factories: Readonly<{
|
|
1032
1040
|
src: Readonly<{
|
|
1033
1041
|
core: "export const srcCore = (options?: UserConfig): UserConfig =>\n\tmergeConfig(\n\t\t{\n\t\t\tresolve,\n\t\t\tpublicDir: false,\n\t\t\tbuild: {\n\t\t\t\temptyOutDir: true,\n\t\t\t\tsourcemap: true,\n\t\t\t\tminify: false,\n\t\t\t},\n\t\t\ttest: {\n\t\t\t\tname: { label: 'src:core', color: 'magenta' },\n\t\t\t\tinclude: ['tests/src/core/**/*.test.ts'],\n\t\t\t\tsetupFiles: ['./tests/setup.ts'],\n\t\t\t\tenvironment: 'node',\n\t\t\t\tbrowser: { enabled: false },\n\t\t\t},\n\t\t},\n\t\toptions ?? {},\n\t)\n";
|
|
1034
1042
|
browser: "export const srcBrowser = (options?: UserConfig): UserConfig =>\n\tmergeConfig(\n\t\t{\n\t\t\tresolve,\n\t\t\tpublicDir: false,\n\t\t\tplugins: [outputBoundary('dist/src/browser'), environmentBoundary('src/browser')],\n\t\t\tbuild: {\n\t\t\t\temptyOutDir: true,\n\t\t\t\tsourcemap: true,\n\t\t\t\tminify: false,\n\t\t\t\tlib: {\n\t\t\t\t\tentry: resolveWorkspacePath('src/browser/index.ts'),\n\t\t\t\t\tformats: ['es'],\n\t\t\t\t\tfileName: () => 'index.js',\n\t\t\t\t},\n\t\t\t\toutDir: 'dist/src/browser',\n\t\t\t\trolldownOptions: {\n\t\t\t\t\t{{external}}\n{{output}}\n\t\t\t\t},\n\t\t\t},\n\t\t\ttest: {\n\t\t\t\tname: { label: 'src:browser', color: 'yellow' },\n\t\t\t\tinclude: ['tests/src/browser/**/*.test.ts'],\n{{exclude}}\t\t\t\tsetupFiles: ['./tests/setup.ts', './tests/setupBrowser.ts'],\n{{global}}\n\t\t\t\tbrowser: {\n\t\t\t\t\tenabled: true,\n\t\t\t\t\tprovider: playwright(browserOptions),\n\t\t\t\t\tinstances: [{ browser: 'chromium', headless: true }],\n\t\t\t\t},\n\t\t\t\tfileParallelism: false,\n\t\t\t},\n\t\t},\n\t\toptions ?? {},\n\t)\n";
|
|
1035
1043
|
server: "export const srcServer = (options?: UserConfig): UserConfig =>\n\tmergeConfig(\n\t\t{\n\t\t\tresolve,\n\t\t\tpublicDir: false,\n\t\t\tplugins: [outputBoundary('dist/src/server'), environmentBoundary('src/server')],\n\t\t\tbuild: {\n\t\t\t\temptyOutDir: true,\n\t\t\t\tsourcemap: true,\n\t\t\t\tminify: false,\n\t\t\t\tlib: {\n\t\t\t\t\tentry: resolveWorkspacePath('src/server/index.ts'),\n\t\t\t\t\tformats: ['es', 'cjs'],\n\t\t\t\t\tfileName: (format: string) => (format === 'es' ? 'index.js' : 'index.cjs'),\n\t\t\t\t},\n\t\t\t\toutDir: 'dist/src/server',\n\t\t\t\ttarget: 'node22',\n\t\t\t\trolldownOptions: {\n\t\t\t\t\tplatform: 'node',\n\t\t\t\t\t{{external}}\n{{output}}\n\t\t\t\t},\n\t\t\t},\n\t\t\ttest: {\n\t\t\t\tname: { label: 'src:server', color: 'red' },\n\t\t\t\tinclude: ['tests/src/server/**/*.test.ts'],\n{{exclude}}\t\t\t\tsetupFiles: ['./tests/setup.ts', './tests/setupServer.ts'],\n\t\t\t\tenvironment: 'node',\n\t\t\t\tbrowser: { enabled: false },\n\t\t\t},\n\t\t},\n\t\toptions ?? {},\n\t)\n";
|
|
1036
|
-
bin: "export const srcBin = (options?: UserConfig): UserConfig =>\n\tmergeConfig(\n\t\t{\n\t\t\tresolve,\n\t\t\tpublicDir: false,\n\t\t\tplugins: [outputBoundary('dist/bin')],\n\t\t\tbuild: {\n\t\t\t\temptyOutDir: true,\n\t\t\t\tsourcemap: true,\n\t\t\t\tminify: false,\n\t\t\t\tlib: {\n\t\t\t\t\tentry: resolveWorkspacePath('src/bin/main.ts'),\n\t\t\t\t\tformats: ['es'],\n\t\t\t\t\tfileName: () => 'main.js',\n\t\t\t\t},\n\t\t\t\toutDir: 'dist/bin',\n\t\t\t\ttarget: 'node22',\n\t\t\t\trolldownOptions: { external: [/^node:/, /^@orkestrel\\//, /^@src\\//] },\n\t\t\t},\n\t\t\ttest: {\n\t\t\t\tname: { label: 'src:bin', color: 'yellow' },\n\t\t\t\tinclude: ['tests/src/bin/**/*.test.ts'],\n\t\t\t\tsetupFiles: ['./tests/setup.ts', './tests/setupServer.ts'],\n\t\t\t\tenvironment: 'node',\n\t\t\t\tbrowser: { enabled: false },\n\t\t\t},\n\t\t},\n\t\toptions ?? {},\n\t)\n";
|
|
1044
|
+
bin: "export const srcBin = (options?: UserConfig): UserConfig =>\n\tmergeConfig(\n\t\t{\n\t\t\tresolve,\n\t\t\tpublicDir: false,\n\t\t\tplugins: [outputBoundary('dist/bin')],\n\t\t\tbuild: {\n\t\t\t\temptyOutDir: true,\n\t\t\t\tsourcemap: true,\n\t\t\t\tminify: false,\n\t\t\t\tlib: {\n\t\t\t\t\tentry: resolveWorkspacePath('src/bin/main.ts'),\n\t\t\t\t\tformats: ['es'],\n\t\t\t\t\tfileName: () => 'main.js',\n\t\t\t\t},\n\t\t\t\toutDir: 'dist/bin',\n\t\t\t\ttarget: 'node22',\n\t\t\t\trolldownOptions: { external: [/^node:/, /^@orkestrel\\//, /^@src\\//] },\n\t\t\t},\n\t\t\ttest: {\n\t\t\t\tname: { label: 'src:bin', color: 'yellow' },\n\t\t\t\tinclude: ['tests/src/bin/**/*.test.ts'],\n\t\t\t\tsetupFiles: ['./tests/setup.ts', './tests/setupServer.ts'],\n\t\t\t\tenvironment: 'node',\n\t\t\t\tbrowser: { enabled: false },\n\t\t\t\t// A bin test drives the real executable over a real temporary repository, so it\n\t\t\t\t// spends seconds in process startup and filesystem work rather than milliseconds.\n\t\t\t\t// Vitest's five-second default clears one alone and times out under a full suite.\n\t\t\t\ttestTimeout: 15_000,\n\t\t\t},\n\t\t},\n\t\toptions ?? {},\n\t)\n";
|
|
1037
1045
|
}>;
|
|
1038
1046
|
app: Readonly<{
|
|
1039
1047
|
core: "export const appCore = (options?: UserConfig): UserConfig =>\n\tmergeConfig(\n\t\t{\n\t\t\tresolve,\n\t\t\tpublicDir: false,\n\t\t\tplugins: [environmentBoundary('app/core')],\n\t\t\ttest: {\n\t\t\t\tname: { label: 'app:core', color: 'cyan' },\n\t\t\t\tinclude: ['tests/app/core/**/*.test.ts'],\n\t\t\t\tsetupFiles: ['./tests/setup.ts'],\n\t\t\t\tenvironment: 'node',\n\t\t\t\tbrowser: { enabled: false },\n\t\t\t},\n\t\t},\n\t\toptions ?? {},\n\t)\n";
|
|
1040
|
-
browser: "function applicationBrowser(showcase: boolean): UserConfig {\n\tconst output = showcase ? 'dist/showcase' : 'dist/app/browser'\n{{showcasePlugins}}\treturn {\n\t\tresolve,\n{{plugins}}\t\troot: resolveWorkspacePath('app/browser'),\n\t\tpublicDir: false,\n\t\tbuild: {\n{{showcaseBuild}}\t\t\temptyOutDir: true,\n\t\t\toutDir: resolveWorkspacePath(output),\n\t\t\trolldownOptions: { input: resolveWorkspacePath('app/browser/index.html') },\n\t\t},\n\t\ttest: {\n\t\t\tname: { label: 'app:browser', color: 'blue' },\n\t\t\troot: resolveWorkspacePath('.'),\n\t\t\tdir: resolveWorkspacePath('.'),\n\t\t\tinclude: ['tests/app/browser/**/*.test.ts'],\n\t\t\tsetupFiles: ['./tests/setup.ts', './tests/setupBrowser.ts'],\n\t\t\tbrowser: {\n\t\t\t\tenabled: true,\n\t\t\t\tprovider: playwright(browserOptions),\n\t\t\t\tinstances: [{ browser: 'chromium', headless: true }],\n\t\t\t},\n\t\t\tfileParallelism: false,\n\t\t},\n\t}\n}\n\nexport function appBrowser(
|
|
1048
|
+
browser: "function applicationBrowser(showcase: boolean): UserConfig {\n\tconst output = showcase ? 'dist/showcase' : 'dist/app/browser'\n{{showcasePlugins}}\treturn {\n\t\tresolve,\n{{plugins}}\t\troot: resolveWorkspacePath('app/browser'),\n\t\tpublicDir: false,\n\t\tbuild: {\n{{showcaseBuild}}\t\t\temptyOutDir: true,\n\t\t\toutDir: resolveWorkspacePath(output),\n\t\t\trolldownOptions: { input: resolveWorkspacePath('app/browser/index.html') },\n\t\t},\n\t\ttest: {\n\t\t\tname: { label: 'app:browser', color: 'blue' },\n\t\t\troot: resolveWorkspacePath('.'),\n\t\t\tdir: resolveWorkspacePath('.'),\n\t\t\tinclude: ['tests/app/browser/**/*.test.ts'],\n\t\t\tsetupFiles: ['./tests/setup.ts', './tests/setupBrowser.ts'],\n\t\t\tbrowser: {\n\t\t\t\tenabled: true,\n\t\t\t\tprovider: playwright(browserOptions),\n\t\t\t\tinstances: [{ browser: 'chromium', headless: true }],\n\t\t\t},\n\t\t\tfileParallelism: false,\n\t\t},\n\t}\n}\n\nexport function appBrowser(): UserConfig {\n\treturn applicationBrowser(false)\n}\n{{showcaseFactory}}";
|
|
1041
1049
|
server: "export const appServer = (options?: UserConfig): UserConfig =>\n\tmergeConfig(\n\t\t{\n\t\t\tresolve,\n\t\t\tpublicDir: false,\n\t\t\tplugins: [outputBoundary('dist/app/server'), environmentBoundary('app/server')],\n\t\t\tbuild: {\n\t\t\t\temptyOutDir: true,\n\t\t\t\tlib: {\n\t\t\t\t\tentry: resolveWorkspacePath('app/server/main.ts'),\n\t\t\t\t\tformats: ['cjs'],\n\t\t\t\t\tfileName: () => 'main.cjs',\n\t\t\t\t},\n\t\t\t\toutDir: resolveWorkspacePath('dist/app/server'),\n\t\t\t\ttarget: 'node22',\n\t\t\t\trolldownOptions: { external: (id: string) => id.startsWith('node:') },\n\t\t\t},\n\t\t\ttest: {\n\t\t\t\tname: { label: 'app:server', color: 'green' },\n\t\t\t\tinclude: ['tests/app/server/**/*.test.ts'],\n\t\t\t\tsetupFiles: ['./tests/setup.ts', './tests/setupServer.ts'],\n\t\t\t\tenvironment: 'node',\n\t\t\t\tbrowser: { enabled: false },\n\t\t\t},\n\t\t},\n\t\toptions ?? {},\n\t)\n";
|
|
1042
1050
|
}>;
|
|
1043
1051
|
policy: "export const policy = (options?: UserConfig): UserConfig =>\n\tmergeConfig(\n\t\t{\n\t\t\tresolve,\n\t\t\ttest: {\n\t\t\t\tname: { label: 'policy', color: 'white' },\n\t\t\t\tinclude: ['tests/policy.test.ts'],\n\t\t\t\tsetupFiles: ['./tests/setup.ts'],\n\t\t\t\tenvironment: 'node',\n\t\t\t\tbrowser: { enabled: false },\n\t\t\t},\n\t\t},\n\t\toptions ?? {},\n\t)\n";
|
|
@@ -1045,8 +1053,9 @@ export declare class Compiler implements CompilerInterface {
|
|
|
1045
1053
|
guides: "export const guides = (options?: UserConfig): UserConfig =>\n\tmergeConfig(\n\t\t{\n\t\t\tresolve,\n\t\t\ttest: {\n\t\t\t\tname: { label: 'guides', color: 'green' },\n\t\t\t\tinclude: ['tests/guides.test.ts'],\n\t\t\t\texclude: ['tests/src/**/*.test.ts', 'tests/app/**/*.test.ts', 'tests/setup.test.ts'],\n\t\t\t\tsetupFiles: ['./tests/setup.ts'],\n\t\t\t\tenvironment: 'node',\n\t\t\t\tbrowser: { enabled: false },\n\t\t\t},\n\t\t},\n\t\toptions ?? {},\n\t)\n";
|
|
1046
1054
|
conformance: "// Where this package drifts from the official tooling it stays compatible with.\n// The subject is this package, so the proof is hermetic and stays in `npm test`.\nexport const conformance = (options?: UserConfig): UserConfig =>\n\tmergeConfig(\n\t\t{\n\t\t\tresolve,\n\t\t\ttest: {\n\t\t\t\tname: { label: 'conformance', color: 'magenta' },\n\t\t\t\tinclude: ['tests/conformance.test.ts'],\n\t\t\t\tsetupFiles: ['./tests/setup.ts'],\n\t\t\t\tenvironment: 'node',\n\t\t\t\tbrowser: { enabled: false },\n\t\t\t},\n\t\t},\n\t\toptions ?? {},\n\t)\n";
|
|
1047
1055
|
service: "// The live external services this package drives. It starts nothing itself:\n// `scripts/service.sh` provisions, `tests/setupService.ts` proves readiness, and\n// the project stays out of `npm test` because a real service answers it.\nexport const service = (options?: UserConfig): UserConfig =>\n\tmergeConfig(\n\t\t{\n\t\t\tresolve,\n\t\t\ttest: {\n\t\t\t\tname: { label: 'service', color: 'red' },\n\t\t\t\tinclude: ['tests/service/**/*.test.ts'],\n\t\t\t\tsetupFiles: ['./tests/setup.ts', './tests/setupService.ts'],\n\t\t\t\tenvironment: 'node',\n\t\t\t\tbrowser: { enabled: false },\n\t\t\t\ttestTimeout: 120_000,\n\t\t\t\thookTimeout: 120_000,\n\t\t\t\tfileParallelism: false,\n\t\t\t},\n\t\t},\n\t\toptions ?? {},\n\t)\n";
|
|
1056
|
+
distribution: "export const distribution = (options?: UserConfig): UserConfig =>\n\tmergeConfig(\n\t\t{\n\t\t\tresolve,\n\t\t\ttest: {\n\t\t\t\tname: { label: 'distribution', color: 'cyan' },\n\t\t\t\tinclude: ['tests/distribution.test.ts'],\n\t\t\t\tsetupFiles: ['./tests/setup.ts'],\n\t\t\t\tenvironment: 'node',\n\t\t\t\ttestTimeout: 120_000,\n\t\t\t\thookTimeout: 120_000,\n\t\t\t\tfileParallelism: false,\n\t\t\t},\n\t\t},\n\t\toptions ?? {},\n\t)\n";
|
|
1048
1057
|
probe: "// A workbench, not a proof. No gate selects this project.\nexport const probe = (options?: UserConfig): UserConfig =>\n\tmergeConfig(\n\t\t{\n\t\t\tresolve,\n\t\t\ttest: {\n\t\t\t\tname: { label: 'probe', color: 'gray' },\n\t\t\t\tinclude: ['tmp/probe/**/*.test.ts'],\n\t\t\t\tsetupFiles: ['./tests/setup.ts'],\n\t\t\t\tenvironment: 'node',\n\t\t\t\tbrowser: { enabled: false },\n\t\t\t},\n\t\t},\n\t\toptions ?? {},\n\t)\n";
|
|
1049
|
-
integration: "export const integration = (options?: UserConfig): UserConfig =>\n\tmergeConfig(\n\t\t{\n\t\t\tresolve,\n\t\t\ttest: {\n\t\t\t\tname: { label: 'integration', color: 'blue' },\n\t\t\t\tinclude: ['tests/integration.test.ts'],\n\t\t\t\tsetupFiles: ['./tests/setup.ts'],\n{{global}}\t\t\t\tenvironment: 'node',\n\t\t\t
|
|
1058
|
+
integration: "export const integration = (options?: UserConfig): UserConfig =>\n\tmergeConfig(\n\t\t{\n\t\t\tresolve,\n\t\t\ttest: {\n\t\t\t\tname: { label: 'integration', color: 'blue' },\n\t\t\t\tinclude: ['tests/integration.test.ts'],\n\t\t\t\tsetupFiles: ['./tests/setup.ts'],\n{{global}}\t\t\t\tenvironment: 'node',\n\t\t\t},\n\t\t},\n\t\toptions ?? {},\n\t)\n";
|
|
1050
1059
|
}>;
|
|
1051
1060
|
tsconfigs: Readonly<{
|
|
1052
1061
|
src: Readonly<{
|
|
@@ -1169,6 +1178,9 @@ export declare class Compiler implements CompilerInterface {
|
|
|
1169
1178
|
*/
|
|
1170
1179
|
export declare function createCompiler(options?: CompilerOptions): CompilerInterface;
|
|
1171
1180
|
|
|
1181
|
+
/** The development dependencies that emit declarations for published source or an executable. */
|
|
1182
|
+
export declare const DECLARATION_DEV_DEPENDENCIES: Readonly<Record<string, string>>;
|
|
1183
|
+
|
|
1172
1184
|
/** The `engines.node` range a workspace starts with. */
|
|
1173
1185
|
export declare const DEFAULT_ENGINES = ">=22.12.0";
|
|
1174
1186
|
|
|
@@ -1235,6 +1247,9 @@ export declare class Compiler implements CompilerInterface {
|
|
|
1235
1247
|
*/
|
|
1236
1248
|
export declare const DEPENDENCY_NAME_PATTERN: RegExp;
|
|
1237
1249
|
|
|
1250
|
+
/** The packed-package proof whose presence makes a workspace `distribution`. */
|
|
1251
|
+
export declare const DISTRIBUTION_TEST_PATH = "tests/distribution.test.ts";
|
|
1252
|
+
|
|
1238
1253
|
/**
|
|
1239
1254
|
* How one target path compares to the artifact planned for it.
|
|
1240
1255
|
*
|
|
@@ -1385,7 +1400,7 @@ export declare class Compiler implements CompilerInterface {
|
|
|
1385
1400
|
*/
|
|
1386
1401
|
export declare const GROUPS: readonly Group[];
|
|
1387
1402
|
|
|
1388
|
-
/** The guide-parity proof whose
|
|
1403
|
+
/** The guide-parity proof whose presence selects the planned `guides` project. */
|
|
1389
1404
|
export declare const GUIDES_TEST_PATH = "tests/guides.test.ts";
|
|
1390
1405
|
|
|
1391
1406
|
/** Exact lowercase hexadecimal bytes: two digits per byte, and empty content is valid. */
|
|
@@ -1416,7 +1431,9 @@ export declare class Compiler implements CompilerInterface {
|
|
|
1416
1431
|
* exist. That is why the ownership here is narrowed away from `content`: a
|
|
1417
1432
|
* claim over bytes nobody has read is a claim that cannot be checked. Reading
|
|
1418
1433
|
* the vendored root turns the ones scaffold owns the bytes of into
|
|
1419
|
-
* {@link HydratedArtifact}.
|
|
1434
|
+
* {@link HydratedArtifact}. Workspace-owned paths and paths whose bytes belong
|
|
1435
|
+
* to another verb stay plain host artifacts, because this writer claims only
|
|
1436
|
+
* their presence.
|
|
1420
1437
|
*/
|
|
1421
1438
|
export declare interface HostArtifact extends ArtifactBase {
|
|
1422
1439
|
readonly origin: 'host';
|
|
@@ -1508,7 +1525,7 @@ export declare class Compiler implements CompilerInterface {
|
|
|
1508
1525
|
*/
|
|
1509
1526
|
export declare function inferGroup(path: string): Group;
|
|
1510
1527
|
|
|
1511
|
-
/** The
|
|
1528
|
+
/** The cross-environment composition proof whose presence makes a workspace `integration`. */
|
|
1512
1529
|
export declare const INTEGRATION_TEST_PATH = "tests/integration.test.ts";
|
|
1513
1530
|
|
|
1514
1531
|
/** Visible characters a target-relative path and a Markdown path cell both forbid. */
|
|
@@ -1962,6 +1979,29 @@ export declare class Compiler implements CompilerInterface {
|
|
|
1962
1979
|
*/
|
|
1963
1980
|
export declare function matchesOrchestrationPath(path: string): boolean;
|
|
1964
1981
|
|
|
1982
|
+
/**
|
|
1983
|
+
* Test whether one emitted line fits the vendored formatter width.
|
|
1984
|
+
*
|
|
1985
|
+
* @param line - One emitted line, leading tabs included.
|
|
1986
|
+
* @returns `true` when the expanded line fits.
|
|
1987
|
+
*
|
|
1988
|
+
* @remarks
|
|
1989
|
+
* A generator writes source the formatter then reads back, so a line packed
|
|
1990
|
+
* past the vendored width is rewrapped on the next `format` run and the emitted
|
|
1991
|
+
* bytes stop matching the plan the audit compares against. The generator
|
|
1992
|
+
* therefore measures a candidate line and chooses the shape the formatter would
|
|
1993
|
+
* have chosen. Tabs are expanded first because the formatter counts them as
|
|
1994
|
+
* `TAB_WIDTH` columns rather than as one character.
|
|
1995
|
+
*
|
|
1996
|
+
* @example
|
|
1997
|
+
* ```ts
|
|
1998
|
+
* import { matchesPrintWidth } from '@orkestrel/scaffold'
|
|
1999
|
+
*
|
|
2000
|
+
* matchesPrintWidth('\t\tprojects: [core],') // true
|
|
2001
|
+
* ```
|
|
2002
|
+
*/
|
|
2003
|
+
export declare function matchesPrintWidth(line: string): boolean;
|
|
2004
|
+
|
|
1965
2005
|
/**
|
|
1966
2006
|
* Test whether a declared range already admits a published version.
|
|
1967
2007
|
*
|
|
@@ -2470,6 +2510,9 @@ export declare class Compiler implements CompilerInterface {
|
|
|
2470
2510
|
*/
|
|
2471
2511
|
export declare function planToSummary(plan: Plan): PlanSummary;
|
|
2472
2512
|
|
|
2513
|
+
/** Columns one emitted line may occupy, matching `printWidth` in `.oxfmtrc.json`. */
|
|
2514
|
+
export declare const PRINT_WIDTH = 100;
|
|
2515
|
+
|
|
2473
2516
|
/**
|
|
2474
2517
|
* One validation issue raised against a blueprint or a plan.
|
|
2475
2518
|
*
|
|
@@ -2771,6 +2814,9 @@ export declare class Compiler implements CompilerInterface {
|
|
|
2771
2814
|
*/
|
|
2772
2815
|
export declare function srcToRoot(src: readonly Environment[]): Environment | undefined;
|
|
2773
2816
|
|
|
2817
|
+
/** Columns one tab occupies when the formatter measures a line, matching `tabWidth`. */
|
|
2818
|
+
export declare const TAB_WIDTH = 2;
|
|
2819
|
+
|
|
2774
2820
|
/** The exact three-component version syntax a blueprint declares. */
|
|
2775
2821
|
export declare const VERSION_PATTERN: RegExp;
|
|
2776
2822
|
|
|
@@ -2793,4 +2839,15 @@ export declare class Compiler implements CompilerInterface {
|
|
|
2793
2839
|
readonly showcase: boolean;
|
|
2794
2840
|
}
|
|
2795
2841
|
|
|
2842
|
+
/**
|
|
2843
|
+
* The vendored paths whose present bytes belong to each workspace, frozen.
|
|
2844
|
+
*
|
|
2845
|
+
* @remarks
|
|
2846
|
+
* These paths are copied into a workspace when absent and are never compared
|
|
2847
|
+
* or replaced while present. A workspace therefore stops receiving later
|
|
2848
|
+
* canonical updates to them. `.gitignore` takes that trade because its correct
|
|
2849
|
+
* rules differ by workspace, so scaffold cannot own its bytes.
|
|
2850
|
+
*/
|
|
2851
|
+
export declare const WORKSPACE_OWNED_PATHS: readonly string[];
|
|
2852
|
+
|
|
2796
2853
|
export { }
|
package/dist/src/core/index.d.ts
CHANGED
|
@@ -95,7 +95,7 @@ export declare const ARTIFACT_TEMPLATES: Readonly<{
|
|
|
95
95
|
global: "export function setup(): void {}\n";
|
|
96
96
|
entry: "import * as entry from {{specifier}}\nimport { describe, expect, it } from 'vitest'\n\ndescribe({{label}}, () => {\n\tit('has no starter exports', () => {\n\t\texpect(Object.keys(entry)).toStrictEqual([])\n\t})\n})\n";
|
|
97
97
|
bin: "import { describe, expect, it } from 'vitest'\n\ndescribe('bin entry', () => {\n\tit('has no starter exports', async () => {\n{{import}}\n\t\texpect(Object.keys(entry)).toStrictEqual([])\n\t})\n})\n";
|
|
98
|
-
integration: "
|
|
98
|
+
integration: "{{imports}}import { describe, expect, it } from 'vitest'\n\ndescribe('workspace integration', () => {\n\tit('loads every selected public barrel together as a composition seed', () => {\n\t\t// Replace this empty-barrel seed with one observable flow that passes one\n\t\t// environment's public result into another.\n\t\t{{actual}}{{expected}})\n\t})\n})\n";
|
|
99
99
|
}>;
|
|
100
100
|
docs: Readonly<{
|
|
101
101
|
readme: "# {{package}}\n\n{{description}}\n\n## Development\n\n```sh\nnpm install\nnpm test\n```\n";
|
|
@@ -235,15 +235,14 @@ export declare const BIN_ENTRY_PATH = "src/bin/main.ts";
|
|
|
235
235
|
* application-only, and mixed workspaces are all first class. `dependencies`
|
|
236
236
|
* and `peers` are runtime `@orkestrel/*` packages; `extras` are
|
|
237
237
|
* package-specific development dependencies and may carry any valid npm name.
|
|
238
|
-
* `bin`, `
|
|
239
|
-
* `showcase` are structural facts: each is set only
|
|
240
|
-
* physically ships the directory or exact-case file that
|
|
241
|
-
* because of the workspace's name and never because a sibling
|
|
242
|
-
*
|
|
243
|
-
* `
|
|
244
|
-
*
|
|
245
|
-
*
|
|
246
|
-
* completes.
|
|
238
|
+
* `bin`, `guides`, `distribution`, `integration`, `conformance`, `service`,
|
|
239
|
+
* `vendors`, `global`, and `showcase` are structural facts: each is set only
|
|
240
|
+
* when the workspace physically ships the directory or exact-case file that
|
|
241
|
+
* defines it, never because of the workspace's name and never because a sibling
|
|
242
|
+
* fact is set.
|
|
243
|
+
* `showcase` projects only a browser `app`. The gate answers an absent browser
|
|
244
|
+
* axis with a non-blocking question, so a caller that set the flag learns it
|
|
245
|
+
* emitted nothing and the compile still completes.
|
|
247
246
|
*
|
|
248
247
|
* `service` says the workspace runs a live-service Vitest project over
|
|
249
248
|
* `tests/service`, and it alone registers that project. `vendors` names each
|
|
@@ -265,6 +264,8 @@ export declare interface Blueprint {
|
|
|
265
264
|
readonly engines: string;
|
|
266
265
|
readonly overrides: readonly Override[];
|
|
267
266
|
readonly bin: boolean;
|
|
267
|
+
readonly guides: boolean;
|
|
268
|
+
readonly distribution: boolean;
|
|
268
269
|
readonly integration: boolean;
|
|
269
270
|
readonly conformance: boolean;
|
|
270
271
|
readonly service: boolean;
|
|
@@ -438,12 +439,19 @@ export declare function blueprintToOrchestrationArtifacts(blueprint: Blueprint):
|
|
|
438
439
|
*
|
|
439
440
|
* A question blocks when it describes a workspace this package cannot generate.
|
|
440
441
|
* Three do not, because each describes a workspace it can describe honestly and
|
|
441
|
-
* should not create: a published axis of several environments without core,
|
|
442
|
-
* manifest names a core build the workspace never runs
|
|
443
|
-
* whose required axis is absent, which emits nothing
|
|
444
|
-
*
|
|
445
|
-
*
|
|
446
|
-
*
|
|
442
|
+
* should not create: a published axis of several environments without core,
|
|
443
|
+
* whose manifest names a core build the workspace never runs; a showcase flag
|
|
444
|
+
* whose required browser axis is absent, which emits nothing; and an
|
|
445
|
+
* integration flag over fewer than two environments, whose seed does emit and
|
|
446
|
+
* has nothing to compose across. Blocking any of them closed the gate for every
|
|
447
|
+
* verb. The verbs that read an existing workspace need the plan the gate
|
|
448
|
+
* refused. The caller that chooses the shape refuses the advisory; the callers
|
|
449
|
+
* that read one report it.
|
|
450
|
+
*
|
|
451
|
+
* The integration advisory counts both axes together, because the proof it
|
|
452
|
+
* seeds spans environments rather than published ones: an application of two
|
|
453
|
+
* environments composes, and a package publishing one does not. Reading either
|
|
454
|
+
* axis alone withdrew the proof from a workspace that does compose.
|
|
447
455
|
*
|
|
448
456
|
* An environment question carries `ENVIRONMENTS` as its candidates, so a caller
|
|
449
457
|
* reads the accepted values from the question instead of from the documentation.
|
|
@@ -511,12 +519,13 @@ export declare function blueprintToRootVite(blueprint: Blueprint): string;
|
|
|
511
519
|
* proofs every workspace can pass before it has a public API, and one build per
|
|
512
520
|
* target that actually builds.
|
|
513
521
|
*
|
|
514
|
-
* A
|
|
515
|
-
*
|
|
516
|
-
*
|
|
517
|
-
*
|
|
518
|
-
*
|
|
519
|
-
*
|
|
522
|
+
* A publishing workspace isolates distribution and live-service proofs from
|
|
523
|
+
* `test` and runs them from `prepublishOnly` instead. A private workspace has
|
|
524
|
+
* no publish lifecycle, so it omits distribution and runs a live-service proof
|
|
525
|
+
* from `test`. Integration and conformance stay in `test` because they neither
|
|
526
|
+
* pack nor install the workspace and drive no external service. A conformance
|
|
527
|
+
* run may start a server, but it starts its own and reaches it over loopback,
|
|
528
|
+
* so the run stays hermetic.
|
|
520
529
|
*
|
|
521
530
|
* The configuration paths interpolated here are the same ones `SRC_MATRIX` and
|
|
522
531
|
* `APP_MATRIX` list as each environment's configuration files, so a rename in
|
|
@@ -562,15 +571,14 @@ export declare function blueprintToSourceArtifacts(blueprint: Blueprint): readon
|
|
|
562
571
|
* Compile every artifact in the `tests` group that is not vendored from the host.
|
|
563
572
|
*
|
|
564
573
|
* @param blueprint - The workspace specification.
|
|
565
|
-
* @returns Shared setup modules, axis tests, and the optional
|
|
574
|
+
* @returns Shared setup modules, axis tests, and the optional integration seed.
|
|
566
575
|
*
|
|
567
576
|
* @remarks
|
|
568
577
|
* `tests/setupPolicy.ts`, `tests/policy.test.ts`, and `tests/config.test.ts` are
|
|
569
578
|
* fleet-invariant host artifacts and therefore do not appear here. A guide
|
|
570
579
|
* proof is not emitted while the workspace intentionally has empty barrels and
|
|
571
|
-
* no package guide. The
|
|
572
|
-
*
|
|
573
|
-
* flag.
|
|
580
|
+
* no package guide. The integration seed follows its structural flag and loads
|
|
581
|
+
* every selected environment through its public barrel.
|
|
574
582
|
*
|
|
575
583
|
* The conformance proof is not emitted either, for the reason the guide proof
|
|
576
584
|
* is not: it names an official artifact only the package knows, so a generated
|
|
@@ -1026,18 +1034,18 @@ export declare class Compiler implements CompilerInterface {
|
|
|
1026
1034
|
export declare const CONFIG_TEMPLATES: Readonly<{
|
|
1027
1035
|
root: Readonly<{
|
|
1028
1036
|
tsconfig: "{\n\t\"compilerOptions\": {\n\t\t\"target\": \"ESNext\",\n\t\t\"module\": \"ESNext\",\n\t\t\"moduleResolution\": \"bundler\",\n\t\t\"allowImportingTsExtensions\": true,\n\t\t\"lib\": [\"ESNext\", \"DOM\", \"DOM.Iterable\"],\n\t\t\"types\": [\"node\", \"vite/client\", \"vitest/globals\"],\n\t\t\"moduleDetection\": \"force\",\n\t\t\"resolveJsonModule\": true,\n\t\t\"strict\": true,\n\t\t\"verbatimModuleSyntax\": true,\n\t\t\"noUncheckedIndexedAccess\": true,\n\t\t\"noUncheckedSideEffectImports\": true,\n\t\t\"exactOptionalPropertyTypes\": true,\n\t\t\"noUnusedLocals\": true,\n\t\t\"noUnusedParameters\": true,\n\t\t\"noImplicitOverride\": true,\n\t\t\"noFallthroughCasesInSwitch\": true,\n\t\t\"forceConsistentCasingInFileNames\": true,\n\t\t\"skipLibCheck\": true,\n\t\t\"noEmit\": true,\n\t\t\"paths\": {\n{{paths}}\n\t\t}\n\t},\n\t\"exclude\": [\"node_modules\", \"dist\", \"tmp\"]\n}\n";
|
|
1029
|
-
vite: "import type { {{viteTypes}} } from 'vite'\n{{imports}}import { defineConfig, mergeConfig } from 'vitest/config'\nimport tsconfig from './tsconfig.json' with { type: 'json' }\n{{helpers}}{{browsers}}import {
|
|
1037
|
+
vite: "import type { {{viteTypes}} } from 'vite'\n{{imports}}import { defineConfig, mergeConfig } from 'vitest/config'\nimport tsconfig from './tsconfig.json' with { type: 'json' }\n{{helpers}}{{browsers}}import { fileURLToPath, URL } from 'node:url'\n\n{{options}}export function resolveWorkspacePath(relativePath: string): string {\n\treturn fileURLToPath(new URL(relativePath, import.meta.url))\n}\n\nconst resolve = {\n\talias: Object.entries(tsconfig.compilerOptions.paths).reduce((aliases, [key, values]) => {\n\t\tconst [path] = values\n\t\tif (path === undefined) throw new Error('tsconfig path alias ' + key + ' has no target')\n\t\treturn Object.assign(aliases, { [key]: resolveWorkspacePath(path) })\n\t}, {}),\n}\n\n{{factories}}export default defineConfig({\n\tresolve,\n\ttest: {\n{{projects}}\n\t},\n})\n";
|
|
1030
1038
|
}>;
|
|
1031
1039
|
factories: Readonly<{
|
|
1032
1040
|
src: Readonly<{
|
|
1033
1041
|
core: "export const srcCore = (options?: UserConfig): UserConfig =>\n\tmergeConfig(\n\t\t{\n\t\t\tresolve,\n\t\t\tpublicDir: false,\n\t\t\tbuild: {\n\t\t\t\temptyOutDir: true,\n\t\t\t\tsourcemap: true,\n\t\t\t\tminify: false,\n\t\t\t},\n\t\t\ttest: {\n\t\t\t\tname: { label: 'src:core', color: 'magenta' },\n\t\t\t\tinclude: ['tests/src/core/**/*.test.ts'],\n\t\t\t\tsetupFiles: ['./tests/setup.ts'],\n\t\t\t\tenvironment: 'node',\n\t\t\t\tbrowser: { enabled: false },\n\t\t\t},\n\t\t},\n\t\toptions ?? {},\n\t)\n";
|
|
1034
1042
|
browser: "export const srcBrowser = (options?: UserConfig): UserConfig =>\n\tmergeConfig(\n\t\t{\n\t\t\tresolve,\n\t\t\tpublicDir: false,\n\t\t\tplugins: [outputBoundary('dist/src/browser'), environmentBoundary('src/browser')],\n\t\t\tbuild: {\n\t\t\t\temptyOutDir: true,\n\t\t\t\tsourcemap: true,\n\t\t\t\tminify: false,\n\t\t\t\tlib: {\n\t\t\t\t\tentry: resolveWorkspacePath('src/browser/index.ts'),\n\t\t\t\t\tformats: ['es'],\n\t\t\t\t\tfileName: () => 'index.js',\n\t\t\t\t},\n\t\t\t\toutDir: 'dist/src/browser',\n\t\t\t\trolldownOptions: {\n\t\t\t\t\t{{external}}\n{{output}}\n\t\t\t\t},\n\t\t\t},\n\t\t\ttest: {\n\t\t\t\tname: { label: 'src:browser', color: 'yellow' },\n\t\t\t\tinclude: ['tests/src/browser/**/*.test.ts'],\n{{exclude}}\t\t\t\tsetupFiles: ['./tests/setup.ts', './tests/setupBrowser.ts'],\n{{global}}\n\t\t\t\tbrowser: {\n\t\t\t\t\tenabled: true,\n\t\t\t\t\tprovider: playwright(browserOptions),\n\t\t\t\t\tinstances: [{ browser: 'chromium', headless: true }],\n\t\t\t\t},\n\t\t\t\tfileParallelism: false,\n\t\t\t},\n\t\t},\n\t\toptions ?? {},\n\t)\n";
|
|
1035
1043
|
server: "export const srcServer = (options?: UserConfig): UserConfig =>\n\tmergeConfig(\n\t\t{\n\t\t\tresolve,\n\t\t\tpublicDir: false,\n\t\t\tplugins: [outputBoundary('dist/src/server'), environmentBoundary('src/server')],\n\t\t\tbuild: {\n\t\t\t\temptyOutDir: true,\n\t\t\t\tsourcemap: true,\n\t\t\t\tminify: false,\n\t\t\t\tlib: {\n\t\t\t\t\tentry: resolveWorkspacePath('src/server/index.ts'),\n\t\t\t\t\tformats: ['es', 'cjs'],\n\t\t\t\t\tfileName: (format: string) => (format === 'es' ? 'index.js' : 'index.cjs'),\n\t\t\t\t},\n\t\t\t\toutDir: 'dist/src/server',\n\t\t\t\ttarget: 'node22',\n\t\t\t\trolldownOptions: {\n\t\t\t\t\tplatform: 'node',\n\t\t\t\t\t{{external}}\n{{output}}\n\t\t\t\t},\n\t\t\t},\n\t\t\ttest: {\n\t\t\t\tname: { label: 'src:server', color: 'red' },\n\t\t\t\tinclude: ['tests/src/server/**/*.test.ts'],\n{{exclude}}\t\t\t\tsetupFiles: ['./tests/setup.ts', './tests/setupServer.ts'],\n\t\t\t\tenvironment: 'node',\n\t\t\t\tbrowser: { enabled: false },\n\t\t\t},\n\t\t},\n\t\toptions ?? {},\n\t)\n";
|
|
1036
|
-
bin: "export const srcBin = (options?: UserConfig): UserConfig =>\n\tmergeConfig(\n\t\t{\n\t\t\tresolve,\n\t\t\tpublicDir: false,\n\t\t\tplugins: [outputBoundary('dist/bin')],\n\t\t\tbuild: {\n\t\t\t\temptyOutDir: true,\n\t\t\t\tsourcemap: true,\n\t\t\t\tminify: false,\n\t\t\t\tlib: {\n\t\t\t\t\tentry: resolveWorkspacePath('src/bin/main.ts'),\n\t\t\t\t\tformats: ['es'],\n\t\t\t\t\tfileName: () => 'main.js',\n\t\t\t\t},\n\t\t\t\toutDir: 'dist/bin',\n\t\t\t\ttarget: 'node22',\n\t\t\t\trolldownOptions: { external: [/^node:/, /^@orkestrel\\//, /^@src\\//] },\n\t\t\t},\n\t\t\ttest: {\n\t\t\t\tname: { label: 'src:bin', color: 'yellow' },\n\t\t\t\tinclude: ['tests/src/bin/**/*.test.ts'],\n\t\t\t\tsetupFiles: ['./tests/setup.ts', './tests/setupServer.ts'],\n\t\t\t\tenvironment: 'node',\n\t\t\t\tbrowser: { enabled: false },\n\t\t\t},\n\t\t},\n\t\toptions ?? {},\n\t)\n";
|
|
1044
|
+
bin: "export const srcBin = (options?: UserConfig): UserConfig =>\n\tmergeConfig(\n\t\t{\n\t\t\tresolve,\n\t\t\tpublicDir: false,\n\t\t\tplugins: [outputBoundary('dist/bin')],\n\t\t\tbuild: {\n\t\t\t\temptyOutDir: true,\n\t\t\t\tsourcemap: true,\n\t\t\t\tminify: false,\n\t\t\t\tlib: {\n\t\t\t\t\tentry: resolveWorkspacePath('src/bin/main.ts'),\n\t\t\t\t\tformats: ['es'],\n\t\t\t\t\tfileName: () => 'main.js',\n\t\t\t\t},\n\t\t\t\toutDir: 'dist/bin',\n\t\t\t\ttarget: 'node22',\n\t\t\t\trolldownOptions: { external: [/^node:/, /^@orkestrel\\//, /^@src\\//] },\n\t\t\t},\n\t\t\ttest: {\n\t\t\t\tname: { label: 'src:bin', color: 'yellow' },\n\t\t\t\tinclude: ['tests/src/bin/**/*.test.ts'],\n\t\t\t\tsetupFiles: ['./tests/setup.ts', './tests/setupServer.ts'],\n\t\t\t\tenvironment: 'node',\n\t\t\t\tbrowser: { enabled: false },\n\t\t\t\t// A bin test drives the real executable over a real temporary repository, so it\n\t\t\t\t// spends seconds in process startup and filesystem work rather than milliseconds.\n\t\t\t\t// Vitest's five-second default clears one alone and times out under a full suite.\n\t\t\t\ttestTimeout: 15_000,\n\t\t\t},\n\t\t},\n\t\toptions ?? {},\n\t)\n";
|
|
1037
1045
|
}>;
|
|
1038
1046
|
app: Readonly<{
|
|
1039
1047
|
core: "export const appCore = (options?: UserConfig): UserConfig =>\n\tmergeConfig(\n\t\t{\n\t\t\tresolve,\n\t\t\tpublicDir: false,\n\t\t\tplugins: [environmentBoundary('app/core')],\n\t\t\ttest: {\n\t\t\t\tname: { label: 'app:core', color: 'cyan' },\n\t\t\t\tinclude: ['tests/app/core/**/*.test.ts'],\n\t\t\t\tsetupFiles: ['./tests/setup.ts'],\n\t\t\t\tenvironment: 'node',\n\t\t\t\tbrowser: { enabled: false },\n\t\t\t},\n\t\t},\n\t\toptions ?? {},\n\t)\n";
|
|
1040
|
-
browser: "function applicationBrowser(showcase: boolean): UserConfig {\n\tconst output = showcase ? 'dist/showcase' : 'dist/app/browser'\n{{showcasePlugins}}\treturn {\n\t\tresolve,\n{{plugins}}\t\troot: resolveWorkspacePath('app/browser'),\n\t\tpublicDir: false,\n\t\tbuild: {\n{{showcaseBuild}}\t\t\temptyOutDir: true,\n\t\t\toutDir: resolveWorkspacePath(output),\n\t\t\trolldownOptions: { input: resolveWorkspacePath('app/browser/index.html') },\n\t\t},\n\t\ttest: {\n\t\t\tname: { label: 'app:browser', color: 'blue' },\n\t\t\troot: resolveWorkspacePath('.'),\n\t\t\tdir: resolveWorkspacePath('.'),\n\t\t\tinclude: ['tests/app/browser/**/*.test.ts'],\n\t\t\tsetupFiles: ['./tests/setup.ts', './tests/setupBrowser.ts'],\n\t\t\tbrowser: {\n\t\t\t\tenabled: true,\n\t\t\t\tprovider: playwright(browserOptions),\n\t\t\t\tinstances: [{ browser: 'chromium', headless: true }],\n\t\t\t},\n\t\t\tfileParallelism: false,\n\t\t},\n\t}\n}\n\nexport function appBrowser(
|
|
1048
|
+
browser: "function applicationBrowser(showcase: boolean): UserConfig {\n\tconst output = showcase ? 'dist/showcase' : 'dist/app/browser'\n{{showcasePlugins}}\treturn {\n\t\tresolve,\n{{plugins}}\t\troot: resolveWorkspacePath('app/browser'),\n\t\tpublicDir: false,\n\t\tbuild: {\n{{showcaseBuild}}\t\t\temptyOutDir: true,\n\t\t\toutDir: resolveWorkspacePath(output),\n\t\t\trolldownOptions: { input: resolveWorkspacePath('app/browser/index.html') },\n\t\t},\n\t\ttest: {\n\t\t\tname: { label: 'app:browser', color: 'blue' },\n\t\t\troot: resolveWorkspacePath('.'),\n\t\t\tdir: resolveWorkspacePath('.'),\n\t\t\tinclude: ['tests/app/browser/**/*.test.ts'],\n\t\t\tsetupFiles: ['./tests/setup.ts', './tests/setupBrowser.ts'],\n\t\t\tbrowser: {\n\t\t\t\tenabled: true,\n\t\t\t\tprovider: playwright(browserOptions),\n\t\t\t\tinstances: [{ browser: 'chromium', headless: true }],\n\t\t\t},\n\t\t\tfileParallelism: false,\n\t\t},\n\t}\n}\n\nexport function appBrowser(): UserConfig {\n\treturn applicationBrowser(false)\n}\n{{showcaseFactory}}";
|
|
1041
1049
|
server: "export const appServer = (options?: UserConfig): UserConfig =>\n\tmergeConfig(\n\t\t{\n\t\t\tresolve,\n\t\t\tpublicDir: false,\n\t\t\tplugins: [outputBoundary('dist/app/server'), environmentBoundary('app/server')],\n\t\t\tbuild: {\n\t\t\t\temptyOutDir: true,\n\t\t\t\tlib: {\n\t\t\t\t\tentry: resolveWorkspacePath('app/server/main.ts'),\n\t\t\t\t\tformats: ['cjs'],\n\t\t\t\t\tfileName: () => 'main.cjs',\n\t\t\t\t},\n\t\t\t\toutDir: resolveWorkspacePath('dist/app/server'),\n\t\t\t\ttarget: 'node22',\n\t\t\t\trolldownOptions: { external: (id: string) => id.startsWith('node:') },\n\t\t\t},\n\t\t\ttest: {\n\t\t\t\tname: { label: 'app:server', color: 'green' },\n\t\t\t\tinclude: ['tests/app/server/**/*.test.ts'],\n\t\t\t\tsetupFiles: ['./tests/setup.ts', './tests/setupServer.ts'],\n\t\t\t\tenvironment: 'node',\n\t\t\t\tbrowser: { enabled: false },\n\t\t\t},\n\t\t},\n\t\toptions ?? {},\n\t)\n";
|
|
1042
1050
|
}>;
|
|
1043
1051
|
policy: "export const policy = (options?: UserConfig): UserConfig =>\n\tmergeConfig(\n\t\t{\n\t\t\tresolve,\n\t\t\ttest: {\n\t\t\t\tname: { label: 'policy', color: 'white' },\n\t\t\t\tinclude: ['tests/policy.test.ts'],\n\t\t\t\tsetupFiles: ['./tests/setup.ts'],\n\t\t\t\tenvironment: 'node',\n\t\t\t\tbrowser: { enabled: false },\n\t\t\t},\n\t\t},\n\t\toptions ?? {},\n\t)\n";
|
|
@@ -1045,8 +1053,9 @@ export declare class Compiler implements CompilerInterface {
|
|
|
1045
1053
|
guides: "export const guides = (options?: UserConfig): UserConfig =>\n\tmergeConfig(\n\t\t{\n\t\t\tresolve,\n\t\t\ttest: {\n\t\t\t\tname: { label: 'guides', color: 'green' },\n\t\t\t\tinclude: ['tests/guides.test.ts'],\n\t\t\t\texclude: ['tests/src/**/*.test.ts', 'tests/app/**/*.test.ts', 'tests/setup.test.ts'],\n\t\t\t\tsetupFiles: ['./tests/setup.ts'],\n\t\t\t\tenvironment: 'node',\n\t\t\t\tbrowser: { enabled: false },\n\t\t\t},\n\t\t},\n\t\toptions ?? {},\n\t)\n";
|
|
1046
1054
|
conformance: "// Where this package drifts from the official tooling it stays compatible with.\n// The subject is this package, so the proof is hermetic and stays in `npm test`.\nexport const conformance = (options?: UserConfig): UserConfig =>\n\tmergeConfig(\n\t\t{\n\t\t\tresolve,\n\t\t\ttest: {\n\t\t\t\tname: { label: 'conformance', color: 'magenta' },\n\t\t\t\tinclude: ['tests/conformance.test.ts'],\n\t\t\t\tsetupFiles: ['./tests/setup.ts'],\n\t\t\t\tenvironment: 'node',\n\t\t\t\tbrowser: { enabled: false },\n\t\t\t},\n\t\t},\n\t\toptions ?? {},\n\t)\n";
|
|
1047
1055
|
service: "// The live external services this package drives. It starts nothing itself:\n// `scripts/service.sh` provisions, `tests/setupService.ts` proves readiness, and\n// the project stays out of `npm test` because a real service answers it.\nexport const service = (options?: UserConfig): UserConfig =>\n\tmergeConfig(\n\t\t{\n\t\t\tresolve,\n\t\t\ttest: {\n\t\t\t\tname: { label: 'service', color: 'red' },\n\t\t\t\tinclude: ['tests/service/**/*.test.ts'],\n\t\t\t\tsetupFiles: ['./tests/setup.ts', './tests/setupService.ts'],\n\t\t\t\tenvironment: 'node',\n\t\t\t\tbrowser: { enabled: false },\n\t\t\t\ttestTimeout: 120_000,\n\t\t\t\thookTimeout: 120_000,\n\t\t\t\tfileParallelism: false,\n\t\t\t},\n\t\t},\n\t\toptions ?? {},\n\t)\n";
|
|
1056
|
+
distribution: "export const distribution = (options?: UserConfig): UserConfig =>\n\tmergeConfig(\n\t\t{\n\t\t\tresolve,\n\t\t\ttest: {\n\t\t\t\tname: { label: 'distribution', color: 'cyan' },\n\t\t\t\tinclude: ['tests/distribution.test.ts'],\n\t\t\t\tsetupFiles: ['./tests/setup.ts'],\n\t\t\t\tenvironment: 'node',\n\t\t\t\ttestTimeout: 120_000,\n\t\t\t\thookTimeout: 120_000,\n\t\t\t\tfileParallelism: false,\n\t\t\t},\n\t\t},\n\t\toptions ?? {},\n\t)\n";
|
|
1048
1057
|
probe: "// A workbench, not a proof. No gate selects this project.\nexport const probe = (options?: UserConfig): UserConfig =>\n\tmergeConfig(\n\t\t{\n\t\t\tresolve,\n\t\t\ttest: {\n\t\t\t\tname: { label: 'probe', color: 'gray' },\n\t\t\t\tinclude: ['tmp/probe/**/*.test.ts'],\n\t\t\t\tsetupFiles: ['./tests/setup.ts'],\n\t\t\t\tenvironment: 'node',\n\t\t\t\tbrowser: { enabled: false },\n\t\t\t},\n\t\t},\n\t\toptions ?? {},\n\t)\n";
|
|
1049
|
-
integration: "export const integration = (options?: UserConfig): UserConfig =>\n\tmergeConfig(\n\t\t{\n\t\t\tresolve,\n\t\t\ttest: {\n\t\t\t\tname: { label: 'integration', color: 'blue' },\n\t\t\t\tinclude: ['tests/integration.test.ts'],\n\t\t\t\tsetupFiles: ['./tests/setup.ts'],\n{{global}}\t\t\t\tenvironment: 'node',\n\t\t\t
|
|
1058
|
+
integration: "export const integration = (options?: UserConfig): UserConfig =>\n\tmergeConfig(\n\t\t{\n\t\t\tresolve,\n\t\t\ttest: {\n\t\t\t\tname: { label: 'integration', color: 'blue' },\n\t\t\t\tinclude: ['tests/integration.test.ts'],\n\t\t\t\tsetupFiles: ['./tests/setup.ts'],\n{{global}}\t\t\t\tenvironment: 'node',\n\t\t\t},\n\t\t},\n\t\toptions ?? {},\n\t)\n";
|
|
1050
1059
|
}>;
|
|
1051
1060
|
tsconfigs: Readonly<{
|
|
1052
1061
|
src: Readonly<{
|
|
@@ -1169,6 +1178,9 @@ export declare class Compiler implements CompilerInterface {
|
|
|
1169
1178
|
*/
|
|
1170
1179
|
export declare function createCompiler(options?: CompilerOptions): CompilerInterface;
|
|
1171
1180
|
|
|
1181
|
+
/** The development dependencies that emit declarations for published source or an executable. */
|
|
1182
|
+
export declare const DECLARATION_DEV_DEPENDENCIES: Readonly<Record<string, string>>;
|
|
1183
|
+
|
|
1172
1184
|
/** The `engines.node` range a workspace starts with. */
|
|
1173
1185
|
export declare const DEFAULT_ENGINES = ">=22.12.0";
|
|
1174
1186
|
|
|
@@ -1235,6 +1247,9 @@ export declare class Compiler implements CompilerInterface {
|
|
|
1235
1247
|
*/
|
|
1236
1248
|
export declare const DEPENDENCY_NAME_PATTERN: RegExp;
|
|
1237
1249
|
|
|
1250
|
+
/** The packed-package proof whose presence makes a workspace `distribution`. */
|
|
1251
|
+
export declare const DISTRIBUTION_TEST_PATH = "tests/distribution.test.ts";
|
|
1252
|
+
|
|
1238
1253
|
/**
|
|
1239
1254
|
* How one target path compares to the artifact planned for it.
|
|
1240
1255
|
*
|
|
@@ -1385,7 +1400,7 @@ export declare class Compiler implements CompilerInterface {
|
|
|
1385
1400
|
*/
|
|
1386
1401
|
export declare const GROUPS: readonly Group[];
|
|
1387
1402
|
|
|
1388
|
-
/** The guide-parity proof whose
|
|
1403
|
+
/** The guide-parity proof whose presence selects the planned `guides` project. */
|
|
1389
1404
|
export declare const GUIDES_TEST_PATH = "tests/guides.test.ts";
|
|
1390
1405
|
|
|
1391
1406
|
/** Exact lowercase hexadecimal bytes: two digits per byte, and empty content is valid. */
|
|
@@ -1416,7 +1431,9 @@ export declare class Compiler implements CompilerInterface {
|
|
|
1416
1431
|
* exist. That is why the ownership here is narrowed away from `content`: a
|
|
1417
1432
|
* claim over bytes nobody has read is a claim that cannot be checked. Reading
|
|
1418
1433
|
* the vendored root turns the ones scaffold owns the bytes of into
|
|
1419
|
-
* {@link HydratedArtifact}.
|
|
1434
|
+
* {@link HydratedArtifact}. Workspace-owned paths and paths whose bytes belong
|
|
1435
|
+
* to another verb stay plain host artifacts, because this writer claims only
|
|
1436
|
+
* their presence.
|
|
1420
1437
|
*/
|
|
1421
1438
|
export declare interface HostArtifact extends ArtifactBase {
|
|
1422
1439
|
readonly origin: 'host';
|
|
@@ -1508,7 +1525,7 @@ export declare class Compiler implements CompilerInterface {
|
|
|
1508
1525
|
*/
|
|
1509
1526
|
export declare function inferGroup(path: string): Group;
|
|
1510
1527
|
|
|
1511
|
-
/** The
|
|
1528
|
+
/** The cross-environment composition proof whose presence makes a workspace `integration`. */
|
|
1512
1529
|
export declare const INTEGRATION_TEST_PATH = "tests/integration.test.ts";
|
|
1513
1530
|
|
|
1514
1531
|
/** Visible characters a target-relative path and a Markdown path cell both forbid. */
|
|
@@ -1962,6 +1979,29 @@ export declare class Compiler implements CompilerInterface {
|
|
|
1962
1979
|
*/
|
|
1963
1980
|
export declare function matchesOrchestrationPath(path: string): boolean;
|
|
1964
1981
|
|
|
1982
|
+
/**
|
|
1983
|
+
* Test whether one emitted line fits the vendored formatter width.
|
|
1984
|
+
*
|
|
1985
|
+
* @param line - One emitted line, leading tabs included.
|
|
1986
|
+
* @returns `true` when the expanded line fits.
|
|
1987
|
+
*
|
|
1988
|
+
* @remarks
|
|
1989
|
+
* A generator writes source the formatter then reads back, so a line packed
|
|
1990
|
+
* past the vendored width is rewrapped on the next `format` run and the emitted
|
|
1991
|
+
* bytes stop matching the plan the audit compares against. The generator
|
|
1992
|
+
* therefore measures a candidate line and chooses the shape the formatter would
|
|
1993
|
+
* have chosen. Tabs are expanded first because the formatter counts them as
|
|
1994
|
+
* `TAB_WIDTH` columns rather than as one character.
|
|
1995
|
+
*
|
|
1996
|
+
* @example
|
|
1997
|
+
* ```ts
|
|
1998
|
+
* import { matchesPrintWidth } from '@orkestrel/scaffold'
|
|
1999
|
+
*
|
|
2000
|
+
* matchesPrintWidth('\t\tprojects: [core],') // true
|
|
2001
|
+
* ```
|
|
2002
|
+
*/
|
|
2003
|
+
export declare function matchesPrintWidth(line: string): boolean;
|
|
2004
|
+
|
|
1965
2005
|
/**
|
|
1966
2006
|
* Test whether a declared range already admits a published version.
|
|
1967
2007
|
*
|
|
@@ -2470,6 +2510,9 @@ export declare class Compiler implements CompilerInterface {
|
|
|
2470
2510
|
*/
|
|
2471
2511
|
export declare function planToSummary(plan: Plan): PlanSummary;
|
|
2472
2512
|
|
|
2513
|
+
/** Columns one emitted line may occupy, matching `printWidth` in `.oxfmtrc.json`. */
|
|
2514
|
+
export declare const PRINT_WIDTH = 100;
|
|
2515
|
+
|
|
2473
2516
|
/**
|
|
2474
2517
|
* One validation issue raised against a blueprint or a plan.
|
|
2475
2518
|
*
|
|
@@ -2771,6 +2814,9 @@ export declare class Compiler implements CompilerInterface {
|
|
|
2771
2814
|
*/
|
|
2772
2815
|
export declare function srcToRoot(src: readonly Environment[]): Environment | undefined;
|
|
2773
2816
|
|
|
2817
|
+
/** Columns one tab occupies when the formatter measures a line, matching `tabWidth`. */
|
|
2818
|
+
export declare const TAB_WIDTH = 2;
|
|
2819
|
+
|
|
2774
2820
|
/** The exact three-component version syntax a blueprint declares. */
|
|
2775
2821
|
export declare const VERSION_PATTERN: RegExp;
|
|
2776
2822
|
|
|
@@ -2793,4 +2839,15 @@ export declare class Compiler implements CompilerInterface {
|
|
|
2793
2839
|
readonly showcase: boolean;
|
|
2794
2840
|
}
|
|
2795
2841
|
|
|
2842
|
+
/**
|
|
2843
|
+
* The vendored paths whose present bytes belong to each workspace, frozen.
|
|
2844
|
+
*
|
|
2845
|
+
* @remarks
|
|
2846
|
+
* These paths are copied into a workspace when absent and are never compared
|
|
2847
|
+
* or replaced while present. A workspace therefore stops receiving later
|
|
2848
|
+
* canonical updates to them. `.gitignore` takes that trade because its correct
|
|
2849
|
+
* rules differ by workspace, so scaffold cannot own its bytes.
|
|
2850
|
+
*/
|
|
2851
|
+
export declare const WORKSPACE_OWNED_PATHS: readonly string[];
|
|
2852
|
+
|
|
2796
2853
|
export { }
|