@orkestrel/scaffold 0.0.71 → 0.0.73
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/host/CLAUDE.md +3 -3
- package/dist/host/agents/orchestration.md +66 -32
- package/dist/host/agents/skills/enterprise-bootstrap/references/bootstrap-reference.md +36 -6
- package/dist/host/agents/skills/enterprise-bootstrap/references/color-modes.md +3 -2
- package/dist/host/agents/skills/enterprise-bootstrap/references/components.md +1 -1
- package/dist/host/agents/skills/orkestrel-build-application/SKILL.md +18 -1
- package/dist/host/agents/skills/orkestrel-debrief/SKILL.md +1 -1
- package/dist/host/agents/skills/orkestrel-debrief/references/instruction-audit.md +2 -4
- package/dist/host/agents/skills/orkestrel-falsify/SKILL.md +12 -9
- package/dist/host/agents/skills/orkestrel-falsify/references/brief.md +16 -8
- package/dist/host/agents/skills/orkestrel-falsify/references/reconcile.md +2 -2
- package/dist/host/agents/skills/orkestrel-harden-package/SKILL.md +1 -1
- package/dist/host/agents/skills/orkestrel-polish-surface/SKILL.md +2 -1
- package/dist/host/agents/skills/orkestrel-prove-journey/SKILL.md +19 -8
- package/dist/host/agents/skills/orkestrel-prove-journey/references/layer.md +16 -15
- package/dist/host/agents/skills/orkestrel-prove-journey/references/statechart.md +5 -2
- package/dist/host/agents/skills/orkestrel-prove-journey/references/styles.md +5 -1
- package/dist/host/agents/templates/brief.md +4 -3
- package/dist/host/agents/transports/claude.md +13 -6
- package/dist/host/agents/transports/codex.md +2 -2
- package/dist/host/agents/transports/cursor.md +85 -0
- package/dist/host/claude/agents/application.md +5 -6
- package/dist/host/claude/agents/builder.md +3 -13
- package/dist/host/claude/agents/checker.md +9 -2
- package/dist/host/claude/agents/distiller.md +37 -0
- package/dist/host/claude/agents/grok.md +9 -56
- package/dist/host/claude/agents/{implementer.md → opus.md} +8 -9
- package/dist/host/claude/agents/orkestrel.md +53 -46
- package/dist/host/claude/agents/planner.md +12 -5
- package/dist/host/claude/agents/researcher.md +7 -0
- package/dist/host/claude/agents/reviewer.md +14 -7
- package/dist/host/claude/agents/scout.md +8 -1
- package/dist/host/claude/agents/sol.md +5 -5
- package/dist/host/claude/rules/documentation.md +1 -0
- package/dist/host/claude/rules/writing.md +27 -24
- package/dist/host/claude/skills/orkestrel-build-application/SKILL.md +1 -1
- package/dist/host/codex/agents/analyst.toml +10 -4
- package/dist/host/codex/agents/application.toml +5 -6
- package/dist/host/codex/agents/builder.toml +5 -5
- package/dist/host/codex/agents/checker.toml +4 -0
- package/dist/host/codex/agents/distiller.toml +28 -0
- package/dist/host/codex/agents/grok.toml +27 -19
- package/dist/host/codex/agents/opus.toml +5 -4
- package/dist/host/codex/agents/orkestrel.toml +5 -0
- package/dist/host/codex/agents/planner.toml +10 -0
- package/dist/host/codex/agents/researcher.toml +4 -0
- package/dist/host/codex/agents/reviewer.toml +12 -2
- package/dist/host/codex/agents/scout.toml +5 -2
- package/dist/host/codex/agents/{implementer.toml → sol.toml} +5 -6
- package/dist/host/codex/agents/verifier.toml +3 -0
- package/dist/host/codex/config.toml +2 -2
- package/dist/host/configs/policy.ts +5 -2
- package/dist/host/dotfiles/gitignore +3 -0
- package/dist/host/guides/test.md +77 -55
- package/dist/host/manifest.json +80 -72
- package/dist/host/tests/config.test.ts +113 -57
- package/dist/src/core/index.cjs +448 -349
- package/dist/src/core/index.cjs.map +1 -1
- package/dist/src/core/index.d.cts +22 -21
- package/dist/src/core/index.d.ts +22 -21
- package/dist/src/core/index.js +448 -349
- package/dist/src/core/index.js.map +1 -1
- package/package.json +4 -4
|
@@ -5,6 +5,7 @@ import { spawnSync } from 'node:child_process'
|
|
|
5
5
|
import {
|
|
6
6
|
existsSync,
|
|
7
7
|
globSync,
|
|
8
|
+
lstatSync,
|
|
8
9
|
mkdtempSync,
|
|
9
10
|
mkdirSync,
|
|
10
11
|
readdirSync,
|
|
@@ -63,6 +64,33 @@ import { describe, expect, it } from 'vitest'
|
|
|
63
64
|
|
|
64
65
|
const root = resolve(dirname(fileURLToPath(import.meta.url)), '..')
|
|
65
66
|
|
|
67
|
+
// The `src` axis a declaration roll-up reads, derived from a recognized source environment that is
|
|
68
|
+
// a physical directory rather than from a `src` entry of any shape. A regular file, an empty
|
|
69
|
+
// directory, a directory holding no recognized environment, a symbolic link, and an entry this host
|
|
70
|
+
// refuses to inspect each leave a workspace publishing nothing, and reading the entry alone would
|
|
71
|
+
// put every one of them under the face proof. The inspection is caught rather than excused by
|
|
72
|
+
// option: `throwIfNoEntry` excuses an absent path alone and rethrows a permission refusal, and a
|
|
73
|
+
// throw on this line is a collection error that takes this whole file down in that target rather
|
|
74
|
+
// than failing one case. `isPhysicalDirectory` reads the same two facts off an `lstat` and returns
|
|
75
|
+
// false for every inspection error, and this reads them the same way. This is the derivation
|
|
76
|
+
// `targetToEnvironments` uses, which filters the environment names by a contained physical
|
|
77
|
+
// directory, and it answers the same question `blueprintToScripts`
|
|
78
|
+
// answers from a blueprint's own `src` list. A workspace declaring app environments alone publishes
|
|
79
|
+
// no library, so it vendors no `configs/src/` face wrapper and has no roll-up to measure. A face
|
|
80
|
+
// proof is conditioned on this axis rather than on a face wrapper: a workspace that declares the
|
|
81
|
+
// axis and vendors no wrapper carries the defect such a proof reports, so that workspace must still
|
|
82
|
+
// fail the proof. The manifest cases read the same fact from their own `private` flag and name it
|
|
83
|
+
// `manifestPublishes` for the source that decides it there; this reads the axis on disk, so a
|
|
84
|
+
// workspace whose manifest and shape disagree fails one of the two rather than neither.
|
|
85
|
+
const publishes = ['core', 'browser', 'server'].some((environment) => {
|
|
86
|
+
try {
|
|
87
|
+
const entry = lstatSync(resolve(root, 'src', environment))
|
|
88
|
+
return entry.isDirectory() && !entry.isSymbolicLink()
|
|
89
|
+
} catch {
|
|
90
|
+
return false
|
|
91
|
+
}
|
|
92
|
+
})
|
|
93
|
+
|
|
66
94
|
// A declaration roll-up loads the extractor package, which only a workspace publishing source from
|
|
67
95
|
// `src` installs. The resolution below is the mechanism its proof is conditioned on.
|
|
68
96
|
let extractorPath: string | undefined
|
|
@@ -199,8 +227,8 @@ describe('root configuration', () => {
|
|
|
199
227
|
setup: ['./tests/setup.ts'],
|
|
200
228
|
})
|
|
201
229
|
// A row that is a configuration rather than a factory. Every generated
|
|
202
|
-
// workspace registers the factory itself, so this shape is required
|
|
203
|
-
// rather than observed: the proof exercises that resolution wherever it runs
|
|
230
|
+
// workspace registers the factory itself, so this shape is required by the
|
|
231
|
+
// expectation rather than observed: the proof exercises that resolution wherever it runs
|
|
204
232
|
// instead of only where a hand-written configuration happens to produce it.
|
|
205
233
|
expected.set('concrete', { include: 'tests/concrete.test.ts', setup: ['./tests/setup.ts'] })
|
|
206
234
|
|
|
@@ -530,7 +558,7 @@ describe('root configuration', () => {
|
|
|
530
558
|
if (typeof scripts !== 'object' || scripts === null) {
|
|
531
559
|
throw new Error('The package manifest carries no scripts')
|
|
532
560
|
}
|
|
533
|
-
const
|
|
561
|
+
const manifestPublishes = Object.getOwnPropertyDescriptor(manifest, 'private')?.value !== true
|
|
534
562
|
const test = Object.getOwnPropertyDescriptor(scripts, 'test')?.value
|
|
535
563
|
const config = Object.getOwnPropertyDescriptor(scripts, 'test:config')?.value
|
|
536
564
|
const distribution = Object.getOwnPropertyDescriptor(scripts, 'test:distribution')?.value
|
|
@@ -576,9 +604,9 @@ describe('root configuration', () => {
|
|
|
576
604
|
)
|
|
577
605
|
expect(typeof test === 'string' && test.includes('test:distribution')).toBe(false)
|
|
578
606
|
expect(typeof publish === 'string' && publish.includes('npm run test:distribution')).toBe(
|
|
579
|
-
hasDistribution &&
|
|
607
|
+
hasDistribution && manifestPublishes,
|
|
580
608
|
)
|
|
581
|
-
expect(typeof publish === 'string').toBe(
|
|
609
|
+
expect(typeof publish === 'string').toBe(manifestPublishes)
|
|
582
610
|
expect(integration).toBe(
|
|
583
611
|
hasIntegration
|
|
584
612
|
? 'vitest run --config vite.config.ts --no-cache --reporter=dot --project integration'
|
|
@@ -610,10 +638,10 @@ describe('root configuration', () => {
|
|
|
610
638
|
: undefined,
|
|
611
639
|
)
|
|
612
640
|
expect(typeof test === 'string' && test.includes('npm run test:service')).toBe(
|
|
613
|
-
hasService && !
|
|
641
|
+
hasService && !manifestPublishes,
|
|
614
642
|
)
|
|
615
643
|
expect(typeof publish === 'string' && publish.includes('npm run test:service')).toBe(
|
|
616
|
-
hasService &&
|
|
644
|
+
hasService && manifestPublishes,
|
|
617
645
|
)
|
|
618
646
|
})
|
|
619
647
|
|
|
@@ -626,14 +654,14 @@ describe('root configuration', () => {
|
|
|
626
654
|
if (typeof scripts !== 'object' || scripts === null) {
|
|
627
655
|
throw new Error('The package manifest carries no scripts')
|
|
628
656
|
}
|
|
629
|
-
const
|
|
657
|
+
const manifestPublishes = Object.getOwnPropertyDescriptor(manifest, 'private')?.value !== true
|
|
630
658
|
const prepack = Object.getOwnPropertyDescriptor(scripts, 'prepack')?.value
|
|
631
|
-
expect(prepack).toBe(
|
|
659
|
+
expect(prepack).toBe(manifestPublishes ? 'npm run build' : undefined)
|
|
632
660
|
|
|
633
661
|
const controlled = { ...scripts, prepack: 'npm run control' }
|
|
634
662
|
expect(() => {
|
|
635
663
|
const control = Object.getOwnPropertyDescriptor(controlled, 'prepack')?.value
|
|
636
|
-
expect(control).toBe(
|
|
664
|
+
expect(control).toBe(manifestPublishes ? 'npm run build' : undefined)
|
|
637
665
|
}).toThrow(/expected/u)
|
|
638
666
|
})
|
|
639
667
|
|
|
@@ -2150,54 +2178,81 @@ describe('configuration helpers', () => {
|
|
|
2150
2178
|
}
|
|
2151
2179
|
})
|
|
2152
2180
|
|
|
2153
|
-
|
|
2154
|
-
|
|
2155
|
-
|
|
2156
|
-
|
|
2157
|
-
|
|
2158
|
-
|
|
2159
|
-
|
|
2160
|
-
|
|
2161
|
-
|
|
2162
|
-
|
|
2163
|
-
|
|
2164
|
-
|
|
2165
|
-
|
|
2166
|
-
|
|
2167
|
-
|
|
2168
|
-
|
|
2169
|
-
|
|
2170
|
-
|
|
2171
|
-
|
|
2172
|
-
|
|
2173
|
-
|
|
2174
|
-
|
|
2175
|
-
|
|
2176
|
-
|
|
2177
|
-
|
|
2178
|
-
|
|
2179
|
-
|
|
2180
|
-
|
|
2181
|
-
'
|
|
2182
|
-
|
|
2183
|
-
|
|
2184
|
-
|
|
2185
|
-
|
|
2186
|
-
|
|
2181
|
+
// The scope reading applies only where the workspace publishes source from `src`, which is what
|
|
2182
|
+
// `publishes` reads, and the name ends at that mechanism. An absent face project is the defect
|
|
2183
|
+
// this case exists to report rather than a second reason to excuse it, so a workspace holding
|
|
2184
|
+
// the axis and vendoring no `configs/src/` wrapper reaches the throw inside the body.
|
|
2185
|
+
// A skip raises the run's skipped count where a guard inside the case would
|
|
2186
|
+
// raise its passed count with nothing measured. Every generated workspace runs its projects
|
|
2187
|
+
// under `--reporter=dot`, which prints a skip as an unnamed `-`, so the case name and the
|
|
2188
|
+
// condition in it are read by re-running the project with a reporter that names skipped cases.
|
|
2189
|
+
it.skipIf(!publishes)(
|
|
2190
|
+
'reads the compiler scope a declaration roll-up requires [inapplicable where src holds no recognized environment directory]',
|
|
2191
|
+
() => {
|
|
2192
|
+
const compiler = createRequire(import.meta.url).resolve('typescript/bin/tsc')
|
|
2193
|
+
// The order mirrors ENVIRONMENTS in src/core/constants.ts; a server-only workspace vendors
|
|
2194
|
+
// no core project, so this walks to the first face the workspace actually carries.
|
|
2195
|
+
const faces = ['core', 'browser', 'server']
|
|
2196
|
+
const face = faces.find((candidate) =>
|
|
2197
|
+
existsSync(resolve(root, `configs/src/tsconfig.${candidate}.json`)),
|
|
2198
|
+
)
|
|
2199
|
+
if (face === undefined) throw new Error('The workspace declares no face project')
|
|
2200
|
+
const project = resolve(root, `configs/src/tsconfig.${face}.json`)
|
|
2201
|
+
const declared: unknown = JSON.parse(readFileSync(project, 'utf8'))
|
|
2202
|
+
if (typeof declared !== 'object' || declared === null) {
|
|
2203
|
+
throw new Error(`The ${face} project is not a TypeScript configuration record`)
|
|
2204
|
+
}
|
|
2205
|
+
const declaredOptions: unknown = Object.getOwnPropertyDescriptor(
|
|
2206
|
+
declared,
|
|
2207
|
+
'compilerOptions',
|
|
2208
|
+
)?.value
|
|
2209
|
+
if (typeof declaredOptions !== 'object' || declaredOptions === null) {
|
|
2210
|
+
throw new Error(`The ${face} project carries no compiler options`)
|
|
2211
|
+
}
|
|
2212
|
+
const declaredLib: unknown = Object.getOwnPropertyDescriptor(declaredOptions, 'lib')?.value
|
|
2213
|
+
const declaredTypes: unknown = Object.getOwnPropertyDescriptor(
|
|
2214
|
+
declaredOptions,
|
|
2215
|
+
'types',
|
|
2216
|
+
)?.value
|
|
2217
|
+
if (!configHelpers.isStringList(declaredLib) || !configHelpers.isStringList(declaredTypes)) {
|
|
2218
|
+
throw new Error(`The ${face} project declares no lib or types`)
|
|
2219
|
+
}
|
|
2220
|
+
const declaredRootDir: unknown = Object.getOwnPropertyDescriptor(
|
|
2221
|
+
declaredOptions,
|
|
2222
|
+
'rootDir',
|
|
2223
|
+
)?.value
|
|
2224
|
+
if (typeof declaredRootDir !== 'string') {
|
|
2225
|
+
throw new Error(`The ${face} project declares no rootDir`)
|
|
2226
|
+
}
|
|
2227
|
+
const expectedRoot = resolve(dirname(project), declaredRootDir)
|
|
2187
2228
|
|
|
2188
|
-
|
|
2189
|
-
|
|
2190
|
-
|
|
2191
|
-
|
|
2192
|
-
|
|
2193
|
-
|
|
2194
|
-
|
|
2195
|
-
|
|
2196
|
-
|
|
2197
|
-
|
|
2198
|
-
|
|
2199
|
-
|
|
2229
|
+
const scope = configHelpers.parseProjectScope(
|
|
2230
|
+
configHelpers.readCompilerOutput(compiler, ['--showConfig', '-p', project]),
|
|
2231
|
+
project,
|
|
2232
|
+
)
|
|
2233
|
+
if (scope === undefined) throw new Error(`The ${face} project resolved no compiler scope`)
|
|
2234
|
+
// The compiler lowercases every resolved library name, so the committed project is the
|
|
2235
|
+
// second mechanism this reading is compared against rather than the reading itself.
|
|
2236
|
+
expect(scope.lib.map((entry) => entry.toLowerCase())).toStrictEqual(
|
|
2237
|
+
declaredLib.map((entry) => entry.toLowerCase()),
|
|
2238
|
+
)
|
|
2239
|
+
expect(scope.types).toStrictEqual(declaredTypes)
|
|
2240
|
+
expect(scope.root).toBe(expectedRoot)
|
|
2241
|
+
},
|
|
2242
|
+
)
|
|
2200
2243
|
|
|
2244
|
+
// No reading in this case reads anything under `configs/src/`, so each one applies to a workspace
|
|
2245
|
+
// on either axis. The refusals are decided by the text handed to them; the compiler refusal by a
|
|
2246
|
+
// path no workspace shape carries; the manifest name, the module resolution, and the extractor
|
|
2247
|
+
// guard by files and packages a workspace carries on either axis. They sit apart from the
|
|
2248
|
+
// preceding scope reading for that reason: the skip that excuses an app-only workspace from
|
|
2249
|
+
// reading a face project must not excuse it from the helpers behind the roll-up, which it
|
|
2250
|
+
// vendors whether or not it publishes.
|
|
2251
|
+
it('reads the refusals, guards, overrides, and rewrites a declaration roll-up requires from every workspace', () => {
|
|
2252
|
+
const compiler = createRequire(import.meta.url).resolve('typescript/bin/tsc')
|
|
2253
|
+
// Any project path resolves these, because each reading is refused by the text before the
|
|
2254
|
+
// path is read. The root project is the one file every workspace carries.
|
|
2255
|
+
const project = resolve(root, 'tsconfig.json')
|
|
2201
2256
|
expect(configHelpers.parseProjectScope('not a configuration', project)).toBeUndefined()
|
|
2202
2257
|
expect(
|
|
2203
2258
|
configHelpers.parseProjectScope('{"compilerOptions":{"lib":[],"types":[]}}', project),
|
|
@@ -2205,11 +2260,12 @@ describe('configuration helpers', () => {
|
|
|
2205
2260
|
expect(
|
|
2206
2261
|
configHelpers.parseProjectScope('{"compilerOptions":{"lib":[1],"rootDir":"."}}', project),
|
|
2207
2262
|
).toBeUndefined()
|
|
2263
|
+
// The compiler's own refusal, read from a path no workspace shape carries.
|
|
2208
2264
|
expect(() =>
|
|
2209
2265
|
configHelpers.readCompilerOutput(compiler, [
|
|
2210
2266
|
'--showConfig',
|
|
2211
2267
|
'-p',
|
|
2212
|
-
resolve(root, 'configs/
|
|
2268
|
+
resolve(root, 'configs/tsconfig.absent.json'),
|
|
2213
2269
|
]),
|
|
2214
2270
|
).toThrow('The declaration compiler failed')
|
|
2215
2271
|
|