@orkestrel/scaffold 0.0.20 → 0.0.22

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (69) hide show
  1. package/dist/bin/scaffold.js +385 -148
  2. package/dist/bin/scaffold.js.map +1 -1
  3. package/dist/host/AGENTS.md +61 -42
  4. package/dist/host/CLAUDE.md +39 -387
  5. package/dist/host/agents/orchestration.md +454 -0
  6. package/dist/host/agents/skills/enterprise-bootstrap/SKILL.md +25 -7
  7. package/dist/host/agents/skills/orkestrel-align-packages/SKILL.md +2 -2
  8. package/dist/host/agents/skills/orkestrel-build-application/SKILL.md +42 -31
  9. package/dist/host/agents/skills/orkestrel-build-application/references/application.md +129 -0
  10. package/dist/host/agents/skills/orkestrel-debrief/SKILL.md +3 -3
  11. package/dist/host/agents/skills/orkestrel-debrief/references/field-testing.md +4 -4
  12. package/dist/host/agents/skills/orkestrel-debrief/references/instruction-audit.md +12 -0
  13. package/dist/host/agents/skills/orkestrel-falsify/SKILL.md +167 -0
  14. package/dist/host/agents/skills/orkestrel-falsify/references/brief.md +98 -0
  15. package/dist/host/agents/skills/orkestrel-falsify/references/reconcile.md +148 -0
  16. package/dist/host/agents/skills/orkestrel-harden-package/SKILL.md +4 -2
  17. package/dist/host/agents/skills/orkestrel-harden-package/references/centralization.md +5 -5
  18. package/dist/host/agents/skills/orkestrel-harden-package/references/research.md +2 -0
  19. package/dist/host/agents/skills/orkestrel-polish-surface/SKILL.md +11 -6
  20. package/dist/host/claude/agents/analyst.md +59 -0
  21. package/dist/host/claude/agents/application.md +1 -1
  22. package/dist/host/claude/agents/builder.md +1 -1
  23. package/dist/host/claude/agents/checker.md +5 -1
  24. package/dist/host/claude/agents/codex.md +120 -87
  25. package/dist/host/claude/agents/grok.md +44 -32
  26. package/dist/host/claude/agents/implementer.md +1 -1
  27. package/dist/host/claude/agents/orkestrel.md +3 -3
  28. package/dist/host/claude/agents/planner.md +9 -3
  29. package/dist/host/claude/agents/researcher.md +6 -5
  30. package/dist/host/claude/agents/reviewer.md +17 -6
  31. package/dist/host/claude/agents/scout.md +7 -4
  32. package/dist/host/claude/agents/verifier.md +1 -1
  33. package/dist/host/claude/rules/application.md +17 -16
  34. package/dist/host/claude/rules/architecture.md +41 -22
  35. package/dist/host/claude/rules/documentation.md +2 -1
  36. package/dist/host/claude/rules/names.md +7 -6
  37. package/dist/host/claude/rules/quality.md +71 -14
  38. package/dist/host/claude/rules/styles.md +1 -1
  39. package/dist/host/claude/rules/tests.md +18 -2
  40. package/dist/host/claude/rules/typescript.md +1 -1
  41. package/dist/host/claude/rules/workspace.md +6 -3
  42. package/dist/host/claude/settings.json +2 -0
  43. package/dist/host/claude/skills/orkestrel-falsify/SKILL.md +10 -0
  44. package/dist/host/codex/agents/analyst.toml +15 -2
  45. package/dist/host/codex/agents/checker.toml +1 -1
  46. package/dist/host/codex/agents/grok.toml +2 -1
  47. package/dist/host/codex/agents/opus.toml +1 -1
  48. package/dist/host/codex/agents/planner.toml +1 -1
  49. package/dist/host/codex/agents/researcher.toml +2 -2
  50. package/dist/host/codex/agents/reviewer.toml +4 -2
  51. package/dist/host/codex/agents/scout.toml +2 -2
  52. package/dist/host/codex/config.toml +23 -64
  53. package/dist/host/cursor/rules/orchestration.mdc +33 -0
  54. package/dist/host/guides/src/scaffold.md +419 -150
  55. package/dist/host/manifest.json +47 -1
  56. package/dist/host/tests/setupPolicy.ts +130 -12
  57. package/dist/src/core/index.cjs +2059 -913
  58. package/dist/src/core/index.cjs.map +1 -1
  59. package/dist/src/core/index.d.cts +202 -47
  60. package/dist/src/core/index.d.ts +202 -47
  61. package/dist/src/core/index.js +2050 -914
  62. package/dist/src/core/index.js.map +1 -1
  63. package/dist/src/server/index.cjs +83 -33
  64. package/dist/src/server/index.cjs.map +1 -1
  65. package/dist/src/server/index.d.cts +32 -16
  66. package/dist/src/server/index.d.ts +32 -16
  67. package/dist/src/server/index.js +84 -35
  68. package/dist/src/server/index.js.map +1 -1
  69. package/package.json +7 -5
@@ -1,5 +1,10 @@
1
1
  {
2
2
  "entries": [
3
+ {
4
+ "storage": "agents/orchestration.md",
5
+ "destination": ".agents/orchestration.md",
6
+ "executable": false
7
+ },
3
8
  {
4
9
  "storage": "agents/skills/enterprise-bootstrap/SKILL.md",
5
10
  "destination": ".agents/skills/enterprise-bootstrap/SKILL.md",
@@ -60,6 +65,11 @@
60
65
  "destination": ".agents/skills/orkestrel-build-application/agents/openai.yaml",
61
66
  "executable": false
62
67
  },
68
+ {
69
+ "storage": "agents/skills/orkestrel-build-application/references/application.md",
70
+ "destination": ".agents/skills/orkestrel-build-application/references/application.md",
71
+ "executable": false
72
+ },
63
73
  {
64
74
  "storage": "agents/skills/orkestrel-debrief/SKILL.md",
65
75
  "destination": ".agents/skills/orkestrel-debrief/SKILL.md",
@@ -80,6 +90,21 @@
80
90
  "destination": ".agents/skills/orkestrel-debrief/references/instruction-audit.md",
81
91
  "executable": false
82
92
  },
93
+ {
94
+ "storage": "agents/skills/orkestrel-falsify/SKILL.md",
95
+ "destination": ".agents/skills/orkestrel-falsify/SKILL.md",
96
+ "executable": false
97
+ },
98
+ {
99
+ "storage": "agents/skills/orkestrel-falsify/references/brief.md",
100
+ "destination": ".agents/skills/orkestrel-falsify/references/brief.md",
101
+ "executable": false
102
+ },
103
+ {
104
+ "storage": "agents/skills/orkestrel-falsify/references/reconcile.md",
105
+ "destination": ".agents/skills/orkestrel-falsify/references/reconcile.md",
106
+ "executable": false
107
+ },
83
108
  {
84
109
  "storage": "agents/skills/orkestrel-harden-package/SKILL.md",
85
110
  "destination": ".agents/skills/orkestrel-harden-package/SKILL.md",
@@ -125,6 +150,11 @@
125
150
  "destination": ".agents/skills/orkestrel-polish-surface/references/capture-harness.md",
126
151
  "executable": false
127
152
  },
153
+ {
154
+ "storage": "claude/agents/analyst.md",
155
+ "destination": ".claude/agents/analyst.md",
156
+ "executable": false
157
+ },
128
158
  {
129
159
  "storage": "claude/agents/application.md",
130
160
  "destination": ".claude/agents/application.md",
@@ -265,6 +295,11 @@
265
295
  "destination": ".claude/skills/orkestrel-debrief/SKILL.md",
266
296
  "executable": false
267
297
  },
298
+ {
299
+ "storage": "claude/skills/orkestrel-falsify/SKILL.md",
300
+ "destination": ".claude/skills/orkestrel-falsify/SKILL.md",
301
+ "executable": false
302
+ },
268
303
  {
269
304
  "storage": "claude/skills/orkestrel-harden-package/SKILL.md",
270
305
  "destination": ".claude/skills/orkestrel-harden-package/SKILL.md",
@@ -350,6 +385,11 @@
350
385
  "destination": ".cursor/mcp.json",
351
386
  "executable": false
352
387
  },
388
+ {
389
+ "storage": "cursor/rules/orchestration.mdc",
390
+ "destination": ".cursor/rules/orchestration.mdc",
391
+ "executable": false
392
+ },
353
393
  {
354
394
  "storage": "dotfiles/editorconfig",
355
395
  "destination": ".editorconfig",
@@ -452,9 +492,12 @@
452
492
  ".agents/skills/orkestrel-align-packages/references",
453
493
  ".agents/skills/orkestrel-build-application",
454
494
  ".agents/skills/orkestrel-build-application/agents",
495
+ ".agents/skills/orkestrel-build-application/references",
455
496
  ".agents/skills/orkestrel-debrief",
456
497
  ".agents/skills/orkestrel-debrief/agents",
457
498
  ".agents/skills/orkestrel-debrief/references",
499
+ ".agents/skills/orkestrel-falsify",
500
+ ".agents/skills/orkestrel-falsify/references",
458
501
  ".agents/skills/orkestrel-harden-package",
459
502
  ".agents/skills/orkestrel-harden-package/agents",
460
503
  ".agents/skills/orkestrel-harden-package/references",
@@ -469,14 +512,17 @@
469
512
  ".claude/skills/orkestrel-align-packages",
470
513
  ".claude/skills/orkestrel-build-application",
471
514
  ".claude/skills/orkestrel-debrief",
515
+ ".claude/skills/orkestrel-falsify",
472
516
  ".claude/skills/orkestrel-harden-package",
473
517
  ".claude/skills/orkestrel-polish-surface",
474
518
  ".codex",
475
519
  ".codex/agents",
476
520
  ".cursor",
521
+ ".cursor/rules",
477
522
  "guides",
478
523
  "guides/src",
479
524
  "scripts",
480
525
  "tests"
481
- ]
526
+ ],
527
+ "digest": "e4351919e4d34e3696ee3ce77e2cce555c20acc58a29649cd9f3c489f3d0bf2b"
482
528
  }
@@ -1,6 +1,6 @@
1
1
  import { globSync, readFileSync } from 'node:fs'
2
2
  import { isBuiltin } from 'node:module'
3
- import { basename, join } from 'node:path'
3
+ import { basename, extname, join } from 'node:path'
4
4
  import * as ts from 'typescript'
5
5
 
6
6
  /** Centralized source modules whose top-level declarations must all be exported. */
@@ -18,6 +18,7 @@ export const CENTRAL_SOURCE_FILES: readonly string[] = Object.freeze([
18
18
  'middlewares.ts',
19
19
  'parsers.ts',
20
20
  'relations.ts',
21
+ 'routes.ts',
21
22
  'schemas.ts',
22
23
  'seeders.ts',
23
24
  'shapers.ts',
@@ -39,6 +40,7 @@ export const FUNCTION_SOURCE_FILES: readonly string[] = Object.freeze([
39
40
  'middlewares.ts',
40
41
  'parsers.ts',
41
42
  'relations.ts',
43
+ 'routes.ts',
42
44
  'schemas.ts',
43
45
  'seeders.ts',
44
46
  'shapers.ts',
@@ -51,12 +53,16 @@ export const DATA_SOURCE_FILES: readonly string[] = Object.freeze([
51
53
  'constants.ts',
52
54
  'contracts.ts',
53
55
  'relations.ts',
56
+ 'routes.ts',
54
57
  'schemas.ts',
55
58
  'shapers.ts',
56
59
  'templates.ts',
57
60
  'validators.ts',
58
61
  ])
59
62
 
63
+ /** Domain folders whose modules each export one named function rather than one class. */
64
+ export const FUNCTION_DOMAIN_FOLDERS: readonly string[] = Object.freeze(['app/browser/composables'])
65
+
60
66
  /** Worker-only value globals that WebWorker typing must not expose to core implementations. */
61
67
  export const WORKER_SCOPE_VALUE_GLOBALS: readonly string[] = Object.freeze([
62
68
  'name',
@@ -90,6 +96,22 @@ export const WORKER_SCOPE_VALUE_GLOBALS: readonly string[] = Object.freeze([
90
96
  'removeEventListener',
91
97
  ])
92
98
 
99
+ /** Source extensions inspected by the repository coding-law sweep. */
100
+ export const CODING_SOURCE_EXTENSIONS: readonly string[] = Object.freeze([
101
+ 'cjs',
102
+ 'cts',
103
+ 'js',
104
+ 'jsx',
105
+ 'mjs',
106
+ 'mts',
107
+ 'ts',
108
+ 'tsx',
109
+ 'vue',
110
+ ])
111
+
112
+ /** Production-source glob derived from the complete inspected extension vocabulary. */
113
+ export const CODING_SOURCE_GLOB = `{app,src}/**/*.{${CODING_SOURCE_EXTENSIONS.join(',')}}`
114
+
93
115
  /** Virtual source text used while binding one policy-inspected module. */
94
116
  export const POLICY_SOURCE_TEXTS: Map<string, string> = new Map()
95
117
 
@@ -109,6 +131,39 @@ export function normalizePolicyPath(path: string): string {
109
131
  return path.replaceAll('\\', '/').replace(/\/+/gu, '/')
110
132
  }
111
133
 
134
+ /** Whether a path belongs to the production-source coding-law corpus. */
135
+ export function isCodingSourcePath(path: string): boolean {
136
+ const normalized = normalizePolicyPath(path)
137
+ const extension = normalized.split('.').pop()
138
+ return (
139
+ (normalized.startsWith('app/') || normalized.startsWith('src/')) &&
140
+ extension !== undefined &&
141
+ CODING_SOURCE_EXTENSIONS.includes(extension)
142
+ )
143
+ }
144
+
145
+ /**
146
+ * Whether a path is an eligible function-domain module.
147
+ *
148
+ * @param path - The workspace-relative source path to inspect
149
+ * @returns `true` when the path is a direct module of a registered function domain
150
+ */
151
+ export function isFunctionDomainPath(path: string): boolean {
152
+ const normalized = normalizePolicyPath(path)
153
+ const file = basename(normalized)
154
+ const separator = normalized.lastIndexOf('/')
155
+ const parent = separator < 0 ? '' : normalized.slice(0, separator)
156
+ return (
157
+ FUNCTION_DOMAIN_FOLDERS.includes(parent) &&
158
+ /^[a-z][A-Za-z0-9]*\.ts$/u.test(file) &&
159
+ file !== 'index.ts' &&
160
+ file !== 'main.ts' &&
161
+ !CENTRAL_SOURCE_FILES.includes(file) &&
162
+ !FUNCTION_SOURCE_FILES.includes(file) &&
163
+ !DATA_SOURCE_FILES.includes(file)
164
+ )
165
+ }
166
+
112
167
  /** Whether a declaration carries an explicit export modifier. */
113
168
  export function hasExportModifier(node: ts.Node): boolean {
114
169
  return (
@@ -416,6 +471,31 @@ export function inspectVueCodingLaw(
416
471
  return violations
417
472
  }
418
473
 
474
+ /** Inspect one production source through the shared coding-law route. */
475
+ export function inspectCodingSource(
476
+ path: string,
477
+ content: string,
478
+ vueScripts?: VueScriptExtractorInterface,
479
+ ): readonly string[] {
480
+ const normalizedPath = normalizePolicyPath(path)
481
+ if (!normalizedPath.endsWith('.vue')) return inspectCodingLaw(normalizedPath, content)
482
+ const violations: string[] = []
483
+ if (!normalizedPath.startsWith('app/browser/')) {
484
+ violations.push(`${normalizedPath} Vue components belong in app/browser`)
485
+ }
486
+ // A missing extractor is reported, never absorbed. Returning [] here would make
487
+ // every SFC's script block silently unchecked while the surrounding sweep still
488
+ // reported success — an instrument claiming a coverage it does not have.
489
+ if (vueScripts === undefined) {
490
+ violations.push(
491
+ `${normalizedPath} requires a Vue script extractor; its script blocks were not inspected`,
492
+ )
493
+ return violations
494
+ }
495
+ violations.push(...inspectVueCodingLaw(normalizedPath, vueScripts(normalizedPath, content)))
496
+ return violations
497
+ }
498
+
419
499
  /** Add syntax-wide coding-law violations while traversing one source tree. */
420
500
  export function inspectCodingNode(
421
501
  path: string,
@@ -490,6 +570,34 @@ export function inspectCodingNode(
490
570
  ts.forEachChild(node, (child) => inspectCodingNode(path, child, violations, checker))
491
571
  }
492
572
 
573
+ /**
574
+ * Inspect one eligible function-domain module for its required declaration shape.
575
+ *
576
+ * @param path - The source path used in diagnostics
577
+ * @param source - The parsed source file to inspect
578
+ * @returns A shape violation when the module is not imports plus one matching named export
579
+ */
580
+ export function inspectFunctionModule(path: string, source: ts.SourceFile): readonly string[] {
581
+ const file = basename(normalizePolicyPath(path))
582
+ const declarations = source.statements.filter(ts.isFunctionDeclaration)
583
+ const functions = declarations.filter((declaration) => declaration.body !== undefined)
584
+ const invalid = source.statements.filter(
585
+ (statement) => !ts.isImportDeclaration(statement) && !ts.isFunctionDeclaration(statement),
586
+ )
587
+ const declaration = functions[0]
588
+ if (
589
+ functions.length === 1 &&
590
+ invalid.length === 0 &&
591
+ declarations.every((candidate) => candidate.name?.text === file.slice(0, -3)) &&
592
+ declaration !== undefined &&
593
+ hasExportModifier(declaration) &&
594
+ !hasModifier(declaration, ts.SyntaxKind.DefaultKeyword)
595
+ ) {
596
+ return []
597
+ }
598
+ return [`${path} declarations do not form one matching exported function implementation`]
599
+ }
600
+
493
601
  /** Inspect one TypeScript source module for repository coding-law violations. */
494
602
  export function inspectCodingLaw(path: string, content: string): readonly string[] {
495
603
  const violations: string[] = []
@@ -498,6 +606,8 @@ export function inspectCodingLaw(path: string, content: string): readonly string
498
606
  if (source === undefined) throw new Error(`Policy source was not bound at ${path}`)
499
607
  const checker = program.getTypeChecker()
500
608
  const file = basename(path)
609
+ const stem = basename(file, extname(file))
610
+ const functionModule = isFunctionDomainPath(path)
501
611
  const placementExempt =
502
612
  !CENTRAL_SOURCE_FILES.includes(file) &&
503
613
  !FUNCTION_SOURCE_FILES.includes(file) &&
@@ -507,6 +617,9 @@ export function inspectCodingLaw(path: string, content: string): readonly string
507
617
  if (/\.[cm]?jsx?$/u.test(path)) {
508
618
  violations.push(`${path} production modules use TypeScript source extensions`)
509
619
  }
620
+ if (FUNCTION_DOMAIN_FOLDERS.some((folder) => basename(folder) === stem)) {
621
+ violations.push(`${path} names a function domain, which belongs in a folder rather than a file`)
622
+ }
510
623
  if (/@ts-(?:expect-error|ignore|nocheck)|eslint-disable|oxlint-disable/u.test(content)) {
511
624
  violations.push(`${path} forbids suppression directives`)
512
625
  }
@@ -552,6 +665,7 @@ export function inspectCodingLaw(path: string, content: string): readonly string
552
665
  }
553
666
  if (
554
667
  !placementExempt &&
668
+ !functionModule &&
555
669
  ts.isFunctionDeclaration(statement) &&
556
670
  !FUNCTION_SOURCE_FILES.includes(file)
557
671
  ) {
@@ -559,6 +673,7 @@ export function inspectCodingLaw(path: string, content: string): readonly string
559
673
  }
560
674
  if (
561
675
  !placementExempt &&
676
+ !functionModule &&
562
677
  ts.isVariableStatement(statement) &&
563
678
  !DATA_SOURCE_FILES.includes(file)
564
679
  ) {
@@ -600,6 +715,10 @@ export function inspectCodingLaw(path: string, content: string): readonly string
600
715
  }
601
716
  }
602
717
 
718
+ if (functionModule) {
719
+ violations.push(...inspectFunctionModule(path, source))
720
+ }
721
+
603
722
  if (/^[A-Z][A-Za-z0-9]*\.ts$/u.test(file)) {
604
723
  const classes = source.statements.filter(ts.isClassDeclaration)
605
724
  const invalid = source.statements.filter(
@@ -627,25 +746,24 @@ export function inspectCodingLaw(path: string, content: string): readonly string
627
746
  return violations
628
747
  }
629
748
 
630
- /** Inspect every production TypeScript module under one workspace. */
749
+ /**
750
+ * Inspect every production source under one workspace.
751
+ *
752
+ * @remarks
753
+ * `vueScripts` is required whenever the workspace contains a `.vue` file: script
754
+ * blocks cannot be read without it, and omitting it is reported as a violation
755
+ * against each SFC rather than passing silently.
756
+ */
631
757
  export function inspectCodingWorkspace(
632
758
  root: string,
633
759
  vueScripts?: VueScriptExtractorInterface,
634
760
  ): readonly string[] {
635
761
  const violations: string[] = []
636
- for (const path of globSync('{app,src}/**/*.{cjs,cts,js,jsx,mjs,mts,ts,tsx,vue}', {
762
+ for (const path of globSync(CODING_SOURCE_GLOB, {
637
763
  cwd: root,
638
764
  })) {
639
765
  const content = readFileSync(join(root, path), 'utf8')
640
- const normalizedPath = normalizePolicyPath(path)
641
- if (path.endsWith('.vue') && !normalizedPath.startsWith('app/browser/')) {
642
- violations.push(`${normalizedPath} Vue components belong in app/browser`)
643
- }
644
- violations.push(
645
- ...(path.endsWith('.vue')
646
- ? inspectVueCodingLaw(normalizedPath, vueScripts?.(normalizedPath, content))
647
- : inspectCodingLaw(normalizedPath, content)),
648
- )
766
+ violations.push(...inspectCodingSource(path, content, vueScripts))
649
767
  }
650
768
  return violations
651
769
  }