@orkestrel/scaffold 0.0.103 → 0.0.104
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/agents/skills/orkestrel-dispatch/scripts/helpers.js +84 -1
- package/dist/agents/skills/orkestrel-dispatch/scripts/launch.js +21 -6
- package/dist/agents/skills/orkestrel-harden/scripts/titles.js +338 -0
- package/dist/agents/skills/orkestrel-publish/scripts/swap.js +3 -39
- package/dist/agents/skills/orkestrel-publish/scripts/wave.js +433 -47
- package/dist/agents/skills/orkestrel-publish/scripts/window.js +2 -1
- package/dist/bin/main.js +16 -9
- package/dist/bin/main.js.map +1 -1
- package/dist/host/agents/orchestration.md +3 -3
- package/dist/host/agents/skills/enterprise-bootstrap/references/components.md +2 -2
- package/dist/host/agents/skills/enterprise-bootstrap/references/inspection.md +1 -1
- package/dist/host/agents/skills/orkestrel-build/SKILL.md +2 -2
- package/dist/host/agents/skills/orkestrel-debrief/SKILL.md +2 -2
- package/dist/host/agents/skills/orkestrel-debrief/references/field-testing.md +1 -1
- package/dist/host/agents/skills/orkestrel-debrief/references/instruction-audit.md +3 -3
- package/dist/host/agents/skills/orkestrel-dispatch/SKILL.md +10 -10
- package/dist/host/agents/skills/orkestrel-dispatch/references/launch.md +1 -0
- package/dist/host/agents/skills/orkestrel-dispatch/scripts/helpers.ts +100 -1
- package/dist/host/agents/skills/orkestrel-dispatch/scripts/launch.ts +27 -6
- package/dist/host/agents/skills/orkestrel-falsify/SKILL.md +4 -4
- package/dist/host/agents/skills/orkestrel-falsify/agents/openai.yaml +1 -1
- package/dist/host/agents/skills/orkestrel-falsify/references/brief.md +8 -7
- package/dist/host/agents/skills/orkestrel-falsify/references/reconcile.md +6 -6
- package/dist/host/agents/skills/orkestrel-harden/SKILL.md +6 -1
- package/dist/host/agents/skills/orkestrel-harden/references/bindings.md +1700 -0
- package/dist/host/agents/skills/orkestrel-harden/references/contract.md +2 -2
- package/dist/host/agents/skills/orkestrel-harden/references/equivalence.md +48 -0
- package/dist/host/agents/skills/orkestrel-harden/references/hardening.md +4 -2
- package/dist/host/agents/skills/orkestrel-harden/scripts/titles.ts +425 -0
- package/dist/host/agents/skills/orkestrel-journey/SKILL.md +2 -2
- package/dist/host/agents/skills/orkestrel-journey/references/captures.md +9 -8
- package/dist/host/agents/skills/orkestrel-polish/SKILL.md +3 -3
- package/dist/host/agents/skills/orkestrel-publish/SKILL.md +2 -2
- package/dist/host/agents/skills/orkestrel-publish/references/release.md +1 -0
- package/dist/host/agents/skills/orkestrel-publish/references/wave.md +56 -13
- package/dist/host/agents/skills/orkestrel-publish/references/window.md +6 -6
- package/dist/host/agents/skills/orkestrel-publish/scripts/swap.ts +5 -49
- package/dist/host/agents/skills/orkestrel-publish/scripts/wave.ts +646 -49
- package/dist/host/agents/skills/orkestrel-publish/scripts/window.ts +2 -1
- package/dist/host/agents/transports/codex.md +1 -1
- package/dist/host/claude/agents/orkestrel.md +54 -53
- package/dist/host/claude/agents/reviewer.md +4 -4
- package/dist/host/claude/rules/documentation.md +2 -1
- package/dist/host/claude/rules/patterns.md +1 -1
- package/dist/host/claude/rules/quality.md +2 -2
- package/dist/host/claude/rules/styles.md +1 -1
- package/dist/host/claude/rules/tests.md +34 -8
- package/dist/host/claude/rules/typescript.md +29 -0
- package/dist/host/claude/rules/workspace.md +32 -22
- package/dist/host/claude/rules/writing.md +34 -26
- package/dist/host/claude/settings.json +2 -0
- package/dist/host/claude/skills/orkestrel-debrief/SKILL.md +1 -1
- package/dist/host/claude/skills/orkestrel-falsify/SKILL.md +1 -1
- package/dist/host/codex/agents/analyst.toml +3 -3
- package/dist/host/codex/agents/reviewer.toml +4 -4
- package/dist/host/configs/policy.ts +13 -2
- package/dist/host/dotfiles/editorconfig +0 -1
- package/dist/host/dotfiles/gitattributes +0 -1
- package/dist/host/dotfiles/gitignore +0 -1
- package/dist/host/dotfiles/oxlintrc.json +24 -0
- package/dist/host/guides/agent.md +1638 -598
- package/dist/host/guides/budget.md +89 -29
- package/dist/host/guides/form.md +477 -91
- package/dist/host/guides/mcp.md +14 -2
- package/dist/host/guides/ollama.md +97 -73
- package/dist/host/guides/probe.md +1 -1
- package/dist/host/guides/scaffold.md +158 -101
- package/dist/host/guides/study.md +2635 -0
- package/dist/host/guides/table.md +225 -15
- package/dist/host/guides/terminal.md +22 -20
- package/dist/host/guides/test.md +689 -255
- package/dist/host/manifest.json +87 -63
- package/dist/host/tests/config.test.ts +136 -82
- package/dist/host/tests/policy.test.ts +39 -1
- package/dist/host/tests/setupPolicy.ts +86 -28
- package/dist/src/core/index.cjs +1387 -611
- package/dist/src/core/index.cjs.map +1 -1
- package/dist/src/core/index.d.cts +35 -20
- package/dist/src/core/index.d.ts +35 -20
- package/dist/src/core/index.js +1385 -612
- package/dist/src/core/index.js.map +1 -1
- package/dist/src/server/index.cjs +12 -12
- package/dist/src/server/index.cjs.map +1 -1
- package/dist/src/server/index.d.cts +12 -12
- package/dist/src/server/index.d.ts +12 -12
- package/dist/src/server/index.js +12 -12
- package/dist/src/server/index.js.map +1 -1
- package/package.json +4 -4
|
@@ -323,16 +323,27 @@ describe('selected faces', () => {
|
|
|
323
323
|
}
|
|
324
324
|
const script =
|
|
325
325
|
'vite build --config configs/src/vite.styles.config.ts && vite build --config configs/src/vite.themes.config.ts'
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
)
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
inspectSheetConfiguration(
|
|
335
|
-
|
|
326
|
+
const scratch = createPolicyScratch({ prefix: 'config-sheet-setup-' })
|
|
327
|
+
const withoutStyles = {
|
|
328
|
+
test: { ...project.test, setupFiles: ['./tests/setup.ts', './tests/setupBrowser.ts'] },
|
|
329
|
+
}
|
|
330
|
+
try {
|
|
331
|
+
expect(inspectSheetConfiguration(withoutStyles, script, scratch.path)).toEqual([])
|
|
332
|
+
scratch.write('tests/setupStyles.ts', 'export {}\n')
|
|
333
|
+
expect(inspectSheetConfiguration(project, script, scratch.path)).toEqual([])
|
|
334
|
+
expect(inspectSheetConfiguration(withoutStyles, script, scratch.path)).toContain(
|
|
335
|
+
'./tests/setupStyles.ts',
|
|
336
|
+
)
|
|
337
|
+
expect(
|
|
338
|
+
inspectSheetConfiguration(
|
|
339
|
+
project,
|
|
340
|
+
script.split(' && ').reverse().join(' && '),
|
|
341
|
+
scratch.path,
|
|
342
|
+
),
|
|
343
|
+
).toContain('themes order')
|
|
344
|
+
} finally {
|
|
345
|
+
scratch.destroy()
|
|
346
|
+
}
|
|
336
347
|
})
|
|
337
348
|
|
|
338
349
|
it('resolves showcase and journey modes for every occupied application', async () => {
|
|
@@ -707,19 +718,24 @@ describe('root configuration', () => {
|
|
|
707
718
|
)
|
|
708
719
|
.filter(([, path]) => existsSync(resolve(POLICY_ROOT, path)))
|
|
709
720
|
.map(([label, , include, setup]): [string, PolicyProject] => [label, { include, setup }]),
|
|
710
|
-
...['policy', 'config', 'guides', 'conformance', 'distribution', 'integration']
|
|
711
|
-
.filter((label) =>
|
|
721
|
+
...['policy', 'config', 'guides', 'conformance', 'tree', 'distribution', 'integration']
|
|
722
|
+
.filter((label) => readdirSync(resolve(POLICY_ROOT, 'tests')).includes(`${label}.test.ts`))
|
|
712
723
|
.map((label): [string, PolicyProject] => [
|
|
713
724
|
label,
|
|
714
725
|
{
|
|
715
726
|
include: `tests/${label}.test.ts`,
|
|
716
727
|
setup: [
|
|
717
728
|
'./tests/setup.ts',
|
|
718
|
-
...(label === 'conformance' ? ['./tests/setupServer.ts'] : []),
|
|
729
|
+
...(label === 'conformance' || label === 'tree' ? ['./tests/setupServer.ts'] : []),
|
|
719
730
|
...(label === 'integration' &&
|
|
720
731
|
(collectSheets(POLICY_ROOT).length > 0 ||
|
|
721
732
|
existsSync(resolve(POLICY_ROOT, 'src/styles/themes/index.scss')))
|
|
722
|
-
? [
|
|
733
|
+
? [
|
|
734
|
+
'./tests/setupBrowser.ts',
|
|
735
|
+
...(existsSync(resolve(POLICY_ROOT, 'tests/setupStyles.ts'))
|
|
736
|
+
? ['./tests/setupStyles.ts']
|
|
737
|
+
: []),
|
|
738
|
+
]
|
|
723
739
|
: []),
|
|
724
740
|
],
|
|
725
741
|
},
|
|
@@ -910,8 +926,8 @@ describe('root configuration', () => {
|
|
|
910
926
|
// before its result is read. Extra factories are ignored without validating their result shape.
|
|
911
927
|
expect(extraLoads).toStrictEqual([])
|
|
912
928
|
for (const [label, project] of expected) expect(configured.get(label)).toStrictEqual(project)
|
|
913
|
-
for (const label of ['setup', 'setup:browser']) {
|
|
914
|
-
const name = label === 'setup' ? '
|
|
929
|
+
for (const label of ['setup', 'setup:browser', 'tree']) {
|
|
930
|
+
const name = label === 'setup:browser' ? 'setupBrowser' : label
|
|
915
931
|
expect(projects.some((entry) => typeof entry === 'function' && entry.name === name)).toBe(
|
|
916
932
|
expected.has(label),
|
|
917
933
|
)
|
|
@@ -1281,6 +1297,7 @@ describe('root configuration', () => {
|
|
|
1281
1297
|
const distribution = Object.getOwnPropertyDescriptor(scripts, 'test:distribution')?.value
|
|
1282
1298
|
const integration = Object.getOwnPropertyDescriptor(scripts, 'test:integration')?.value
|
|
1283
1299
|
const conformance = Object.getOwnPropertyDescriptor(scripts, 'test:conformance')?.value
|
|
1300
|
+
const tree = Object.getOwnPropertyDescriptor(scripts, 'test:tree')?.value
|
|
1284
1301
|
const service = Object.getOwnPropertyDescriptor(scripts, 'test:service')?.value
|
|
1285
1302
|
const studies = Object.getOwnPropertyDescriptor(scripts, 'test:studies')?.value
|
|
1286
1303
|
const publish = Object.getOwnPropertyDescriptor(scripts, 'prepublishOnly')?.value
|
|
@@ -1307,6 +1324,7 @@ describe('root configuration', () => {
|
|
|
1307
1324
|
expect(registered.has('config')).toBe(true)
|
|
1308
1325
|
expect(registered.has('control')).toBe(false)
|
|
1309
1326
|
const hasConformance = registered.has('conformance')
|
|
1327
|
+
const hasTree = registered.has('tree')
|
|
1310
1328
|
const hasDistribution = registered.has('distribution')
|
|
1311
1329
|
const hasService = registered.has('service')
|
|
1312
1330
|
const hasStudies = registered.has('studies')
|
|
@@ -1349,6 +1367,13 @@ describe('root configuration', () => {
|
|
|
1349
1367
|
expect(typeof test === 'string' && test.includes('npm run test:conformance')).toBe(
|
|
1350
1368
|
hasConformance,
|
|
1351
1369
|
)
|
|
1370
|
+
expect(tree).toBe(
|
|
1371
|
+
hasTree
|
|
1372
|
+
? 'vitest run --config vite.config.ts --no-cache --reporter=dot --project tree'
|
|
1373
|
+
: undefined,
|
|
1374
|
+
)
|
|
1375
|
+
expect(typeof test === 'string' && test.includes('npm run test:tree')).toBe(hasTree)
|
|
1376
|
+
expect(typeof publish === 'string' && publish.includes('npm run test:tree')).toBe(false)
|
|
1352
1377
|
expect(service).toBe(
|
|
1353
1378
|
hasService
|
|
1354
1379
|
? 'vitest run --config vite.config.ts --no-cache --reporter=dot --project service'
|
|
@@ -2916,72 +2941,89 @@ createSomething({
|
|
|
2916
2941
|
const pattern = readConfigRecord(patternValue)
|
|
2917
2942
|
const message = pattern.message
|
|
2918
2943
|
if (typeof message !== 'string') throw new Error('Missing pattern message')
|
|
2919
|
-
const
|
|
2920
|
-
|
|
2921
|
-
|
|
2922
|
-
['data:text/plain,x', true],
|
|
2923
|
-
['node:fs', false],
|
|
2924
|
-
['n:entry', true],
|
|
2925
|
-
['no:entry', true],
|
|
2926
|
-
['nod:entry', true],
|
|
2927
|
-
['nodea:entry', true],
|
|
2928
|
-
['1bad:entry', false],
|
|
2929
|
-
['./data:entry', false],
|
|
2930
|
-
]
|
|
2931
|
-
: message.includes('noncanonical dot')
|
|
2944
|
+
const alias = /@src\/(core|browser|server) alias/u.exec(message)?.[1]
|
|
2945
|
+
const listed: ReadonlyArray<readonly [string, boolean]> =
|
|
2946
|
+
alias !== undefined
|
|
2932
2947
|
? [
|
|
2933
|
-
[
|
|
2934
|
-
[
|
|
2935
|
-
[
|
|
2936
|
-
[
|
|
2937
|
-
[
|
|
2938
|
-
[
|
|
2939
|
-
[
|
|
2948
|
+
[`../${alias}/index.js`, true],
|
|
2949
|
+
[`../../${alias}/types.js`, true],
|
|
2950
|
+
[`../../src/${alias}/index.js`, true],
|
|
2951
|
+
[`../${alias}`, true],
|
|
2952
|
+
[`../${alias}/`, true],
|
|
2953
|
+
[`../${alias}?raw`, true],
|
|
2954
|
+
[`../${alias}#fragment`, true],
|
|
2955
|
+
[`@src/${alias}`, false],
|
|
2956
|
+
[`./${alias}/index.js`, false],
|
|
2957
|
+
[`../${alias}x/index.js`, false],
|
|
2958
|
+
[`../${alias}.ext/index.js`, false],
|
|
2940
2959
|
]
|
|
2941
|
-
: message.includes('
|
|
2960
|
+
: message.includes('URL schemes')
|
|
2942
2961
|
? [
|
|
2943
|
-
['
|
|
2944
|
-
['
|
|
2945
|
-
['
|
|
2946
|
-
['
|
|
2947
|
-
['
|
|
2948
|
-
['
|
|
2949
|
-
['
|
|
2950
|
-
['
|
|
2951
|
-
['
|
|
2952
|
-
['../src/print/index.js', true],
|
|
2953
|
-
['../browser?x', true],
|
|
2954
|
-
['../print.ext/index.js', false],
|
|
2955
|
-
...(Array.isArray(block.files) &&
|
|
2956
|
-
block.files.some(
|
|
2957
|
-
(file: unknown) => typeof file === 'string' && file.startsWith('app/vue/'),
|
|
2958
|
-
)
|
|
2959
|
-
? [['@app/print', true] as const]
|
|
2960
|
-
: []),
|
|
2961
|
-
]
|
|
2962
|
-
: [
|
|
2963
|
-
[
|
|
2964
|
-
message.includes('absolute paths')
|
|
2965
|
-
? '/machine/module.js'
|
|
2966
|
-
: message.includes('normalized traversal')
|
|
2967
|
-
? './../core/index.js'
|
|
2968
|
-
: message.includes('forward slashes')
|
|
2969
|
-
? '..\\core\\index.js'
|
|
2970
|
-
: message.includes('compiler API')
|
|
2971
|
-
? 'typescript'
|
|
2972
|
-
: message.includes('private app')
|
|
2973
|
-
? '@app/core'
|
|
2974
|
-
: message.includes('stylesheets')
|
|
2975
|
-
? './index.css'
|
|
2976
|
-
: message.includes('host-independent') ||
|
|
2977
|
-
message.includes('Node or server')
|
|
2978
|
-
? 'node:fs'
|
|
2979
|
-
: message.includes('Vue extension')
|
|
2980
|
-
? '@src/vue'
|
|
2981
|
-
: '@src/browser',
|
|
2982
|
-
true,
|
|
2983
|
-
],
|
|
2962
|
+
['https://host/x', true],
|
|
2963
|
+
['data:text/plain,x', true],
|
|
2964
|
+
['node:fs', false],
|
|
2965
|
+
['n:entry', true],
|
|
2966
|
+
['no:entry', true],
|
|
2967
|
+
['nod:entry', true],
|
|
2968
|
+
['nodea:entry', true],
|
|
2969
|
+
['1bad:entry', false],
|
|
2970
|
+
['./data:entry', false],
|
|
2984
2971
|
]
|
|
2972
|
+
: message.includes('noncanonical dot')
|
|
2973
|
+
? [
|
|
2974
|
+
['../core/../server/index.js', true],
|
|
2975
|
+
['../core/./index.js', true],
|
|
2976
|
+
['../core/index.js', false],
|
|
2977
|
+
['./index.js', false],
|
|
2978
|
+
['../../core/index.js', false],
|
|
2979
|
+
['.../../index.js', true],
|
|
2980
|
+
['.name/../index.js', true],
|
|
2981
|
+
]
|
|
2982
|
+
: message.includes('sibling sheet')
|
|
2983
|
+
? [
|
|
2984
|
+
['@src/print', true],
|
|
2985
|
+
['../print/index.js', true],
|
|
2986
|
+
['@src/core', false],
|
|
2987
|
+
['@src/browser', false],
|
|
2988
|
+
['@src/vue', false],
|
|
2989
|
+
['@app/core', false],
|
|
2990
|
+
['@app/browser', false],
|
|
2991
|
+
['@src/corex', true],
|
|
2992
|
+
['@src/', true],
|
|
2993
|
+
['../src/print/index.js', true],
|
|
2994
|
+
['../browser?x', true],
|
|
2995
|
+
['../print.ext/index.js', false],
|
|
2996
|
+
...(Array.isArray(block.files) &&
|
|
2997
|
+
block.files.some(
|
|
2998
|
+
(file: unknown) =>
|
|
2999
|
+
typeof file === 'string' && file.startsWith('app/vue/'),
|
|
3000
|
+
)
|
|
3001
|
+
? [['@app/print', true] as const]
|
|
3002
|
+
: []),
|
|
3003
|
+
]
|
|
3004
|
+
: [
|
|
3005
|
+
[
|
|
3006
|
+
message.includes('absolute paths')
|
|
3007
|
+
? '/machine/module.js'
|
|
3008
|
+
: message.includes('normalized traversal')
|
|
3009
|
+
? './../core/index.js'
|
|
3010
|
+
: message.includes('forward slashes')
|
|
3011
|
+
? '..\\core\\index.js'
|
|
3012
|
+
: message.includes('compiler API')
|
|
3013
|
+
? 'typescript'
|
|
3014
|
+
: message.includes('private app')
|
|
3015
|
+
? '@app/core'
|
|
3016
|
+
: message.includes('stylesheets')
|
|
3017
|
+
? './index.css'
|
|
3018
|
+
: message.includes('host-independent') ||
|
|
3019
|
+
message.includes('Node or server')
|
|
3020
|
+
? 'node:fs'
|
|
3021
|
+
: message.includes('Vue extension')
|
|
3022
|
+
? '@src/vue'
|
|
3023
|
+
: '@src/browser',
|
|
3024
|
+
true,
|
|
3025
|
+
],
|
|
3026
|
+
]
|
|
2985
3027
|
const face =
|
|
2986
3028
|
message.includes('another styles face') && typeof pattern.regex === 'string'
|
|
2987
3029
|
? /@src\/(bootstrap|tailwindcss|styles)\(/u.exec(pattern.regex)?.[1]
|
|
@@ -3135,21 +3177,34 @@ createSomething({
|
|
|
3135
3177
|
]),
|
|
3136
3178
|
]
|
|
3137
3179
|
: []),
|
|
3180
|
+
...(['src/browser', 'src/server', 'src/vue', 'src/bin'].includes(owner)
|
|
3181
|
+
? ['../core/index.js', '../../src/core/index.js']
|
|
3182
|
+
: []),
|
|
3183
|
+
...(owner === 'src/vue' ? ['../browser/index.js', '../../src/browser/index.js'] : []),
|
|
3184
|
+
...(owner === 'src/bin' ? ['../server/index.js', '../../src/server/index.js'] : []),
|
|
3138
3185
|
]
|
|
3139
3186
|
const admitted = [
|
|
3140
3187
|
...(owner.endsWith('/vue')
|
|
3141
3188
|
? [
|
|
3142
3189
|
'@src/core',
|
|
3143
3190
|
'@src/browser',
|
|
3144
|
-
'../core/index.js',
|
|
3145
|
-
'../browser/index.js',
|
|
3146
3191
|
'vue',
|
|
3147
3192
|
'@vue/runtime-core',
|
|
3148
3193
|
...(owner.startsWith('app/')
|
|
3149
|
-
? [
|
|
3194
|
+
? [
|
|
3195
|
+
'@app/core',
|
|
3196
|
+
'@app/browser',
|
|
3197
|
+
'@src/vue',
|
|
3198
|
+
'../../src/vue/index.js',
|
|
3199
|
+
'../browser/index.js',
|
|
3200
|
+
]
|
|
3150
3201
|
: []),
|
|
3151
3202
|
]
|
|
3152
3203
|
: ['@src/core']),
|
|
3204
|
+
...(['src/browser', 'src/server', 'src/vue', 'src/bin'].includes(owner)
|
|
3205
|
+
? []
|
|
3206
|
+
: ['../core/index.js']),
|
|
3207
|
+
...(owner === 'src/bin' ? ['@src/server'] : []),
|
|
3153
3208
|
...(sheet
|
|
3154
3209
|
? [
|
|
3155
3210
|
...faces
|
|
@@ -3177,7 +3232,6 @@ createSomething({
|
|
|
3177
3232
|
[
|
|
3178
3233
|
...admitted,
|
|
3179
3234
|
'./index.js',
|
|
3180
|
-
'../core/index.js',
|
|
3181
3235
|
...(owner.endsWith('/server') || owner === 'src/bin' ? ['node:fs'] : []),
|
|
3182
3236
|
],
|
|
3183
3237
|
false,
|
|
@@ -88,10 +88,23 @@ describe('surface policy controls', () => {
|
|
|
88
88
|
}
|
|
89
89
|
})
|
|
90
90
|
|
|
91
|
-
it('
|
|
91
|
+
it('ignores a target catalog row the installed scaffold does not stage', () => {
|
|
92
92
|
const scratch = createPolicySurfaceFixture()
|
|
93
93
|
try {
|
|
94
94
|
scratch.write(POLICY_CATALOG_FILE, createPolicyCatalog(['other', 'sample', 'uncovered']))
|
|
95
|
+
expect(inspectPolicyWorkspace(scratch.path)).toEqual([])
|
|
96
|
+
} finally {
|
|
97
|
+
scratch.destroy()
|
|
98
|
+
}
|
|
99
|
+
})
|
|
100
|
+
|
|
101
|
+
it('refuses a staged catalog row absent from the installed guides', () => {
|
|
102
|
+
const scratch = createPolicySurfaceFixture()
|
|
103
|
+
try {
|
|
104
|
+
scratch.write(
|
|
105
|
+
`${POLICY_SURFACE_HOST}/${POLICY_SURFACE_CATALOG}`,
|
|
106
|
+
createPolicyCatalog(['other', 'sample', 'uncovered']),
|
|
107
|
+
)
|
|
95
108
|
expect(inspectPolicyWorkspace(scratch.path)).toEqual([
|
|
96
109
|
{
|
|
97
110
|
rule: 'surface',
|
|
@@ -212,6 +225,31 @@ describe('surface policy controls', () => {
|
|
|
212
225
|
}
|
|
213
226
|
})
|
|
214
227
|
|
|
228
|
+
it('excludes the distribution harness in an adopter while reporting target-owned collisions', () => {
|
|
229
|
+
const scratch = createPolicySurfaceFixture()
|
|
230
|
+
try {
|
|
231
|
+
scratch.write('tests/setupDistribution.ts', 'export function readShared() {}\n')
|
|
232
|
+
expect(inspectPolicyWorkspace(scratch.path)).toEqual([])
|
|
233
|
+
scratch.write('tests/setupExtra.ts', 'export function readShared() {}\n')
|
|
234
|
+
expect(inspectPolicyWorkspace(scratch.path)).toEqual([
|
|
235
|
+
{
|
|
236
|
+
rule: 'mirror',
|
|
237
|
+
path: 'tests/setupExtra.ts',
|
|
238
|
+
message:
|
|
239
|
+
'exporting setup module requires its sibling proof or an import from tests/setup.test.ts',
|
|
240
|
+
},
|
|
241
|
+
{
|
|
242
|
+
rule: 'surface',
|
|
243
|
+
path: 'tests/setupExtra.ts',
|
|
244
|
+
line: 1,
|
|
245
|
+
message: 'surface name belongs to one package: readShared (other)',
|
|
246
|
+
},
|
|
247
|
+
])
|
|
248
|
+
} finally {
|
|
249
|
+
scratch.destroy()
|
|
250
|
+
}
|
|
251
|
+
})
|
|
252
|
+
|
|
215
253
|
it('refuses a barrel statement outside the relative star-export population', () => {
|
|
216
254
|
const scratch = createPolicySurfaceFixture()
|
|
217
255
|
try {
|
|
@@ -5,7 +5,7 @@ import {
|
|
|
5
5
|
hasCanonicalSegments,
|
|
6
6
|
resolveLink,
|
|
7
7
|
} from '@orkestrel/guide'
|
|
8
|
-
import { BASE_DEV_DEPENDENCIES, HOST_PATHS } from '@orkestrel/scaffold'
|
|
8
|
+
import { BASE_DEV_DEPENDENCIES, DISTRIBUTION_SETUP_PATH, HOST_PATHS } from '@orkestrel/scaffold'
|
|
9
9
|
import { spawnSync } from 'node:child_process'
|
|
10
10
|
import { createRequire } from 'node:module'
|
|
11
11
|
import {
|
|
@@ -172,7 +172,7 @@ export interface PolicyProject {
|
|
|
172
172
|
readonly setup: readonly string[]
|
|
173
173
|
}
|
|
174
174
|
|
|
175
|
-
/** Describes one physical negative control, including the population boundary it
|
|
175
|
+
/** Describes one physical negative control, including the population boundary it tests. */
|
|
176
176
|
export interface PolicyControl {
|
|
177
177
|
readonly label: string
|
|
178
178
|
readonly membership: string
|
|
@@ -1104,9 +1104,28 @@ export function inspectPolicyMirrors(root: string): readonly PolicyViolation[] {
|
|
|
1104
1104
|
return [...inspectPolicyMirrorPaths(tests, modules), ...inspectPolicySetup(root)]
|
|
1105
1105
|
}
|
|
1106
1106
|
|
|
1107
|
+
/**
|
|
1108
|
+
* Checks whether a normalized path belongs to a scaffold-owned setup module.
|
|
1109
|
+
* @param path - The workspace-relative module path.
|
|
1110
|
+
* @param root - The workspace root whose manifest determines harness ownership.
|
|
1111
|
+
* @returns True if scaffold owns the module; false otherwise.
|
|
1112
|
+
*/
|
|
1113
|
+
export function matchesScaffoldSetup(path: string, root: string): boolean {
|
|
1114
|
+
const normalized = normalizePolicyPath(path)
|
|
1115
|
+
const manifest = readPolicyJSON(join(root, 'package.json'))
|
|
1116
|
+
return (
|
|
1117
|
+
(normalized === DISTRIBUTION_SETUP_PATH &&
|
|
1118
|
+
(!isPolicyRecord(manifest) || manifest.private !== true)) ||
|
|
1119
|
+
HOST_PATHS.some(
|
|
1120
|
+
(vendored) =>
|
|
1121
|
+
normalized === normalizePolicyPath(vendored) ||
|
|
1122
|
+
normalized.startsWith(normalizePolicyPath(vendored) + '/'),
|
|
1123
|
+
)
|
|
1124
|
+
)
|
|
1125
|
+
}
|
|
1126
|
+
|
|
1107
1127
|
/**
|
|
1108
1128
|
* Inspects root setup modules and their proofs in both directions.
|
|
1109
|
-
*
|
|
1110
1129
|
* @param root - The workspace root to inspect.
|
|
1111
1130
|
* @returns Missing modules and uncovered exporting setup modules.
|
|
1112
1131
|
*/
|
|
@@ -1125,14 +1144,7 @@ export function inspectPolicySetup(root: string): readonly PolicyViolation[] {
|
|
|
1125
1144
|
)
|
|
1126
1145
|
return [...paths].sort().flatMap((path) => {
|
|
1127
1146
|
const module = path.endsWith('.test.ts') ? path.replace(/\.test\.ts$/u, '.ts') : path
|
|
1128
|
-
if (
|
|
1129
|
-
HOST_PATHS.some(
|
|
1130
|
-
(vendored) =>
|
|
1131
|
-
module === normalizePolicyPath(vendored) ||
|
|
1132
|
-
module.startsWith(normalizePolicyPath(vendored) + '/'),
|
|
1133
|
-
)
|
|
1134
|
-
)
|
|
1135
|
-
return []
|
|
1147
|
+
if (matchesScaffoldSetup(module, root)) return []
|
|
1136
1148
|
if (path.endsWith('.test.ts')) {
|
|
1137
1149
|
return paths.has(module)
|
|
1138
1150
|
? []
|
|
@@ -3075,7 +3087,9 @@ export function readPolicySurface(root: string): PolicySurfacePopulation {
|
|
|
3075
3087
|
*
|
|
3076
3088
|
* @remarks
|
|
3077
3089
|
* Source names claimed by the target's own hosted guide are grandfathered. Setup names have no
|
|
3078
|
-
* grandfather.
|
|
3090
|
+
* grandfather. Catalog rows come from beside the guides: when reading installed guides, from the
|
|
3091
|
+
* staged catalog and never from the target's own table, which can list a package without a guide in
|
|
3092
|
+
* that host. An absent installed host falls back to checkout guides only with catalog coverage.
|
|
3079
3093
|
* Missing comparison evidence and unread barrel statements produce surface violations.
|
|
3080
3094
|
*
|
|
3081
3095
|
* @param root - The workspace root to inspect.
|
|
@@ -3088,7 +3102,7 @@ export function inspectPolicySurface(root: string): readonly PolicyViolation[] {
|
|
|
3088
3102
|
const host = hosted ? installed : root
|
|
3089
3103
|
const catalog = hosted ? POLICY_SURFACE_CATALOG : POLICY_CATALOG_FILE
|
|
3090
3104
|
const directory = hosted ? `${POLICY_SURFACE_HOST}/guides` : 'guides'
|
|
3091
|
-
const names = new Set(
|
|
3105
|
+
const names = new Set(readPolicyCatalog(host, catalog))
|
|
3092
3106
|
if (!existsSync(join(host, 'guides')) || names.size === 0) {
|
|
3093
3107
|
return [
|
|
3094
3108
|
createPolicyViolation(
|
|
@@ -3153,12 +3167,7 @@ export function inspectPolicySurface(root: string): readonly PolicyViolation[] {
|
|
|
3153
3167
|
.map(normalizePolicyPath)
|
|
3154
3168
|
.sort()
|
|
3155
3169
|
.flatMap((path) =>
|
|
3156
|
-
path.endsWith('.test.ts') ||
|
|
3157
|
-
HOST_PATHS.some(
|
|
3158
|
-
(vendored) =>
|
|
3159
|
-
path === normalizePolicyPath(vendored) ||
|
|
3160
|
-
path.startsWith(`${normalizePolicyPath(vendored)}/`),
|
|
3161
|
-
)
|
|
3170
|
+
path.endsWith('.test.ts') || matchesScaffoldSetup(path, root)
|
|
3162
3171
|
? []
|
|
3163
3172
|
: [collectPolicyDeclarations(root, path, readFileSync(join(root, path), 'utf8'))],
|
|
3164
3173
|
)
|
|
@@ -3392,6 +3401,13 @@ export const SETUP_POLICY_CONTROLS: readonly PolicyControl[] = Object.freeze([
|
|
|
3392
3401
|
},
|
|
3393
3402
|
],
|
|
3394
3403
|
},
|
|
3404
|
+
{
|
|
3405
|
+
label: 'admits the distribution harness without a sibling proof',
|
|
3406
|
+
membership: 'content-owned distribution setup module outside the mirror population',
|
|
3407
|
+
rule: 'mirror',
|
|
3408
|
+
files: [{ path: 'tests/setupDistribution.ts', content: 'export const DISTRIBUTION = 1\n' }],
|
|
3409
|
+
violations: [],
|
|
3410
|
+
},
|
|
3395
3411
|
{
|
|
3396
3412
|
label: 'admits an inventory-vendored setup module without proof',
|
|
3397
3413
|
membership: 'host-inventory setup modules outside the mirror population',
|
|
@@ -3399,12 +3415,30 @@ export const SETUP_POLICY_CONTROLS: readonly PolicyControl[] = Object.freeze([
|
|
|
3399
3415
|
files: [{ path: 'tests/setupPolicy.ts', content: 'export const POLICY = 1\n' }],
|
|
3400
3416
|
violations: [],
|
|
3401
3417
|
},
|
|
3418
|
+
{
|
|
3419
|
+
label: 'requires a proof for a private workspace distribution module',
|
|
3420
|
+
membership: 'target-owned distribution setup module in a private workspace',
|
|
3421
|
+
rule: 'mirror',
|
|
3422
|
+
files: [
|
|
3423
|
+
{ path: 'package.json', content: '{"private":true}\n' },
|
|
3424
|
+
{ path: 'tests/setupDistribution.ts', content: 'export const DISTRIBUTION = 1\n' },
|
|
3425
|
+
],
|
|
3426
|
+
violations: [
|
|
3427
|
+
{
|
|
3428
|
+
rule: 'mirror',
|
|
3429
|
+
path: 'tests/setupDistribution.ts',
|
|
3430
|
+
message:
|
|
3431
|
+
'exporting setup module requires its sibling proof or an import from tests/setup.test.ts',
|
|
3432
|
+
},
|
|
3433
|
+
],
|
|
3434
|
+
},
|
|
3402
3435
|
])
|
|
3403
3436
|
|
|
3404
3437
|
/** Lists standalone sheet selections and their core-bearing control for the vendored proof. */
|
|
3405
3438
|
export const SHEET_POLICY_SELECTIONS: ReadonlyArray<
|
|
3406
3439
|
Pick<Blueprint, 'src' | 'styles' | 'themes'> & {
|
|
3407
3440
|
readonly conformance?: boolean
|
|
3441
|
+
readonly tree?: boolean
|
|
3408
3442
|
readonly integration?: boolean
|
|
3409
3443
|
readonly files?: readonly PolicySource[]
|
|
3410
3444
|
readonly control?: {
|
|
@@ -3416,8 +3450,25 @@ export const SHEET_POLICY_SELECTIONS: ReadonlyArray<
|
|
|
3416
3450
|
> = Object.freeze([
|
|
3417
3451
|
{ src: [], styles: true, themes: true },
|
|
3418
3452
|
{ src: [], styles: false, themes: true },
|
|
3419
|
-
{
|
|
3453
|
+
{
|
|
3454
|
+
src: [],
|
|
3455
|
+
styles: false,
|
|
3456
|
+
themes: true,
|
|
3457
|
+
integration: true,
|
|
3458
|
+
control: {
|
|
3459
|
+
before: "existsSync(resolveWorkspacePath('tests/setupStyles.ts'))",
|
|
3460
|
+
after: 'true',
|
|
3461
|
+
failure: './tests/setupStyles.ts',
|
|
3462
|
+
},
|
|
3463
|
+
},
|
|
3420
3464
|
{ src: ['core'], styles: true, themes: true },
|
|
3465
|
+
{
|
|
3466
|
+
src: ['core'],
|
|
3467
|
+
styles: false,
|
|
3468
|
+
themes: false,
|
|
3469
|
+
tree: true,
|
|
3470
|
+
files: [{ path: 'tests/tree.test.ts', content: 'export {}\n' }],
|
|
3471
|
+
},
|
|
3421
3472
|
{
|
|
3422
3473
|
src: ['core', 'browser'],
|
|
3423
3474
|
styles: true,
|
|
@@ -3457,10 +3508,10 @@ export const SHEET_POLICY_SELECTIONS: ReadonlyArray<
|
|
|
3457
3508
|
styles: true,
|
|
3458
3509
|
themes: false,
|
|
3459
3510
|
integration: true,
|
|
3511
|
+
files: [{ path: 'tests/setupStyles.ts', content: 'export {}\n' }],
|
|
3460
3512
|
control: {
|
|
3461
|
-
before:
|
|
3462
|
-
|
|
3463
|
-
after: "setupFiles: ['./tests/setup.ts', './tests/setupBrowser.ts']",
|
|
3513
|
+
before: "? ['./tests/setupStyles.ts']",
|
|
3514
|
+
after: '? []',
|
|
3464
3515
|
failure: './tests/setupStyles.ts',
|
|
3465
3516
|
},
|
|
3466
3517
|
},
|
|
@@ -4283,7 +4334,7 @@ export const PROSE_POLICY_MANIFEST = '{\n\t"name": "@orkestrel/sample"\n}\n'
|
|
|
4283
4334
|
* Lists the physical controls for every prose-population boundary the workspace route reaches.
|
|
4284
4335
|
*
|
|
4285
4336
|
* @remarks
|
|
4286
|
-
* Each control that
|
|
4337
|
+
* Each control that tests an exclusion also writes the arrival file, whose different term proves
|
|
4287
4338
|
* the sweep ran over the control workspace rather than reporting nothing because it found nothing.
|
|
4288
4339
|
*/
|
|
4289
4340
|
export const PROSE_POLICY_CONTROLS: readonly PolicyControl[] = Object.freeze([
|
|
@@ -4559,15 +4610,22 @@ export function collectFaceWrappers(directory: string): readonly string[] {
|
|
|
4559
4610
|
* Inspects sheet setup membership and themes ordering from configuration data.
|
|
4560
4611
|
* @param project - The resolved sheet project.
|
|
4561
4612
|
* @param script - The optional chained styles and themes build command.
|
|
4613
|
+
* @param directory - The target workspace root; defaults to the policy root.
|
|
4562
4614
|
* @returns Missing setup paths and invalid isolation or ordering fields.
|
|
4563
4615
|
*/
|
|
4564
|
-
export function inspectSheetConfiguration(
|
|
4616
|
+
export function inspectSheetConfiguration(
|
|
4617
|
+
project: unknown,
|
|
4618
|
+
script?: string,
|
|
4619
|
+
directory: string = POLICY_ROOT,
|
|
4620
|
+
): readonly string[] {
|
|
4565
4621
|
const test = readConfigRecord(readConfigRecord(project).test)
|
|
4566
4622
|
const setup = test.setupFiles
|
|
4567
4623
|
return [
|
|
4568
|
-
...[
|
|
4569
|
-
|
|
4570
|
-
|
|
4624
|
+
...[
|
|
4625
|
+
'./tests/setup.ts',
|
|
4626
|
+
'./tests/setupBrowser.ts',
|
|
4627
|
+
...(existsSync(resolve(directory, 'tests/setupStyles.ts')) ? ['./tests/setupStyles.ts'] : []),
|
|
4628
|
+
].filter((path) => !Array.isArray(setup) || !setup.includes(path)),
|
|
4571
4629
|
...(test.isolate !== false ? ['isolate'] : []),
|
|
4572
4630
|
...(script !== undefined &&
|
|
4573
4631
|
(!script.includes('vite.styles.config.ts') ||
|