@cat-factory/orchestration 0.230.0 → 0.232.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.
- package/dist/modules/board/BoardService.d.ts +1 -0
- package/dist/modules/board/BoardService.d.ts.map +1 -1
- package/dist/modules/board/BoardService.js +16 -7
- package/dist/modules/board/BoardService.js.map +1 -1
- package/dist/modules/board/blockPatchNarrowing.d.ts +2 -31
- package/dist/modules/board/blockPatchNarrowing.d.ts.map +1 -1
- package/dist/modules/board/blockPatchNarrowing.js +0 -31
- package/dist/modules/board/blockPatchNarrowing.js.map +1 -1
- package/dist/modules/board/reviewTaskTarget.d.ts +43 -0
- package/dist/modules/board/reviewTaskTarget.d.ts.map +1 -1
- package/dist/modules/board/reviewTaskTarget.js +86 -6
- package/dist/modules/board/reviewTaskTarget.js.map +1 -1
- package/dist/modules/board/taskTypeFieldsPatch.d.ts +38 -0
- package/dist/modules/board/taskTypeFieldsPatch.d.ts.map +1 -0
- package/dist/modules/board/taskTypeFieldsPatch.js +84 -0
- package/dist/modules/board/taskTypeFieldsPatch.js.map +1 -0
- package/dist/modules/execution/ExecutionService.d.ts +10 -8
- package/dist/modules/execution/ExecutionService.d.ts.map +1 -1
- package/dist/modules/execution/ExecutionService.js +20 -11
- package/dist/modules/execution/ExecutionService.js.map +1 -1
- package/dist/modules/execution/PrVerificationReportController.d.ts +35 -39
- package/dist/modules/execution/PrVerificationReportController.d.ts.map +1 -1
- package/dist/modules/execution/PrVerificationReportController.js +62 -80
- package/dist/modules/execution/PrVerificationReportController.js.map +1 -1
- package/dist/modules/execution/RunEvidenceLoader.d.ts +79 -0
- package/dist/modules/execution/RunEvidenceLoader.d.ts.map +1 -0
- package/dist/modules/execution/RunEvidenceLoader.js +114 -0
- package/dist/modules/execution/RunEvidenceLoader.js.map +1 -0
- package/dist/modules/execution/RunEvidenceReads.d.ts +53 -0
- package/dist/modules/execution/RunEvidenceReads.d.ts.map +1 -0
- package/dist/modules/execution/RunEvidenceReads.js +57 -0
- package/dist/modules/execution/RunEvidenceReads.js.map +1 -0
- package/dist/modules/execution/ci.logic.d.ts +8 -2
- package/dist/modules/execution/ci.logic.d.ts.map +1 -1
- package/dist/modules/execution/ci.logic.js +8 -4
- package/dist/modules/execution/ci.logic.js.map +1 -1
- package/dist/modules/execution/prReport.logic.d.ts.map +1 -1
- package/dist/modules/execution/prReport.logic.js +53 -45
- package/dist/modules/execution/prReport.logic.js.map +1 -1
- package/dist/modules/execution/prReport.steps.d.ts +4 -0
- package/dist/modules/execution/prReport.steps.d.ts.map +1 -1
- package/dist/modules/execution/prReport.steps.js +6 -6
- package/dist/modules/execution/prReport.steps.js.map +1 -1
- package/dist/modules/execution/runOutcome.boundary.d.ts +11 -0
- package/dist/modules/execution/runOutcome.boundary.d.ts.map +1 -0
- package/dist/modules/execution/runOutcome.boundary.js +163 -0
- package/dist/modules/execution/runOutcome.boundary.js.map +1 -0
- package/package.json +11 -11
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { DEFAULT_WORKSPACE_SETTINGS, describeError } from '@cat-factory/kernel';
|
|
2
|
-
import { readServiceSpec } from '@cat-factory/agents';
|
|
3
2
|
import { DEPLOYER_AGENT_KIND } from '@cat-factory/integrations';
|
|
3
|
+
import { composeRunOutcome } from '@cat-factory/contracts';
|
|
4
|
+
import { RunEvidenceLoader, specDocOf } from './RunEvidenceLoader.js';
|
|
5
|
+
import { boundOutcomeForApi } from './runOutcome.boundary.js';
|
|
4
6
|
import { composePrVerificationReport, renderPrVerificationReport } from './prReport.logic.js';
|
|
5
|
-
import { isTesterKind } from './ci.logic.js';
|
|
6
7
|
/**
|
|
7
8
|
* How many of the run's environment provisioning rows the lifecycle timeline reads. A run stands
|
|
8
9
|
* up one environment per involved service frame and retries a failing provision, so the realistic
|
|
@@ -77,9 +78,10 @@ export class PrVerificationReportController {
|
|
|
77
78
|
lastPublished = new Map();
|
|
78
79
|
/**
|
|
79
80
|
* Hard cap on {@link lastPublished}, counted in PULL REQUESTS rather than runs: a single-repo
|
|
80
|
-
* run holds one entry and a cross-service run one per PR it writes. Sized above
|
|
81
|
-
*
|
|
82
|
-
* cross-service runs would otherwise evict the single-repo runs' entries out from
|
|
81
|
+
* run holds one entry and a cross-service run one per PR it writes. Sized above the
|
|
82
|
+
* `RunEvidenceLoader`'s per-RUN spec bound for that reason. Keyed per run, a handful of
|
|
83
|
+
* concurrent cross-service runs would otherwise evict the single-repo runs' entries out from
|
|
84
|
+
* under them.
|
|
83
85
|
*
|
|
84
86
|
* A long-lived Node replica serves an unbounded number of runs and each entry holds a rendered
|
|
85
87
|
* section, so the map is bounded here rather than relying on a call site to evict finished runs
|
|
@@ -89,15 +91,60 @@ export class PrVerificationReportController {
|
|
|
89
91
|
*/
|
|
90
92
|
static MAX_TRACKED_SECTIONS = 1024;
|
|
91
93
|
/**
|
|
92
|
-
*
|
|
93
|
-
*
|
|
94
|
-
*
|
|
95
|
-
* because they count different things, and one number standing for both is how a change to
|
|
96
|
-
* either silently re-sizes the other.
|
|
94
|
+
* The block + `spec/` reads both of this run's reductions share. A collaborator rather than two
|
|
95
|
+
* private methods because {@link composeOutcomeForRun} needs exactly the same two answers, and a
|
|
96
|
+
* second reader with its own branch choice or its own memo would drift from this one.
|
|
97
97
|
*/
|
|
98
|
-
|
|
98
|
+
evidence;
|
|
99
99
|
constructor(deps) {
|
|
100
100
|
this.deps = deps;
|
|
101
|
+
this.evidence = new RunEvidenceLoader(deps);
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* The run's OUTCOME summary (`GET /api/v1/runs/:runId/outcome`): the non-code answer to "what
|
|
105
|
+
* did this run change, and what backs that up", for a reader who does not open the diff. Null
|
|
106
|
+
* when the run's block is gone, exactly as {@link composeForRun} is.
|
|
107
|
+
*
|
|
108
|
+
* It lives on this controller because it reads the SAME evidence as the verification report and
|
|
109
|
+
* must not read it differently: the reduction itself is `composeRunOutcome` in
|
|
110
|
+
* `@cat-factory/contracts` (shared with the SPA, which composes it live off its own store), and
|
|
111
|
+
* the coverage rules underneath both documents are shared too. What this method contributes is
|
|
112
|
+
* the loader, so the summary a headless consumer fetches and the report on the pull request
|
|
113
|
+
* cannot be built from two different reads of one run.
|
|
114
|
+
*
|
|
115
|
+
* Cheaper than the report on the ordinary path and never more expensive: it needs no linked
|
|
116
|
+
* issues, no provisioning history and no pull-request target resolution, and it hits the same
|
|
117
|
+
* gated, memoised `spec/` read.
|
|
118
|
+
*/
|
|
119
|
+
async composeOutcomeForRun(workspaceId, instance) {
|
|
120
|
+
const evidence = await this.evidence.load(workspaceId, instance);
|
|
121
|
+
if (!evidence)
|
|
122
|
+
return null;
|
|
123
|
+
// Composed from the loader's read VIEW, the same value the SPA's store now holds for this
|
|
124
|
+
// run: the composer's `spec: 'not_read'` arm and a repo carrying no `spec/` are the one fact
|
|
125
|
+
// arriving from two sides, and fabricating a view here would have been a third.
|
|
126
|
+
const outcome = composeRunOutcome({
|
|
127
|
+
block: evidence.block,
|
|
128
|
+
instance,
|
|
129
|
+
spec: evidence.specView,
|
|
130
|
+
});
|
|
131
|
+
// The BOUNDARY treatment, owed here and nowhere earlier: `composeRunOutcome` is shared with
|
|
132
|
+
// the SPA, which renders into a DOM for a member of the workspace, while this value is the
|
|
133
|
+
// response body of a public endpoint any read-scope key can fetch. The report already scrubs
|
|
134
|
+
// and clamps the same tester text on its way onto a pull request; serving it verbatim here
|
|
135
|
+
// would have made the weaker of the two surfaces the one an integration reads.
|
|
136
|
+
return boundOutcomeForApi(outcome);
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* The run's `spec/` as the SPA's outcome card must join against it: the same read, through the
|
|
140
|
+
* same loader and the same branch rule, that {@link composeOutcomeForRun} uses.
|
|
141
|
+
*
|
|
142
|
+
* Here rather than on a spec-owning module because the branch is a fact about the RUN, and the
|
|
143
|
+
* card asking a service-scoped endpoint for it is exactly how the two came to answer one
|
|
144
|
+
* question differently. See {@link RunEvidenceLoader.specViewForRun}.
|
|
145
|
+
*/
|
|
146
|
+
async readRunSpec(workspaceId, instance) {
|
|
147
|
+
return this.evidence.specViewForRun(workspaceId, instance);
|
|
101
148
|
}
|
|
102
149
|
/**
|
|
103
150
|
* Compose the report for `instance` and upsert it onto every pull request the run opened.
|
|
@@ -249,16 +296,16 @@ export class PrVerificationReportController {
|
|
|
249
296
|
* key is a fine price for that; a per-target read would not have been.
|
|
250
297
|
*/
|
|
251
298
|
async loadRunScopedInputs(workspaceId, instance) {
|
|
252
|
-
const
|
|
253
|
-
if (!
|
|
299
|
+
const evidence = await this.evidence.load(workspaceId, instance);
|
|
300
|
+
if (!evidence)
|
|
254
301
|
return null;
|
|
255
302
|
return {
|
|
256
|
-
block,
|
|
303
|
+
block: evidence.block,
|
|
257
304
|
issues: await this.linkedIssues(workspaceId, instance.blockId),
|
|
258
305
|
runUrl: this.deepLink(workspaceId, instance, 'observability'),
|
|
259
306
|
trajectoryUrl: this.apiLink(`/api/v1/debug/runs/${encodeURIComponent(instance.id)}/tool-calls?order=trajectory`),
|
|
260
307
|
reportUrl: this.apiLink(`/api/v1/runs/${encodeURIComponent(instance.id)}/report`),
|
|
261
|
-
spec:
|
|
308
|
+
spec: specDocOf(evidence.specView),
|
|
262
309
|
environments: {
|
|
263
310
|
provisioning: await this.provisioningEvents(workspaceId, instance),
|
|
264
311
|
evidenceUrl: this.deepLink(workspaceId, instance, 'test-evidence'),
|
|
@@ -293,71 +340,6 @@ export class PrVerificationReportController {
|
|
|
293
340
|
const settings = (await repo.get(workspaceId)) ?? DEFAULT_WORKSPACE_SETTINGS;
|
|
294
341
|
return settings.publishPrVerificationReport;
|
|
295
342
|
}
|
|
296
|
-
/**
|
|
297
|
-
* The service's in-repo `spec/`, reassembled from the run's branch for the requirement →
|
|
298
|
-
* evidence join. Null whenever it could not be read — which the section reports with a note
|
|
299
|
-
* rather than a blank.
|
|
300
|
-
*
|
|
301
|
-
* GATED, then MEMOISED, because this is the report's only repo-reading path and the hook
|
|
302
|
-
* fires on EVERY settled step:
|
|
303
|
-
* - Gate: nothing is read until a tester step has actually produced a report. Before that
|
|
304
|
-
* the section's answer is already determined ("no tester step" / "no report yet"), so a
|
|
305
|
-
* read would buy nothing; this keeps the ~15 settlements before the tester at zero repo
|
|
306
|
-
* calls, exactly as they were before this feature.
|
|
307
|
-
* - Memo: reassembling the sharded tree costs one read per module + per group, so the
|
|
308
|
-
* handful of settlements AFTER the tester would otherwise repeat it each time. Cached
|
|
309
|
-
* per execution id under the same bound as {@link lastPublished}.
|
|
310
|
-
*
|
|
311
|
-
* The memo deliberately holds the spec as it stood when the tester ruled. That is the tree
|
|
312
|
-
* the verdicts were made against, so pairing a later re-read with those same verdicts would
|
|
313
|
-
* be less truthful, not more — and the promotion post-op rewrites the spec on this very
|
|
314
|
-
* branch right after the tester settles.
|
|
315
|
-
*
|
|
316
|
-
* Only an ANSWER is memoised — a tree that was read, or a repo that demonstrably carries no
|
|
317
|
-
* `spec/`. A FAILURE (an unresolvable repo, a throwing transport) is not: caching it would
|
|
318
|
-
* turn one flaky read into "the spec could not be read" on every remaining publish of the
|
|
319
|
-
* run, when the very next settlement would have succeeded.
|
|
320
|
-
*/
|
|
321
|
-
async serviceSpec(workspaceId, instance, prBranch) {
|
|
322
|
-
const resolve = this.deps.resolveRunRepoContext;
|
|
323
|
-
if (!resolve)
|
|
324
|
-
return null;
|
|
325
|
-
const testerReported = instance.steps.some((s) => isTesterKind(s.agentKind) && s.test?.lastReport != null);
|
|
326
|
-
if (!testerReported)
|
|
327
|
-
return null;
|
|
328
|
-
const cached = this.specByRun.get(instance.id);
|
|
329
|
-
if (cached !== undefined)
|
|
330
|
-
return cached;
|
|
331
|
-
try {
|
|
332
|
-
const ctx = await resolve(workspaceId, instance.blockId);
|
|
333
|
-
if (!ctx)
|
|
334
|
-
return null;
|
|
335
|
-
// Read the RUN's branch, not the repo default: the spec increment this task wrote is on
|
|
336
|
-
// the PR branch and has not merged yet, so the default branch would be missing exactly
|
|
337
|
-
// the requirements the tester just ruled on.
|
|
338
|
-
const view = await readServiceSpec(ctx.repo, prBranch ?? ctx.baseBranch);
|
|
339
|
-
const spec = view.present ? view.spec : null;
|
|
340
|
-
this.rememberSpec(instance.id, spec);
|
|
341
|
-
return spec;
|
|
342
|
-
}
|
|
343
|
-
catch {
|
|
344
|
-
// Best-effort, like every other part of this hook: an unreadable spec reports `absent`
|
|
345
|
-
// with a note, never fails the run, and is re-attempted on the next settlement.
|
|
346
|
-
return null;
|
|
347
|
-
}
|
|
348
|
-
}
|
|
349
|
-
/** Per-execution spec memo, bounded exactly like {@link lastPublished}. */
|
|
350
|
-
specByRun = new Map();
|
|
351
|
-
rememberSpec(executionId, spec) {
|
|
352
|
-
this.specByRun.delete(executionId);
|
|
353
|
-
this.specByRun.set(executionId, spec);
|
|
354
|
-
while (this.specByRun.size > PrVerificationReportController.MAX_TRACKED_RUNS) {
|
|
355
|
-
const oldest = this.specByRun.keys().next();
|
|
356
|
-
if (oldest.done)
|
|
357
|
-
break;
|
|
358
|
-
this.specByRun.delete(oldest.value);
|
|
359
|
-
}
|
|
360
|
-
}
|
|
361
343
|
async linkedIssues(workspaceId, blockId) {
|
|
362
344
|
const repo = this.deps.taskRepository;
|
|
363
345
|
if (!repo)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PrVerificationReportController.js","sourceRoot":"","sources":["../../../src/modules/execution/PrVerificationReportController.ts"],"names":[],"mappings":"
|
|
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
|
-
/**
|
|
38
|
-
|
|
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
|
|
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
|
-
/**
|
|
78
|
-
|
|
79
|
-
|
|
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
|
|
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,
|
|
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"}
|