@cat-factory/orchestration 0.230.0 → 0.231.0

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 (32) hide show
  1. package/dist/modules/execution/ExecutionService.d.ts +10 -8
  2. package/dist/modules/execution/ExecutionService.d.ts.map +1 -1
  3. package/dist/modules/execution/ExecutionService.js +20 -11
  4. package/dist/modules/execution/ExecutionService.js.map +1 -1
  5. package/dist/modules/execution/PrVerificationReportController.d.ts +35 -39
  6. package/dist/modules/execution/PrVerificationReportController.d.ts.map +1 -1
  7. package/dist/modules/execution/PrVerificationReportController.js +62 -80
  8. package/dist/modules/execution/PrVerificationReportController.js.map +1 -1
  9. package/dist/modules/execution/RunEvidenceLoader.d.ts +79 -0
  10. package/dist/modules/execution/RunEvidenceLoader.d.ts.map +1 -0
  11. package/dist/modules/execution/RunEvidenceLoader.js +114 -0
  12. package/dist/modules/execution/RunEvidenceLoader.js.map +1 -0
  13. package/dist/modules/execution/RunEvidenceReads.d.ts +53 -0
  14. package/dist/modules/execution/RunEvidenceReads.d.ts.map +1 -0
  15. package/dist/modules/execution/RunEvidenceReads.js +57 -0
  16. package/dist/modules/execution/RunEvidenceReads.js.map +1 -0
  17. package/dist/modules/execution/ci.logic.d.ts +8 -2
  18. package/dist/modules/execution/ci.logic.d.ts.map +1 -1
  19. package/dist/modules/execution/ci.logic.js +8 -4
  20. package/dist/modules/execution/ci.logic.js.map +1 -1
  21. package/dist/modules/execution/prReport.logic.d.ts.map +1 -1
  22. package/dist/modules/execution/prReport.logic.js +53 -45
  23. package/dist/modules/execution/prReport.logic.js.map +1 -1
  24. package/dist/modules/execution/prReport.steps.d.ts +4 -0
  25. package/dist/modules/execution/prReport.steps.d.ts.map +1 -1
  26. package/dist/modules/execution/prReport.steps.js +6 -6
  27. package/dist/modules/execution/prReport.steps.js.map +1 -1
  28. package/dist/modules/execution/runOutcome.boundary.d.ts +11 -0
  29. package/dist/modules/execution/runOutcome.boundary.d.ts.map +1 -0
  30. package/dist/modules/execution/runOutcome.boundary.js +163 -0
  31. package/dist/modules/execution/runOutcome.boundary.js.map +1 -0
  32. package/package.json +11 -11
@@ -1 +1 @@
1
- {"version":3,"file":"PrVerificationReportController.js","sourceRoot":"","sources":["../../../src/modules/execution/PrVerificationReportController.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"PrVerificationReportController.js","sourceRoot":"","sources":["../../../src/modules/execution/PrVerificationReportController.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,79 @@
1
+ import type { Block, BlockRepository, ExecutionInstance, ResolveRunRepoContext, SpecDoc } from '@cat-factory/kernel';
2
+ import type { ServiceSpecView } from '@cat-factory/contracts';
3
+ /** What a run's evidence reductions read before they compose anything. */
4
+ export interface RunEvidence {
5
+ block: Block;
6
+ /**
7
+ * The service's in-repo `spec/` as it stands on the RUN's branch, or null when it could not be
8
+ * read at all (no VCS wired, no repo resolved, a transport failure, or a tester that has not
9
+ * reported yet). Every consumer reports that absence explicitly rather than as a clean, empty
10
+ * coverage section.
11
+ *
12
+ * The read VIEW rather than the doc, because the SPA's outcome card is served this same answer
13
+ * over {@link RunEvidenceLoader.specViewForRun} and a `present: false` spec (a repo that
14
+ * carries no `spec/`) is a different fact from an unread one.
15
+ */
16
+ specView: ServiceSpecView | null;
17
+ }
18
+ /** The doc a reduction counts against, or null when there is none. */
19
+ export declare function specDocOf(view: ServiceSpecView | null): SpecDoc | null;
20
+ export interface RunEvidenceLoaderDeps {
21
+ blockRepository: BlockRepository;
22
+ /**
23
+ * Optional: per-run, checkout-free repo access, used to reassemble the service's `spec/`.
24
+ * Absent (tests, a no-VCS deployment) ⇒ `spec` is null and each consumer says so.
25
+ */
26
+ resolveRunRepoContext?: ResolveRunRepoContext;
27
+ }
28
+ export declare class RunEvidenceLoader {
29
+ private readonly deps;
30
+ constructor(deps: RunEvidenceLoaderDeps);
31
+ /**
32
+ * Read a run's block and its service spec. Null when the block is gone, which is the only way
33
+ * a run has nothing to report on at all.
34
+ */
35
+ load(workspaceId: string, instance: ExecutionInstance): Promise<RunEvidence | null>;
36
+ /**
37
+ * The run's `spec/` as a read VIEW, for the SPA's outcome card.
38
+ *
39
+ * The card composes `composeRunOutcome` live off its own store, so the ONE input it cannot
40
+ * derive from pushed state is this spec, and it used to fetch the SERVICE's spec from the
41
+ * repo's DEFAULT branch. That is a different document: the requirement ids this run's verdicts
42
+ * name are on the run's own branch until the pull request merges, so every one of them landed
43
+ * as "not checked" and the card's counts contradicted `GET /api/v1/runs/:runId/outcome` for the
44
+ * same run. Served from here, the two read one branch through one rule.
45
+ *
46
+ * `EMPTY_SERVICE_SPEC_VIEW` rather than null on an unread spec: the card's own composer already
47
+ * treats an absent spec as `spec: 'not_read'` and says so, and the read is best-effort by
48
+ * design (see {@link serviceSpec}).
49
+ */
50
+ specViewForRun(workspaceId: string, instance: ExecutionInstance): Promise<ServiceSpecView>;
51
+ /**
52
+ * The service's in-repo `spec/`, reassembled from the run's branch for the requirement →
53
+ * evidence join. Null whenever it could not be read, which every consumer reports with a
54
+ * stated absence rather than a blank.
55
+ *
56
+ * GATED, then MEMOISED, because this is the only repo-reading path either reduction has and
57
+ * the PR-report hook fires on EVERY settled step:
58
+ * - Gate: nothing is read until a tester step has actually produced a report. Before that the
59
+ * coverage answer is already determined ("no tester step" / "no report yet"), so a read
60
+ * would buy nothing; this keeps the ~15 settlements before the tester at zero repo calls.
61
+ * - Memo: reassembling the sharded tree costs one read per module + per group, so the handful
62
+ * of settlements AFTER the tester would otherwise repeat it each time.
63
+ *
64
+ * The memo deliberately holds the spec as it stood when the tester ruled. That is the tree the
65
+ * verdicts were made against, so pairing a later re-read with those same verdicts would be less
66
+ * truthful, not more, and the promotion post-op rewrites the spec on this very branch right
67
+ * after the tester settles.
68
+ *
69
+ * Only an ANSWER is memoised: a tree that was read, or a repo that demonstrably carries no
70
+ * `spec/`. A FAILURE (an unresolvable repo, a throwing transport) is not: caching it would turn
71
+ * one flaky read into "the spec could not be read" for the rest of the run, when the very next
72
+ * settlement would have succeeded.
73
+ */
74
+ private serviceSpec;
75
+ /** Per-execution spec memo, bounded by {@link MAX_TRACKED_RUNS}. */
76
+ private readonly specByRun;
77
+ private rememberSpec;
78
+ }
79
+ //# sourceMappingURL=RunEvidenceLoader.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RunEvidenceLoader.d.ts","sourceRoot":"","sources":["../../../src/modules/execution/RunEvidenceLoader.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,KAAK,EACL,eAAe,EACf,iBAAiB,EACjB,qBAAqB,EACrB,OAAO,EACR,MAAM,qBAAqB,CAAA;AAC5B,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAA;AAiB7D,0EAA0E;AAC1E,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,KAAK,CAAA;IACZ;;;;;;;;;OASG;IACH,QAAQ,EAAE,eAAe,GAAG,IAAI,CAAA;CACjC;AAED,sEAAsE;AACtE,wBAAgB,SAAS,CAAC,IAAI,EAAE,eAAe,GAAG,IAAI,GAAG,OAAO,GAAG,IAAI,CAEtE;AAED,MAAM,WAAW,qBAAqB;IACpC,eAAe,EAAE,eAAe,CAAA;IAChC;;;OAGG;IACH,qBAAqB,CAAC,EAAE,qBAAqB,CAAA;CAC9C;AAWD,qBAAa,iBAAiB;IAChB,OAAO,CAAC,QAAQ,CAAC,IAAI;IAAjC,YAA6B,IAAI,EAAE,qBAAqB,EAAI;IAE5D;;;OAGG;IACG,IAAI,CAAC,WAAW,EAAE,MAAM,EAAE,QAAQ,EAAE,iBAAiB,GAAG,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC,CAIxF;IAED;;;;;;;;;;;;;OAaG;IACG,cAAc,CAAC,WAAW,EAAE,MAAM,EAAE,QAAQ,EAAE,iBAAiB,GAAG,OAAO,CAAC,eAAe,CAAC,CAI/F;IAED;;;;;;;;;;;;;;;;;;;;;;OAsBG;YACW,WAAW;IA8BzB,oEAAoE;IACpE,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAqC;IAE/D,OAAO,CAAC,YAAY;CASrB"}
@@ -0,0 +1,114 @@
1
+ import { EMPTY_SERVICE_SPEC_VIEW, isTesterKind, runSpecBranch } from '@cat-factory/contracts';
2
+ import { readServiceSpec } from '@cat-factory/agents';
3
+ /** The doc a reduction counts against, or null when there is none. */
4
+ export function specDocOf(view) {
5
+ return view?.present ? view.spec : null;
6
+ }
7
+ /**
8
+ * How many runs' spec answers are memoised. A long-lived Node replica serves an unbounded number
9
+ * of runs and each entry holds a reassembled tree, so the map is bounded here rather than relying
10
+ * on a call site to evict finished runs (a coupling that would silently leak the moment a new
11
+ * terminal path forgot to call it). Oldest-first eviction: `Map` preserves insertion order, and
12
+ * evicting an entry only costs one repeated read.
13
+ */
14
+ const MAX_TRACKED_RUNS = 256;
15
+ export class RunEvidenceLoader {
16
+ deps;
17
+ constructor(deps) {
18
+ this.deps = deps;
19
+ }
20
+ /**
21
+ * Read a run's block and its service spec. Null when the block is gone, which is the only way
22
+ * a run has nothing to report on at all.
23
+ */
24
+ async load(workspaceId, instance) {
25
+ const block = await this.deps.blockRepository.get(workspaceId, instance.blockId);
26
+ if (!block)
27
+ return null;
28
+ return { block, specView: await this.serviceSpec(workspaceId, instance, block) };
29
+ }
30
+ /**
31
+ * The run's `spec/` as a read VIEW, for the SPA's outcome card.
32
+ *
33
+ * The card composes `composeRunOutcome` live off its own store, so the ONE input it cannot
34
+ * derive from pushed state is this spec, and it used to fetch the SERVICE's spec from the
35
+ * repo's DEFAULT branch. That is a different document: the requirement ids this run's verdicts
36
+ * name are on the run's own branch until the pull request merges, so every one of them landed
37
+ * as "not checked" and the card's counts contradicted `GET /api/v1/runs/:runId/outcome` for the
38
+ * same run. Served from here, the two read one branch through one rule.
39
+ *
40
+ * `EMPTY_SERVICE_SPEC_VIEW` rather than null on an unread spec: the card's own composer already
41
+ * treats an absent spec as `spec: 'not_read'` and says so, and the read is best-effort by
42
+ * design (see {@link serviceSpec}).
43
+ */
44
+ async specViewForRun(workspaceId, instance) {
45
+ const block = await this.deps.blockRepository.get(workspaceId, instance.blockId);
46
+ if (!block)
47
+ return EMPTY_SERVICE_SPEC_VIEW;
48
+ return (await this.serviceSpec(workspaceId, instance, block)) ?? EMPTY_SERVICE_SPEC_VIEW;
49
+ }
50
+ /**
51
+ * The service's in-repo `spec/`, reassembled from the run's branch for the requirement →
52
+ * evidence join. Null whenever it could not be read, which every consumer reports with a
53
+ * stated absence rather than a blank.
54
+ *
55
+ * GATED, then MEMOISED, because this is the only repo-reading path either reduction has and
56
+ * the PR-report hook fires on EVERY settled step:
57
+ * - Gate: nothing is read until a tester step has actually produced a report. Before that the
58
+ * coverage answer is already determined ("no tester step" / "no report yet"), so a read
59
+ * would buy nothing; this keeps the ~15 settlements before the tester at zero repo calls.
60
+ * - Memo: reassembling the sharded tree costs one read per module + per group, so the handful
61
+ * of settlements AFTER the tester would otherwise repeat it each time.
62
+ *
63
+ * The memo deliberately holds the spec as it stood when the tester ruled. That is the tree the
64
+ * verdicts were made against, so pairing a later re-read with those same verdicts would be less
65
+ * truthful, not more, and the promotion post-op rewrites the spec on this very branch right
66
+ * after the tester settles.
67
+ *
68
+ * Only an ANSWER is memoised: a tree that was read, or a repo that demonstrably carries no
69
+ * `spec/`. A FAILURE (an unresolvable repo, a throwing transport) is not: caching it would turn
70
+ * one flaky read into "the spec could not be read" for the rest of the run, when the very next
71
+ * settlement would have succeeded.
72
+ */
73
+ async serviceSpec(workspaceId, instance, block) {
74
+ const resolve = this.deps.resolveRunRepoContext;
75
+ if (!resolve)
76
+ return null;
77
+ const testerReported = instance.steps.some((s) => isTesterKind(s.agentKind) && s.test?.lastReport != null);
78
+ if (!testerReported)
79
+ return null;
80
+ const cached = this.specByRun.get(instance.id);
81
+ if (cached !== undefined)
82
+ return cached;
83
+ try {
84
+ const ctx = await resolve(workspaceId, instance.blockId);
85
+ if (!ctx)
86
+ return null;
87
+ // Read the RUN's branch, not the repo default: the spec increment this task wrote is on
88
+ // the PR branch and has not merged yet, so the default branch would be missing exactly
89
+ // the requirements the tester just ruled on. The rule is `runSpecBranch` rather than a
90
+ // local `??` because the SPA answers the same question and the two had already drifted.
91
+ const view = await readServiceSpec(ctx.repo, runSpecBranch(block, ctx.baseBranch));
92
+ this.rememberSpec(instance.id, view);
93
+ return view;
94
+ }
95
+ catch {
96
+ // Best-effort: an unreadable spec is reported as such by each consumer, never fails a run,
97
+ // and is re-attempted on the next settlement.
98
+ return null;
99
+ }
100
+ }
101
+ /** Per-execution spec memo, bounded by {@link MAX_TRACKED_RUNS}. */
102
+ specByRun = new Map();
103
+ rememberSpec(executionId, spec) {
104
+ this.specByRun.delete(executionId);
105
+ this.specByRun.set(executionId, spec);
106
+ while (this.specByRun.size > MAX_TRACKED_RUNS) {
107
+ const oldest = this.specByRun.keys().next();
108
+ if (oldest.done)
109
+ break;
110
+ this.specByRun.delete(oldest.value);
111
+ }
112
+ }
113
+ }
114
+ //# sourceMappingURL=RunEvidenceLoader.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RunEvidenceLoader.js","sourceRoot":"","sources":["../../../src/modules/execution/RunEvidenceLoader.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,53 @@
1
+ import type { ExecutionInstance } from '@cat-factory/kernel';
2
+ import type { PrVerificationReport, RunOutcome, ServiceSpecView } from '@cat-factory/contracts';
3
+ /**
4
+ * Bound callbacks rather than the collaborators themselves, so this stays testable standalone and
5
+ * cannot reach for anything its three reads do not need.
6
+ */
7
+ export interface RunEvidenceReadsDeps {
8
+ /** Resolve a run within a workspace. Null when the workspace has no such run. */
9
+ getInstance(workspaceId: string, executionId: string): Promise<ExecutionInstance | null>;
10
+ composeReport(workspaceId: string, instance: ExecutionInstance): Promise<PrVerificationReport | null>;
11
+ composeOutcome(workspaceId: string, instance: ExecutionInstance): Promise<RunOutcome | null>;
12
+ readSpec(workspaceId: string, instance: ExecutionInstance): Promise<ServiceSpecView>;
13
+ }
14
+ export declare class RunEvidenceReads {
15
+ private readonly deps;
16
+ constructor(deps: RunEvidenceReadsDeps);
17
+ /**
18
+ * The run's verification report, composed for a READER rather than published onto a pull
19
+ * request. Null when the workspace has no such run, or when the run's block is gone.
20
+ *
21
+ * The SAME composition the PR body carries (see
22
+ * `PrVerificationReportController.composeForRun` for the three differences the read path makes,
23
+ * all of them about audience rather than content).
24
+ */
25
+ report(workspaceId: string, executionId: string): Promise<PrVerificationReport | null>;
26
+ /**
27
+ * The run's OUTCOME summary. Null on the same two conditions as {@link report}.
28
+ *
29
+ * Its sibling, and deliberately routed through the same collaborator: the two documents answer
30
+ * one question for different readers (a reviewer who will open the diff, and someone who never
31
+ * will), so they read one run's evidence once, through one loader, and share the coverage rules
32
+ * underneath. The SPA composes this same reduction live off its own store, which is why it is a
33
+ * pure function in `@cat-factory/contracts` rather than a projection invented on this side of
34
+ * the wire.
35
+ */
36
+ outcome(workspaceId: string, executionId: string): Promise<RunOutcome | null>;
37
+ /**
38
+ * The run's `spec/`, read from the branch the run pushed its work to: what the SPA's outcome
39
+ * card joins this run's requirement verdicts against.
40
+ *
41
+ * The card composes {@link outcome}'s reduction locally so it can react to pushed step updates,
42
+ * which leaves the spec as the one input it has to fetch. Fetching the SERVICE's spec (the repo
43
+ * DEFAULT branch, what the inspector's requirements window wants) is a different document while
44
+ * a pull request is open, and every verdict naming a requirement the increment added landed as
45
+ * "not checked". Routed through the loader the two documents above use, so all three read one
46
+ * branch by one rule.
47
+ *
48
+ * Null when the workspace has no such run. An unreadable spec is `{ present: false }`, which the
49
+ * card already states as `spec: 'not_read'` rather than as a clean, empty section.
50
+ */
51
+ spec(workspaceId: string, executionId: string): Promise<ServiceSpecView | null>;
52
+ }
53
+ //# sourceMappingURL=RunEvidenceReads.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RunEvidenceReads.d.ts","sourceRoot":"","sources":["../../../src/modules/execution/RunEvidenceReads.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAA;AAC5D,OAAO,KAAK,EAAE,oBAAoB,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAA;AAc/F;;;GAGG;AACH,MAAM,WAAW,oBAAoB;IACnC,iFAAiF;IACjF,WAAW,CAAC,WAAW,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,iBAAiB,GAAG,IAAI,CAAC,CAAA;IACxF,aAAa,CACX,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,iBAAiB,GAC1B,OAAO,CAAC,oBAAoB,GAAG,IAAI,CAAC,CAAA;IACvC,cAAc,CAAC,WAAW,EAAE,MAAM,EAAE,QAAQ,EAAE,iBAAiB,GAAG,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC,CAAA;IAC5F,QAAQ,CAAC,WAAW,EAAE,MAAM,EAAE,QAAQ,EAAE,iBAAiB,GAAG,OAAO,CAAC,eAAe,CAAC,CAAA;CACrF;AAED,qBAAa,gBAAgB;IACf,OAAO,CAAC,QAAQ,CAAC,IAAI;IAAjC,YAA6B,IAAI,EAAE,oBAAoB,EAAI;IAE3D;;;;;;;OAOG;IACG,MAAM,CAAC,WAAW,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,oBAAoB,GAAG,IAAI,CAAC,CAI3F;IAED;;;;;;;;;OASG;IACG,OAAO,CAAC,WAAW,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC,CAIlF;IAED;;;;;;;;;;;;;OAaG;IACG,IAAI,CAAC,WAAW,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,GAAG,IAAI,CAAC,CAIpF;CACF"}
@@ -0,0 +1,57 @@
1
+ export class RunEvidenceReads {
2
+ deps;
3
+ constructor(deps) {
4
+ this.deps = deps;
5
+ }
6
+ /**
7
+ * The run's verification report, composed for a READER rather than published onto a pull
8
+ * request. Null when the workspace has no such run, or when the run's block is gone.
9
+ *
10
+ * The SAME composition the PR body carries (see
11
+ * `PrVerificationReportController.composeForRun` for the three differences the read path makes,
12
+ * all of them about audience rather than content).
13
+ */
14
+ async report(workspaceId, executionId) {
15
+ const instance = await this.deps.getInstance(workspaceId, executionId);
16
+ if (!instance)
17
+ return null;
18
+ return this.deps.composeReport(workspaceId, instance);
19
+ }
20
+ /**
21
+ * The run's OUTCOME summary. Null on the same two conditions as {@link report}.
22
+ *
23
+ * Its sibling, and deliberately routed through the same collaborator: the two documents answer
24
+ * one question for different readers (a reviewer who will open the diff, and someone who never
25
+ * will), so they read one run's evidence once, through one loader, and share the coverage rules
26
+ * underneath. The SPA composes this same reduction live off its own store, which is why it is a
27
+ * pure function in `@cat-factory/contracts` rather than a projection invented on this side of
28
+ * the wire.
29
+ */
30
+ async outcome(workspaceId, executionId) {
31
+ const instance = await this.deps.getInstance(workspaceId, executionId);
32
+ if (!instance)
33
+ return null;
34
+ return this.deps.composeOutcome(workspaceId, instance);
35
+ }
36
+ /**
37
+ * The run's `spec/`, read from the branch the run pushed its work to: what the SPA's outcome
38
+ * card joins this run's requirement verdicts against.
39
+ *
40
+ * The card composes {@link outcome}'s reduction locally so it can react to pushed step updates,
41
+ * which leaves the spec as the one input it has to fetch. Fetching the SERVICE's spec (the repo
42
+ * DEFAULT branch, what the inspector's requirements window wants) is a different document while
43
+ * a pull request is open, and every verdict naming a requirement the increment added landed as
44
+ * "not checked". Routed through the loader the two documents above use, so all three read one
45
+ * branch by one rule.
46
+ *
47
+ * Null when the workspace has no such run. An unreadable spec is `{ present: false }`, which the
48
+ * card already states as `spec: 'not_read'` rather than as a clean, empty section.
49
+ */
50
+ async spec(workspaceId, executionId) {
51
+ const instance = await this.deps.getInstance(workspaceId, executionId);
52
+ if (!instance)
53
+ return null;
54
+ return this.deps.readSpec(workspaceId, instance);
55
+ }
56
+ }
57
+ //# sourceMappingURL=RunEvidenceReads.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RunEvidenceReads.js","sourceRoot":"","sources":["../../../src/modules/execution/RunEvidenceReads.ts"],"names":[],"mappings":"AA8BA,MAAM,OAAO,gBAAgB;IACE,IAAI;IAAjC,YAA6B,IAA0B;oBAA1B,IAAI;IAAyB,CAAC;IAE3D;;;;;;;OAOG;IACH,KAAK,CAAC,MAAM,CAAC,WAAmB,EAAE,WAAmB;QACnD,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,WAAW,EAAE,WAAW,CAAC,CAAA;QACtE,IAAI,CAAC,QAAQ;YAAE,OAAO,IAAI,CAAA;QAC1B,OAAO,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAA;IACvD,CAAC;IAED;;;;;;;;;OASG;IACH,KAAK,CAAC,OAAO,CAAC,WAAmB,EAAE,WAAmB;QACpD,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,WAAW,EAAE,WAAW,CAAC,CAAA;QACtE,IAAI,CAAC,QAAQ;YAAE,OAAO,IAAI,CAAA;QAC1B,OAAO,IAAI,CAAC,IAAI,CAAC,cAAc,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAA;IACxD,CAAC;IAED;;;;;;;;;;;;;OAaG;IACH,KAAK,CAAC,IAAI,CAAC,WAAmB,EAAE,WAAmB;QACjD,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,WAAW,EAAE,WAAW,CAAC,CAAA;QACtE,IAAI,CAAC,QAAQ;YAAE,OAAO,IAAI,CAAA;QAC1B,OAAO,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAA;IAClD,CAAC;CACF"}
@@ -34,8 +34,14 @@ export { ANALYSIS_AGENT_KIND, MERGER_AGENT_KIND, TESTER_AGENT_KIND } from '@cat-
34
34
  export { UI_TESTER_AGENT_KIND } from '@cat-factory/contracts';
35
35
  /** Both tester gate kinds (API + UI). They share the Tester→Fixer loop + infra choice. */
36
36
  export declare const TESTER_KINDS: readonly string[];
37
- /** Whether an agent kind is one of the tester gate kinds (API or UI). */
38
- export declare function isTesterKind(kind: string): boolean;
37
+ /**
38
+ * Whether an agent kind is one of the tester gate kinds (API or UI).
39
+ *
40
+ * Re-exported from `@cat-factory/contracts` rather than restated: it is the first question every
41
+ * reduction of a run's test evidence asks, and the SPA has to ask it too, which is exactly how
42
+ * the engine's copy and a hand-written frontend one came to be two spellings of one rule.
43
+ */
44
+ export { isTesterKind } from '@cat-factory/contracts';
39
45
  /**
40
46
  * The agent kind of the special `tracker` step: a non-LLM step that files a GitHub
41
47
  * issue / Jira ticket from the preceding `analysis` output before implementation,
@@ -1 +1 @@
1
- {"version":3,"file":"ci.logic.d.ts","sourceRoot":"","sources":["../../../src/modules/execution/ci.logic.ts"],"names":[],"mappings":"AAIA,OAAO,EACL,aAAa,EACb,mBAAmB,EACnB,oBAAoB,EACpB,4BAA4B,EAC5B,gBAAgB,EAChB,uBAAuB,EACvB,KAAK,SAAS,EACd,WAAW,EACX,SAAS,EACT,qBAAqB,GACtB,MAAM,qBAAqB,CAAA;AAmB5B,OAAO,EACL,8BAA8B,EAC9B,yBAAyB,EACzB,kCAAkC,EAClC,kCAAkC,GACnC,MAAM,qBAAqB,CAAA;AAE5B;;;;;;;GAOG;AACH,eAAO,MAAM,2BAA2B,qBAAqB,CAAA;AAE7D;;;;;;;GAOG;AACH,eAAO,MAAM,qBAAqB,eAAe,CAAA;AAMjD,OAAO,EAAE,qBAAqB,EAAE,sBAAsB,EAAE,MAAM,qBAAqB,CAAA;AAenF,OAAO,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAA;AAG/F;;;;;;;;;;GAUG;AACH,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAA;AAG7D,0FAA0F;AAC1F,eAAO,MAAM,YAAY,EAAE,SAAS,MAAM,EAA8C,CAAA;AAExF,yEAAyE;AACzE,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAElD;AAED;;;;;GAKG;AACH,eAAO,MAAM,kBAAkB,YAAY,CAAA;AAE3C;;;;;;;GAOG;AACH,eAAO,MAAM,qBAAqB,eAAe,CAAA;AAEjD;;;;;;;;;;GAUG;AACH,OAAO,EAAE,yBAAyB,EAAE,MAAM,wBAAwB,CAAA"}
1
+ {"version":3,"file":"ci.logic.d.ts","sourceRoot":"","sources":["../../../src/modules/execution/ci.logic.ts"],"names":[],"mappings":"AAIA,OAAO,EACL,aAAa,EACb,mBAAmB,EACnB,oBAAoB,EACpB,4BAA4B,EAC5B,gBAAgB,EAChB,uBAAuB,EACvB,KAAK,SAAS,EACd,WAAW,EACX,SAAS,EACT,qBAAqB,GACtB,MAAM,qBAAqB,CAAA;AAmB5B,OAAO,EACL,8BAA8B,EAC9B,yBAAyB,EACzB,kCAAkC,EAClC,kCAAkC,GACnC,MAAM,qBAAqB,CAAA;AAE5B;;;;;;;GAOG;AACH,eAAO,MAAM,2BAA2B,qBAAqB,CAAA;AAE7D;;;;;;;GAOG;AACH,eAAO,MAAM,qBAAqB,eAAe,CAAA;AAMjD,OAAO,EAAE,qBAAqB,EAAE,sBAAsB,EAAE,MAAM,qBAAqB,CAAA;AAenF,OAAO,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAA;AAG/F;;;;;;;;;;GAUG;AACH,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAA;AAG7D,0FAA0F;AAC1F,eAAO,MAAM,YAAY,EAAE,SAAS,MAAM,EAA8C,CAAA;AAExF;;;;;;GAMG;AACH,OAAO,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAA;AAErD;;;;;GAKG;AACH,eAAO,MAAM,kBAAkB,YAAY,CAAA;AAE3C;;;;;;;GAOG;AACH,eAAO,MAAM,qBAAqB,eAAe,CAAA;AAEjD;;;;;;;;;;GAUG;AACH,OAAO,EAAE,yBAAyB,EAAE,MAAM,wBAAwB,CAAA"}
@@ -74,10 +74,14 @@ export { UI_TESTER_AGENT_KIND } from '@cat-factory/contracts';
74
74
  import { UI_TESTER_AGENT_KIND } from '@cat-factory/contracts';
75
75
  /** Both tester gate kinds (API + UI). They share the Tester→Fixer loop + infra choice. */
76
76
  export const TESTER_KINDS = [TESTER_AGENT_KIND, UI_TESTER_AGENT_KIND];
77
- /** Whether an agent kind is one of the tester gate kinds (API or UI). */
78
- export function isTesterKind(kind) {
79
- return kind === TESTER_AGENT_KIND || kind === UI_TESTER_AGENT_KIND;
80
- }
77
+ /**
78
+ * Whether an agent kind is one of the tester gate kinds (API or UI).
79
+ *
80
+ * Re-exported from `@cat-factory/contracts` rather than restated: it is the first question every
81
+ * reduction of a run's test evidence asks, and the SPA has to ask it too, which is exactly how
82
+ * the engine's copy and a hand-written frontend one came to be two spellings of one rule.
83
+ */
84
+ export { isTesterKind } from '@cat-factory/contracts';
81
85
  /**
82
86
  * The agent kind of the special `tracker` step: a non-LLM step that files a GitHub
83
87
  * issue / Jira ticket from the preceding `analysis` output before implementation,
@@ -1 +1 @@
1
- {"version":3,"file":"ci.logic.js","sourceRoot":"","sources":["../../../src/modules/execution/ci.logic.ts"],"names":[],"mappings":"AAAA,sFAAsF;AACtF,oFAAoF;AACpF,yFAAyF;AACzF,iDAAiD;AACjD,OAAO,EACL,aAAa,EACb,mBAAmB,EACnB,oBAAoB,EACpB,4BAA4B,EAC5B,gBAAgB,EAChB,uBAAuB,EAEvB,WAAW,EACX,SAAS,EACT,qBAAqB,GACtB,MAAM,qBAAqB,CAAA;AAE5B,wFAAwF;AACxF,qFAAqF;AACrF,6FAA6F;AAC7F,uFAAuF;AACvF,uDAAuD;AACvD,EAAE;AACF,4FAA4F;AAC5F,wFAAwF;AACxF,2DAA2D;AAC3D,0FAA0F;AAC1F,uFAAuF;AACvF,qFAAqF;AACrF,0FAA0F;AAC1F,2FAA2F;AAC3F,gFAAgF;AAChF,EAAE;AACF,oEAAoE;AACpE,OAAO,EACL,8BAA8B,EAC9B,yBAAyB,EACzB,kCAAkC,EAClC,kCAAkC,GACnC,MAAM,qBAAqB,CAAA;AAE5B;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,2BAA2B,GAAG,kBAAkB,CAAA;AAE7D;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAAG,YAAY,CAAA;AAEjD,+FAA+F;AAC/F,8FAA8F;AAC9F,+FAA+F;AAC/F,wFAAwF;AACxF,OAAO,EAAE,qBAAqB,EAAE,sBAAsB,EAAE,MAAM,qBAAqB,CAAA;AAEnF,gGAAgG;AAChG,iGAAiG;AACjG,gEAAgE;AAChE,kGAAkG;AAClG,2EAA2E;AAC3E,EAAE;AACF,6FAA6F;AAC7F,yFAAyF;AACzF,6FAA6F;AAC7F,kGAAkG;AAClG,6FAA6F;AAC7F,+FAA+F;AAC/F,mEAAmE;AACnE,OAAO,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAA;AAC/F,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAA;AAEvD;;;;;;;;;;GAUG;AACH,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAA;AAC7D,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAA;AAE7D,0FAA0F;AAC1F,MAAM,CAAC,MAAM,YAAY,GAAsB,CAAC,iBAAiB,EAAE,oBAAoB,CAAC,CAAA;AAExF,yEAAyE;AACzE,MAAM,UAAU,YAAY,CAAC,IAAY;IACvC,OAAO,IAAI,KAAK,iBAAiB,IAAI,IAAI,KAAK,oBAAoB,CAAA;AACpE,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,SAAS,CAAA;AAE3C;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAAG,YAAY,CAAA;AAEjD;;;;;;;;;;GAUG;AACH,OAAO,EAAE,yBAAyB,EAAE,MAAM,wBAAwB,CAAA"}
1
+ {"version":3,"file":"ci.logic.js","sourceRoot":"","sources":["../../../src/modules/execution/ci.logic.ts"],"names":[],"mappings":"AAAA,sFAAsF;AACtF,oFAAoF;AACpF,yFAAyF;AACzF,iDAAiD;AACjD,OAAO,EACL,aAAa,EACb,mBAAmB,EACnB,oBAAoB,EACpB,4BAA4B,EAC5B,gBAAgB,EAChB,uBAAuB,EAEvB,WAAW,EACX,SAAS,EACT,qBAAqB,GACtB,MAAM,qBAAqB,CAAA;AAE5B,wFAAwF;AACxF,qFAAqF;AACrF,6FAA6F;AAC7F,uFAAuF;AACvF,uDAAuD;AACvD,EAAE;AACF,4FAA4F;AAC5F,wFAAwF;AACxF,2DAA2D;AAC3D,0FAA0F;AAC1F,uFAAuF;AACvF,qFAAqF;AACrF,0FAA0F;AAC1F,2FAA2F;AAC3F,gFAAgF;AAChF,EAAE;AACF,oEAAoE;AACpE,OAAO,EACL,8BAA8B,EAC9B,yBAAyB,EACzB,kCAAkC,EAClC,kCAAkC,GACnC,MAAM,qBAAqB,CAAA;AAE5B;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,2BAA2B,GAAG,kBAAkB,CAAA;AAE7D;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAAG,YAAY,CAAA;AAEjD,+FAA+F;AAC/F,8FAA8F;AAC9F,+FAA+F;AAC/F,wFAAwF;AACxF,OAAO,EAAE,qBAAqB,EAAE,sBAAsB,EAAE,MAAM,qBAAqB,CAAA;AAEnF,gGAAgG;AAChG,iGAAiG;AACjG,gEAAgE;AAChE,kGAAkG;AAClG,2EAA2E;AAC3E,EAAE;AACF,6FAA6F;AAC7F,yFAAyF;AACzF,6FAA6F;AAC7F,kGAAkG;AAClG,6FAA6F;AAC7F,+FAA+F;AAC/F,mEAAmE;AACnE,OAAO,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAA;AAC/F,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAA;AAEvD;;;;;;;;;;GAUG;AACH,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAA;AAC7D,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAA;AAE7D,0FAA0F;AAC1F,MAAM,CAAC,MAAM,YAAY,GAAsB,CAAC,iBAAiB,EAAE,oBAAoB,CAAC,CAAA;AAExF;;;;;;GAMG;AACH,OAAO,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAA;AAErD;;;;;GAKG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,SAAS,CAAA;AAE3C;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAAG,YAAY,CAAA;AAEjD;;;;;;;;;;GAUG;AACH,OAAO,EAAE,yBAAyB,EAAE,MAAM,wBAAwB,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"prReport.logic.d.ts","sourceRoot":"","sources":["../../../src/modules/execution/prReport.logic.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,KAAK,EACL,iBAAiB,EAKjB,aAAa,EAGb,aAAa,EACb,oBAAoB,EAEpB,OAAO,EAER,MAAM,qBAAqB,CAAA;AAI5B,OAAO,EACL,KAAK,yBAAyB,EAG/B,MAAM,4BAA4B,CAAA;AAuFnC,wEAAwE;AACxE,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,KAAK,CAAA;IACZ,2FAA2F;IAC3F,MAAM,EAAE,aAAa,EAAE,CAAA;IACvB,gEAAgE;IAChE,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACpB,uFAAuF;IACvF,QAAQ,CAAC,EAAE,QAAQ,GAAG,QAAQ,GAAG,IAAI,CAAA;IACrC,+FAA+F;IAC/F,MAAM,EAAE,MAAM,GAAG,IAAI,CAAA;IACrB;;;;OAIG;IACH,aAAa,EAAE,MAAM,GAAG,IAAI,CAAA;IAC5B,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;IACxB;;;;;OAKG;IACH,IAAI,CAAC,EAAE,OAAO,GAAG,IAAI,CAAA;IACrB;;;;OAIG;IACH,YAAY,EAAE,yBAAyB,CAAA;IACvC;;;;;;;OAOG;IACH,KAAK,CAAC,EAAE,aAAa,CAAA;IACrB,sDAAsD;IACtD,GAAG,EAAE,MAAM,CAAA;CACZ;AAiaD,oFAAoF;AACpF,wBAAgB,2BAA2B,CACzC,QAAQ,EAAE,iBAAiB,EAC3B,MAAM,EAAE,cAAc,GACrB,oBAAoB,CAkFtB;AAgTD;;;;;GAKG;AACH,wBAAgB,0BAA0B,CAAC,MAAM,EAAE,oBAAoB,GAAG,MAAM,CAqD/E"}
1
+ {"version":3,"file":"prReport.logic.d.ts","sourceRoot":"","sources":["../../../src/modules/execution/prReport.logic.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,KAAK,EACL,iBAAiB,EAKjB,aAAa,EAGb,aAAa,EACb,oBAAoB,EACpB,OAAO,EAER,MAAM,qBAAqB,CAAA;AAW5B,OAAO,EACL,KAAK,yBAAyB,EAG/B,MAAM,4BAA4B,CAAA;AAuFnC,wEAAwE;AACxE,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,KAAK,CAAA;IACZ,2FAA2F;IAC3F,MAAM,EAAE,aAAa,EAAE,CAAA;IACvB,gEAAgE;IAChE,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACpB,uFAAuF;IACvF,QAAQ,CAAC,EAAE,QAAQ,GAAG,QAAQ,GAAG,IAAI,CAAA;IACrC,+FAA+F;IAC/F,MAAM,EAAE,MAAM,GAAG,IAAI,CAAA;IACrB;;;;OAIG;IACH,aAAa,EAAE,MAAM,GAAG,IAAI,CAAA;IAC5B,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;IACxB;;;;;OAKG;IACH,IAAI,CAAC,EAAE,OAAO,GAAG,IAAI,CAAA;IACrB;;;;OAIG;IACH,YAAY,EAAE,yBAAyB,CAAA;IACvC;;;;;;;OAOG;IACH,KAAK,CAAC,EAAE,aAAa,CAAA;IACrB,sDAAsD;IACtD,GAAG,EAAE,MAAM,CAAA;CACZ;AAyZD,oFAAoF;AACpF,wBAAgB,2BAA2B,CACzC,QAAQ,EAAE,iBAAiB,EAC3B,MAAM,EAAE,cAAc,GACrB,oBAAoB,CAkFtB;AAkUD;;;;;GAKG;AACH,wBAAgB,0BAA0B,CAAC,MAAM,EAAE,oBAAoB,GAAG,MAAM,CAqD/E"}
@@ -1,5 +1,5 @@
1
1
  import { hostMarkdown, redactSecrets } from '@cat-factory/kernel';
2
- import { PR_VERIFICATION_REPORT_VERSION } from '@cat-factory/contracts';
2
+ import { indexRequirementVerdicts, isRequirementRegression, joinSpecRequirements, PR_VERIFICATION_REPORT_VERSION, tallyRequirements, unmatchedVerdictIds, } from '@cat-factory/contracts';
3
3
  import { CI_AGENT_KIND, MERGER_AGENT_KIND, isTesterKind } from './ci.logic.js';
4
4
  import { composeEnvironments, renderEnvironments, } from './prReport.environments.js';
5
5
  import { composeReproduction, composeValidation, makeOutputCapper, renderReproduction, renderValidation, } from './prReport.commands.js';
@@ -250,10 +250,12 @@ function composeMerge(instance) {
250
250
  * for a human. A `not_met` against an `aspirational` requirement is in-flight work; a `not_met`
251
251
  * against an `established` one is the service losing behaviour it had. Left uncomputed, the two
252
252
  * arrive at a reviewer as the same `not met` cell.
253
+ *
254
+ * The RULE lives in `@cat-factory/contracts` because the run outcome summary states the same
255
+ * judgement to a different audience, and a regression that the pull request calls a regression
256
+ * and the summary calls an ordinary failure is worse than either surface alone.
253
257
  */
254
- function isRegression(row) {
255
- return row.state === 'established' && row.verdict === 'not_met';
256
- }
258
+ const isRegression = isRequirementRegression;
257
259
  /**
258
260
  * Cap the requirement table by SEVERITY FIRST, so a regression is the last thing dropped.
259
261
  *
@@ -319,7 +321,15 @@ function selectRequirementEntries(rows, truncations) {
319
321
  * already records as `established`. The contract's two consumers have to agree.
320
322
  */
321
323
  function composeRequirements(instance, spec, truncations) {
322
- const empty = { entries: [], met: 0, notMet: 0, notCovered: 0, regressions: 0, total: 0 };
324
+ const empty = {
325
+ entries: [],
326
+ met: 0,
327
+ notMet: 0,
328
+ notCovered: 0,
329
+ regressions: 0,
330
+ total: 0,
331
+ unmatchedVerdicts: 0,
332
+ };
323
333
  const testerSteps = instance.steps.filter((s) => isTesterKind(s.agentKind));
324
334
  if (testerSteps.length === 0) {
325
335
  return {
@@ -329,8 +339,7 @@ function composeRequirements(instance, spec, truncations) {
329
339
  ...empty,
330
340
  };
331
341
  }
332
- const reports = testerSteps.map((s) => s.test?.lastReport).filter((r) => r != null);
333
- if (reports.length === 0) {
342
+ if (!testerSteps.some((s) => s.test?.lastReport != null)) {
334
343
  return {
335
344
  status: 'absent',
336
345
  note: 'The tester step produced no report, so no requirement was ruled on.',
@@ -345,37 +354,25 @@ function composeRequirements(instance, spec, truncations) {
345
354
  ...empty,
346
355
  };
347
356
  }
348
- // Index the verdicts by requirement id, across every tester step in pipeline order. A
349
- // duplicate id keeps the FIRST verdict whether it repeats within one report or across two
350
- // testers because last-wins would let a trailing `not_covered` quietly erase a real
351
- // observation, which is the one thing this section exists to prevent.
352
- const verdicts = new Map();
353
- for (const report of reports) {
354
- for (const verdict of report.requirementVerdicts ?? []) {
355
- if (!verdicts.has(verdict.requirementId))
356
- verdicts.set(verdict.requirementId, verdict);
357
- }
358
- }
359
- const rows = [];
360
- for (const module of spec.modules ?? []) {
361
- for (const group of module.groups ?? []) {
362
- for (const req of group.requirements ?? []) {
363
- const verdict = verdicts.get(req.id);
364
- rows.push({
365
- id: req.id,
366
- title: scrubbed(req.title),
367
- module: scrubbed(module.name),
368
- group: scrubbed(group.name),
369
- priority: req.priority,
370
- state: req.state ?? 'aspirational',
371
- verdict: verdict?.status ?? 'not_covered',
372
- detail: verdictDetail(verdict?.detail),
373
- criteriaCount: (req.acceptance ?? []).length,
374
- });
375
- }
376
- }
377
- }
378
- if (rows.length === 0) {
357
+ // The index and the join are the shared rules (`@cat-factory/contracts`, `run-evidence.ts`),
358
+ // not this file's own: the run outcome summary counts the same coverage for a different reader,
359
+ // and two spellings of "which tester steps count" is how the two came to print different
360
+ // totals for one run. What stays here is the boundary treatment: a spec title and a tester's
361
+ // evidence are agent- and human-authored text heading for a PARSED, PUBLIC surface.
362
+ const verdicts = indexRequirementVerdicts(instance.steps);
363
+ const joined = joinSpecRequirements(spec, verdicts);
364
+ const rows = joined.map((row) => ({
365
+ ...row,
366
+ title: scrubbed(row.title),
367
+ module: scrubbed(row.module),
368
+ group: scrubbed(row.group),
369
+ detail: verdictDetail(row.detail),
370
+ }));
371
+ // A verdict against an id the spec does not carry has no row to land on. Counted rather than
372
+ // dropped: the difference between this table's rulings and the tester's own is otherwise
373
+ // unexplainable, and it reads as a miscount in whichever of the two the reviewer trusts less.
374
+ const unmatched = unmatchedVerdictIds(joined, verdicts);
375
+ if (rows.length === 0 && unmatched.length === 0) {
379
376
  return {
380
377
  status: 'absent',
381
378
  note: 'No acceptance criteria are recorded in `spec/` for this service, so there was ' +
@@ -385,15 +382,11 @@ function composeRequirements(instance, spec, truncations) {
385
382
  }
386
383
  // Counts are computed over EVERY row, before the cap — so a capped table still reports the
387
384
  // true totals and the `truncations` note says how much of the table was shown.
388
- const count = (status) => rows.filter((r) => r.verdict === status).length;
389
385
  return {
390
386
  status: 'reported',
391
387
  entries: selectRequirementEntries(rows, truncations),
392
- met: count('met'),
393
- notMet: count('not_met'),
394
- notCovered: count('not_covered'),
395
- regressions: rows.filter(isRegression).length,
396
- total: rows.length,
388
+ ...tallyRequirements(joined),
389
+ unmatchedVerdicts: unmatched.length,
397
390
  };
398
391
  }
399
392
  /**
@@ -620,7 +613,22 @@ function renderRequirements(reqs) {
620
613
  : ''), '');
621
614
  }
622
615
  out.push(`**${reqs.met} met** · **${reqs.notMet} not met** · **${reqs.notCovered} not checked** ` +
623
- `(of ${reqs.total} requirement${reqs.total === 1 ? '' : 's'} in \`spec/\`)`, '', '| Requirement | Feature | State | Verdict | Observed |', '| --- | --- | --- | --- | --- |');
616
+ `(of ${reqs.total} requirement${reqs.total === 1 ? '' : 's'} in \`spec/\`)`, '');
617
+ // The count is computed for this reader and was, until now, computed and then not shown. A
618
+ // section reporting fewer rulings than the tester made, with nothing to explain the
619
+ // difference, is the miscount it exists to prevent.
620
+ // Optional on the schema (it post-dates report version 7), always set by the composer above.
621
+ const n = reqs.unmatchedVerdicts ?? 0;
622
+ if (n > 0) {
623
+ out.push(`_${n} tester verdict${n === 1 ? '' : 's'} ${n === 1 ? 'names a requirement id' : 'name requirement ids'} ` +
624
+ `\`spec/\` does not carry on this branch, so ${n === 1 ? 'it has' : 'they have'} no row above. ` +
625
+ `The spec moved under the run, or the tester keyed ${n === 1 ? 'it' : 'them'} by something else._`, '');
626
+ }
627
+ // An empty join is a real state now that a spec declaring nothing no longer discards the
628
+ // verdicts standing against it. A header-only table would read as a rendering fault.
629
+ if (reqs.total === 0)
630
+ return out;
631
+ out.push('| Requirement | Feature | State | Verdict | Observed |', '| --- | --- | --- | --- | --- |');
624
632
  for (const entry of reqs.entries) {
625
633
  const regression = isRegression(entry);
626
634
  const verdict = entry.verdict === 'met'