@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.
Files changed (37) hide show
  1. package/dist/domain/monorepo-adoption.logic.d.ts +87 -0
  2. package/dist/domain/monorepo-adoption.logic.d.ts.map +1 -0
  3. package/dist/domain/monorepo-adoption.logic.js +323 -0
  4. package/dist/domain/monorepo-adoption.logic.js.map +1 -0
  5. package/dist/domain/pr-report.d.ts +27 -3
  6. package/dist/domain/pr-report.d.ts.map +1 -1
  7. package/dist/domain/pr-report.js +28 -10
  8. package/dist/domain/pr-report.js.map +1 -1
  9. package/dist/domain/service-registration.d.ts +11 -3
  10. package/dist/domain/service-registration.d.ts.map +1 -1
  11. package/dist/domain/service-registration.js +9 -1
  12. package/dist/domain/service-registration.js.map +1 -1
  13. package/dist/domain/types.d.ts +1 -1
  14. package/dist/domain/types.d.ts.map +1 -1
  15. package/dist/index.d.ts +2 -1
  16. package/dist/index.d.ts.map +1 -1
  17. package/dist/index.js +7 -2
  18. package/dist/index.js.map +1 -1
  19. package/dist/ports/agent-runs.d.ts +4 -1
  20. package/dist/ports/agent-runs.d.ts.map +1 -1
  21. package/dist/ports/bootstrap-repositories.d.ts +49 -2
  22. package/dist/ports/bootstrap-repositories.d.ts.map +1 -1
  23. package/dist/ports/bootstrap-runner.d.ts +15 -8
  24. package/dist/ports/bootstrap-runner.d.ts.map +1 -1
  25. package/dist/ports/bootstrap-runner.js.map +1 -1
  26. package/dist/ports/index.d.ts +3 -2
  27. package/dist/ports/index.d.ts.map +1 -1
  28. package/dist/ports/index.js.map +1 -1
  29. package/dist/ports/monorepo-adoption.d.ts +37 -0
  30. package/dist/ports/monorepo-adoption.d.ts.map +1 -0
  31. package/dist/ports/monorepo-adoption.js +2 -0
  32. package/dist/ports/monorepo-adoption.js.map +1 -0
  33. package/dist/ports/repo-bootstrapper.d.ts +89 -3
  34. package/dist/ports/repo-bootstrapper.d.ts.map +1 -1
  35. package/dist/ports/repo-files.d.ts +16 -0
  36. package/dist/ports/repo-files.d.ts.map +1 -1
  37. 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":"AAAA,OAAO,EACL,kBAAkB,EAClB,oBAAoB,EACpB,uBAAuB,GASxB,MAAM,wBAAwB,CAAA;AAC/B,OAAO,KAAK,YAAY,MAAM,kCAAkC,CAAA;AAChE,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAA;AAE7C,8EAA8E;AAC9E,2FAA2F;AAC3F,4FAA4F;AAC5F,4CAA4C;AAC5C,EAAE;AACF,6FAA6F;AAC7F,+FAA+F;AAC/F,+BAA+B;AAC/B,EAAE;AACF,6FAA6F;AAC7F,+FAA+F;AAC/F,yFAAyF;AACzF,+FAA+F;AAC/F,qBAAqB;AACrB,uFAAuF;AACvF,qFAAqF;AACrF,8EAA8E;AAE9E,qGAAqG;AACrG,MAAM,CAAC,MAAM,sBAAsB,GAAG,EAAE,CAAA;AAExC;;;;;;;GAOG;AACH,SAAS,mBAAmB,CAAC,IAAW;IACtC,OAAO,IAAI,MAAM,CAAC,IAAI,CAAC,kEAAkE,CAAA;AAC3F,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,oBAAoB,CAAC,IAAkB;IACrD,QAAQ,IAAI,EAAE,CAAC;QACb,KAAK,eAAe;YAClB,OAAO,eAAe,CAAA;QACxB,KAAK,cAAc;YACjB,OAAO,4CAA4C,CAAA;QACrD,KAAK,aAAa;YAChB,OAAO,wBAAwB,CAAA;QACjC,KAAK,WAAW;YACd,OAAO,eAAe,CAAA;QACxB,KAAK,SAAS;YACZ,OAAO,6BAA6B,CAAA;QACtC,KAAK,IAAI;YACP,OAAO,cAAc,CAAA;QACvB,KAAK,kBAAkB;YACrB,OAAO,kCAAkC,CAAA;QAC3C,KAAK,gBAAgB;YACnB,OAAO,mCAAmC,CAAA;QAC5C,KAAK,eAAe;YAClB,OAAO,8BAA8B,CAAA;QACvC,KAAK,eAAe;YAClB,OAAO,oCAAoC,CAAA;QAC7C,KAAK,MAAM;YACT,OAAO,eAAe,CAAA;QACxB,KAAK,OAAO;YACV,OAAO,mBAAmB,CAAA;QAC5B;YACE,OAAO,mBAAmB,CAAC,IAAI,CAAC,CAAA;IACpC,CAAC;AACH,CAAC;AAED,0GAA0G;AAC1G,SAAS,qBAAqB,CAAC,MAAa;IAC1C,OAAO,IAAI,MAAM,CAAC,MAAM,CAAC,mEAAmE,CAAA;AAC9F,CAAC;AAED,iGAAiG;AACjG,MAAM,UAAU,sBAAsB,CAAC,MAAsB;IAC3D,QAAQ,MAAM,EAAE,CAAC;QACf,KAAK,UAAU;YACb,OAAO,kEAAkE,CAAA;QAC3E,KAAK,UAAU;YACb,OAAO,6CAA6C,CAAA;QACtD,KAAK,MAAM;YACT,OAAO,gGAAgG,CAAA;QACzG,KAAK,SAAS;YACZ,OAAO,0DAA0D,CAAA;QACnE;YACE,OAAO,qBAAqB,CAAC,MAAM,CAAC,CAAA;IACxC,CAAC;AACH,CAAC;AAED,qGAAqG;AACrG,MAAM,UAAU,cAAc,CAAC,KAAc;IAC3C,OAAO,CACL,OAAO,KAAK,KAAK,QAAQ,IAAK,kBAAkB,CAAC,OAA6B,CAAC,QAAQ,CAAC,KAAK,CAAC,CAC/F,CAAA;AACH,CAAC;AAED,sGAAsG;AACtG,MAAM,UAAU,gBAAgB,CAAC,KAAc;IAC7C,OAAO,CACL,OAAO,KAAK,KAAK,QAAQ,IAAK,oBAAoB,CAAC,OAA6B,CAAC,QAAQ,CAAC,KAAK,CAAC,CACjG,CAAA;AACH,CAAC;AASD,8FAA8F;AAC9F,SAAS,aAAa,CAAC,MAAsB;IAC3C,OAAO,IAAI,GAAG,CAAC;QACb,GAAG,MAAM,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,YAAY,IAAI,EAAE,CAAC;QACzD,GAAG,MAAM,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,YAAY,IAAI,EAAE,CAAC;KAC1D,CAAC,CAAA;AACJ,CAAC;AAED,SAAS,QAAQ,CAAC,KAAc,EAAE,GAAW;IAC3C,OAAO,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAA;AACpE,CAAC;AAED,SAAS,gBAAgB,CAAC,KAAc,EAAE,GAAW;IACnD,MAAM,IAAI,GAAG,QAAQ,CAAC,KAAK,EAAE,GAAG,CAAC,CAAA;IACjC,OAAO,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAA;AACtC,CAAC;AAED;;;;;;;;;;;;;;GAcG;AACH,MAAM,UAAU,sBAAsB,CACpC,GAAY,EACZ,MAAsB;IAEtB,MAAM,OAAO,GAAa,EAAE,CAAA;IAC5B,IAAI,UAAU,GAAG,CAAC,CAAA;IAClB,iGAAiG;IACjG,MAAM,IAAI,GAAG,CAAC,IAAY,EAAQ,EAAE;QAClC,IAAI,OAAO,CAAC,MAAM,GAAG,uBAAuB;YAAE,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;;YAC3D,UAAU,IAAI,CAAC,CAAA;IACtB,CAAC,CAAA;IACD,MAAM,SAAS,GAAG,GAAqC,CAAA;IACvD,MAAM,IAAI,GAAG,KAAK,CAAC,OAAO,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAA;IAC7E,IAAI,CAAC,IAAI;QAAE,OAAO,EAAE,SAAS,EAAE,EAAE,EAAE,OAAO,EAAE,CAAC,wCAAwC,CAAC,EAAE,CAAA;IAExF,MAAM,KAAK,GAAG,aAAa,CAAC,MAAM,CAAC,CAAA;IACnC,MAAM,SAAS,GAAuB,EAAE,CAAA;IACxC,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAA;IAC9B,KAAK,MAAM,KAAK,IAAI,IAAI,EAAE,CAAC;QACzB,IAAI,SAAS,CAAC,MAAM,IAAI,sBAAsB,EAAE,CAAC;YAC/C,IAAI,CACF,gCAAgC,sBAAsB,oCAAoC,CAC3F,CAAA;YACD,MAAK;QACP,CAAC;QACD,MAAM,IAAI,GAAG,KAAuC,CAAA;QACpD,IAAI,CAAC,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ;YAAE,SAAQ;QAC/C,MAAM,EAAE,GAAG,QAAQ,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,CAAC,CAAA;QAChC,MAAM,KAAK,GAAG,QAAQ,CAAC,IAAI,CAAC,KAAK,EAAE,GAAG,CAAC,CAAA;QACvC,IAAI,CAAC,EAAE,IAAI,CAAC,KAAK,EAAE,CAAC;YAClB,IAAI,CAAC,2CAA2C,EAAE,IAAI,KAAK,IAAI,SAAS,GAAG,CAAC,CAAA;YAC5E,SAAQ;QACV,CAAC;QACD,IAAI,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC;YACjB,IAAI,CAAC,IAAI,EAAE,+CAA+C,CAAC,CAAA;YAC3D,SAAQ;QACV,CAAC;QACD,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;YAC/B,IAAI,CAAC,IAAI,KAAK,iDAAiD,CAAC,CAAA;YAChE,SAAQ;QACV,CAAC;QACD,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,WAAW,CAAC,EAAE,CAAC;YACxC,IAAI,CAAC,IAAI,KAAK,wDAAwD,CAAC,CAAA;YACvE,SAAQ;QACV,CAAC;QACD,MAAM,QAAQ,GAAG,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC;YAC3C,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,IAAI,EAAkB,EAAE,CAAC,OAAO,IAAI,KAAK,QAAQ,IAAI,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;YAC7F,CAAC,CAAC,EAAE,CAAA;QACN,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC1B,IAAI,CAAC,IAAI,KAAK,yEAAyE,CAAC,CAAA;YACxF,SAAQ;QACV,CAAC;QACD,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;QACZ,SAAS,CAAC,IAAI,CAAC;YACb,EAAE;YACF,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,KAAK;YACL,gBAAgB,EAAE,gBAAgB,CAAC,IAAI,CAAC,gBAAgB,EAAE,GAAG,CAAC;YAC9D,gBAAgB,EAAE,gBAAgB,CAAC,IAAI,CAAC,gBAAgB,EAAE,GAAG,CAAC;YAC9D,WAAW,EAAE,IAAI,CAAC,WAAW;YAC7B,SAAS,EAAE,QAAQ,CAAC,IAAI,CAAC,SAAS,EAAE,GAAG,CAAC;YACxC,QAAQ;SACT,CAAC,CAAA;IACJ,CAAC;IACD,IAAI,UAAU,GAAG,CAAC,EAAE,CAAC;QACnB,OAAO,CAAC,IAAI,CAAC,OAAO,UAAU,8DAA8D,CAAC,CAAA;IAC/F,CAAC;IACD,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,CAAA;AAC/B,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,qBAAqB,CACnC,IAAkB,EAClB,OAAkC,EAClC,OAA4F;IAE5F,wFAAwF;IACxF,+FAA+F;IAC/F,gGAAgG;IAChG,+FAA+F;IAC/F,gGAAgG;IAChG,uFAAuF;IACvF,gGAAgG;IAChG,MAAM,IAAI,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,MAAM,CAAC,EAAE,EAAE,MAAM,CAAC,CAAC,CAAC,CAAA;IAClE,MAAM,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,MAAM,CAAC,EAAE,CAAC,CAAC,CAAA;IAC3F,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACvB,MAAM,IAAI,eAAe,CACvB,4DAA4D,OAAO;aAChE,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,IAAI,MAAM,CAAC,EAAE,GAAG,CAAC;aACjC,IAAI,CAAC,IAAI,CAAC,wCAAwC,EACrD,EAAE,MAAM,EAAE,yBAAyB,EAAE,GAAG,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,CAC/E,CAAA;IACH,CAAC;IACD,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,CAAA;IAC3E,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACvB,MAAM,IAAI,eAAe,CACvB,6CAA6C,OAAO,CAAC,MAAM,IACzD,OAAO,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,KAChC,gBAAgB,OAAO,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,IAAI,QAAQ,CAAC,KAAK,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAC9E,EAAE,MAAM,EAAE,4BAA4B,EAAE,GAAG,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,EAAE,CACtF,CAAA;IACH,CAAC;IAED,MAAM,SAAS,GAA+B,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,EAAE;QAC5E,sFAAsF;QACtF,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAmB,CAAA;QACtD,OAAO;YACL,EAAE,EAAE,QAAQ,CAAC,EAAE;YACf,IAAI,EAAE,QAAQ,CAAC,IAAI;YACnB,KAAK,EAAE,QAAQ,CAAC,KAAK;YACrB,MAAM,EAAE,MAAM,CAAC,MAAM;YACrB,sBAAsB,EAAE,MAAM,CAAC,MAAM,KAAK,QAAQ,CAAC,WAAW;YAC9D,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI;SACtD,CAAA;IACH,CAAC,CAAC,CAAA;IACF,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,EAAE,IAAI,EAAE,CAAA;IACnC,OAAO;QACL,SAAS;QACT,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI;QAC3B,gBAAgB,EAAE,OAAO,CAAC,gBAAgB;QAC1C,UAAU,EAAE,OAAO,CAAC,UAAU;KAC/B,CAAA;AACH,CAAC;AAoBD,gGAAgG;AAChG,MAAM,UAAU,GAAqB,EAAE,MAAM,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,EAAE,CAAA;AAE1F,gGAAgG;AAChG,MAAM,SAAS,GAAqB;IAClC,MAAM,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,YAAY,CAAC,MAAM,CAAC,KAAK,CAAC;IAC7C,KAAK,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,YAAY,CAAC,KAAK,CAAC,KAAK,CAAC;CAC5C,CAAA;AAED,gGAAgG;AAChG,SAAS,uBAAuB,CAC9B,QAA0B,EAC1B,IAAsB,EACtB,IAAY;IAEZ,MAAM,KAAK,GAAa;QACtB,0EAA0E;QAC1E,EAAE;QACF,IAAI;QACJ,EAAE;KACH,CAAA;IACD,IAAI,QAAQ,CAAC,SAAS,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACpC,KAAK,CAAC,IAAI,CACR,qFAAqF;YACnF,mEAAmE,EACrE,EAAE,CACH,CAAA;IACH,CAAC;IACD,KAAK,MAAM,QAAQ,IAAI,QAAQ,CAAC,SAAS,EAAE,CAAC;QAC1C,MAAM,QAAQ,GAAG,QAAQ,CAAC,sBAAsB,CAAC,CAAC,CAAC,qCAAqC,CAAC,CAAC,CAAC,EAAE,CAAA;QAC7F,KAAK,CAAC,IAAI,CACR,OAAO,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK;YAC/E,GAAG,sBAAsB,CAAC,QAAQ,CAAC,MAAM,CAAC,GAAG,QAAQ,GAAG;YACxD,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,wBAAwB,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAC9E,CAAA;IACH,CAAC;IACD,IAAI,QAAQ,CAAC,KAAK,EAAE,CAAC;QACnB,KAAK,CAAC,IAAI,CAAC,EAAE,EAAE,+CAA+C,EAAE,EAAE,EAAE,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAA;IACjG,CAAC;IACD,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;AACzB,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,mBAAmB,CAAC,QAA0B,EAAE,SAAiB;IAC/E,OAAO,uBAAuB,CAC5B,QAAQ,EACR,UAAU,EACV,8BAA8B,SAAS,kDAAkD;QACvF,mFAAmF;QACnF,wFAAwF;QACxF,2FAA2F;QAC3F,wFAAwF,CAC3F,CAAA;AACH,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,uBAAuB,CAAC,QAA0B,EAAE,SAAiB;IACnF,MAAM,SAAS,GAAG,QAAQ,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,QAAQ,CAAC,sBAAsB,CAAC,CAAC,MAAM,CAAA;IACjG,MAAM,MAAM,GACV,QAAQ,CAAC,SAAS,CAAC,MAAM,KAAK,CAAC;QAC7B,CAAC,CAAC,kEAAkE;QACpE,CAAC,CAAC,SAAS,GAAG,CAAC;YACb,CAAC,CAAC,GAAG,SAAS,8CAA8C;YAC5D,CAAC,CAAC,iDAAiD,CAAA;IACzD,OAAO,uBAAuB,CAC5B,QAAQ,EACR,SAAS,EACT,wCAAwC,YAAY,CAAC,MAAM,CAAC,SAAS,CAAC,qBAAqB;QACzF,mDAAmD,MAAM,8BAA8B;QACvF,iFAAiF,CACpF,CAAA;AACH,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,uBAAuB,CAAC,KAAa;IACnD,OAAO,yBAAyB,KAAK,EAAE,CAAA;AACzC,CAAC"}
@@ -1,7 +1,31 @@
1
- /** Opens the engine-managed region of a PR body. Never change this it is the identity. */
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,4FAA4F;AAC5F,eAAO,MAAM,sBAAsB,mDAAmD,CAAA;AACtF,qDAAqD;AACrD,eAAO,MAAM,oBAAoB,iDAAiD,CAAA;AAElF;;;;;;;;;;;;;GAaG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAY7F;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM,GAAG,IAAI,CAMjF"}
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"}
@@ -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 it is the identity. */
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 = `${PR_REPORT_MARKER_START}\n${section.trim()}\n${PR_REPORT_MARKER_END}`;
35
- const start = existing.indexOf(PR_REPORT_MARKER_START);
36
- const end = existing.indexOf(PR_REPORT_MARKER_END);
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 + PR_REPORT_MARKER_END.length);
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(PR_REPORT_MARKER_START);
52
- const end = existing.indexOf(PR_REPORT_MARKER_END);
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 + PR_REPORT_MARKER_START.length, end).trim();
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,4FAA4F;AAC5F,MAAM,CAAC,MAAM,sBAAsB,GAAG,gDAAgD,CAAA;AACtF,qDAAqD;AACrD,MAAM,CAAC,MAAM,oBAAoB,GAAG,8CAA8C,CAAA;AAElF;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,oBAAoB,CAAC,IAA+B,EAAE,OAAe;IACnF,MAAM,QAAQ,GAAG,IAAI,IAAI,EAAE,CAAA;IAC3B,MAAM,OAAO,GAAG,GAAG,sBAAsB,KAAK,OAAO,CAAC,IAAI,EAAE,KAAK,oBAAoB,EAAE,CAAA;IACvF,MAAM,KAAK,GAAG,QAAQ,CAAC,OAAO,CAAC,sBAAsB,CAAC,CAAA;IACtD,MAAM,GAAG,GAAG,QAAQ,CAAC,OAAO,CAAC,oBAAoB,CAAC,CAAA;IAClD,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,oBAAoB,CAAC,MAAM,CAAC,CAAA;QAC/D,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,CAAC,IAA+B;IAChE,MAAM,QAAQ,GAAG,IAAI,IAAI,EAAE,CAAA;IAC3B,MAAM,KAAK,GAAG,QAAQ,CAAC,OAAO,CAAC,sBAAsB,CAAC,CAAA;IACtD,MAAM,GAAG,GAAG,QAAQ,CAAC,OAAO,CAAC,oBAAoB,CAAC,CAAA;IAClD,IAAI,KAAK,KAAK,CAAC,CAAC,IAAI,GAAG,IAAI,KAAK;QAAE,OAAO,IAAI,CAAA;IAC7C,OAAO,QAAQ,CAAC,KAAK,CAAC,KAAK,GAAG,sBAAsB,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,IAAI,EAAE,CAAA;AAC1E,CAAC"}
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'>, repo?: {
27
- installationId: number;
28
- githubId: number;
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,EAC9C,IAAI,CAAC,EAAE;IAAE,cAAc,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,GAC7E,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAuB7B"}
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, repo) {
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,EAC9C,IAA8E;IAE9E,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"}
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"}