halfcycle 0.3.17 → 0.3.18
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/.claude-plugin/plugin.json +1 -1
- package/bin/bin.bundle.mjs +203 -29
- package/dist/bin.js +401 -139
- package/dist/bin.js.map +3 -3
- package/dist/build-record/close-record.d.ts +124 -0
- package/dist/build-record/close-record.d.ts.map +1 -0
- package/dist/build-record/index.d.ts +8 -5
- package/dist/build-record/index.d.ts.map +1 -1
- package/dist/build-record/sources.d.ts +49 -18
- package/dist/build-record/sources.d.ts.map +1 -1
- package/dist/build-record/template.d.ts.map +1 -1
- package/dist/build-record/types.d.ts +49 -12
- package/dist/build-record/types.d.ts.map +1 -1
- package/dist/build-record/write.d.ts +60 -3
- package/dist/build-record/write.d.ts.map +1 -1
- package/dist/close-phase.d.ts +21 -2
- package/dist/close-phase.d.ts.map +1 -1
- package/dist/engagement-credential.d.ts +58 -2
- package/dist/engagement-credential.d.ts.map +1 -1
- package/dist/index.js +339 -120
- package/dist/index.js.map +3 -3
- package/dist/open-phase.d.ts +58 -1
- package/dist/open-phase.d.ts.map +1 -1
- package/package.json +1 -1
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Source loading + fail-loud validation for the Build-Record assembler.
|
|
3
3
|
*
|
|
4
|
-
* INV-001 (local by construction): every source is a LOCAL file
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
4
|
+
* INV-001 (local by construction): every source is a LOCAL file. The guard-eval
|
|
5
|
+
* log is a phase-scoped JSONL file the runner wrote locally (E2-T-03b) and the
|
|
6
|
+
* close commit/date come from the phase's own close record — never a hosted
|
|
7
|
+
* store call, and since `phase-close-commit` never a live git call either. This
|
|
8
|
+
* module imports only @halfcycle/events (for the wire schema), Node builtins and
|
|
9
|
+
* its own package.
|
|
8
10
|
*
|
|
9
11
|
* INV-007: the guard-eval log is parsed through `guardEvalRunSchema` from
|
|
10
12
|
* @halfcycle/events, so only the FiredGuard-safe fields survive. A line
|
|
@@ -14,8 +16,8 @@
|
|
|
14
16
|
* Fail-loud (AC2): a missing required source throws `MissingSourceError` naming
|
|
15
17
|
* the input. Nothing is blanked or invented.
|
|
16
18
|
*/
|
|
17
|
-
import { type GuardEvalRun } from '@halfcycle/events';
|
|
18
|
-
import type { BuildRecordSources,
|
|
19
|
+
import { type GuardEvalRun, type PhaseIdentity } from '@halfcycle/events';
|
|
20
|
+
import type { BuildRecordSources, NarratedSource, OrchestrationStateSource, PhaseCloseSource } from './types.js';
|
|
19
21
|
import { type SeedGuard } from './types.js';
|
|
20
22
|
/** Thrown when a required source artefact is missing — fail loud, never blank. */
|
|
21
23
|
export declare class MissingSourceError extends Error {
|
|
@@ -39,41 +41,70 @@ export declare class MissingSourceError extends Error {
|
|
|
39
41
|
*/
|
|
40
42
|
export declare function projectSeedGuards(runs: GuardEvalRun[]): SeedGuard[];
|
|
41
43
|
/**
|
|
42
|
-
* Read + parse the phase-scoped guard-eval log file
|
|
44
|
+
* Read + parse the phase-scoped guard-eval log file, whose name comes from
|
|
45
|
+
* `renderPhaseSegment` — the same renderer the writer uses, so the reader cannot
|
|
46
|
+
* drift from it by inspection. The identity is a name or a number; an unsafe one
|
|
47
|
+
* is refused by the renderer before any path is joined.
|
|
48
|
+
*
|
|
43
49
|
* Every line is legacy-normalised (see `normalizeLegacyLine`) then validated
|
|
44
50
|
* through the strict `guardEvalRunSchema` — a mixed-era log (pre-amendment lines
|
|
45
51
|
* with no `runId`/`outcome`, plus new-era `evaluated`/failure/`unconfigured`
|
|
46
52
|
* lines) assembles cleanly, while an undeclared field still rejects. Fails loud
|
|
47
53
|
* when the log file is absent (a required source per the field→source map).
|
|
48
54
|
*/
|
|
49
|
-
export declare function readGuardEvalLog(logDir: string, phaseId:
|
|
50
|
-
/** Load the orchestration-state task map; fail loud if the file is absent. */
|
|
51
|
-
export declare function readOrchestrationState(phasesDir: string, phaseId: number): OrchestrationStateSource;
|
|
55
|
+
export declare function readGuardEvalLog(logDir: string, phaseId: PhaseIdentity): GuardEvalRun[];
|
|
52
56
|
/**
|
|
53
|
-
*
|
|
54
|
-
*
|
|
55
|
-
*
|
|
57
|
+
* Load the orchestration-state task map; fail loud if the file is absent.
|
|
58
|
+
* The filename is produced by `renderPhaseSegment`, so this reader and the
|
|
59
|
+
* Build-Record writer name a phase the same way by construction.
|
|
56
60
|
*/
|
|
57
|
-
export declare function
|
|
61
|
+
export declare function readOrchestrationState(phasesDir: string, phaseId: PhaseIdentity): OrchestrationStateSource;
|
|
62
|
+
/**
|
|
63
|
+
* Read what the phase's close recorded about the repository.
|
|
64
|
+
*
|
|
65
|
+
* THIS REPLACED A GIT CALL, and the replacement is the feature. The assembler
|
|
66
|
+
* used to run `git rev-parse --short HEAD` here, at ASSEMBLY time, so the commit
|
|
67
|
+
* and date a record named were a function of when someone happened to assemble
|
|
68
|
+
* it — close on Monday, assemble on Friday, and the record described Friday
|
|
69
|
+
* while claiming to describe the close. Nothing re-derives either value now.
|
|
70
|
+
*
|
|
71
|
+
* The filename comes from `closeRecordPath` — the same function the close-side
|
|
72
|
+
* writer calls, which builds it through the same renderer every other
|
|
73
|
+
* phase-scoped filename here goes through. Writer and reader cannot drift.
|
|
74
|
+
*
|
|
75
|
+
* AN ABSENT FILE IS ABSENCE, not a failure, and it is the one required-source
|
|
76
|
+
* reader here that does not fail loud. Closing a phase has never needed git, so
|
|
77
|
+
* a close that recorded nothing is legitimate — as is a close made before this
|
|
78
|
+
* file existed, whose commit is simply unrecoverable. Both read as `null` and
|
|
79
|
+
* the record says so. A PRESENT file that cannot be trusted still fails loud,
|
|
80
|
+
* because that is a broken input rather than an absent one.
|
|
81
|
+
*/
|
|
82
|
+
export declare function readPhaseClose(repoRoot: string, phaseId: PhaseIdentity): PhaseCloseSource;
|
|
58
83
|
/**
|
|
59
84
|
* Validate that a caller-supplied narrated bundle has every required field.
|
|
60
85
|
* The narrated fields are lifted from prose artefacts (phase doc, acceptance
|
|
61
86
|
* report, COE notes, ENGAGEMENT ledger) by the loader; this guard makes the
|
|
62
87
|
* "missing source fails loud" contract hold for them too.
|
|
88
|
+
*
|
|
89
|
+
* It also refuses an unsafe `phase.id` (INV-023). That field is not merely data:
|
|
90
|
+
* it is copied into the assembled record and interpolated into the record's own
|
|
91
|
+
* output filename, so it is the one narrated field that decides where the record
|
|
92
|
+
* is written. It is validated here because this is where every route converges.
|
|
63
93
|
*/
|
|
64
94
|
export declare function validateNarrated(narrated: NarratedSource): NarratedSource;
|
|
65
95
|
/**
|
|
66
96
|
* Assemble the complete `BuildRecordSources` bundle from a phase's local
|
|
67
97
|
* artefacts. This is the local-by-construction (INV-001) loader: it reads the
|
|
68
|
-
* orchestration state, the runner's local guard-eval log,
|
|
69
|
-
* caller-lifted narrated + touched-invariants inputs. Every
|
|
70
|
-
* present or it throws
|
|
98
|
+
* orchestration state, the runner's local guard-eval log, the phase's own close
|
|
99
|
+
* record, and the caller-lifted narrated + touched-invariants inputs. Every
|
|
100
|
+
* required source is present or it throws — with one deliberate exception named
|
|
101
|
+
* at `readPhaseClose`, whose absence is a legitimate answer rather than a gap.
|
|
71
102
|
*/
|
|
72
103
|
export declare function loadSources(opts: {
|
|
73
104
|
repoRoot: string;
|
|
74
105
|
phasesDir: string;
|
|
75
106
|
guardEvalLogDir: string;
|
|
76
|
-
phaseId:
|
|
107
|
+
phaseId: PhaseIdentity;
|
|
77
108
|
narrated: NarratedSource;
|
|
78
109
|
touchedInvariants: string[];
|
|
79
110
|
}): BuildRecordSources;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sources.d.ts","sourceRoot":"","sources":["../../src/build-record/sources.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"sources.d.ts","sourceRoot":"","sources":["../../src/build-record/sources.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAKH,OAAO,EAIL,KAAK,YAAY,EACjB,KAAK,aAAa,EACnB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,KAAK,EACV,kBAAkB,EAClB,cAAc,EACd,wBAAwB,EACxB,gBAAgB,EACjB,MAAM,YAAY,CAAC;AACpB,OAAO,EAAoB,KAAK,SAAS,EAAE,MAAM,YAAY,CAAC;AAI9D,kFAAkF;AAClF,qBAAa,kBAAmB,SAAQ,KAAK;gBAC/B,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM;CAI/C;AAMD;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,YAAY,EAAE,GAAG,SAAS,EAAE,CAwBnE;AAwED;;;;;;;;;;;GAWG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,aAAa,GAAG,YAAY,EAAE,CAoBvF;AAMD;;;;GAIG;AACH,wBAAgB,sBAAsB,CACpC,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,aAAa,GACrB,wBAAwB,CAsB1B;AAMD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,aAAa,GAAG,gBAAgB,CAyBzF;AAMD;;;;;;;;;;GAUG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,cAAc,GAAG,cAAc,CA2BzE;AAED;;;;;;;GAOG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE;IAChC,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,eAAe,EAAE,MAAM,CAAC;IACxB,OAAO,EAAE,aAAa,CAAC;IACvB,QAAQ,EAAE,cAAc,CAAC;IACzB,iBAAiB,EAAE,MAAM,EAAE,CAAC;CAC7B,GAAG,kBAAkB,CAerB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"template.d.ts","sourceRoot":"","sources":["../../src/build-record/template.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;
|
|
1
|
+
{"version":3,"file":"template.d.ts","sourceRoot":"","sources":["../../src/build-record/template.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAGH,OAAO,KAAK,EAAE,aAAa,EAAa,MAAM,YAAY,CAAC;AAsD3D;;GAEG;AACH,wBAAgB,yBAAyB,CAAC,MAAM,EAAE,aAAa,GAAG,MAAM,CAiFvE"}
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
* `severity`, optional per-firing `explanation`). It is the ONLY guard-derived
|
|
13
13
|
* shape in the record. There is no path from a `GuardRecord` to this file.
|
|
14
14
|
*/
|
|
15
|
-
import type { FiredGuard, GuardEvalRun } from '@halfcycle/events';
|
|
15
|
+
import type { FiredGuard, GuardEvalRun, PhaseIdentity } from '@halfcycle/events';
|
|
16
16
|
/** The v1 format string — a single literal, one home. */
|
|
17
17
|
export declare const BUILD_RECORD_FORMAT: "halfcycle-build-record/v1";
|
|
18
18
|
/**
|
|
@@ -81,18 +81,40 @@ export interface Tasks {
|
|
|
81
81
|
landed: number;
|
|
82
82
|
cancelled: string[];
|
|
83
83
|
}
|
|
84
|
-
/**
|
|
84
|
+
/**
|
|
85
|
+
* The v1 Build Record — the JSON companion. Field order matters for the seed.
|
|
86
|
+
*
|
|
87
|
+
* `phase.id` is a `PhaseIdentity` — a name OR a number — because a phase is
|
|
88
|
+
* identified by whatever the client called it, and three of this repo's own
|
|
89
|
+
* phases are numbered while twenty-four are named. The widening is deliberately
|
|
90
|
+
* NOT a narrowing to `string`: `docs/build-records/phase-0.json` carries the
|
|
91
|
+
* JSON number `0`, the assembler copies the identity through untransformed, and
|
|
92
|
+
* `packages/bundle/test/build-record-phase0.test.ts` deep-equals the two. Under
|
|
93
|
+
* the union that conformance seed passes with no fixture edit; under `string`
|
|
94
|
+
* alone it would have needed a re-conform and a second operator approval.
|
|
95
|
+
*
|
|
96
|
+
* `closeCommit` and `closedDate` ADMIT ABSENCE, which is the v1 shape moving
|
|
97
|
+
* rather than a field being added. Both were required strings, on the premise
|
|
98
|
+
* that a record could always be given them because they were derived from git at
|
|
99
|
+
* assembly time. They are now captured at the close, and a client with no git
|
|
100
|
+
* closes successfully — so the pair has a legitimate "not recorded" state, and a
|
|
101
|
+
* required string could only have been satisfied by inventing one or by
|
|
102
|
+
* refusing to assemble the record at all. The conformance seed carries strings
|
|
103
|
+
* in both and is unaffected: widening a field admits the value it already held.
|
|
104
|
+
*/
|
|
85
105
|
export interface BuildRecordV1 {
|
|
86
106
|
format: typeof BUILD_RECORD_FORMAT;
|
|
87
107
|
engagement: string;
|
|
88
108
|
engagementType: string;
|
|
89
109
|
phase: {
|
|
90
|
-
id:
|
|
110
|
+
id: PhaseIdentity;
|
|
91
111
|
name: string;
|
|
92
112
|
};
|
|
93
113
|
status: string;
|
|
94
|
-
|
|
95
|
-
|
|
114
|
+
/** The date the phase closed, or null when the close recorded none. */
|
|
115
|
+
closedDate: string | null;
|
|
116
|
+
/** The commit the phase closed at, or null when the close recorded none. */
|
|
117
|
+
closeCommit: string | null;
|
|
96
118
|
thesis: string;
|
|
97
119
|
thesisHeld: boolean;
|
|
98
120
|
delivered: Delivered;
|
|
@@ -106,7 +128,8 @@ export interface BuildRecordV1 {
|
|
|
106
128
|
}
|
|
107
129
|
/**
|
|
108
130
|
* Orchestration-state projection: task terminal states + engagement identity.
|
|
109
|
-
* Loaded from
|
|
131
|
+
* Loaded from the phase-scoped orchestration-state file, whose name is produced
|
|
132
|
+
* by `renderPhaseSegment` and never spelled out here (Zone-B process artefact).
|
|
110
133
|
* Terminal states: `merged`/`done` → landed; `cancelled` → cancelled.
|
|
111
134
|
*/
|
|
112
135
|
export interface OrchestrationStateSource {
|
|
@@ -127,7 +150,7 @@ export interface NarratedSource {
|
|
|
127
150
|
engagement: string;
|
|
128
151
|
engagementType: string;
|
|
129
152
|
phase: {
|
|
130
|
-
id:
|
|
153
|
+
id: PhaseIdentity;
|
|
131
154
|
name: string;
|
|
132
155
|
};
|
|
133
156
|
status: string;
|
|
@@ -138,10 +161,24 @@ export interface NarratedSource {
|
|
|
138
161
|
instruments: Instruments;
|
|
139
162
|
deviations: string[];
|
|
140
163
|
}
|
|
141
|
-
/**
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
164
|
+
/**
|
|
165
|
+
* What the phase's close recorded about the repository.
|
|
166
|
+
*
|
|
167
|
+
* NOT resolved at assembly time, which is the change this type carries. Both
|
|
168
|
+
* values are captured when the phase closes and read back from the local close
|
|
169
|
+
* record (`close-record.ts`), so assembling the same phase twice returns the
|
|
170
|
+
* same document however much work has happened since.
|
|
171
|
+
*
|
|
172
|
+
* `null` on both is a close that recorded neither — a client with no git, no
|
|
173
|
+
* repository or no commit yet closes successfully and this reads as absence
|
|
174
|
+
* rather than as a blank or a value derived later. The pair moves together on
|
|
175
|
+
* both paths, so one is never null while the other is a string.
|
|
176
|
+
*/
|
|
177
|
+
export interface PhaseCloseSource {
|
|
178
|
+
/** The commit the repository was on when the phase closed, or null if none was recorded. */
|
|
179
|
+
closeCommit: string | null;
|
|
180
|
+
/** The date of that commit, or null if none was recorded. */
|
|
181
|
+
closedDate: string | null;
|
|
145
182
|
}
|
|
146
183
|
/**
|
|
147
184
|
* The complete typed source bundle. Every required source is present or the
|
|
@@ -151,7 +188,7 @@ export interface GitSource {
|
|
|
151
188
|
export interface BuildRecordSources {
|
|
152
189
|
orchestration: OrchestrationStateSource;
|
|
153
190
|
narrated: NarratedSource;
|
|
154
|
-
|
|
191
|
+
close: PhaseCloseSource;
|
|
155
192
|
/** The runner's LOCAL guard-eval log for the phase (INV-007-safe wire records). */
|
|
156
193
|
guardEvalRuns: GuardEvalRun[];
|
|
157
194
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/build-record/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/build-record/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAEjF,yDAAyD;AACzD,eAAO,MAAM,mBAAmB,EAAG,2BAAoC,CAAC;AAExE;;;;;;;;;;GAUG;AACH,MAAM,WAAW,SAAS;IACxB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,UAAU,CAAC,UAAU,CAAC,CAAC;IACjC,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;;;;;;;GAQG;AACH,wBAAgB,gBAAgB,CAC9B,KAAK,EAAE,IAAI,CAAC,UAAU,EAAE,YAAY,GAAG,UAAU,GAAG,aAAa,CAAC,EAClE,kBAAkB,EAAE,OAAO,GAC1B,SAAS,CAOX;AAED,yFAAyF;AACzF,MAAM,WAAW,SAAS;IACxB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACpC,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,+BAA+B;AAC/B,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,kEAAkE;AAClE,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;IACzC,qBAAqB,CAAC,EAAE,cAAc,CAAC;CACxC;AAED,MAAM,WAAW,eAAe;IAC9B,qBAAqB,EAAE,MAAM,CAAC;IAC9B,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,qBAAqB,EAAE,MAAM,CAAC;CAC/B;AAED,MAAM,WAAW,WAAW;IAC1B,0BAA0B,EAAE,MAAM,CAAC;IACnC,UAAU,EAAE;QACV,OAAO,EAAE,MAAM,CAAC;QAChB,UAAU,EAAE,MAAM,CAAC;QACnB,eAAe,EAAE,MAAM,CAAC;QACxB,KAAK,EAAE,MAAM,CAAC;KACf,CAAC;CACH;AAED,MAAM,WAAW,KAAK;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,EAAE,CAAC;CACrB;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,OAAO,mBAAmB,CAAC;IACnC,UAAU,EAAE,MAAM,CAAC;IACnB,cAAc,EAAE,MAAM,CAAC;IACvB,KAAK,EAAE;QAAE,EAAE,EAAE,aAAa,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;IAC3C,MAAM,EAAE,MAAM,CAAC;IACf,uEAAuE;IACvE,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,4EAA4E;IAC5E,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,OAAO,CAAC;IACpB,SAAS,EAAE,SAAS,CAAC;IACrB,UAAU,EAAE,SAAS,EAAE,CAAC;IACxB,UAAU,EAAE,UAAU,CAAC;IACvB,eAAe,EAAE,eAAe,CAAC;IACjC,WAAW,EAAE,WAAW,CAAC;IACzB,mBAAmB,EAAE,MAAM,EAAE,CAAC;IAC9B,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,KAAK,EAAE,KAAK,CAAC;CACd;AAMD;;;;;GAKG;AACH,MAAM,WAAW,wBAAwB;IACvC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE;QAAE,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CAC3C;AAED;;;;;;;;GAQG;AACH,MAAM,WAAW,cAAc;IAC7B,UAAU,EAAE,MAAM,CAAC;IACnB,cAAc,EAAE,MAAM,CAAC;IACvB,KAAK,EAAE;QAAE,EAAE,EAAE,aAAa,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;IAC3C,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,SAAS,CAAC;IACrB,UAAU,EAAE,UAAU,CAAC;IACvB,eAAe,EAAE,eAAe,CAAC;IACjC,WAAW,EAAE,WAAW,CAAC;IACzB,UAAU,EAAE,MAAM,EAAE,CAAC;CACtB;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,WAAW,gBAAgB;IAC/B,4FAA4F;IAC5F,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,6DAA6D;IAC7D,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B;AAED;;;;GAIG;AACH,MAAM,WAAW,kBAAkB;IACjC,aAAa,EAAE,wBAAwB,CAAC;IACxC,QAAQ,EAAE,cAAc,CAAC;IACzB,KAAK,EAAE,gBAAgB,CAAC;IACxB,mFAAmF;IACnF,aAAa,EAAE,YAAY,EAAE,CAAC;IAC9B;;;OAGG;IACH,iBAAiB,EAAE,MAAM,EAAE,CAAC;CAC7B"}
|
|
@@ -2,8 +2,50 @@
|
|
|
2
2
|
* Write-disciplined Build-Record writer.
|
|
3
3
|
*
|
|
4
4
|
* Blast radius: the writer touches ONLY `docs/build-records/` in the target
|
|
5
|
-
* repo (same write-discipline as the bundle installer, E1-T-06)
|
|
6
|
-
*
|
|
5
|
+
* repo (same write-discipline as the bundle installer, E1-T-06), and now
|
|
6
|
+
* enforces it rather than claiming it (INV-023).
|
|
7
|
+
*
|
|
8
|
+
* THE RESIDUAL CHECK, AND WHY IT IS NOT DEFENCE IN DEPTH. The identity is
|
|
9
|
+
* validated where every caller converges (`validateNarrated`), but
|
|
10
|
+
* `assembleBuildRecord` and `writeBuildRecord` are exported individually too, so
|
|
11
|
+
* a library caller can compose them without entering `loadSources` at all. For
|
|
12
|
+
* that caller the assertion below is the ONLY guard.
|
|
13
|
+
*
|
|
14
|
+
* It asserts on the joined OUTPUT PATH, not on the output directory. The
|
|
15
|
+
* directory is a constant and the filename is the caller-influenced half, so a
|
|
16
|
+
* directory comparison guards the half that was never at risk — which is exactly
|
|
17
|
+
* how this function's previous check came to compare a value with itself and
|
|
18
|
+
* refuse nothing. The two operands here are genuinely different: `outDir` is
|
|
19
|
+
* derived from `repoRoot` and a constant and does not move when the record
|
|
20
|
+
* changes, while the candidate path is derived from `record.phase.id` and moves
|
|
21
|
+
* with every record.
|
|
22
|
+
*
|
|
23
|
+
* WHAT REFUSES FIRST CHANGED WHEN THE FILENAME MOVED TO THE RENDERER, and saying
|
|
24
|
+
* so is better than leaving a reader to discover it. The residual refusal for a
|
|
25
|
+
* library caller is now the `isValidPhaseIdentity` check in `writeBuildRecord`
|
|
26
|
+
* below, which throws `InvalidPhaseIdentityError` naming this module's allowed
|
|
27
|
+
* location — same error and same message a caller entering through
|
|
28
|
+
* `validateNarrated` gets. `assertInsideOutDir` still runs on every write, but it
|
|
29
|
+
* can no longer be the thing that fires on a hostile identity, because a hostile
|
|
30
|
+
* identity never reaches the join: the identity check refuses it and the renderer
|
|
31
|
+
* refuses it again.
|
|
32
|
+
*
|
|
33
|
+
* SO THE RESIDUAL GUARD IS UNREACHABLE FROM THIS PACKAGE, and that is measured
|
|
34
|
+
* rather than assumed: deleting both of its call sites leaves this package's
|
|
35
|
+
* whole suite green, and sixteen adversarial identities that pass the predicate
|
|
36
|
+
* were probed without one reaching it. What it still guards is real and it is
|
|
37
|
+
* CROSS-PACKAGE — the RENDERER'S OUTPUT. Every segment the renderer emits today
|
|
38
|
+
* is a plain basename, so an edit in `packages/events` that let a separator into
|
|
39
|
+
* one is the only way this can fire, and that edit is invisible from here. A
|
|
40
|
+
* guard whose subject lives in another package cannot be exercised by a
|
|
41
|
+
* behavioural test of this one, so it is exported and tested directly rather
|
|
42
|
+
* than left module-private, where nothing could reach it and nothing would
|
|
43
|
+
* notice its deletion.
|
|
44
|
+
*
|
|
45
|
+
* Refusal is ALL-OR-NOTHING because both paths are asserted BEFORE the first
|
|
46
|
+
* `writeFileSync` — and before the `mkdirSync`, so a refused record does not
|
|
47
|
+
* leave an empty directory behind either. There is no rollback and no two-phase
|
|
48
|
+
* commit; nothing here asks for one.
|
|
7
49
|
*
|
|
8
50
|
* The JSON is serialised with a stable 2-space indent + trailing newline; the
|
|
9
51
|
* markdown data slots are projected from the same record object, so the pair
|
|
@@ -18,9 +60,24 @@ export interface WriteResult {
|
|
|
18
60
|
}
|
|
19
61
|
/** Serialise the record JSON deterministically (2-space indent + trailing NL). */
|
|
20
62
|
export declare function serialiseRecordJson(record: BuildRecordV1): string;
|
|
63
|
+
/**
|
|
64
|
+
* Assert that a joined output path is still a plain file directly inside
|
|
65
|
+
* `outDir`. `relative` is computed between two values that move independently —
|
|
66
|
+
* the allowed directory, and a candidate path built from the record — so this
|
|
67
|
+
* comparison can actually fail.
|
|
68
|
+
*
|
|
69
|
+
* EXPORTED SO IT CAN BE TESTED AT ALL. Its subject is a filename segment that
|
|
70
|
+
* grew a separator, which only an edit in another package can produce, so no
|
|
71
|
+
* behavioural test of this package can reach it — see the module header. It is
|
|
72
|
+
* called directly by `build-record-write-discipline.test.ts` with a candidate
|
|
73
|
+
* outside the directory, which is the only control that can tell this guard
|
|
74
|
+
* from a deleted one.
|
|
75
|
+
*/
|
|
76
|
+
export declare function assertInsideOutDir(outDir: string, candidate: string, identity: unknown): void;
|
|
21
77
|
/**
|
|
22
78
|
* Write the `.json` + `.md` pair for a phase into `docs/build-records/`.
|
|
23
|
-
* Refuses
|
|
79
|
+
* Refuses — writing nothing at all — if the record's identity would put either
|
|
80
|
+
* file anywhere else.
|
|
24
81
|
*/
|
|
25
82
|
export declare function writeBuildRecord(repoRoot: string, record: BuildRecordV1): WriteResult;
|
|
26
83
|
//# sourceMappingURL=write.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"write.d.ts","sourceRoot":"","sources":["../../src/build-record/write.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"write.d.ts","sourceRoot":"","sources":["../../src/build-record/write.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoDG;AAIH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAIhD,4EAA4E;AAC5E,eAAO,MAAM,gBAAgB,QAAgC,CAAC;AAE9D,MAAM,WAAW,WAAW;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,kFAAkF;AAClF,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,aAAa,GAAG,MAAM,CAEjE;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,GAAG,IAAI,CAM7F;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,aAAa,GAAG,WAAW,CA2BrF"}
|
package/dist/close-phase.d.ts
CHANGED
|
@@ -34,12 +34,25 @@
|
|
|
34
34
|
* parses with. It never imports the control service.
|
|
35
35
|
*/
|
|
36
36
|
import { type AcceptanceOutcome, type PhaseCloseDecision } from '@halfcycle/events';
|
|
37
|
-
import type
|
|
37
|
+
import { type PhaseStampFailure, type RepoCredential } from './open-phase.js';
|
|
38
|
+
import { type CloseRecordOutcome } from './build-record/close-record.js';
|
|
38
39
|
/** What `POST /engagements/:id/accept` returns on 200 (the fields the CLI reports). */
|
|
39
40
|
export interface ClosedPhase {
|
|
40
41
|
engagementId: string;
|
|
41
42
|
/** The lifecycle status after the close — `closed`. */
|
|
42
43
|
status: string;
|
|
44
|
+
/**
|
|
45
|
+
* Set when the phase closed but this machine's record of it could not be
|
|
46
|
+
* cleared. `null` on every ordinary success. Until it is cleared, work on this
|
|
47
|
+
* machine is still filed under a phase that is no longer open.
|
|
48
|
+
*/
|
|
49
|
+
stampFailure: PhaseStampFailure | null;
|
|
50
|
+
/**
|
|
51
|
+
* Whether the commit this phase closed at was written down on this machine,
|
|
52
|
+
* and where. When it was not, this says why, and the phase's Build Record will
|
|
53
|
+
* say the commit and the close date were not recorded.
|
|
54
|
+
*/
|
|
55
|
+
closeRecord: CloseRecordOutcome;
|
|
43
56
|
}
|
|
44
57
|
/**
|
|
45
58
|
* A refusal from the control plane, carried as an error the CLI can print whole.
|
|
@@ -105,10 +118,16 @@ export declare class ClosePhaseRefused extends Error {
|
|
|
105
118
|
* for the same reason `openPhase` requires its entry decision: there
|
|
106
119
|
* is no argument-less way to move the phase axis, so an unattributed
|
|
107
120
|
* close is unreachable from any caller that compiles.
|
|
121
|
+
* @param repoRoot the repository whose commit this close is being recorded against.
|
|
122
|
+
* Optional so that a caller with no repository in hand — a test
|
|
123
|
+
* harness, a future non-repo surface — is not forced to invent one;
|
|
124
|
+
* omitting it records no commit rather than silently resolving the
|
|
125
|
+
* process's working directory, which would write a stranger's HEAD
|
|
126
|
+
* into this phase's record.
|
|
108
127
|
*
|
|
109
128
|
* @throws ClosePhaseRefused on a 4xx the plane explained, so the CLI prints the
|
|
110
129
|
* plane's own sentence and exits non-zero.
|
|
111
130
|
* @throws Error on transport failure or a body that is not the expected shape.
|
|
112
131
|
*/
|
|
113
|
-
export declare function closePhase(credential: RepoCredential, phase: string, outcome: AcceptanceOutcome, close: PhaseCloseDecision): Promise<ClosedPhase>;
|
|
132
|
+
export declare function closePhase(credential: RepoCredential, phase: string, outcome: AcceptanceOutcome, close: PhaseCloseDecision, home?: string, repoRoot?: string): Promise<ClosedPhase>;
|
|
114
133
|
//# sourceMappingURL=close-phase.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"close-phase.d.ts","sourceRoot":"","sources":["../src/close-phase.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AAEH,OAAO,EAGL,KAAK,iBAAiB,EACtB,KAAK,kBAAkB,EACxB,MAAM,mBAAmB,CAAC;AAE3B,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"close-phase.d.ts","sourceRoot":"","sources":["../src/close-phase.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AAEH,OAAO,EAGL,KAAK,iBAAiB,EACtB,KAAK,kBAAkB,EACxB,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EAAmB,KAAK,iBAAiB,EAAE,KAAK,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAC/F,OAAO,EAAoB,KAAK,kBAAkB,EAAE,MAAM,gCAAgC,CAAC;AAE3F,uFAAuF;AACvF,MAAM,WAAW,WAAW;IAC1B,YAAY,EAAE,MAAM,CAAC;IACrB,uDAAuD;IACvD,MAAM,EAAE,MAAM,CAAC;IACf;;;;OAIG;IACH,YAAY,EAAE,iBAAiB,GAAG,IAAI,CAAC;IACvC;;;;OAIG;IACH,WAAW,EAAE,kBAAkB,CAAC;CACjC;AAED;;;;;;;;;;;GAWG;AACH,qBAAa,iBAAkB,SAAQ,KAAK;aAExB,MAAM,EAAE,MAAM;IAE9B;;;;;OAKG;aACa,OAAO,CAAC,EAAE,MAAM;IAChC;;;;;;;;;;OAUG;aACa,IAAI,CAAC,EAAE,MAAM;gBApBb,MAAM,EAAE,MAAM,EAC9B,OAAO,EAAE,MAAM;IACf;;;;;OAKG;IACa,OAAO,CAAC,EAAE,MAAM,YAAA;IAChC;;;;;;;;;;OAUG;IACa,IAAI,CAAC,EAAE,MAAM,YAAA;CAKhC;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAsB,UAAU,CAC9B,UAAU,EAAE,cAAc,EAC1B,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,iBAAiB,EAC1B,KAAK,EAAE,kBAAkB,EACzB,IAAI,CAAC,EAAE,MAAM,EACb,QAAQ,CAAC,EAAE,MAAM,GAChB,OAAO,CAAC,WAAW,CAAC,CAwFtB"}
|
|
@@ -181,6 +181,25 @@ export declare const GUARD_COVERAGE_REQUIRED_KEYS: ("GUARD_SERVICE_TOKEN" | "GUA
|
|
|
181
181
|
*/
|
|
182
182
|
export declare const ENGAGEMENT_ENV_KEYS: readonly ["HALFCYCLE_SERVICE_URL", "HALFCYCLE_MCP_URL", "HALFCYCLE_TOKEN", "HALFCYCLE_ENGAGEMENT_ID", "GUARD_SERVICE_URL", "GUARD_SERVICE_TOKEN", "GUARD_ENGAGEMENT_ID", "CONTROL_TELEMETRY_URL"];
|
|
183
183
|
export type EngagementEnvKey = (typeof ENGAGEMENT_ENV_KEYS)[number];
|
|
184
|
+
/**
|
|
185
|
+
* The phase stamp — the one key in this file that is NOT a credential, named once
|
|
186
|
+
* here so the two verbs that move it (`open-phase.ts`, `close-phase.ts`) and this
|
|
187
|
+
* writer agree on the spelling.
|
|
188
|
+
*
|
|
189
|
+
* **Deliberately absent from `ENGAGEMENT_ENV_KEYS` above**, and that is the whole
|
|
190
|
+
* reason `reconcileEnvText`/`writeEngagementEnv` take a `keys` argument. It is not
|
|
191
|
+
* a secret, it is not written by the installer, and an install must not blank it:
|
|
192
|
+
* a re-install re-writes the eight credential keys and this key's line has to
|
|
193
|
+
* survive that untouched, which it does precisely because it is not in the list.
|
|
194
|
+
* The runner reads it out of this file (via the wrapper that sources it) to stamp
|
|
195
|
+
* the phase on every evaluation.
|
|
196
|
+
*
|
|
197
|
+
* `packages/mac-workspace-provider` writes the same name into the same file for a
|
|
198
|
+
* Studio-managed engagement (its own whole-file writer, INV-001-unreachable from
|
|
199
|
+
* here). Nothing is shared: this is the Connect writer, and the two topologies
|
|
200
|
+
* never run against one engagement.
|
|
201
|
+
*/
|
|
202
|
+
export declare const PHASE_STAMP_ENV_KEY = "HALFCYCLE_PHASE";
|
|
184
203
|
/**
|
|
185
204
|
* Parse `KEY=value` lines. **PARSES, NEVER SOURCES** — a credential store is not
|
|
186
205
|
* code, and `.` would execute whatever the file happens to contain. An optional
|
|
@@ -231,8 +250,31 @@ export declare function parseEnvText(raw: string): Record<string, string>;
|
|
|
231
250
|
* install, not preserved as a foreign writer's key. A Studio-written value for it is
|
|
232
251
|
* legitimately overwritten on the next Connect install; only `CONTROL_TELEMETRY_TOKEN`
|
|
233
252
|
* is still genuinely foreign.
|
|
253
|
+
*
|
|
254
|
+
* **A `null` VALUE REMOVES THE KEY'S LINE. An absent one still writes `KEY=''`.**
|
|
255
|
+
* The two are different requests and this function had no way to make the first
|
|
256
|
+
* one: `values[k] ?? ''` mapped both to the empty string, so the only reachable
|
|
257
|
+
* way to "unset" a key was to write it blank. Blank is not absent to any reader of
|
|
258
|
+
* this file — the shell that SOURCES it sets the variable to the empty string, and
|
|
259
|
+
* the Build-Record write predicate refuses an empty phase identity, so a phase
|
|
260
|
+
* stamp cleared by blanking would fire a refusal on the ordinary project-scope
|
|
261
|
+
* return. `open-phase --none` and `close-phase` therefore pass `null` and the
|
|
262
|
+
* assignment leaves the file wherever it sat, `export ` prefix and all. Nothing is
|
|
263
|
+
* appended for a removed key.
|
|
264
|
+
*
|
|
265
|
+
* **The header block is appended AT MOST ONCE per file**, and that follows from the
|
|
266
|
+
* same pair of verbs: `HALFCYCLE_PHASE` leaves on every close and comes back on
|
|
267
|
+
* every open, so a header emitted with each re-appearance would grow the file by a
|
|
268
|
+
* comment block per phase. A file that already carries the header gets the new
|
|
269
|
+
* lines under the one it has.
|
|
270
|
+
*
|
|
271
|
+
* **Appended lines go BEFORE the file's final newline, not after a blank one.** The
|
|
272
|
+
* append used to land after the trailing empty element of the split, which put a
|
|
273
|
+
* blank line above the new block — invisible when a key is written once and never
|
|
274
|
+
* removed, and one blank line per phase once a key comes and goes. The
|
|
275
|
+
* pre-existing text is still an untouched prefix either way.
|
|
234
276
|
*/
|
|
235
|
-
export declare function reconcileEnvText(existing: string | null, values: Record<string, string>, keys?: readonly string[]): string;
|
|
277
|
+
export declare function reconcileEnvText(existing: string | null, values: Record<string, string | null | undefined>, keys?: readonly string[]): string;
|
|
236
278
|
/**
|
|
237
279
|
* Read this engagement's machine-level credential, or `null` when this machine
|
|
238
280
|
* holds none for it.
|
|
@@ -254,8 +296,22 @@ export type EnvWriteOutcome = 'written' | 'skipped';
|
|
|
254
296
|
* The mode is re-applied on the skipped path too — a store that already existed at
|
|
255
297
|
* the wrong mode is exactly the case `writeFileSync`'s `mode` option cannot fix,
|
|
256
298
|
* and a re-install is the natural moment to repair it.
|
|
299
|
+
*
|
|
300
|
+
* **`keys` NARROWS WHAT THIS CALL OWNS, and it is why the phase stamp does not need
|
|
301
|
+
* a writer of its own.** Left off, this writes the eight credential keys, which is
|
|
302
|
+
* the installer's call and is unchanged. Passed a subset, it touches exactly those
|
|
303
|
+
* keys and copies every other line — ours and anyone else's — through untouched, so
|
|
304
|
+
* a caller that owns ONE key writes that key without re-implementing the
|
|
305
|
+
* read/merge/write/chmod sequence around it. That re-implementation is the failure
|
|
306
|
+
* this parameter exists to remove: a second writer that forgot `0o600` would loosen
|
|
307
|
+
* the credential file and pass every test that only checked which keys survived.
|
|
308
|
+
* A value of `null` deletes its key's line (see `reconcileEnvText`).
|
|
309
|
+
*
|
|
310
|
+
* The directory is created only when there is something to write. A removal-only
|
|
311
|
+
* call against a machine holding no store for this engagement leaves the disk
|
|
312
|
+
* alone rather than creating an empty file under a fresh directory.
|
|
257
313
|
*/
|
|
258
|
-
export declare function writeEngagementEnv(engagementId: string, values: Record<string, string>, home?: string): EnvWriteOutcome;
|
|
314
|
+
export declare function writeEngagementEnv(engagementId: string, values: Record<string, string | null | undefined>, home?: string, keys?: readonly string[]): EnvWriteOutcome;
|
|
259
315
|
/**
|
|
260
316
|
* The shell function both generated consumers embed to find this file.
|
|
261
317
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"engagement-credential.d.ts","sourceRoot":"","sources":["../src/engagement-credential.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwFG;AAiBH;;;;;;;;GAQG;AACH,eAAO,MAAM,uBAAuB,iBAAiB,CAAC;AAEtD,oFAAoF;AACpF,wBAAgB,kBAAkB,CAAC,YAAY,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,CAE9E;AAED,oFAAoF;AACpF,wBAAgB,iBAAiB,CAAC,YAAY,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,CAE7E;AAMD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,eAAO,MAAM,cAAc,8EAIjB,CAAC;AAEX;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,eAAO,MAAM,4BAA4B,mDAExC,CAAC;AAEF;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,mBAAmB,mMAOtB,CAAC;AAEX,MAAM,MAAM,gBAAgB,GAAG,CAAC,OAAO,mBAAmB,CAAC,CAAC,MAAM,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"engagement-credential.d.ts","sourceRoot":"","sources":["../src/engagement-credential.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwFG;AAiBH;;;;;;;;GAQG;AACH,eAAO,MAAM,uBAAuB,iBAAiB,CAAC;AAEtD,oFAAoF;AACpF,wBAAgB,kBAAkB,CAAC,YAAY,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,CAE9E;AAED,oFAAoF;AACpF,wBAAgB,iBAAiB,CAAC,YAAY,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,CAE7E;AAMD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,eAAO,MAAM,cAAc,8EAIjB,CAAC;AAEX;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,eAAO,MAAM,4BAA4B,mDAExC,CAAC;AAEF;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,mBAAmB,mMAOtB,CAAC;AAEX,MAAM,MAAM,gBAAgB,GAAG,CAAC,OAAO,mBAAmB,CAAC,CAAC,MAAM,CAAC,CAAC;AAEpE;;;;;;;;;;;;;;;;;GAiBG;AACH,eAAO,MAAM,mBAAmB,oBAAoB,CAAC;AAmErD;;;;;;;;;;;;GAYG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAUhE;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2DG;AACH,wBAAgB,gBAAgB,CAC9B,QAAQ,EAAE,MAAM,GAAG,IAAI,EACvB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC,EACjD,IAAI,GAAE,SAAS,MAAM,EAAwB,GAC5C,MAAM,CAwDR;AAMD;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAC/B,YAAY,EAAE,MAAM,EACpB,IAAI,CAAC,EAAE,MAAM,GACZ,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI,CAM/B;AAED,8DAA8D;AAC9D,MAAM,MAAM,eAAe,GAAG,SAAS,GAAG,SAAS,CAAC;AAEpD;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAgB,kBAAkB,CAChC,YAAY,EAAE,MAAM,EACpB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC,EACjD,IAAI,CAAC,EAAE,MAAM,EACb,IAAI,GAAE,SAAS,MAAM,EAAwB,GAC5C,eAAe,CAoBjB;AA4BD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AACH,wBAAgB,yBAAyB,IAAI,MAAM,CA0ClD"}
|