static-shards.ts 3.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  1. /** Static-gate shard definitions for GitHub Actions. */
  2. /** A static CI lane identified by the gate IDs it owns. */
  3. export interface StaticShard {
  4. /** Stable lane identifier passed through `DSH_STATIC_SHARD`. */
  5. name: string
  6. /** Gate IDs selected from the static gate inventory. */
  7. gateIds: readonly string[]
  8. }
  9. /** Exhaustive, non-overlapping ownership of static CI gates. */
  10. export const staticShards = [
  11. {
  12. name: 'foundation',
  13. gateIds: [
  14. 'runtime-closure',
  15. 'constraints',
  16. 'package-invariants',
  17. 'cordis-config',
  18. 'module-graph',
  19. 'knip',
  20. ],
  21. },
  22. { name: 'doc-types', gateIds: ['build', 'doc-typecheck'] },
  23. {
  24. name: 'api-contracts',
  25. gateIds: ['cordis-api', 'export-jsdoc', 'scoped-events', 'type-equivalence'],
  26. },
  27. {
  28. name: 'catalogs',
  29. gateIds: ['cordis-catalog', 'tool-catalog', 'config-catalog', 'persistence-catalog', 'doc-graphs'],
  30. },
  31. {
  32. name: 'prose',
  33. gateIds: [
  34. 'markdown-wrap',
  35. 'markdown-links',
  36. 'doc-refs',
  37. 'package-paths',
  38. 'package-readme-model-experience',
  39. 'mermaid',
  40. 'agent-note-classification',
  41. 'agent-note-format',
  42. 'translation-prompt',
  43. 'translation-pairing',
  44. 'doc-budgets',
  45. 'package-readme-limitations',
  46. ],
  47. },
  48. { name: 'site-projection', gateIds: ['docs-site-projection'] },
  49. { name: 'site-build', gateIds: ['docs-site-build'] },
  50. ] as const satisfies readonly StaticShard[]
  51. /**
  52. * Validate the complete gate partition and optionally select one lane.
  53. *
  54. * @param gates Complete static gate inventory.
  55. * @param name Optional comma-separated stable shard names.
  56. * @returns All gates when no shard is requested, otherwise the selected lanes in inventory order.
  57. */
  58. export function selectStaticGates<T extends { id: string }>(gates: readonly T[], name?: string): T[] {
  59. const gateIds = gates.map(gate => gate.id)
  60. const assignedIds = staticShards.flatMap(shard => shard.gateIds)
  61. const uniqueGateIds = new Set<string>(gateIds)
  62. const uniqueAssignedIds = new Set<string>(assignedIds)
  63. if (uniqueGateIds.size !== gateIds.length) throw new Error('run-gates: static gate IDs must be unique.')
  64. if (uniqueAssignedIds.size !== assignedIds.length) throw new Error('run-gates: static shard gate IDs must be unique.')
  65. if (gateIds.length !== assignedIds.length
  66. || gateIds.some(id => !uniqueAssignedIds.has(id))
  67. || assignedIds.some(id => !uniqueGateIds.has(id))) {
  68. throw new Error('run-gates: static shards must assign every static gate exactly once.')
  69. }
  70. if (name === undefined || name === '') return [...gates]
  71. const shardNames = name.split(',')
  72. if (shardNames.some(shardName => shardName === '') || new Set(shardNames).size !== shardNames.length) {
  73. throw new Error(`run-gates: DSH_STATIC_SHARD names must be nonempty and unique, got ${JSON.stringify(name)}.`)
  74. }
  75. const selectedShards = shardNames.map((shardName) => {
  76. const shard = staticShards.find(candidate => candidate.name === shardName)
  77. if (shard === undefined) throw new Error(`run-gates: unknown DSH_STATIC_SHARD ${JSON.stringify(shardName)}.`)
  78. return shard
  79. })
  80. const selectedIds = new Set<string>(selectedShards.flatMap(shard => shard.gateIds))
  81. return gates.filter(gate => selectedIds.has(gate.id))
  82. }