@coderifts/agent-guard 3.0.1 → 4.0.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 (84) hide show
  1. package/README.md +46 -1
  2. package/dist/cjs/artifact-resolver.d.ts +8 -0
  3. package/dist/cjs/artifact-resolver.d.ts.map +1 -1
  4. package/dist/cjs/artifact-resolver.js +12 -1
  5. package/dist/cjs/artifact-resolver.js.map +1 -1
  6. package/dist/cjs/deploy-bind.d.ts +123 -0
  7. package/dist/cjs/deploy-bind.d.ts.map +1 -0
  8. package/dist/cjs/deploy-bind.js +112 -0
  9. package/dist/cjs/deploy-bind.js.map +1 -0
  10. package/dist/cjs/enforcement-gate.d.ts +13 -4
  11. package/dist/cjs/enforcement-gate.d.ts.map +1 -1
  12. package/dist/cjs/enforcement-gate.js +32 -7
  13. package/dist/cjs/enforcement-gate.js.map +1 -1
  14. package/dist/cjs/execution-proof.d.ts +132 -0
  15. package/dist/cjs/execution-proof.d.ts.map +1 -0
  16. package/dist/cjs/execution-proof.js +157 -0
  17. package/dist/cjs/execution-proof.js.map +1 -0
  18. package/dist/cjs/freshness.d.ts +244 -0
  19. package/dist/cjs/freshness.d.ts.map +1 -0
  20. package/dist/cjs/freshness.js +395 -0
  21. package/dist/cjs/freshness.js.map +1 -0
  22. package/dist/cjs/guard.d.ts +7 -1
  23. package/dist/cjs/guard.d.ts.map +1 -1
  24. package/dist/cjs/guard.js +114 -38
  25. package/dist/cjs/guard.js.map +1 -1
  26. package/dist/cjs/index.d.ts +10 -4
  27. package/dist/cjs/index.d.ts.map +1 -1
  28. package/dist/cjs/index.js +28 -3
  29. package/dist/cjs/index.js.map +1 -1
  30. package/dist/cjs/read-decision.d.ts +47 -0
  31. package/dist/cjs/read-decision.d.ts.map +1 -0
  32. package/dist/cjs/read-decision.js +161 -0
  33. package/dist/cjs/read-decision.js.map +1 -0
  34. package/dist/cjs/tool-registry.d.ts.map +1 -1
  35. package/dist/cjs/tool-registry.js +12 -1
  36. package/dist/cjs/tool-registry.js.map +1 -1
  37. package/dist/cjs/types.d.ts +28 -1
  38. package/dist/cjs/types.d.ts.map +1 -1
  39. package/dist/cjs/with-coderifts.d.ts +70 -8
  40. package/dist/cjs/with-coderifts.d.ts.map +1 -1
  41. package/dist/cjs/with-coderifts.js +177 -14
  42. package/dist/cjs/with-coderifts.js.map +1 -1
  43. package/dist/esm/artifact-resolver.d.ts +8 -0
  44. package/dist/esm/artifact-resolver.d.ts.map +1 -1
  45. package/dist/esm/artifact-resolver.js +11 -1
  46. package/dist/esm/artifact-resolver.js.map +1 -1
  47. package/dist/esm/deploy-bind.d.ts +123 -0
  48. package/dist/esm/deploy-bind.d.ts.map +1 -0
  49. package/dist/esm/deploy-bind.js +108 -0
  50. package/dist/esm/deploy-bind.js.map +1 -0
  51. package/dist/esm/enforcement-gate.d.ts +13 -4
  52. package/dist/esm/enforcement-gate.d.ts.map +1 -1
  53. package/dist/esm/enforcement-gate.js +32 -7
  54. package/dist/esm/enforcement-gate.js.map +1 -1
  55. package/dist/esm/execution-proof.d.ts +132 -0
  56. package/dist/esm/execution-proof.d.ts.map +1 -0
  57. package/dist/esm/execution-proof.js +151 -0
  58. package/dist/esm/execution-proof.js.map +1 -0
  59. package/dist/esm/freshness.d.ts +244 -0
  60. package/dist/esm/freshness.d.ts.map +1 -0
  61. package/dist/esm/freshness.js +384 -0
  62. package/dist/esm/freshness.js.map +1 -0
  63. package/dist/esm/guard.d.ts +7 -1
  64. package/dist/esm/guard.d.ts.map +1 -1
  65. package/dist/esm/guard.js +113 -37
  66. package/dist/esm/guard.js.map +1 -1
  67. package/dist/esm/index.d.ts +10 -4
  68. package/dist/esm/index.d.ts.map +1 -1
  69. package/dist/esm/index.js +10 -2
  70. package/dist/esm/index.js.map +1 -1
  71. package/dist/esm/read-decision.d.ts +47 -0
  72. package/dist/esm/read-decision.d.ts.map +1 -0
  73. package/dist/esm/read-decision.js +153 -0
  74. package/dist/esm/read-decision.js.map +1 -0
  75. package/dist/esm/tool-registry.d.ts.map +1 -1
  76. package/dist/esm/tool-registry.js +12 -1
  77. package/dist/esm/tool-registry.js.map +1 -1
  78. package/dist/esm/types.d.ts +28 -1
  79. package/dist/esm/types.d.ts.map +1 -1
  80. package/dist/esm/with-coderifts.d.ts +70 -8
  81. package/dist/esm/with-coderifts.d.ts.map +1 -1
  82. package/dist/esm/with-coderifts.js +177 -14
  83. package/dist/esm/with-coderifts.js.map +1 -1
  84. package/package.json +1 -1
@@ -0,0 +1,244 @@
1
+ /**
2
+ * Freshness-safe prior content — PURE comparison core (TOCTOU close for the fresh-snapshot conjunct).
3
+ *
4
+ * Settled decisions (do not relitigate):
5
+ * 1. Freshness is CONTENT IDENTITY, not time. No TTL. Byte identity of `before` vs gate-time resolve.
6
+ * 2. The caller NAMES (artifact id); the gate RESOLVES prior content. A caller-supplied `before`
7
+ * is a claim, not a measurement — no fallback ladder that relabels a guess as measured.
8
+ * 3. Four outcomes, never collapsed: TARGET_MUTATED | STALE_CONTEXT | TAMPERED | UNKNOWN_FRESHNESS.
9
+ * 4. STALE_CONTEXT fails closed by default; policy may opt out deliberately.
10
+ * 5. Tree hash is OPTIONAL in the binding. Without it, STALE_CONTEXT is skipped, TARGET_MUTATED
11
+ * still runs, and the result SAYS the reduced level (never silently pretends full check ran).
12
+ *
13
+ * Merge-gate pattern generalized: recompute from current inputs; compare to what preflight bound;
14
+ * do not trust a claim about itself. Tree hash stays OUT of verdict_fingerprint and input_fingerprint
15
+ * (those preimages are frozen — their frozenness is what makes recompute meaningful).
16
+ *
17
+ * PURE: no I/O, no network, no Date.now(). Host supplies resolved content as inputs.
18
+ */
19
+ /**
20
+ * Four outcomes. Callers distinguish them by the `outcome` field (never by message text alone).
21
+ *
22
+ * TARGET_MUTATED — the contract `before` bytes moved (field removal, type change, …)
23
+ * STALE_CONTEXT — repository path-set tree moved, contract `before` identical (e.g. format-only
24
+ * neighbouring files, or raw blob change with same contract content). Message
25
+ * MUST state this is not tampering.
26
+ * TAMPERED — contract moved AND tree moved (both axes disagree)
27
+ * UNKNOWN_FRESHNESS — a candidate was named, but current state is not measurable (missing resolve)
28
+ *
29
+ * Plus FRESH when both applicable axes match.
30
+ */
31
+ export type FreshnessOutcome = 'FRESH' | 'TARGET_MUTATED' | 'STALE_CONTEXT' | 'TAMPERED' | 'UNKNOWN_FRESHNESS';
32
+ /**
33
+ * Which axes were eligible to run.
34
+ * full — tree hash was bound; contract + tree both evaluated
35
+ * contract_only — no tree hash on the binding; only TARGET_MUTATED axis ran (reported, not silent)
36
+ */
37
+ export type FreshnessCheckLevel = 'full' | 'contract_only';
38
+ export type FreshnessAssessInput = {
39
+ /**
40
+ * Contract `before` that entered preflight (and thus digests / the decision). Bound measurement —
41
+ * not a host claim at execute time.
42
+ */
43
+ preflightBefore: string;
44
+ /**
45
+ * Gate-resolved prior content for the same artifact id NOW.
46
+ * null/undefined = current state not measurable → UNKNOWN_FRESHNESS.
47
+ * The gate (or host adapter feeding the gate) supplies this by resolving the caller's artifact id;
48
+ * a caller-supplied `before` string must NOT be passed here as if measured.
49
+ */
50
+ resolvedBeforeNow: string | null | undefined;
51
+ /**
52
+ * Optional tree commitment bound at preflight (additive; NOT in input_fingerprint / verdict_fp).
53
+ * Absent/empty → level is contract_only; STALE_CONTEXT axis is skipped.
54
+ */
55
+ preflightTreeHash?: string | null;
56
+ /**
57
+ * Tree commitment recomputed at gate time from the same path set + current blobs.
58
+ * Only consulted when preflightTreeHash is present.
59
+ * null/undefined when tree was bound but cannot be re-measured → UNKNOWN_FRESHNESS.
60
+ */
61
+ resolvedTreeHashNow?: string | null | undefined;
62
+ /**
63
+ * Policy opt-out for STALE_CONTEXT only (default false = fail closed).
64
+ * TARGET_MUTATED / TAMPERED / UNKNOWN_FRESHNESS are never opted out by this flag.
65
+ * Same shape as an explicit team choice (approver allowlist): say so deliberately.
66
+ */
67
+ allowStaleContext?: boolean;
68
+ };
69
+ export type FreshnessAssessResult = {
70
+ outcome: FreshnessOutcome;
71
+ /** Which axes ran. Always set — even on FRESH — so a reduced check cannot look like a full one. */
72
+ level: FreshnessCheckLevel;
73
+ /** True when the gate must refuse enforced execution. */
74
+ failClosed: boolean;
75
+ /** Contract before bytes match (only meaningful when resolvedBeforeNow was measurable). */
76
+ contractMatch: boolean | null;
77
+ /** Tree match; null when tree axis skipped or unmeasurable. */
78
+ treeMatch: boolean | null;
79
+ /**
80
+ * Human message. For STALE_CONTEXT always includes that this is not tampering.
81
+ * Machine consumers should branch on `outcome`, not parse the message.
82
+ */
83
+ message: string;
84
+ };
85
+ /**
86
+ * Write-style call: path + new content only is the shape the composition residual names.
87
+ * Gateable requires an artifact identifier the gate can resolve — not a caller-supplied before.
88
+ */
89
+ export type WriteStylePriorInput = {
90
+ /** Artifact id from a prior preflight artifacts[] entry (caller names; gate resolves). */
91
+ artifactId?: string | null;
92
+ path?: string | null;
93
+ /** New content (the write payload). */
94
+ after?: string | null;
95
+ /**
96
+ * If present, this is a CLAIM. It is never treated as a measurement and never substitutes
97
+ * for artifactId. Recorded only so tests can assert there is no "use claimed before" ladder.
98
+ */
99
+ claimedBefore?: string | null;
100
+ };
101
+ export type WriteStylePriorResult = {
102
+ gateable: boolean;
103
+ reason: 'ok' | 'MISSING_ARTIFACT_ID' | 'CLAIMED_BEFORE_NOT_MEASUREMENT';
104
+ message: string;
105
+ /** Always false — claimedBefore is never elevated to a measurement. */
106
+ claimedBeforeAcceptedAsMeasurement: false;
107
+ };
108
+ /** Byte identity of two content strings (freshness definition: not time, not TTL). */
109
+ export declare function contentByteIdentical(a: string, b: string): boolean;
110
+ /**
111
+ * Optional path-set tree commitment. Additive only — never fold into input_fingerprint or
112
+ * verdict_fingerprint. Preimage: sorted path + sha256(content), then outer sha256.
113
+ * Missing content for a path is the caller's problem: pass only complete pairs.
114
+ */
115
+ export declare function computePathSetTreeHash(entries: ReadonlyArray<{
116
+ path: string;
117
+ content: string;
118
+ }>): string;
119
+ /**
120
+ * Assess freshness of prior content by recompute-and-compare (merge-gate pattern generalized).
121
+ *
122
+ * Pure. Does not read the filesystem; the host/adapter resolves artifact id → content and passes
123
+ * `resolvedBeforeNow` / optional tree hashes as inputs.
124
+ */
125
+ export declare function assessFreshness(input: FreshnessAssessInput): FreshnessAssessResult;
126
+ /**
127
+ * Write-style prior requirements (Decision 2).
128
+ * Caller must supply artifactId. claimedBefore is never accepted as measurement.
129
+ */
130
+ export declare function assessWriteStylePrior(input: WriteStylePriorInput): WriteStylePriorResult;
131
+ /**
132
+ * Convenience: whether enforced execution is allowed for this freshness result.
133
+ * Equivalent to !failClosed: FRESH always; STALE_CONTEXT only when the team opted out;
134
+ * TARGET_MUTATED / TAMPERED / UNKNOWN never.
135
+ */
136
+ export declare function freshnessAllowsEnforce(result: FreshnessAssessResult): boolean;
137
+ /**
138
+ * Whether a resolver ran for THIS call.
139
+ * ACTIVE — resolver was supplied and returned content for at least one artifact id
140
+ * NOT_CONFIGURED — no resolver on the host config; we never attempted measurement
141
+ * DEGRADED — resolver was supplied and threw, or returned nothing usable
142
+ *
143
+ * NOT_CONFIGURED ≠ UNKNOWN_FRESHNESS. The latter is an assessFreshness outcome after a measurement
144
+ * was attempted with empty/unusable resolved content under ACTIVE wiring.
145
+ */
146
+ export type FreshnessWiringState = 'ACTIVE' | 'NOT_CONFIGURED' | 'DEGRADED';
147
+ export type FreshnessDegradeReason = 'resolver_threw' | 'resolver_returned_empty' | 'resolver_returned_non_string';
148
+ /**
149
+ * Per-call forensic basis. Rides on the GuardOutcome so a receipt chain audited later can see,
150
+ * call by call, whether the check ran — not only a composition-level "wired?" flag.
151
+ */
152
+ export type FreshnessBasis = {
153
+ wiring: FreshnessWiringState;
154
+ /** Present when wiring === ACTIVE and assessFreshness ran against preflight before. */
155
+ assessment?: FreshnessAssessResult;
156
+ /** Present when wiring === DEGRADED — never report DEGRADED as NOT_CONFIGURED. */
157
+ degrade?: {
158
+ reason: FreshnessDegradeReason;
159
+ detail?: string;
160
+ };
161
+ /**
162
+ * Whether this call was treated as write-style (path + new content / needs prior resolve).
163
+ * Forensic: opt-out on a write is not silent.
164
+ */
165
+ write_style: boolean;
166
+ /** Config requireFreshness for this call (policy). */
167
+ require_freshness: boolean;
168
+ };
169
+ /** Host callback: artifact id → current prior content. Async I/O lives here — never inside assessFreshness. */
170
+ export type PriorContentResolver = (req: {
171
+ artifactId: string;
172
+ path?: string;
173
+ toolName: string;
174
+ }) => Promise<string | null | undefined> | string | null | undefined;
175
+ /**
176
+ * Values the RUNNER collected before entering the pure guard path.
177
+ * The guard never invokes the resolver; it only consumes these values.
178
+ */
179
+ export type FreshnessCallContext = {
180
+ wiring: FreshnessWiringState;
181
+ /** artifactId → resolved current before (only when wiring ACTIVE or partial DEGRADED with empties) */
182
+ priorResolved?: Record<string, string | null | undefined>;
183
+ degrade?: {
184
+ reason: FreshnessDegradeReason;
185
+ detail?: string;
186
+ };
187
+ };
188
+ /**
189
+ * Detect write-style: contract-relevant path present, but no both-side artifacts on the descriptor.
190
+ * (edits[]/old_string+new_string binders already lift both sides — those are not write-style.)
191
+ */
192
+ export declare function isWriteStyleCall(call: {
193
+ artifacts?: ReadonlyArray<{
194
+ before?: unknown;
195
+ after?: unknown;
196
+ }> | undefined;
197
+ arguments?: unknown;
198
+ filesTouched?: string[];
199
+ }): boolean;
200
+ /** Artifact ids the runner should ask the host to resolve (from lifted artifacts or path-derived id). */
201
+ export declare function artifactIdsForResolve(call: {
202
+ toolName?: string;
203
+ artifacts?: ReadonlyArray<{
204
+ id?: unknown;
205
+ }> | undefined;
206
+ arguments?: unknown;
207
+ }): string[];
208
+ /**
209
+ * RUNNER-side collection. Invokes the host resolver (async I/O). Never call from pure assessFreshness.
210
+ * - no resolver → NOT_CONFIGURED (did not try)
211
+ * - resolver throws → DEGRADED (opted in, failed)
212
+ * - resolver returns empty/non-string for all ids → DEGRADED
213
+ * - otherwise ACTIVE with priorResolved map
214
+ */
215
+ export declare function collectFreshnessCallContext(input: {
216
+ call: {
217
+ toolName: string;
218
+ artifacts?: ReadonlyArray<{
219
+ id?: unknown;
220
+ before?: unknown;
221
+ }> | undefined;
222
+ arguments?: unknown;
223
+ };
224
+ resolvePriorContent?: PriorContentResolver | null;
225
+ }): Promise<FreshnessCallContext>;
226
+ /**
227
+ * Build the per-call basis and optional enforce block reason from context + preflight artifacts.
228
+ * Pure once priorResolved is a value (no I/O).
229
+ */
230
+ export declare function buildFreshnessBasis(input: {
231
+ writeStyle: boolean;
232
+ requireFreshness: boolean;
233
+ ctx: FreshnessCallContext;
234
+ /** Preflight-bound before per artifact id (from call.artifacts after detect/bind). */
235
+ preflightBeforeById?: Record<string, string>;
236
+ allowStaleContext?: boolean;
237
+ preflightTreeHash?: string | null;
238
+ resolvedTreeHashNow?: string | null;
239
+ }): {
240
+ basis: FreshnessBasis;
241
+ /** If set, enforced execution must not proceed (permission fail-closed). */
242
+ blockCause?: 'FRESHNESS_REQUIRED' | 'FRESHNESS_FAILED';
243
+ };
244
+ //# sourceMappingURL=freshness.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"freshness.d.ts","sourceRoot":"","sources":["../../src/freshness.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,384 @@
1
+ /**
2
+ * Freshness-safe prior content — PURE comparison core (TOCTOU close for the fresh-snapshot conjunct).
3
+ *
4
+ * Settled decisions (do not relitigate):
5
+ * 1. Freshness is CONTENT IDENTITY, not time. No TTL. Byte identity of `before` vs gate-time resolve.
6
+ * 2. The caller NAMES (artifact id); the gate RESOLVES prior content. A caller-supplied `before`
7
+ * is a claim, not a measurement — no fallback ladder that relabels a guess as measured.
8
+ * 3. Four outcomes, never collapsed: TARGET_MUTATED | STALE_CONTEXT | TAMPERED | UNKNOWN_FRESHNESS.
9
+ * 4. STALE_CONTEXT fails closed by default; policy may opt out deliberately.
10
+ * 5. Tree hash is OPTIONAL in the binding. Without it, STALE_CONTEXT is skipped, TARGET_MUTATED
11
+ * still runs, and the result SAYS the reduced level (never silently pretends full check ran).
12
+ *
13
+ * Merge-gate pattern generalized: recompute from current inputs; compare to what preflight bound;
14
+ * do not trust a claim about itself. Tree hash stays OUT of verdict_fingerprint and input_fingerprint
15
+ * (those preimages are frozen — their frozenness is what makes recompute meaningful).
16
+ *
17
+ * PURE: no I/O, no network, no Date.now(). Host supplies resolved content as inputs.
18
+ */
19
+ import { createHash } from 'node:crypto';
20
+ // ── pure digests (tree hash OUT of frozen fingerprint preimages) ─────────────────────────────────
21
+ function sha256hex(s) {
22
+ return createHash('sha256').update(s, 'utf8').digest('hex');
23
+ }
24
+ /** Byte identity of two content strings (freshness definition: not time, not TTL). */
25
+ export function contentByteIdentical(a, b) {
26
+ return a === b;
27
+ }
28
+ /**
29
+ * Optional path-set tree commitment. Additive only — never fold into input_fingerprint or
30
+ * verdict_fingerprint. Preimage: sorted path + sha256(content), then outer sha256.
31
+ * Missing content for a path is the caller's problem: pass only complete pairs.
32
+ */
33
+ export function computePathSetTreeHash(entries) {
34
+ const parts = entries
35
+ .slice()
36
+ .map((e) => ({ path: String(e.path), content: String(e.content) }))
37
+ .sort((x, y) => (x.path < y.path ? -1 : x.path > y.path ? 1 : 0))
38
+ .map((e) => `${e.path}\x1f${sha256hex(e.content)}`);
39
+ return `sha256:${sha256hex(parts.join('\x1e'))}`;
40
+ }
41
+ // ── assess ───────────────────────────────────────────────────────────────────────────────────────
42
+ const MSG = {
43
+ FRESH_FULL: 'Prior content is fresh: gate-resolved before matches preflight (byte identity); tree commitment matches.',
44
+ FRESH_CONTRACT_ONLY: 'Prior content is fresh at contract level (byte identity of before). '
45
+ + 'Tree-hash check was not bound on this receipt — level is contract_only, not full.',
46
+ TARGET_MUTATED: 'TARGET_MUTATED: gate-resolved contract before differs from preflight (byte identity failed). '
47
+ + 'The contract itself changed under the bound artifact; re-preflight.',
48
+ STALE_CONTEXT: 'STALE_CONTEXT: repository path-set tree moved, but the contract before is byte-identical. '
49
+ + 'This is NOT tampering — neighbouring or formatting-only material changed while the analyzed '
50
+ + 'contract content did not. Default policy fails closed; set allowStaleContext to accept deliberately.',
51
+ TAMPERED: 'TAMPERED: contract before moved AND tree commitment moved. Both axes disagree with the preflight binding.',
52
+ UNKNOWN_BEFORE: 'UNKNOWN_FRESHNESS: artifact was named but current prior content is not measurable '
53
+ + '(gate could not resolve before at execution time). Not the same as a measured mismatch.',
54
+ UNKNOWN_TREE: 'UNKNOWN_FRESHNESS: tree hash was bound on the preflight, but current tree commitment is not measurable. '
55
+ + 'Not the same as STALE_CONTEXT (which requires a measured tree that differs).',
56
+ };
57
+ /**
58
+ * Assess freshness of prior content by recompute-and-compare (merge-gate pattern generalized).
59
+ *
60
+ * Pure. Does not read the filesystem; the host/adapter resolves artifact id → content and passes
61
+ * `resolvedBeforeNow` / optional tree hashes as inputs.
62
+ */
63
+ export function assessFreshness(input) {
64
+ const hasTreeBinding = typeof input.preflightTreeHash === 'string' && input.preflightTreeHash.length > 0;
65
+ const level = hasTreeBinding ? 'full' : 'contract_only';
66
+ // Current prior must be measurable.
67
+ if (input.resolvedBeforeNow === null || input.resolvedBeforeNow === undefined) {
68
+ return {
69
+ outcome: 'UNKNOWN_FRESHNESS',
70
+ level,
71
+ failClosed: true,
72
+ contractMatch: null,
73
+ treeMatch: hasTreeBinding ? null : null,
74
+ message: MSG.UNKNOWN_BEFORE,
75
+ };
76
+ }
77
+ const contractMatch = contentByteIdentical(String(input.preflightBefore), String(input.resolvedBeforeNow));
78
+ // Tree axis: only when bound (Decision 5).
79
+ let treeMatch = null;
80
+ if (hasTreeBinding) {
81
+ if (input.resolvedTreeHashNow === null || input.resolvedTreeHashNow === undefined) {
82
+ return {
83
+ outcome: 'UNKNOWN_FRESHNESS',
84
+ level: 'full',
85
+ failClosed: true,
86
+ contractMatch,
87
+ treeMatch: null,
88
+ message: MSG.UNKNOWN_TREE,
89
+ };
90
+ }
91
+ treeMatch = contentByteIdentical(String(input.preflightTreeHash), String(input.resolvedTreeHashNow));
92
+ }
93
+ // Four outcomes from the two axes (tree may be skipped).
94
+ if (!contractMatch && treeMatch === false) {
95
+ return {
96
+ outcome: 'TAMPERED',
97
+ level,
98
+ failClosed: true,
99
+ contractMatch,
100
+ treeMatch,
101
+ message: MSG.TAMPERED,
102
+ };
103
+ }
104
+ if (!contractMatch) {
105
+ return {
106
+ outcome: 'TARGET_MUTATED',
107
+ level,
108
+ failClosed: true,
109
+ contractMatch,
110
+ treeMatch,
111
+ message: MSG.TARGET_MUTATED,
112
+ };
113
+ }
114
+ if (contractMatch && treeMatch === false) {
115
+ const allow = input.allowStaleContext === true;
116
+ return {
117
+ outcome: 'STALE_CONTEXT',
118
+ level,
119
+ // Default closed; policy opt-out only for this outcome (Decision 4).
120
+ failClosed: !allow,
121
+ contractMatch,
122
+ treeMatch,
123
+ message: MSG.STALE_CONTEXT,
124
+ };
125
+ }
126
+ // contractMatch && (treeMatch === true || treeMatch === null)
127
+ return {
128
+ outcome: 'FRESH',
129
+ level,
130
+ failClosed: false,
131
+ contractMatch,
132
+ treeMatch,
133
+ message: level === 'full' ? MSG.FRESH_FULL : MSG.FRESH_CONTRACT_ONLY,
134
+ };
135
+ }
136
+ /**
137
+ * Write-style prior requirements (Decision 2).
138
+ * Caller must supply artifactId. claimedBefore is never accepted as measurement.
139
+ */
140
+ export function assessWriteStylePrior(input) {
141
+ const id = input.artifactId;
142
+ if (typeof id !== 'string' || id.trim().length === 0) {
143
+ // If they only offered a claimed before, still missing the identifier — and do not climb a ladder.
144
+ const claimed = typeof input.claimedBefore === 'string' && input.claimedBefore.length > 0;
145
+ return {
146
+ gateable: false,
147
+ reason: claimed ? 'CLAIMED_BEFORE_NOT_MEASUREMENT' : 'MISSING_ARTIFACT_ID',
148
+ claimedBeforeAcceptedAsMeasurement: false,
149
+ message: claimed
150
+ ? 'Write-style call supplied claimed before content without an artifact id. '
151
+ + 'A caller-supplied before is a claim, not a measurement. '
152
+ + 'Pass the artifact id from the preflight artifacts[] entry; the gate resolves prior content.'
153
+ : 'Write-style call is missing an artifact identifier. '
154
+ + 'Pass the id from a prior preflight artifacts[] entry (path + new content alone is not gateable). '
155
+ + 'The gate resolves prior content; do not invent a before.',
156
+ };
157
+ }
158
+ return {
159
+ gateable: true,
160
+ reason: 'ok',
161
+ claimedBeforeAcceptedAsMeasurement: false,
162
+ message: 'Artifact id present; gate may resolve prior content for freshness recompute.',
163
+ };
164
+ }
165
+ /**
166
+ * Convenience: whether enforced execution is allowed for this freshness result.
167
+ * Equivalent to !failClosed: FRESH always; STALE_CONTEXT only when the team opted out;
168
+ * TARGET_MUTATED / TAMPERED / UNKNOWN never.
169
+ */
170
+ export function freshnessAllowsEnforce(result) {
171
+ return result.failClosed === false;
172
+ }
173
+ /**
174
+ * Detect write-style: contract-relevant path present, but no both-side artifacts on the descriptor.
175
+ * (edits[]/old_string+new_string binders already lift both sides — those are not write-style.)
176
+ */
177
+ export function isWriteStyleCall(call) {
178
+ const arts = call.artifacts;
179
+ if (Array.isArray(arts) && arts.length > 0) {
180
+ const anyBoth = arts.some((a) => a
181
+ && typeof a.before === 'string'
182
+ && a.before.length > 0
183
+ && typeof a.after === 'string'
184
+ && a.after.length > 0);
185
+ if (anyBoth)
186
+ return false;
187
+ }
188
+ const args = call.arguments && typeof call.arguments === 'object'
189
+ ? call.arguments
190
+ : {};
191
+ const path = typeof args.path === 'string' && args.path.length > 0
192
+ ? args.path
193
+ : (Array.isArray(call.filesTouched) && typeof call.filesTouched[0] === 'string'
194
+ ? call.filesTouched[0]
195
+ : '');
196
+ if (!path)
197
+ return false;
198
+ // path + new content / contents without old_string both sides
199
+ const hasAfter = (typeof args.contents === 'string' && args.contents.length > 0)
200
+ || (typeof args.content === 'string' && args.content.length > 0)
201
+ || (typeof args.new_string === 'string' && args.new_string.length > 0);
202
+ const hasOld = typeof args.old_string === 'string' && args.old_string.length > 0;
203
+ if (hasAfter && !hasOld)
204
+ return true;
205
+ // path-only write-like with no artifacts
206
+ if (!Array.isArray(arts) || arts.length === 0) {
207
+ return hasAfter || typeof args.contents === 'string' || typeof args.content === 'string';
208
+ }
209
+ return false;
210
+ }
211
+ /** Artifact ids the runner should ask the host to resolve (from lifted artifacts or path-derived id). */
212
+ export function artifactIdsForResolve(call) {
213
+ const ids = [];
214
+ if (Array.isArray(call.artifacts)) {
215
+ for (const a of call.artifacts) {
216
+ if (a && typeof a.id === 'string' && a.id.trim())
217
+ ids.push(a.id);
218
+ }
219
+ }
220
+ if (ids.length > 0)
221
+ return [...new Set(ids)];
222
+ const args = call.arguments && typeof call.arguments === 'object'
223
+ ? call.arguments
224
+ : {};
225
+ if (typeof args.artifact_id === 'string' && args.artifact_id.trim())
226
+ return [args.artifact_id.trim()];
227
+ if (typeof args.artifactId === 'string' && args.artifactId.trim())
228
+ return [args.artifactId.trim()];
229
+ // path alone is not an id — host must pass artifact id from preflight; still list path-key for resolve attempts
230
+ if (typeof args.path === 'string' && args.path.trim()) {
231
+ // Prefer explicit id fields only; path is path, not artifact id (Decision 2).
232
+ }
233
+ return ids;
234
+ }
235
+ /**
236
+ * RUNNER-side collection. Invokes the host resolver (async I/O). Never call from pure assessFreshness.
237
+ * - no resolver → NOT_CONFIGURED (did not try)
238
+ * - resolver throws → DEGRADED (opted in, failed)
239
+ * - resolver returns empty/non-string for all ids → DEGRADED
240
+ * - otherwise ACTIVE with priorResolved map
241
+ */
242
+ export async function collectFreshnessCallContext(input) {
243
+ const resolver = input.resolvePriorContent;
244
+ if (typeof resolver !== 'function') {
245
+ return { wiring: 'NOT_CONFIGURED' };
246
+ }
247
+ const ids = artifactIdsForResolve(input.call);
248
+ const args = input.call.arguments && typeof input.call.arguments === 'object'
249
+ ? input.call.arguments
250
+ : {};
251
+ const path = typeof args.path === 'string' ? args.path : undefined;
252
+ // Resolver present but nothing to resolve on this call — still ACTIVE commitment for wiring state
253
+ // only if we attempted; for zero ids, we attempted zero calls → ACTIVE with empty map means
254
+ // "resolver is configured" but assessment may UNKNOWN. Distinguish: DEGRADED only on throw/empty return.
255
+ if (ids.length === 0) {
256
+ // Host opted in; no artifact id to resolve. Not NOT_CONFIGURED (we would have resolved if we could).
257
+ // Leave ACTIVE with empty priorResolved — assess path handles missing content.
258
+ return { wiring: 'ACTIVE', priorResolved: {} };
259
+ }
260
+ const priorResolved = {};
261
+ try {
262
+ for (const artifactId of ids) {
263
+ const raw = await resolver({
264
+ artifactId,
265
+ path,
266
+ toolName: input.call.toolName,
267
+ });
268
+ if (raw === null || raw === undefined) {
269
+ priorResolved[artifactId] = raw;
270
+ continue;
271
+ }
272
+ if (typeof raw !== 'string') {
273
+ return {
274
+ wiring: 'DEGRADED',
275
+ degrade: { reason: 'resolver_returned_non_string', detail: `artifactId=${artifactId}` },
276
+ priorResolved,
277
+ };
278
+ }
279
+ if (raw.length === 0) {
280
+ priorResolved[artifactId] = raw;
281
+ continue;
282
+ }
283
+ priorResolved[artifactId] = raw;
284
+ }
285
+ }
286
+ catch (err) {
287
+ return {
288
+ wiring: 'DEGRADED',
289
+ degrade: {
290
+ reason: 'resolver_threw',
291
+ detail: err instanceof Error ? err.message : String(err),
292
+ },
293
+ };
294
+ }
295
+ const values = ids.map((id) => priorResolved[id]);
296
+ const allEmpty = values.every((v) => v === null || v === undefined || v === '');
297
+ if (allEmpty) {
298
+ return {
299
+ wiring: 'DEGRADED',
300
+ degrade: { reason: 'resolver_returned_empty' },
301
+ priorResolved,
302
+ };
303
+ }
304
+ return { wiring: 'ACTIVE', priorResolved };
305
+ }
306
+ /**
307
+ * Build the per-call basis and optional enforce block reason from context + preflight artifacts.
308
+ * Pure once priorResolved is a value (no I/O).
309
+ */
310
+ export function buildFreshnessBasis(input) {
311
+ const require_freshness = input.requireFreshness === true;
312
+ const write_style = input.writeStyle === true;
313
+ const { ctx } = input;
314
+ if (ctx.wiring === 'NOT_CONFIGURED') {
315
+ const basis = {
316
+ wiring: 'NOT_CONFIGURED',
317
+ write_style,
318
+ require_freshness,
319
+ };
320
+ // Policy requires freshness on write → permission denied (API still opt-in for non-required).
321
+ if (write_style && require_freshness) {
322
+ return { basis, blockCause: 'FRESHNESS_REQUIRED' };
323
+ }
324
+ return { basis };
325
+ }
326
+ if (ctx.wiring === 'DEGRADED') {
327
+ const basis = {
328
+ wiring: 'DEGRADED',
329
+ write_style,
330
+ require_freshness,
331
+ degrade: ctx.degrade ?? { reason: 'resolver_returned_empty' },
332
+ };
333
+ // Opted in, then failed: never silently unprotected. Fail closed on write when required,
334
+ // and also when requireFreshness is false? Decision 1: permission fail when policy requires.
335
+ // Decision 2: DEGRADED must not drop to unprotected — for enforce path always block on DEGRADED
336
+ // for write-style, and for requireFreshness always block.
337
+ if (write_style || require_freshness) {
338
+ return { basis, blockCause: 'FRESHNESS_REQUIRED' };
339
+ }
340
+ return { basis };
341
+ }
342
+ // ACTIVE
343
+ const preflightMap = input.preflightBeforeById ?? {};
344
+ const ids = Object.keys(preflightMap);
345
+ // If we have preflight before sides, assess the first (or all — fail if any fails).
346
+ let assessment;
347
+ if (ids.length > 0) {
348
+ for (const id of ids) {
349
+ const resolved = ctx.priorResolved ? ctx.priorResolved[id] : undefined;
350
+ const one = assessFreshness({
351
+ preflightBefore: preflightMap[id],
352
+ resolvedBeforeNow: resolved,
353
+ preflightTreeHash: input.preflightTreeHash,
354
+ resolvedTreeHashNow: input.resolvedTreeHashNow,
355
+ allowStaleContext: input.allowStaleContext,
356
+ });
357
+ assessment = one;
358
+ if (one.failClosed)
359
+ break;
360
+ }
361
+ }
362
+ else if (write_style) {
363
+ // ACTIVE but no preflight before to compare — measurement incomplete.
364
+ assessment = assessFreshness({
365
+ preflightBefore: '',
366
+ resolvedBeforeNow: null,
367
+ allowStaleContext: input.allowStaleContext,
368
+ });
369
+ }
370
+ const basis = {
371
+ wiring: 'ACTIVE',
372
+ write_style,
373
+ require_freshness,
374
+ assessment,
375
+ };
376
+ if (assessment && assessment.failClosed) {
377
+ return { basis, blockCause: 'FRESHNESS_FAILED' };
378
+ }
379
+ if (write_style && require_freshness && !assessment) {
380
+ return { basis, blockCause: 'FRESHNESS_REQUIRED' };
381
+ }
382
+ return { basis };
383
+ }
384
+ //# sourceMappingURL=freshness.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"freshness.js","sourceRoot":"","sources":["../../src/freshness.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AA6GzC,oGAAoG;AAEpG,SAAS,SAAS,CAAC,CAAS;IAC1B,OAAO,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AAC9D,CAAC;AAED,sFAAsF;AACtF,MAAM,UAAU,oBAAoB,CAAC,CAAS,EAAE,CAAS;IACvD,OAAO,CAAC,KAAK,CAAC,CAAC;AACjB,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,sBAAsB,CACpC,OAAyD;IAEzD,MAAM,KAAK,GAAG,OAAO;SAClB,KAAK,EAAE;SACP,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;SAClE,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;SAChE,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC,IAAI,OAAO,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IACtD,OAAO,UAAU,SAAS,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC;AACnD,CAAC;AAED,oGAAoG;AAEpG,MAAM,GAAG,GAAG;IACV,UAAU,EACR,0GAA0G;IAC5G,mBAAmB,EACjB,sEAAsE;UACpE,mFAAmF;IACvF,cAAc,EACZ,+FAA+F;UAC7F,qEAAqE;IACzE,aAAa,EACX,4FAA4F;UAC1F,8FAA8F;UAC9F,sGAAsG;IAC1G,QAAQ,EACN,2GAA2G;IAC7G,cAAc,EACZ,oFAAoF;UAClF,yFAAyF;IAC7F,YAAY,EACV,0GAA0G;UACxG,8EAA8E;CAC1E,CAAC;AAEX;;;;;GAKG;AACH,MAAM,UAAU,eAAe,CAAC,KAA2B;IACzD,MAAM,cAAc,GAClB,OAAO,KAAK,CAAC,iBAAiB,KAAK,QAAQ,IAAI,KAAK,CAAC,iBAAiB,CAAC,MAAM,GAAG,CAAC,CAAC;IACpF,MAAM,KAAK,GAAwB,cAAc,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,eAAe,CAAC;IAE7E,oCAAoC;IACpC,IAAI,KAAK,CAAC,iBAAiB,KAAK,IAAI,IAAI,KAAK,CAAC,iBAAiB,KAAK,SAAS,EAAE,CAAC;QAC9E,OAAO;YACL,OAAO,EAAE,mBAAmB;YAC5B,KAAK;YACL,UAAU,EAAE,IAAI;YAChB,aAAa,EAAE,IAAI;YACnB,SAAS,EAAE,cAAc,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI;YACvC,OAAO,EAAE,GAAG,CAAC,cAAc;SAC5B,CAAC;IACJ,CAAC;IAED,MAAM,aAAa,GAAG,oBAAoB,CACxC,MAAM,CAAC,KAAK,CAAC,eAAe,CAAC,EAC7B,MAAM,CAAC,KAAK,CAAC,iBAAiB,CAAC,CAChC,CAAC;IAEF,2CAA2C;IAC3C,IAAI,SAAS,GAAmB,IAAI,CAAC;IACrC,IAAI,cAAc,EAAE,CAAC;QACnB,IAAI,KAAK,CAAC,mBAAmB,KAAK,IAAI,IAAI,KAAK,CAAC,mBAAmB,KAAK,SAAS,EAAE,CAAC;YAClF,OAAO;gBACL,OAAO,EAAE,mBAAmB;gBAC5B,KAAK,EAAE,MAAM;gBACb,UAAU,EAAE,IAAI;gBAChB,aAAa;gBACb,SAAS,EAAE,IAAI;gBACf,OAAO,EAAE,GAAG,CAAC,YAAY;aAC1B,CAAC;QACJ,CAAC;QACD,SAAS,GAAG,oBAAoB,CAC9B,MAAM,CAAC,KAAK,CAAC,iBAAiB,CAAC,EAC/B,MAAM,CAAC,KAAK,CAAC,mBAAmB,CAAC,CAClC,CAAC;IACJ,CAAC;IAED,yDAAyD;IACzD,IAAI,CAAC,aAAa,IAAI,SAAS,KAAK,KAAK,EAAE,CAAC;QAC1C,OAAO;YACL,OAAO,EAAE,UAAU;YACnB,KAAK;YACL,UAAU,EAAE,IAAI;YAChB,aAAa;YACb,SAAS;YACT,OAAO,EAAE,GAAG,CAAC,QAAQ;SACtB,CAAC;IACJ,CAAC;IACD,IAAI,CAAC,aAAa,EAAE,CAAC;QACnB,OAAO;YACL,OAAO,EAAE,gBAAgB;YACzB,KAAK;YACL,UAAU,EAAE,IAAI;YAChB,aAAa;YACb,SAAS;YACT,OAAO,EAAE,GAAG,CAAC,cAAc;SAC5B,CAAC;IACJ,CAAC;IACD,IAAI,aAAa,IAAI,SAAS,KAAK,KAAK,EAAE,CAAC;QACzC,MAAM,KAAK,GAAG,KAAK,CAAC,iBAAiB,KAAK,IAAI,CAAC;QAC/C,OAAO;YACL,OAAO,EAAE,eAAe;YACxB,KAAK;YACL,qEAAqE;YACrE,UAAU,EAAE,CAAC,KAAK;YAClB,aAAa;YACb,SAAS;YACT,OAAO,EAAE,GAAG,CAAC,aAAa;SAC3B,CAAC;IACJ,CAAC;IAED,8DAA8D;IAC9D,OAAO;QACL,OAAO,EAAE,OAAO;QAChB,KAAK;QACL,UAAU,EAAE,KAAK;QACjB,aAAa;QACb,SAAS;QACT,OAAO,EAAE,KAAK,KAAK,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,GAAG,CAAC,mBAAmB;KACrE,CAAC;AACJ,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,qBAAqB,CAAC,KAA2B;IAC/D,MAAM,EAAE,GAAG,KAAK,CAAC,UAAU,CAAC;IAC5B,IAAI,OAAO,EAAE,KAAK,QAAQ,IAAI,EAAE,CAAC,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACrD,mGAAmG;QACnG,MAAM,OAAO,GAAG,OAAO,KAAK,CAAC,aAAa,KAAK,QAAQ,IAAI,KAAK,CAAC,aAAa,CAAC,MAAM,GAAG,CAAC,CAAC;QAC1F,OAAO;YACL,QAAQ,EAAE,KAAK;YACf,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,gCAAgC,CAAC,CAAC,CAAC,qBAAqB;YAC1E,kCAAkC,EAAE,KAAK;YACzC,OAAO,EAAE,OAAO;gBACd,CAAC,CAAC,2EAA2E;sBACzE,0DAA0D;sBAC1D,6FAA6F;gBACjG,CAAC,CAAC,sDAAsD;sBACpD,mGAAmG;sBACnG,0DAA0D;SACjE,CAAC;IACJ,CAAC;IACD,OAAO;QACL,QAAQ,EAAE,IAAI;QACd,MAAM,EAAE,IAAI;QACZ,kCAAkC,EAAE,KAAK;QACzC,OAAO,EAAE,8EAA8E;KACxF,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,sBAAsB,CAAC,MAA6B;IAClE,OAAO,MAAM,CAAC,UAAU,KAAK,KAAK,CAAC;AACrC,CAAC;AAyDD;;;GAGG;AACH,MAAM,UAAU,gBAAgB,CAAC,IAIhC;IACC,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC;IAC5B,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC3C,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CACvB,CAAC,CAAC,EAAE,EAAE,CACJ,CAAC;eACE,OAAO,CAAC,CAAC,MAAM,KAAK,QAAQ;eAC5B,CAAC,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC;eACnB,OAAO,CAAC,CAAC,KAAK,KAAK,QAAQ;eAC3B,CAAC,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CACxB,CAAC;QACF,IAAI,OAAO;YAAE,OAAO,KAAK,CAAC;IAC5B,CAAC;IACD,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,IAAI,OAAO,IAAI,CAAC,SAAS,KAAK,QAAQ;QAC/D,CAAC,CAAE,IAAI,CAAC,SAAqC;QAC7C,CAAC,CAAC,EAAE,CAAC;IACP,MAAM,IAAI,GAAG,OAAO,IAAI,CAAC,IAAI,KAAK,QAAQ,IAAI,IAAI,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC;QAChE,CAAC,CAAC,IAAI,CAAC,IAAI;QACX,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,YAAY,CAAC,IAAI,OAAO,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,KAAK,QAAQ;YAC7E,CAAC,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC;YACtB,CAAC,CAAC,EAAE,CAAC,CAAC;IACV,IAAI,CAAC,IAAI;QAAE,OAAO,KAAK,CAAC;IACxB,8DAA8D;IAC9D,MAAM,QAAQ,GACZ,CAAC,OAAO,IAAI,CAAC,QAAQ,KAAK,QAAQ,IAAI,IAAI,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC;WAC5D,CAAC,OAAO,IAAI,CAAC,OAAO,KAAK,QAAQ,IAAI,IAAI,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC;WAC7D,CAAC,OAAO,IAAI,CAAC,UAAU,KAAK,QAAQ,IAAI,IAAI,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IACzE,MAAM,MAAM,GAAG,OAAO,IAAI,CAAC,UAAU,KAAK,QAAQ,IAAI,IAAI,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC,CAAC;IACjF,IAAI,QAAQ,IAAI,CAAC,MAAM;QAAE,OAAO,IAAI,CAAC;IACrC,yCAAyC;IACzC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC9C,OAAO,QAAQ,IAAI,OAAO,IAAI,CAAC,QAAQ,KAAK,QAAQ,IAAI,OAAO,IAAI,CAAC,OAAO,KAAK,QAAQ,CAAC;IAC3F,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,yGAAyG;AACzG,MAAM,UAAU,qBAAqB,CAAC,IAIrC;IACC,MAAM,GAAG,GAAa,EAAE,CAAC;IACzB,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC;QAClC,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;YAC/B,IAAI,CAAC,IAAI,OAAO,CAAC,CAAC,EAAE,KAAK,QAAQ,IAAI,CAAC,CAAC,EAAE,CAAC,IAAI,EAAE;gBAAE,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QACnE,CAAC;IACH,CAAC;IACD,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC;QAAE,OAAO,CAAC,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;IAC7C,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,IAAI,OAAO,IAAI,CAAC,SAAS,KAAK,QAAQ;QAC/D,CAAC,CAAE,IAAI,CAAC,SAAqC;QAC7C,CAAC,CAAC,EAAE,CAAC;IACP,IAAI,OAAO,IAAI,CAAC,WAAW,KAAK,QAAQ,IAAI,IAAI,CAAC,WAAW,CAAC,IAAI,EAAE;QAAE,OAAO,CAAC,IAAI,CAAC,WAAW,CAAC,IAAI,EAAE,CAAC,CAAC;IACtG,IAAI,OAAO,IAAI,CAAC,UAAU,KAAK,QAAQ,IAAI,IAAI,CAAC,UAAU,CAAC,IAAI,EAAE;QAAE,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,EAAE,CAAC,CAAC;IACnG,gHAAgH;IAChH,IAAI,OAAO,IAAI,CAAC,IAAI,KAAK,QAAQ,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,EAAE,CAAC;QACtD,8EAA8E;IAChF,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,2BAA2B,CAAC,KAGjD;IACC,MAAM,QAAQ,GAAG,KAAK,CAAC,mBAAmB,CAAC;IAC3C,IAAI,OAAO,QAAQ,KAAK,UAAU,EAAE,CAAC;QACnC,OAAO,EAAE,MAAM,EAAE,gBAAgB,EAAE,CAAC;IACtC,CAAC;IAED,MAAM,GAAG,GAAG,qBAAqB,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAC9C,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC,SAAS,IAAI,OAAO,KAAK,CAAC,IAAI,CAAC,SAAS,KAAK,QAAQ;QAC3E,CAAC,CAAE,KAAK,CAAC,IAAI,CAAC,SAAqC;QACnD,CAAC,CAAC,EAAE,CAAC;IACP,MAAM,IAAI,GAAG,OAAO,IAAI,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC;IAEnE,kGAAkG;IAClG,4FAA4F;IAC5F,yGAAyG;IACzG,IAAI,GAAG,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACrB,qGAAqG;QACrG,+EAA+E;QAC/E,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,aAAa,EAAE,EAAE,EAAE,CAAC;IACjD,CAAC;IAED,MAAM,aAAa,GAA8C,EAAE,CAAC;IACpE,IAAI,CAAC;QACH,KAAK,MAAM,UAAU,IAAI,GAAG,EAAE,CAAC;YAC7B,MAAM,GAAG,GAAG,MAAM,QAAQ,CAAC;gBACzB,UAAU;gBACV,IAAI;gBACJ,QAAQ,EAAE,KAAK,CAAC,IAAI,CAAC,QAAQ;aAC9B,CAAC,CAAC;YACH,IAAI,GAAG,KAAK,IAAI,IAAI,GAAG,KAAK,SAAS,EAAE,CAAC;gBACtC,aAAa,CAAC,UAAU,CAAC,GAAG,GAAG,CAAC;gBAChC,SAAS;YACX,CAAC;YACD,IAAI,OAAO,GAAG,KAAK,QAAQ,EAAE,CAAC;gBAC5B,OAAO;oBACL,MAAM,EAAE,UAAU;oBAClB,OAAO,EAAE,EAAE,MAAM,EAAE,8BAA8B,EAAE,MAAM,EAAE,cAAc,UAAU,EAAE,EAAE;oBACvF,aAAa;iBACd,CAAC;YACJ,CAAC;YACD,IAAI,GAAG,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBACrB,aAAa,CAAC,UAAU,CAAC,GAAG,GAAG,CAAC;gBAChC,SAAS;YACX,CAAC;YACD,aAAa,CAAC,UAAU,CAAC,GAAG,GAAG,CAAC;QAClC,CAAC;IACH,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO;YACL,MAAM,EAAE,UAAU;YAClB,OAAO,EAAE;gBACP,MAAM,EAAE,gBAAgB;gBACxB,MAAM,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC;aACzD;SACF,CAAC;IACJ,CAAC;IAED,MAAM,MAAM,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,aAAa,CAAC,EAAE,CAAC,CAAC,CAAC;IAClD,MAAM,QAAQ,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,IAAI,IAAI,CAAC,KAAK,SAAS,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC;IAChF,IAAI,QAAQ,EAAE,CAAC;QACb,OAAO;YACL,MAAM,EAAE,UAAU;YAClB,OAAO,EAAE,EAAE,MAAM,EAAE,yBAAyB,EAAE;YAC9C,aAAa;SACd,CAAC;IACJ,CAAC;IAED,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,aAAa,EAAE,CAAC;AAC7C,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,mBAAmB,CAAC,KASnC;IAKC,MAAM,iBAAiB,GAAG,KAAK,CAAC,gBAAgB,KAAK,IAAI,CAAC;IAC1D,MAAM,WAAW,GAAG,KAAK,CAAC,UAAU,KAAK,IAAI,CAAC;IAC9C,MAAM,EAAE,GAAG,EAAE,GAAG,KAAK,CAAC;IAEtB,IAAI,GAAG,CAAC,MAAM,KAAK,gBAAgB,EAAE,CAAC;QACpC,MAAM,KAAK,GAAmB;YAC5B,MAAM,EAAE,gBAAgB;YACxB,WAAW;YACX,iBAAiB;SAClB,CAAC;QACF,8FAA8F;QAC9F,IAAI,WAAW,IAAI,iBAAiB,EAAE,CAAC;YACrC,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,oBAAoB,EAAE,CAAC;QACrD,CAAC;QACD,OAAO,EAAE,KAAK,EAAE,CAAC;IACnB,CAAC;IAED,IAAI,GAAG,CAAC,MAAM,KAAK,UAAU,EAAE,CAAC;QAC9B,MAAM,KAAK,GAAmB;YAC5B,MAAM,EAAE,UAAU;YAClB,WAAW;YACX,iBAAiB;YACjB,OAAO,EAAE,GAAG,CAAC,OAAO,IAAI,EAAE,MAAM,EAAE,yBAAyB,EAAE;SAC9D,CAAC;QACF,yFAAyF;QACzF,6FAA6F;QAC7F,gGAAgG;QAChG,0DAA0D;QAC1D,IAAI,WAAW,IAAI,iBAAiB,EAAE,CAAC;YACrC,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,oBAAoB,EAAE,CAAC;QACrD,CAAC;QACD,OAAO,EAAE,KAAK,EAAE,CAAC;IACnB,CAAC;IAED,SAAS;IACT,MAAM,YAAY,GAAG,KAAK,CAAC,mBAAmB,IAAI,EAAE,CAAC;IACrD,MAAM,GAAG,GAAG,MAAM,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;IACtC,oFAAoF;IACpF,IAAI,UAA6C,CAAC;IAClD,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACnB,KAAK,MAAM,EAAE,IAAI,GAAG,EAAE,CAAC;YACrB,MAAM,QAAQ,GAAG,GAAG,CAAC,aAAa,CAAC,CAAC,CAAC,GAAG,CAAC,aAAa,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;YACvE,MAAM,GAAG,GAAG,eAAe,CAAC;gBAC1B,eAAe,EAAE,YAAY,CAAC,EAAE,CAAC;gBACjC,iBAAiB,EAAE,QAAQ;gBAC3B,iBAAiB,EAAE,KAAK,CAAC,iBAAiB;gBAC1C,mBAAmB,EAAE,KAAK,CAAC,mBAAmB;gBAC9C,iBAAiB,EAAE,KAAK,CAAC,iBAAiB;aAC3C,CAAC,CAAC;YACH,UAAU,GAAG,GAAG,CAAC;YACjB,IAAI,GAAG,CAAC,UAAU;gBAAE,MAAM;QAC5B,CAAC;IACH,CAAC;SAAM,IAAI,WAAW,EAAE,CAAC;QACvB,sEAAsE;QACtE,UAAU,GAAG,eAAe,CAAC;YAC3B,eAAe,EAAE,EAAE;YACnB,iBAAiB,EAAE,IAAI;YACvB,iBAAiB,EAAE,KAAK,CAAC,iBAAiB;SAC3C,CAAC,CAAC;IACL,CAAC;IAED,MAAM,KAAK,GAAmB;QAC5B,MAAM,EAAE,QAAQ;QAChB,WAAW;QACX,iBAAiB;QACjB,UAAU;KACX,CAAC;IAEF,IAAI,UAAU,IAAI,UAAU,CAAC,UAAU,EAAE,CAAC;QACxC,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,kBAAkB,EAAE,CAAC;IACnD,CAAC;IACD,IAAI,WAAW,IAAI,iBAAiB,IAAI,CAAC,UAAU,EAAE,CAAC;QACpD,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,oBAAoB,EAAE,CAAC;IACrD,CAAC;IACD,OAAO,EAAE,KAAK,EAAE,CAAC;AACnB,CAAC"}