coverage-shards.ts 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. /** Coverage shard definitions for the GitHub Actions source-test lanes. */
  2. /** A coverage lane that owns complete package roots and optional cross-package tests. */
  3. export interface CoverageShard {
  4. /** Stable lane identifier passed through `DSH_COVERAGE_SHARD`. */
  5. name: string
  6. /** Group or package paths below `packages/` whose tests and source coverage belong to the lane. */
  7. packageRoots: readonly string[]
  8. /** Additional test roots needed for cross-package behavior or repository scripts. */
  9. extraTestRoots?: readonly string[]
  10. }
  11. /** Exhaustive, non-overlapping ownership of workspace packages in coverage CI. */
  12. export const coverageShards = [
  13. {
  14. name: 'core-loop',
  15. packageRoots: ['core/agent', 'core/agent-loop', 'core/tools'],
  16. },
  17. {
  18. name: 'state-session',
  19. packageRoots: [
  20. 'core/session',
  21. 'core/scope',
  22. 'core/system-prompt',
  23. 'context',
  24. 'session-persistence',
  25. 'session-query',
  26. 'support/invariants',
  27. ],
  28. extraTestRoots: [
  29. 'packages/examples/cli-demo/tests',
  30. 'packages/llm/token-meter/tests',
  31. 'scripts',
  32. ],
  33. },
  34. {
  35. name: 'models',
  36. packageRoots: ['llm', 'compact'],
  37. },
  38. {
  39. name: 'session-title',
  40. packageRoots: ['session-title'],
  41. },
  42. {
  43. name: 'integrations',
  44. packageRoots: ['hooks/hook-protocol', 'lsp', 'mcp', 'hooks/hooks-claude'],
  45. },
  46. {
  47. name: 'sdk-capabilities',
  48. packageRoots: [
  49. 'sdk',
  50. 'hooks/hooks-codex',
  51. 'web',
  52. 'skill',
  53. 'spill',
  54. 'util',
  55. 'guard',
  56. 'todo',
  57. 'timeout',
  58. ],
  59. },
  60. {
  61. name: 'interfaces',
  62. packageRoots: ['ui', 'examples', 'goal'],
  63. extraTestRoots: ['examples'],
  64. },
  65. { name: 'execution', packageRoots: ['fs', 'bash', 'sandbox', 'code-runtime'] },
  66. {
  67. name: 'workflow',
  68. packageRoots: ['workflow/workflow', 'workflow/tool-workflow', 'workflow/tool-ralph'],
  69. },
  70. {
  71. name: 'workflow-worker',
  72. packageRoots: ['workflow/workflow-workerthread'],
  73. },
  74. { name: 'delegation', packageRoots: ['subagent', 'tasks'] },
  75. {
  76. name: 'repository',
  77. packageRoots: [
  78. 'cordis',
  79. 'support/acp-snapshot',
  80. 'support/agent-loop-testkit',
  81. 'support/llm-replay',
  82. 'support/loader-smoke',
  83. ],
  84. },
  85. ] as const satisfies readonly CoverageShard[]
  86. /**
  87. * Build Vitest filters and coverage include globs for one source-test lane.
  88. *
  89. * @param name Stable shard name from {@link coverageShards}.
  90. * @returns Positional test roots followed by per-group coverage include flags.
  91. */
  92. export function coverageArgs(name: string): string[] {
  93. const shard = coverageShards.find(candidate => candidate.name === name)
  94. if (shard === undefined) {
  95. throw new Error(`run-gates: unknown DSH_COVERAGE_SHARD ${JSON.stringify(name)}.`)
  96. }
  97. // Vitest positional filters are substrings; the trailing separator keeps
  98. // prefix-named sibling packages out of each lane.
  99. const testRoots = new Set([
  100. ...shard.packageRoots.map(packageRoot => `packages/${packageRoot}/`),
  101. ...('extraTestRoots' in shard ? shard.extraTestRoots.map(testRoot => `${testRoot}/`) : []),
  102. 'scripts/test-invariants.spec.ts',
  103. ])
  104. return [
  105. ...testRoots,
  106. ...shard.packageRoots.map(packageRoot => packageRoot.includes('/')
  107. ? `--coverage.include=packages/${packageRoot}/src/**/*.ts`
  108. : `--coverage.include=packages/${packageRoot}/*/src/**/*.ts`),
  109. ]
  110. }