@cat-factory/kernel 0.328.0 → 0.329.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/domain/monorepo-adoption.logic.d.ts +87 -0
- package/dist/domain/monorepo-adoption.logic.d.ts.map +1 -0
- package/dist/domain/monorepo-adoption.logic.js +323 -0
- package/dist/domain/monorepo-adoption.logic.js.map +1 -0
- package/dist/domain/pr-report.d.ts +27 -3
- package/dist/domain/pr-report.d.ts.map +1 -1
- package/dist/domain/pr-report.js +28 -10
- package/dist/domain/pr-report.js.map +1 -1
- package/dist/domain/service-registration.d.ts +11 -3
- package/dist/domain/service-registration.d.ts.map +1 -1
- package/dist/domain/service-registration.js +9 -1
- package/dist/domain/service-registration.js.map +1 -1
- package/dist/domain/types.d.ts +1 -1
- package/dist/domain/types.d.ts.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +7 -2
- package/dist/index.js.map +1 -1
- package/dist/ports/agent-runs.d.ts +4 -1
- package/dist/ports/agent-runs.d.ts.map +1 -1
- package/dist/ports/bootstrap-repositories.d.ts +49 -2
- package/dist/ports/bootstrap-repositories.d.ts.map +1 -1
- package/dist/ports/bootstrap-runner.d.ts +15 -8
- package/dist/ports/bootstrap-runner.d.ts.map +1 -1
- package/dist/ports/bootstrap-runner.js.map +1 -1
- package/dist/ports/index.d.ts +3 -2
- package/dist/ports/index.d.ts.map +1 -1
- package/dist/ports/index.js.map +1 -1
- package/dist/ports/monorepo-adoption.d.ts +37 -0
- package/dist/ports/monorepo-adoption.d.ts.map +1 -0
- package/dist/ports/monorepo-adoption.js +2 -0
- package/dist/ports/monorepo-adoption.js.map +1 -0
- package/dist/ports/repo-bootstrapper.d.ts +89 -3
- package/dist/ports/repo-bootstrapper.d.ts.map +1 -1
- package/dist/ports/repo-files.d.ts +16 -0
- package/dist/ports/repo-files.d.ts.map +1 -1
- package/package.json +2 -2
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { type AdoptionArea, type AdoptionChoice, type AdoptionDecision, type AdoptionPlan, type AdoptionSource, type AdoptionSurvey, type ResolvedAdoption } from '@cat-factory/contracts';
|
|
2
|
+
/** Cap on how many decisions one plan may carry, so a runaway reply can't produce a wall of them. */
|
|
3
|
+
export declare const MAX_ADOPTION_DECISIONS = 24;
|
|
4
|
+
/**
|
|
5
|
+
* One convention area, in the words the review UI and the agent brief both use.
|
|
6
|
+
*
|
|
7
|
+
* The `default` is unreachable while the type is honoured, which is the point: adding a member
|
|
8
|
+
* fails the build here, and a member RETIRED after a plan was stored still renders honestly
|
|
9
|
+
* instead of splicing `undefined` into the sentence a human is deciding from.
|
|
10
|
+
*/
|
|
11
|
+
export declare function describeAdoptionArea(area: AdoptionArea): string;
|
|
12
|
+
/** One side of the decision, as an instruction an agent can act on without further inference. */
|
|
13
|
+
export declare function describeAdoptionSource(source: AdoptionSource): string;
|
|
14
|
+
/** Whether a stored string is an area THIS build defines, narrowed from the schema's own options. */
|
|
15
|
+
export declare function isAdoptionArea(value: unknown): value is AdoptionArea;
|
|
16
|
+
/** Whether a stored string is a choice THIS build defines, narrowed from the schema's own options. */
|
|
17
|
+
export declare function isAdoptionSource(value: unknown): value is AdoptionSource;
|
|
18
|
+
/** What {@link parseAdoptionDecisions} produced, plus what it refused to carry through. */
|
|
19
|
+
export interface ParsedAdoptionDecisions {
|
|
20
|
+
decisions: AdoptionDecision[];
|
|
21
|
+
/** One line per dropped recommendation, naming it and why. Rendered to the reviewer. */
|
|
22
|
+
dropped: string[];
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Read a model's raw reply into the stored decision list, keeping only what it can support.
|
|
26
|
+
*
|
|
27
|
+
* The model is asked for `{ decisions: [...] }`; anything else is not a plan. Each decision has
|
|
28
|
+
* to survive three checks, and each one is a way the review would otherwise mislead:
|
|
29
|
+
*
|
|
30
|
+
* - a duplicate or missing `id` makes the human's answer unaddressable, so the line is dropped;
|
|
31
|
+
* - an area or recommendation outside the CURRENT vocabulary cannot be rendered or acted on;
|
|
32
|
+
* - evidence that names no path the survey actually read means the claim about the monorepo
|
|
33
|
+
* has nothing behind it. The line is dropped rather than shown unmarked, because a reviewer
|
|
34
|
+
* reads an unmarked line as something the platform checked.
|
|
35
|
+
*
|
|
36
|
+
* Every drop is REPORTED, never silent: a plan that lost half its lines to invention looks
|
|
37
|
+
* exactly like a monorepo with few conventions, and those need opposite reactions.
|
|
38
|
+
*/
|
|
39
|
+
export declare function parseAdoptionDecisions(raw: unknown, survey: AdoptionSurvey): ParsedAdoptionDecisions;
|
|
40
|
+
/**
|
|
41
|
+
* Settle a human review against the plan it answers, or throw the refusal naming what is wrong.
|
|
42
|
+
*
|
|
43
|
+
* Refuses rather than repairs, on both sides of the mismatch. An UNANSWERED decision cannot be
|
|
44
|
+
* defaulted to the recommendation without erasing the difference between agreeing with it and
|
|
45
|
+
* never having read it, which is the single fact this whole step exists to record. An answer
|
|
46
|
+
* naming a decision the plan does not have means the reviewer was looking at a different plan
|
|
47
|
+
* (a stale tab, a re-run survey), and applying the rest of it would build under a review that
|
|
48
|
+
* was never given for this proposal.
|
|
49
|
+
*/
|
|
50
|
+
export declare function resolveAdoptionReview(plan: AdoptionPlan, choices: readonly AdoptionChoice[], context: {
|
|
51
|
+
reviewedByUserId: string | null;
|
|
52
|
+
reviewedAt: number;
|
|
53
|
+
notes?: string | undefined;
|
|
54
|
+
}): ResolvedAdoption;
|
|
55
|
+
/**
|
|
56
|
+
* Render the settled review as the adoption section of the apply phase's brief.
|
|
57
|
+
*
|
|
58
|
+
* Every decision is stated as a SIDE plus the reviewer's own words where they left any, and the
|
|
59
|
+
* overrides are called out: an agent told only "use the monorepo's test runner" cannot tell a
|
|
60
|
+
* default it may reason around from a human who deliberately overruled the recommendation, and
|
|
61
|
+
* the second is not negotiable. The list is exhaustive on purpose: an area the reviewer settled
|
|
62
|
+
* and the brief omits is an area the agent decides again, unreviewed.
|
|
63
|
+
*
|
|
64
|
+
* The holes are VERBATIM here. {@link renderAdoptionPrSection} is the rendering for the pull
|
|
65
|
+
* request; do not send this one to a host.
|
|
66
|
+
*/
|
|
67
|
+
export declare function renderAdoptionBrief(resolved: ResolvedAdoption, directory: string): string;
|
|
68
|
+
/**
|
|
69
|
+
* Render the settled review for the PULL REQUEST the apply phase opens.
|
|
70
|
+
*
|
|
71
|
+
* The same list, addressed to the human reviewing the change rather than to the agent making it:
|
|
72
|
+
* what a reviewer of a bootstrap PR is being asked is whether the service fits the monorepo, and
|
|
73
|
+
* what settles that is which side each area came from and who chose it, which the diff cannot
|
|
74
|
+
* show. Every hole crosses {@link HOST_SINK}, because both the titles (model-authored) and the
|
|
75
|
+
* notes (reviewer-authored) are untrusted text landing on a parsed surface. The caller scrubs
|
|
76
|
+
* secrets at compose time, before any of this is capped.
|
|
77
|
+
*/
|
|
78
|
+
export declare function renderAdoptionPrSection(resolved: ResolvedAdoption, directory: string): string;
|
|
79
|
+
/**
|
|
80
|
+
* The default branch name for a monorepo bootstrap's pull request.
|
|
81
|
+
*
|
|
82
|
+
* Derived from the run's own id rather than the service name so two bootstraps of similarly
|
|
83
|
+
* named services can never collide on one branch, and stable per run so a retry of the SAME run
|
|
84
|
+
* resumes its branch instead of opening a second pull request against the monorepo.
|
|
85
|
+
*/
|
|
86
|
+
export declare function monorepoBootstrapBranch(jobId: string): string;
|
|
87
|
+
//# sourceMappingURL=monorepo-adoption.logic.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"monorepo-adoption.logic.d.ts","sourceRoot":"","sources":["../../src/domain/monorepo-adoption.logic.ts"],"names":[],"mappings":"AAAA,OAAO,EAIL,KAAK,YAAY,EACjB,KAAK,cAAc,EACnB,KAAK,gBAAgB,EACrB,KAAK,YAAY,EACjB,KAAK,cAAc,EACnB,KAAK,cAAc,EACnB,KAAK,gBAAgB,EAEtB,MAAM,wBAAwB,CAAA;AAsB/B,qGAAqG;AACrG,eAAO,MAAM,sBAAsB,KAAK,CAAA;AAcxC;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,YAAY,GAAG,MAAM,CA6B/D;AAOD,iGAAiG;AACjG,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,cAAc,GAAG,MAAM,CAarE;AAED,qGAAqG;AACrG,wBAAgB,cAAc,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,YAAY,CAIpE;AAED,sGAAsG;AACtG,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,cAAc,CAIxE;AAED,2FAA2F;AAC3F,MAAM,WAAW,uBAAuB;IACtC,SAAS,EAAE,gBAAgB,EAAE,CAAA;IAC7B,wFAAwF;IACxF,OAAO,EAAE,MAAM,EAAE,CAAA;CAClB;AAmBD;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,sBAAsB,CACpC,GAAG,EAAE,OAAO,EACZ,MAAM,EAAE,cAAc,GACrB,uBAAuB,CAiEzB;AAED;;;;;;;;;GASG;AACH,wBAAgB,qBAAqB,CACnC,IAAI,EAAE,YAAY,EAClB,OAAO,EAAE,SAAS,cAAc,EAAE,EAClC,OAAO,EAAE;IAAE,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,UAAU,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;CAAE,GAC3F,gBAAgB,CA+ClB;AA8DD;;;;;;;;;;;GAWG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,gBAAgB,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAUzF;AAED;;;;;;;;;GASG;AACH,wBAAgB,uBAAuB,CAAC,QAAQ,EAAE,gBAAgB,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAe7F;AAED;;;;;;GAMG;AACH,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAE7D"}
|
|
@@ -0,0 +1,323 @@
|
|
|
1
|
+
import { adoptionAreaSchema, adoptionSourceSchema, MAX_ADOPTION_DROP_LINES, } from '@cat-factory/contracts';
|
|
2
|
+
import * as hostMarkdown from '../shared/host-markdown.logic.js';
|
|
3
|
+
import { ValidationError } from './errors.js';
|
|
4
|
+
// ---------------------------------------------------------------------------
|
|
5
|
+
// The rules over a monorepo bootstrap's adoption plan: reading a model's proposal into the
|
|
6
|
+
// stored shape, settling a human review against it, and rendering the settled result as the
|
|
7
|
+
// brief the apply phase's agent works from.
|
|
8
|
+
//
|
|
9
|
+
// Pure (no repository, no model, no clock beyond what is passed), because every one of these
|
|
10
|
+
// is a place the flow can silently become useless, and the failure modes are only visible when
|
|
11
|
+
// they can be driven directly:
|
|
12
|
+
//
|
|
13
|
+
// - a recommendation whose EVIDENCE names nothing the survey read is the model asserting a
|
|
14
|
+
// monorepo convention it invented, and it is the one claim a reviewer cannot check by eye;
|
|
15
|
+
// - a review that leaves a decision unanswered must be REFUSED, not defaulted onto the
|
|
16
|
+
// recommendation, because "I agree" and "I did not look" are exactly what this step exists
|
|
17
|
+
// to tell apart;
|
|
18
|
+
// - a settled decision must reach the agent's brief in words that name a SIDE, since
|
|
19
|
+
// "adopt from the monorepo" and "keep the template's" are the whole deliverable.
|
|
20
|
+
// ---------------------------------------------------------------------------
|
|
21
|
+
/** Cap on how many decisions one plan may carry, so a runaway reply can't produce a wall of them. */
|
|
22
|
+
export const MAX_ADOPTION_DECISIONS = 24;
|
|
23
|
+
/**
|
|
24
|
+
* A stored area this build no longer defines, named as the retired value it is.
|
|
25
|
+
*
|
|
26
|
+
* Deliberately NOT mapped onto a current member: nothing here knows which one was meant, and a
|
|
27
|
+
* plan is PERSISTED, so a run parked before a vocabulary change is read back by exactly the
|
|
28
|
+
* surface whose job is to tell a human what they are approving. Guessing would put a wrong
|
|
29
|
+
* label on a decision that changes what gets built.
|
|
30
|
+
*/
|
|
31
|
+
function describeRetiredArea(area) {
|
|
32
|
+
return `'${String(area)}' (an area this deployment no longer defines; re-run the survey)`;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* One convention area, in the words the review UI and the agent brief both use.
|
|
36
|
+
*
|
|
37
|
+
* The `default` is unreachable while the type is honoured, which is the point: adding a member
|
|
38
|
+
* fails the build here, and a member RETIRED after a plan was stored still renders honestly
|
|
39
|
+
* instead of splicing `undefined` into the sentence a human is deciding from.
|
|
40
|
+
*/
|
|
41
|
+
export function describeAdoptionArea(area) {
|
|
42
|
+
switch (area) {
|
|
43
|
+
case 'build-tooling':
|
|
44
|
+
return 'build tooling';
|
|
45
|
+
case 'dependencies':
|
|
46
|
+
return 'dependency versions and package management';
|
|
47
|
+
case 'lint-format':
|
|
48
|
+
return 'linting and formatting';
|
|
49
|
+
case 'typecheck':
|
|
50
|
+
return 'type checking';
|
|
51
|
+
case 'testing':
|
|
52
|
+
return 'test runner and test layout';
|
|
53
|
+
case 'ci':
|
|
54
|
+
return 'CI pipelines';
|
|
55
|
+
case 'containerization':
|
|
56
|
+
return 'containerization and image build';
|
|
57
|
+
case 'runtime-config':
|
|
58
|
+
return 'runtime configuration and secrets';
|
|
59
|
+
case 'observability':
|
|
60
|
+
return 'logging, metrics and tracing';
|
|
61
|
+
case 'source-layout':
|
|
62
|
+
return 'source layout and module structure';
|
|
63
|
+
case 'docs':
|
|
64
|
+
return 'documentation';
|
|
65
|
+
case 'other':
|
|
66
|
+
return 'other conventions';
|
|
67
|
+
default:
|
|
68
|
+
return describeRetiredArea(area);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
/** A stored side this build no longer defines. Same rule, same reason, as {@link describeRetiredArea}. */
|
|
72
|
+
function describeRetiredSource(source) {
|
|
73
|
+
return `'${String(source)}' (a choice this deployment no longer defines; re-run the survey)`;
|
|
74
|
+
}
|
|
75
|
+
/** One side of the decision, as an instruction an agent can act on without further inference. */
|
|
76
|
+
export function describeAdoptionSource(source) {
|
|
77
|
+
switch (source) {
|
|
78
|
+
case 'monorepo':
|
|
79
|
+
return "adopt the monorepo's existing convention and drop the template's";
|
|
80
|
+
case 'template':
|
|
81
|
+
return "keep the reference template's version as-is";
|
|
82
|
+
case 'both':
|
|
83
|
+
return "compose the two: build on the monorepo's shared setup and layer the template's addition on top";
|
|
84
|
+
case 'neither':
|
|
85
|
+
return 'take neither: leave this out of the new service entirely';
|
|
86
|
+
default:
|
|
87
|
+
return describeRetiredSource(source);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
/** Whether a stored string is an area THIS build defines, narrowed from the schema's own options. */
|
|
91
|
+
export function isAdoptionArea(value) {
|
|
92
|
+
return (typeof value === 'string' && adoptionAreaSchema.options.includes(value));
|
|
93
|
+
}
|
|
94
|
+
/** Whether a stored string is a choice THIS build defines, narrowed from the schema's own options. */
|
|
95
|
+
export function isAdoptionSource(value) {
|
|
96
|
+
return (typeof value === 'string' && adoptionSourceSchema.options.includes(value));
|
|
97
|
+
}
|
|
98
|
+
/** Every path the survey managed to read, in the prefixed form a decision's evidence uses. */
|
|
99
|
+
function surveyedPaths(survey) {
|
|
100
|
+
return new Set([
|
|
101
|
+
...survey.monorepoPaths.map((path) => `monorepo:${path}`),
|
|
102
|
+
...survey.templatePaths.map((path) => `template:${path}`),
|
|
103
|
+
]);
|
|
104
|
+
}
|
|
105
|
+
function asString(value, max) {
|
|
106
|
+
return typeof value === 'string' ? value.trim().slice(0, max) : '';
|
|
107
|
+
}
|
|
108
|
+
function asNullableString(value, max) {
|
|
109
|
+
const text = asString(value, max);
|
|
110
|
+
return text.length > 0 ? text : null;
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Read a model's raw reply into the stored decision list, keeping only what it can support.
|
|
114
|
+
*
|
|
115
|
+
* The model is asked for `{ decisions: [...] }`; anything else is not a plan. Each decision has
|
|
116
|
+
* to survive three checks, and each one is a way the review would otherwise mislead:
|
|
117
|
+
*
|
|
118
|
+
* - a duplicate or missing `id` makes the human's answer unaddressable, so the line is dropped;
|
|
119
|
+
* - an area or recommendation outside the CURRENT vocabulary cannot be rendered or acted on;
|
|
120
|
+
* - evidence that names no path the survey actually read means the claim about the monorepo
|
|
121
|
+
* has nothing behind it. The line is dropped rather than shown unmarked, because a reviewer
|
|
122
|
+
* reads an unmarked line as something the platform checked.
|
|
123
|
+
*
|
|
124
|
+
* Every drop is REPORTED, never silent: a plan that lost half its lines to invention looks
|
|
125
|
+
* exactly like a monorepo with few conventions, and those need opposite reactions.
|
|
126
|
+
*/
|
|
127
|
+
export function parseAdoptionDecisions(raw, survey) {
|
|
128
|
+
const dropped = [];
|
|
129
|
+
let unreported = 0;
|
|
130
|
+
/** Record a drop, or count it once the report is full (contracts' `MAX_ADOPTION_DROP_LINES`). */
|
|
131
|
+
const drop = (line) => {
|
|
132
|
+
if (dropped.length < MAX_ADOPTION_DROP_LINES)
|
|
133
|
+
dropped.push(line);
|
|
134
|
+
else
|
|
135
|
+
unreported += 1;
|
|
136
|
+
};
|
|
137
|
+
const container = raw;
|
|
138
|
+
const list = Array.isArray(container?.decisions) ? container.decisions : null;
|
|
139
|
+
if (!list)
|
|
140
|
+
return { decisions: [], dropped: ['the reply carried no `decisions` array'] };
|
|
141
|
+
const known = surveyedPaths(survey);
|
|
142
|
+
const decisions = [];
|
|
143
|
+
const seen = new Set();
|
|
144
|
+
for (const entry of list) {
|
|
145
|
+
if (decisions.length >= MAX_ADOPTION_DECISIONS) {
|
|
146
|
+
drop(`the reply proposed more than ${MAX_ADOPTION_DECISIONS} decisions; the rest were not read`);
|
|
147
|
+
break;
|
|
148
|
+
}
|
|
149
|
+
const item = entry;
|
|
150
|
+
if (!item || typeof item !== 'object')
|
|
151
|
+
continue;
|
|
152
|
+
const id = asString(item.id, 80);
|
|
153
|
+
const title = asString(item.title, 200);
|
|
154
|
+
if (!id || !title) {
|
|
155
|
+
drop(`a proposed decision had no id or title (${id || title || 'unnamed'})`);
|
|
156
|
+
continue;
|
|
157
|
+
}
|
|
158
|
+
if (seen.has(id)) {
|
|
159
|
+
drop(`'${id}' was proposed twice; only the first was kept`);
|
|
160
|
+
continue;
|
|
161
|
+
}
|
|
162
|
+
if (!isAdoptionArea(item.area)) {
|
|
163
|
+
drop(`'${title}' named an area this deployment does not define`);
|
|
164
|
+
continue;
|
|
165
|
+
}
|
|
166
|
+
if (!isAdoptionSource(item.recommended)) {
|
|
167
|
+
drop(`'${title}' recommended a choice this deployment does not define`);
|
|
168
|
+
continue;
|
|
169
|
+
}
|
|
170
|
+
const evidence = Array.isArray(item.evidence)
|
|
171
|
+
? item.evidence.filter((path) => typeof path === 'string' && known.has(path))
|
|
172
|
+
: [];
|
|
173
|
+
if (evidence.length === 0) {
|
|
174
|
+
drop(`'${title}' cited no file the survey actually read, so it was not carried through`);
|
|
175
|
+
continue;
|
|
176
|
+
}
|
|
177
|
+
seen.add(id);
|
|
178
|
+
decisions.push({
|
|
179
|
+
id,
|
|
180
|
+
area: item.area,
|
|
181
|
+
title,
|
|
182
|
+
monorepoPractice: asNullableString(item.monorepoPractice, 600),
|
|
183
|
+
templatePractice: asNullableString(item.templatePractice, 600),
|
|
184
|
+
recommended: item.recommended,
|
|
185
|
+
rationale: asString(item.rationale, 600),
|
|
186
|
+
evidence,
|
|
187
|
+
});
|
|
188
|
+
}
|
|
189
|
+
if (unreported > 0) {
|
|
190
|
+
dropped.push(`and ${unreported} further proposals were dropped for the same kinds of reason`);
|
|
191
|
+
}
|
|
192
|
+
return { decisions, dropped };
|
|
193
|
+
}
|
|
194
|
+
/**
|
|
195
|
+
* Settle a human review against the plan it answers, or throw the refusal naming what is wrong.
|
|
196
|
+
*
|
|
197
|
+
* Refuses rather than repairs, on both sides of the mismatch. An UNANSWERED decision cannot be
|
|
198
|
+
* defaulted to the recommendation without erasing the difference between agreeing with it and
|
|
199
|
+
* never having read it, which is the single fact this whole step exists to record. An answer
|
|
200
|
+
* naming a decision the plan does not have means the reviewer was looking at a different plan
|
|
201
|
+
* (a stale tab, a re-run survey), and applying the rest of it would build under a review that
|
|
202
|
+
* was never given for this proposal.
|
|
203
|
+
*/
|
|
204
|
+
export function resolveAdoptionReview(plan, choices, context) {
|
|
205
|
+
// Deliberately NOT gated on `plan.status === 'ready'`. An `unavailable` plan carries no
|
|
206
|
+
// decisions, so settling it answers nothing, but it is still the human's decision to make, and
|
|
207
|
+
// refusing it strands the run: the review is the ONLY exit from the park, and a retry re-enters
|
|
208
|
+
// the same phase. A deployment with no adoption model would then be unable to bootstrap into a
|
|
209
|
+
// monorepo at all, which is the opposite of the "they just make it unaided" this flow promises.
|
|
210
|
+
// The two checks below are what keep that safe: nothing to answer means nothing may be
|
|
211
|
+
// answered, so a review aimed at a plan that has since been re-surveyed is still refused whole.
|
|
212
|
+
const byId = new Map(choices.map((choice) => [choice.id, choice]));
|
|
213
|
+
const unknown = choices.filter((choice) => !plan.decisions.some((d) => d.id === choice.id));
|
|
214
|
+
if (unknown.length > 0) {
|
|
215
|
+
throw new ValidationError(`The review answers decisions this plan does not contain: ${unknown
|
|
216
|
+
.map((choice) => `'${choice.id}'`)
|
|
217
|
+
.join(', ')}. Reload the plan and review it again.`, { reason: 'adoption_choice_unknown', ids: unknown.map((choice) => choice.id) });
|
|
218
|
+
}
|
|
219
|
+
const missing = plan.decisions.filter((decision) => !byId.has(decision.id));
|
|
220
|
+
if (missing.length > 0) {
|
|
221
|
+
throw new ValidationError(`Every adoption decision must be answered; ${missing.length} ${missing.length === 1 ? 'is' : 'are'} still open: ${missing.map((decision) => `'${decision.title}'`).join(', ')}.`, { reason: 'adoption_review_incomplete', ids: missing.map((decision) => decision.id) });
|
|
222
|
+
}
|
|
223
|
+
const decisions = plan.decisions.map((decision) => {
|
|
224
|
+
// Total by construction: `missing` above already refused any decision with no answer.
|
|
225
|
+
const choice = byId.get(decision.id);
|
|
226
|
+
return {
|
|
227
|
+
id: decision.id,
|
|
228
|
+
area: decision.area,
|
|
229
|
+
title: decision.title,
|
|
230
|
+
choice: choice.choice,
|
|
231
|
+
overrodeRecommendation: choice.choice !== decision.recommended,
|
|
232
|
+
note: choice.note?.trim() ? choice.note.trim() : null,
|
|
233
|
+
};
|
|
234
|
+
});
|
|
235
|
+
const notes = context.notes?.trim();
|
|
236
|
+
return {
|
|
237
|
+
decisions,
|
|
238
|
+
notes: notes ? notes : null,
|
|
239
|
+
reviewedByUserId: context.reviewedByUserId,
|
|
240
|
+
reviewedAt: context.reviewedAt,
|
|
241
|
+
};
|
|
242
|
+
}
|
|
243
|
+
/** The prompt sink: verbatim, because the reader is a model and the text is its instruction. */
|
|
244
|
+
const AGENT_SINK = { inline: (value) => value, prose: (value) => value };
|
|
245
|
+
/** The host sink: every auto-link trigger neutralised, every hole capped and fence-balanced. */
|
|
246
|
+
const HOST_SINK = {
|
|
247
|
+
inline: (value) => hostMarkdown.inline(value),
|
|
248
|
+
prose: (value) => hostMarkdown.prose(value),
|
|
249
|
+
};
|
|
250
|
+
/** The shared body of both renderings; only the holes differ (see {@link AdoptionTextSink}). */
|
|
251
|
+
function renderAdoptionDecisions(resolved, sink, lead) {
|
|
252
|
+
const lines = [
|
|
253
|
+
`## Adoption decisions (settled by a human reviewer; follow them exactly)`,
|
|
254
|
+
'',
|
|
255
|
+
lead,
|
|
256
|
+
'',
|
|
257
|
+
];
|
|
258
|
+
if (resolved.decisions.length === 0) {
|
|
259
|
+
lines.push('_The reviewer settled no areas: follow the surrounding monorepo wherever it has an ' +
|
|
260
|
+
'established convention, and the template only where it does not._', '');
|
|
261
|
+
}
|
|
262
|
+
for (const decision of resolved.decisions) {
|
|
263
|
+
const override = decision.overrodeRecommendation ? ' (reviewer overrode the suggestion)' : '';
|
|
264
|
+
lines.push(`- **${sink.inline(decision.title)}** (${describeAdoptionArea(decision.area)}): ` +
|
|
265
|
+
`${describeAdoptionSource(decision.choice)}${override}.` +
|
|
266
|
+
(decision.note ? `\n Reviewer's note: ${sink.inline(decision.note)}` : ''));
|
|
267
|
+
}
|
|
268
|
+
if (resolved.notes) {
|
|
269
|
+
lines.push('', '### Reviewer notes for the service as a whole', '', sink.prose(resolved.notes));
|
|
270
|
+
}
|
|
271
|
+
return lines.join('\n');
|
|
272
|
+
}
|
|
273
|
+
/**
|
|
274
|
+
* Render the settled review as the adoption section of the apply phase's brief.
|
|
275
|
+
*
|
|
276
|
+
* Every decision is stated as a SIDE plus the reviewer's own words where they left any, and the
|
|
277
|
+
* overrides are called out: an agent told only "use the monorepo's test runner" cannot tell a
|
|
278
|
+
* default it may reason around from a human who deliberately overruled the recommendation, and
|
|
279
|
+
* the second is not negotiable. The list is exhaustive on purpose: an area the reviewer settled
|
|
280
|
+
* and the brief omits is an area the agent decides again, unreviewed.
|
|
281
|
+
*
|
|
282
|
+
* The holes are VERBATIM here. {@link renderAdoptionPrSection} is the rendering for the pull
|
|
283
|
+
* request; do not send this one to a host.
|
|
284
|
+
*/
|
|
285
|
+
export function renderAdoptionBrief(resolved, directory) {
|
|
286
|
+
return renderAdoptionDecisions(resolved, AGENT_SINK, `The new service lives at \`${directory}\`. For each area below, a reviewer has decided ` +
|
|
287
|
+
`whether it follows the surrounding monorepo or the reference template. These are ` +
|
|
288
|
+
`decisions, not suggestions: do not substitute your own judgement for one of them, and ` +
|
|
289
|
+
`if a decision turns out to be impossible as stated, do the closest thing that honours it ` +
|
|
290
|
+
`and say so in the pull request description rather than quietly picking the other side.`);
|
|
291
|
+
}
|
|
292
|
+
/**
|
|
293
|
+
* Render the settled review for the PULL REQUEST the apply phase opens.
|
|
294
|
+
*
|
|
295
|
+
* The same list, addressed to the human reviewing the change rather than to the agent making it:
|
|
296
|
+
* what a reviewer of a bootstrap PR is being asked is whether the service fits the monorepo, and
|
|
297
|
+
* what settles that is which side each area came from and who chose it, which the diff cannot
|
|
298
|
+
* show. Every hole crosses {@link HOST_SINK}, because both the titles (model-authored) and the
|
|
299
|
+
* notes (reviewer-authored) are untrusted text landing on a parsed surface. The caller scrubs
|
|
300
|
+
* secrets at compose time, before any of this is capped.
|
|
301
|
+
*/
|
|
302
|
+
export function renderAdoptionPrSection(resolved, directory) {
|
|
303
|
+
const overrides = resolved.decisions.filter((decision) => decision.overrodeRecommendation).length;
|
|
304
|
+
const stance = resolved.decisions.length === 0
|
|
305
|
+
? 'with no suggestion to review: the platform could not produce one'
|
|
306
|
+
: overrides > 0
|
|
307
|
+
? `${overrides} of which overrode the platform's suggestion`
|
|
308
|
+
: "all of which accepted the platform's suggestion";
|
|
309
|
+
return renderAdoptionDecisions(resolved, HOST_SINK, `This service was bootstrapped into \`${hostMarkdown.inline(directory)}\` under decisions ` +
|
|
310
|
+
`settled by a human before any code was written, ${stance}. Each line below names the ` +
|
|
311
|
+
`area, the side the new service follows for it, and anything the reviewer added.`);
|
|
312
|
+
}
|
|
313
|
+
/**
|
|
314
|
+
* The default branch name for a monorepo bootstrap's pull request.
|
|
315
|
+
*
|
|
316
|
+
* Derived from the run's own id rather than the service name so two bootstraps of similarly
|
|
317
|
+
* named services can never collide on one branch, and stable per run so a retry of the SAME run
|
|
318
|
+
* resumes its branch instead of opening a second pull request against the monorepo.
|
|
319
|
+
*/
|
|
320
|
+
export function monorepoBootstrapBranch(jobId) {
|
|
321
|
+
return `cat-factory/bootstrap-${jobId}`;
|
|
322
|
+
}
|
|
323
|
+
//# sourceMappingURL=monorepo-adoption.logic.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"monorepo-adoption.logic.js","sourceRoot":"","sources":["../../src/domain/monorepo-adoption.logic.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,7 +1,31 @@
|
|
|
1
|
-
/** Opens the engine-managed region of a PR body. Never change this
|
|
1
|
+
/** Opens the engine-managed region of a PR body. Never change this: it is the identity. */
|
|
2
2
|
export declare const PR_REPORT_MARKER_START = "<!-- cat-factory:verification-report:start -->";
|
|
3
3
|
/** Closes the engine-managed region of a PR body. */
|
|
4
4
|
export declare const PR_REPORT_MARKER_END = "<!-- cat-factory:verification-report:end -->";
|
|
5
|
+
/**
|
|
6
|
+
* One engine-managed region's identity: the comment pair that delimits it.
|
|
7
|
+
*
|
|
8
|
+
* A region is identified by its markers alone, so a body may carry several independent ones and
|
|
9
|
+
* each writer replaces only its own. That is what lets the monorepo bootstrap keep its settled
|
|
10
|
+
* adoption decisions on the pull request without owning the description: the agent writes the
|
|
11
|
+
* narrative, the engine owns one marked block inside it, and neither overwrites the other.
|
|
12
|
+
*/
|
|
13
|
+
export interface ManagedSectionMarkers {
|
|
14
|
+
start: string;
|
|
15
|
+
end: string;
|
|
16
|
+
}
|
|
17
|
+
/** The verification report's markers, as a pair (the default for the helpers below). */
|
|
18
|
+
export declare const PR_REPORT_MARKERS: ManagedSectionMarkers;
|
|
19
|
+
/**
|
|
20
|
+
* The monorepo bootstrap's adoption-decision region.
|
|
21
|
+
*
|
|
22
|
+
* Distinct markers rather than a second use of the report's, because the two are written by
|
|
23
|
+
* different flows at different times and a shared identity would mean whichever ran last erased
|
|
24
|
+
* the other. A bootstrap opens no run whose steps settle, so it never publishes a verification
|
|
25
|
+
* report; a task run on the same repository later can, and its report must not land on top of
|
|
26
|
+
* the decisions this service was created under.
|
|
27
|
+
*/
|
|
28
|
+
export declare const PR_ADOPTION_MARKERS: ManagedSectionMarkers;
|
|
5
29
|
/**
|
|
6
30
|
* Splice `section` into `body` as the engine-managed region.
|
|
7
31
|
*
|
|
@@ -16,10 +40,10 @@ export declare const PR_REPORT_MARKER_END = "<!-- cat-factory:verification-repor
|
|
|
16
40
|
* Returns the new body. The caller compares it against what it read and skips the remote write
|
|
17
41
|
* when nothing changed.
|
|
18
42
|
*/
|
|
19
|
-
export declare function spliceManagedSection(body: string | null | undefined, section: string): string;
|
|
43
|
+
export declare function spliceManagedSection(body: string | null | undefined, section: string, markers?: ManagedSectionMarkers): string;
|
|
20
44
|
/**
|
|
21
45
|
* The engine-managed region's current contents, or null when the body carries none. Used by
|
|
22
46
|
* tests and by any consumer that wants to read a report back off a PR without re-composing it.
|
|
23
47
|
*/
|
|
24
|
-
export declare function readManagedSection(body: string | null | undefined): string | null;
|
|
48
|
+
export declare function readManagedSection(body: string | null | undefined, markers?: ManagedSectionMarkers): string | null;
|
|
25
49
|
//# sourceMappingURL=pr-report.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pr-report.d.ts","sourceRoot":"","sources":["../../src/domain/pr-report.ts"],"names":[],"mappings":"AAcA,
|
|
1
|
+
{"version":3,"file":"pr-report.d.ts","sourceRoot":"","sources":["../../src/domain/pr-report.ts"],"names":[],"mappings":"AAcA,2FAA2F;AAC3F,eAAO,MAAM,sBAAsB,mDAAmD,CAAA;AACtF,qDAAqD;AACrD,eAAO,MAAM,oBAAoB,iDAAiD,CAAA;AAElF;;;;;;;GAOG;AACH,MAAM,WAAW,qBAAqB;IACpC,KAAK,EAAE,MAAM,CAAA;IACb,GAAG,EAAE,MAAM,CAAA;CACZ;AAED,wFAAwF;AACxF,eAAO,MAAM,iBAAiB,EAAE,qBAG/B,CAAA;AAED;;;;;;;;GAQG;AACH,eAAO,MAAM,mBAAmB,EAAE,qBAGjC,CAAA;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,oBAAoB,CAClC,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EAC/B,OAAO,EAAE,MAAM,EACf,OAAO,GAAE,qBAAyC,GACjD,MAAM,CAYR;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAChC,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EAC/B,OAAO,GAAE,qBAAyC,GACjD,MAAM,GAAG,IAAI,CAMf"}
|
package/dist/domain/pr-report.js
CHANGED
|
@@ -11,10 +11,28 @@
|
|
|
11
11
|
// Pure string logic, so it lives in kernel and is shared by the orchestration composer and
|
|
12
12
|
// the `@cat-factory/server` publisher without either depending on the other.
|
|
13
13
|
// ---------------------------------------------------------------------------
|
|
14
|
-
/** Opens the engine-managed region of a PR body. Never change this
|
|
14
|
+
/** Opens the engine-managed region of a PR body. Never change this: it is the identity. */
|
|
15
15
|
export const PR_REPORT_MARKER_START = '<!-- cat-factory:verification-report:start -->';
|
|
16
16
|
/** Closes the engine-managed region of a PR body. */
|
|
17
17
|
export const PR_REPORT_MARKER_END = '<!-- cat-factory:verification-report:end -->';
|
|
18
|
+
/** The verification report's markers, as a pair (the default for the helpers below). */
|
|
19
|
+
export const PR_REPORT_MARKERS = {
|
|
20
|
+
start: PR_REPORT_MARKER_START,
|
|
21
|
+
end: PR_REPORT_MARKER_END,
|
|
22
|
+
};
|
|
23
|
+
/**
|
|
24
|
+
* The monorepo bootstrap's adoption-decision region.
|
|
25
|
+
*
|
|
26
|
+
* Distinct markers rather than a second use of the report's, because the two are written by
|
|
27
|
+
* different flows at different times and a shared identity would mean whichever ran last erased
|
|
28
|
+
* the other. A bootstrap opens no run whose steps settle, so it never publishes a verification
|
|
29
|
+
* report; a task run on the same repository later can, and its report must not land on top of
|
|
30
|
+
* the decisions this service was created under.
|
|
31
|
+
*/
|
|
32
|
+
export const PR_ADOPTION_MARKERS = {
|
|
33
|
+
start: '<!-- cat-factory:adoption-decisions:start -->',
|
|
34
|
+
end: '<!-- cat-factory:adoption-decisions:end -->',
|
|
35
|
+
};
|
|
18
36
|
/**
|
|
19
37
|
* Splice `section` into `body` as the engine-managed region.
|
|
20
38
|
*
|
|
@@ -29,14 +47,14 @@ export const PR_REPORT_MARKER_END = '<!-- cat-factory:verification-report:end --
|
|
|
29
47
|
* Returns the new body. The caller compares it against what it read and skips the remote write
|
|
30
48
|
* when nothing changed.
|
|
31
49
|
*/
|
|
32
|
-
export function spliceManagedSection(body, section) {
|
|
50
|
+
export function spliceManagedSection(body, section, markers = PR_REPORT_MARKERS) {
|
|
33
51
|
const existing = body ?? '';
|
|
34
|
-
const wrapped = `${
|
|
35
|
-
const start = existing.indexOf(
|
|
36
|
-
const end = existing.indexOf(
|
|
52
|
+
const wrapped = `${markers.start}\n${section.trim()}\n${markers.end}`;
|
|
53
|
+
const start = existing.indexOf(markers.start);
|
|
54
|
+
const end = existing.indexOf(markers.end);
|
|
37
55
|
if (start !== -1 && end > start) {
|
|
38
56
|
const before = existing.slice(0, start);
|
|
39
|
-
const after = existing.slice(end +
|
|
57
|
+
const after = existing.slice(end + markers.end.length);
|
|
40
58
|
return `${before}${wrapped}${after}`;
|
|
41
59
|
}
|
|
42
60
|
const prefix = existing.trim();
|
|
@@ -46,12 +64,12 @@ export function spliceManagedSection(body, section) {
|
|
|
46
64
|
* The engine-managed region's current contents, or null when the body carries none. Used by
|
|
47
65
|
* tests and by any consumer that wants to read a report back off a PR without re-composing it.
|
|
48
66
|
*/
|
|
49
|
-
export function readManagedSection(body) {
|
|
67
|
+
export function readManagedSection(body, markers = PR_REPORT_MARKERS) {
|
|
50
68
|
const existing = body ?? '';
|
|
51
|
-
const start = existing.indexOf(
|
|
52
|
-
const end = existing.indexOf(
|
|
69
|
+
const start = existing.indexOf(markers.start);
|
|
70
|
+
const end = existing.indexOf(markers.end);
|
|
53
71
|
if (start === -1 || end <= start)
|
|
54
72
|
return null;
|
|
55
|
-
return existing.slice(start +
|
|
73
|
+
return existing.slice(start + markers.start.length, end).trim();
|
|
56
74
|
}
|
|
57
75
|
//# sourceMappingURL=pr-report.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pr-report.js","sourceRoot":"","sources":["../../src/domain/pr-report.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAC9E,gEAAgE;AAChE,EAAE;AACF,yFAAyF;AACzF,wFAAwF;AACxF,sFAAsF;AACtF,kFAAkF;AAClF,4FAA4F;AAC5F,iBAAiB;AACjB,EAAE;AACF,2FAA2F;AAC3F,6EAA6E;AAC7E,8EAA8E;AAE9E,
|
|
1
|
+
{"version":3,"file":"pr-report.js","sourceRoot":"","sources":["../../src/domain/pr-report.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAC9E,gEAAgE;AAChE,EAAE;AACF,yFAAyF;AACzF,wFAAwF;AACxF,sFAAsF;AACtF,kFAAkF;AAClF,4FAA4F;AAC5F,iBAAiB;AACjB,EAAE;AACF,2FAA2F;AAC3F,6EAA6E;AAC7E,8EAA8E;AAE9E,2FAA2F;AAC3F,MAAM,CAAC,MAAM,sBAAsB,GAAG,gDAAgD,CAAA;AACtF,qDAAqD;AACrD,MAAM,CAAC,MAAM,oBAAoB,GAAG,8CAA8C,CAAA;AAelF,wFAAwF;AACxF,MAAM,CAAC,MAAM,iBAAiB,GAA0B;IACtD,KAAK,EAAE,sBAAsB;IAC7B,GAAG,EAAE,oBAAoB;CAC1B,CAAA;AAED;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAA0B;IACxD,KAAK,EAAE,+CAA+C;IACtD,GAAG,EAAE,6CAA6C;CACnD,CAAA;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,oBAAoB,CAClC,IAA+B,EAC/B,OAAe,EACf,OAAO,GAA0B,iBAAiB;IAElD,MAAM,QAAQ,GAAG,IAAI,IAAI,EAAE,CAAA;IAC3B,MAAM,OAAO,GAAG,GAAG,OAAO,CAAC,KAAK,KAAK,OAAO,CAAC,IAAI,EAAE,KAAK,OAAO,CAAC,GAAG,EAAE,CAAA;IACrE,MAAM,KAAK,GAAG,QAAQ,CAAC,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,CAAA;IAC7C,MAAM,GAAG,GAAG,QAAQ,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,CAAA;IACzC,IAAI,KAAK,KAAK,CAAC,CAAC,IAAI,GAAG,GAAG,KAAK,EAAE,CAAC;QAChC,MAAM,MAAM,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAA;QACvC,MAAM,KAAK,GAAG,QAAQ,CAAC,KAAK,CAAC,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAA;QACtD,OAAO,GAAG,MAAM,GAAG,OAAO,GAAG,KAAK,EAAE,CAAA;IACtC,CAAC;IACD,MAAM,MAAM,GAAG,QAAQ,CAAC,IAAI,EAAE,CAAA;IAC9B,OAAO,MAAM,CAAC,CAAC,CAAC,GAAG,MAAM,OAAO,OAAO,IAAI,CAAC,CAAC,CAAC,GAAG,OAAO,IAAI,CAAA;AAC9D,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,kBAAkB,CAChC,IAA+B,EAC/B,OAAO,GAA0B,iBAAiB;IAElD,MAAM,QAAQ,GAAG,IAAI,IAAI,EAAE,CAAA;IAC3B,MAAM,KAAK,GAAG,QAAQ,CAAC,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,CAAA;IAC7C,MAAM,GAAG,GAAG,QAAQ,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,CAAA;IACzC,IAAI,KAAK,KAAK,CAAC,CAAC,IAAI,GAAG,IAAI,KAAK;QAAE,OAAO,IAAI,CAAA;IAC7C,OAAO,QAAQ,CAAC,KAAK,CAAC,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,IAAI,EAAE,CAAA;AACjE,CAAC"}
|
|
@@ -23,9 +23,17 @@ export interface ServiceRegistrationDeps {
|
|
|
23
23
|
* Shared by every site that creates a top-level frame (board drops, repo import, seeded demo
|
|
24
24
|
* boards, repo bootstrap) so they all produce a consistent, shareable service.
|
|
25
25
|
*/
|
|
26
|
-
export declare function registerServiceForFrame(deps: ServiceRegistrationDeps, workspaceId: string, frame: Pick<Block, 'id' | 'position' | 'size'>,
|
|
27
|
-
|
|
28
|
-
|
|
26
|
+
export declare function registerServiceForFrame(deps: ServiceRegistrationDeps, workspaceId: string, frame: Pick<Block, 'id' | 'position' | 'size'>,
|
|
27
|
+
/**
|
|
28
|
+
* What the frame is pinned to. The two repo ids and the `directory` are INDEPENDENTLY
|
|
29
|
+
* optional: a monorepo bootstrap knows the subdirectory its service will occupy from the
|
|
30
|
+
* moment it is pre-flighted, but must not claim a repo binding until the run has actually
|
|
31
|
+
* written code there: a service bound to a repo whose directory is still empty dispatches
|
|
32
|
+
* tasks into nothing.
|
|
33
|
+
*/
|
|
34
|
+
repo?: {
|
|
35
|
+
installationId?: number | null;
|
|
36
|
+
githubId?: number | null;
|
|
29
37
|
directory?: string | null;
|
|
30
38
|
}): Promise<string | undefined>;
|
|
31
39
|
//# sourceMappingURL=service-registration.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"service-registration.d.ts","sourceRoot":"","sources":["../../src/domain/service-registration.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAW,MAAM,YAAY,CAAA;AAChD,OAAO,KAAK,EACV,KAAK,EACL,WAAW,EACX,iBAAiB,EACjB,wBAAwB,EACxB,mBAAmB,EACpB,MAAM,mBAAmB,CAAA;AAE1B;;;;GAIG;AACH,MAAM,WAAW,uBAAuB;IACtC,iBAAiB,CAAC,EAAE,iBAAiB,CAAA;IACrC,wBAAwB,CAAC,EAAE,wBAAwB,CAAA;IACnD,mBAAmB,EAAE,mBAAmB,CAAA;IACxC,WAAW,EAAE,WAAW,CAAA;IACxB,KAAK,EAAE,KAAK,CAAA;CACb;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,uBAAuB,CAC3C,IAAI,EAAE,uBAAuB,EAC7B,WAAW,EAAE,MAAM,EACnB,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,IAAI,GAAG,UAAU,GAAG,MAAM,CAAC,
|
|
1
|
+
{"version":3,"file":"service-registration.d.ts","sourceRoot":"","sources":["../../src/domain/service-registration.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAW,MAAM,YAAY,CAAA;AAChD,OAAO,KAAK,EACV,KAAK,EACL,WAAW,EACX,iBAAiB,EACjB,wBAAwB,EACxB,mBAAmB,EACpB,MAAM,mBAAmB,CAAA;AAE1B;;;;GAIG;AACH,MAAM,WAAW,uBAAuB;IACtC,iBAAiB,CAAC,EAAE,iBAAiB,CAAA;IACrC,wBAAwB,CAAC,EAAE,wBAAwB,CAAA;IACnD,mBAAmB,EAAE,mBAAmB,CAAA;IACxC,WAAW,EAAE,WAAW,CAAA;IACxB,KAAK,EAAE,KAAK,CAAA;CACb;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,uBAAuB,CAC3C,IAAI,EAAE,uBAAuB,EAC7B,WAAW,EAAE,MAAM,EACnB,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,IAAI,GAAG,UAAU,GAAG,MAAM,CAAC;AAC9C;;;;;;GAMG;AACH,IAAI,CAAC,EAAE;IACL,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC9B,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACxB,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CAC1B,GACA,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAuB7B"}
|
|
@@ -9,7 +9,15 @@
|
|
|
9
9
|
* Shared by every site that creates a top-level frame (board drops, repo import, seeded demo
|
|
10
10
|
* boards, repo bootstrap) so they all produce a consistent, shareable service.
|
|
11
11
|
*/
|
|
12
|
-
export async function registerServiceForFrame(deps, workspaceId, frame,
|
|
12
|
+
export async function registerServiceForFrame(deps, workspaceId, frame,
|
|
13
|
+
/**
|
|
14
|
+
* What the frame is pinned to. The two repo ids and the `directory` are INDEPENDENTLY
|
|
15
|
+
* optional: a monorepo bootstrap knows the subdirectory its service will occupy from the
|
|
16
|
+
* moment it is pre-flighted, but must not claim a repo binding until the run has actually
|
|
17
|
+
* written code there: a service bound to a repo whose directory is still empty dispatches
|
|
18
|
+
* tasks into nothing.
|
|
19
|
+
*/
|
|
20
|
+
repo) {
|
|
13
21
|
const { serviceRepository, workspaceMountRepository } = deps;
|
|
14
22
|
if (!serviceRepository || !workspaceMountRepository)
|
|
15
23
|
return undefined;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"service-registration.js","sourceRoot":"","sources":["../../src/domain/service-registration.ts"],"names":[],"mappings":"AAsBA;;;;;;;;;;GAUG;AACH,MAAM,CAAC,KAAK,UAAU,uBAAuB,CAC3C,IAA6B,EAC7B,WAAmB,EACnB,KAA8C,
|
|
1
|
+
{"version":3,"file":"service-registration.js","sourceRoot":"","sources":["../../src/domain/service-registration.ts"],"names":[],"mappings":"AAsBA;;;;;;;;;;GAUG;AACH,MAAM,CAAC,KAAK,UAAU,uBAAuB,CAC3C,IAA6B,EAC7B,WAAmB,EACnB,KAA8C;AAC9C;;;;;;GAMG;AACH,IAIC;IAED,MAAM,EAAE,iBAAiB,EAAE,wBAAwB,EAAE,GAAG,IAAI,CAAA;IAC5D,IAAI,CAAC,iBAAiB,IAAI,CAAC,wBAAwB;QAAE,OAAO,SAAS,CAAA;IACrE,MAAM,SAAS,GAAG,CAAC,MAAM,IAAI,CAAC,mBAAmB,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC,IAAI,IAAI,CAAA;IACjF,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,EAAE,CAAA;IAC5B,MAAM,OAAO,GAAY;QACvB,EAAE,EAAE,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,KAAK,CAAC;QAChC,SAAS;QACT,YAAY,EAAE,KAAK,CAAC,EAAE;QACtB,cAAc,EAAE,IAAI,EAAE,cAAc,IAAI,IAAI;QAC5C,YAAY,EAAE,IAAI,EAAE,QAAQ,IAAI,IAAI;QACpC,SAAS,EAAE,IAAI,EAAE,SAAS,IAAI,IAAI;QAClC,SAAS,EAAE,GAAG;KACf,CAAA;IACD,MAAM,iBAAiB,CAAC,MAAM,CAAC,OAAO,CAAC,CAAA;IACvC,MAAM,wBAAwB,CAAC,MAAM,CAAC;QACpC,WAAW;QACX,SAAS,EAAE,OAAO,CAAC,EAAE;QACrB,QAAQ,EAAE,KAAK,CAAC,QAAQ;QACxB,IAAI,EAAE,KAAK,CAAC,IAAI,IAAI,IAAI;QACxB,SAAS,EAAE,GAAG;KACf,CAAC,CAAA;IACF,OAAO,OAAO,CAAC,EAAE,CAAA;AACnB,CAAC"}
|