@intentius/chant 0.49.0 → 0.51.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/audit/catalog.d.ts +13 -3
- package/dist/audit/catalog.d.ts.map +1 -1
- package/dist/audit/core.d.ts +9 -0
- package/dist/audit/core.d.ts.map +1 -1
- package/dist/audit/discover.d.ts +6 -0
- package/dist/audit/discover.d.ts.map +1 -1
- package/dist/audit/fetch.d.ts.map +1 -1
- package/dist/audit/report-html.d.ts.map +1 -1
- package/dist/audit/report-model.d.ts +6 -0
- package/dist/audit/report-model.d.ts.map +1 -1
- package/dist/audit/report.d.ts.map +1 -1
- package/dist/audit/rules-doc.d.ts.map +1 -1
- package/dist/audit/secrets.d.ts +95 -0
- package/dist/audit/secrets.d.ts.map +1 -0
- package/dist/audit/wrangler.d.ts +33 -0
- package/dist/audit/wrangler.d.ts.map +1 -0
- package/dist/build.d.ts.map +1 -1
- package/dist/cli/commands/audit.d.ts +7 -0
- package/dist/cli/commands/audit.d.ts.map +1 -1
- package/dist/cli/commands/build.d.ts +23 -0
- package/dist/cli/commands/build.d.ts.map +1 -1
- package/dist/cli/handlers/build.d.ts.map +1 -1
- package/dist/cli/handlers/components.d.ts +31 -0
- package/dist/cli/handlers/components.d.ts.map +1 -1
- package/dist/cli/handlers/lifecycle.d.ts +11 -0
- package/dist/cli/handlers/lifecycle.d.ts.map +1 -1
- package/dist/cli/handlers/op-progress.d.ts +57 -0
- package/dist/cli/handlers/op-progress.d.ts.map +1 -0
- package/dist/cli/handlers/operator.d.ts +32 -0
- package/dist/cli/handlers/operator.d.ts.map +1 -0
- package/dist/cli/handlers/run-client.d.ts +21 -1
- package/dist/cli/handlers/run-client.d.ts.map +1 -1
- package/dist/cli/handlers/run-report.d.ts.map +1 -1
- package/dist/cli/handlers/run.d.ts.map +1 -1
- package/dist/cli/handlers/scenario.d.ts +39 -0
- package/dist/cli/handlers/scenario.d.ts.map +1 -0
- package/dist/cli/handlers/search.d.ts +22 -0
- package/dist/cli/handlers/search.d.ts.map +1 -1
- package/dist/cli/main.d.ts.map +1 -1
- package/dist/cli/mcp/op-tools.d.ts.map +1 -1
- package/dist/cli/mcp/resource-handlers.d.ts.map +1 -1
- package/dist/cli/mcp/server.d.ts +35 -2
- package/dist/cli/mcp/server.d.ts.map +1 -1
- package/dist/cli/mcp/types.d.ts +29 -1
- package/dist/cli/mcp/types.d.ts.map +1 -1
- package/dist/cli/registry.d.ts +47 -3
- package/dist/cli/registry.d.ts.map +1 -1
- package/dist/codegen/docs-rule-scanning.d.ts.map +1 -1
- package/dist/components/capability.d.ts +17 -2
- package/dist/components/capability.d.ts.map +1 -1
- package/dist/components/cli-support.d.ts +7 -0
- package/dist/components/cli-support.d.ts.map +1 -1
- package/dist/components/component.d.ts +15 -0
- package/dist/components/component.d.ts.map +1 -1
- package/dist/components/driver.d.ts.map +1 -1
- package/dist/components/run-progress.d.ts +7 -5
- package/dist/components/run-progress.d.ts.map +1 -1
- package/dist/components/verbs/index.d.ts +6 -1
- package/dist/components/verbs/index.d.ts.map +1 -1
- package/dist/components/verbs/run-agent.d.ts +499 -0
- package/dist/components/verbs/run-agent.d.ts.map +1 -0
- package/dist/components/verbs/sign.d.ts +30 -0
- package/dist/components/verbs/sign.d.ts.map +1 -1
- package/dist/composite.d.ts +6 -1
- package/dist/composite.d.ts.map +1 -1
- package/dist/discovery/collect.d.ts.map +1 -1
- package/dist/discovery/fold-import.d.ts +15 -1
- package/dist/discovery/fold-import.d.ts.map +1 -1
- package/dist/discovery/fold-rank.d.ts +66 -0
- package/dist/discovery/fold-rank.d.ts.map +1 -0
- package/dist/discovery/index.d.ts +15 -0
- package/dist/discovery/index.d.ts.map +1 -1
- package/dist/discovery/param-deps.d.ts +17 -0
- package/dist/discovery/param-deps.d.ts.map +1 -0
- package/dist/fold/fold.d.ts +55 -2
- package/dist/fold/fold.d.ts.map +1 -1
- package/dist/fold/subset.d.ts +21 -14
- package/dist/fold/subset.d.ts.map +1 -1
- package/dist/lexicon-schema.d.ts +2 -0
- package/dist/lexicon-schema.d.ts.map +1 -1
- package/dist/lexicon.d.ts +134 -0
- package/dist/lexicon.d.ts.map +1 -1
- package/dist/lifecycle/assert-live.d.ts +77 -0
- package/dist/lifecycle/assert-live.d.ts.map +1 -0
- package/dist/lifecycle/change-set.d.ts +17 -0
- package/dist/lifecycle/change-set.d.ts.map +1 -1
- package/dist/lifecycle/converge-ledger.d.ts +90 -0
- package/dist/lifecycle/converge-ledger.d.ts.map +1 -0
- package/dist/lifecycle/deep-diff.d.ts +18 -0
- package/dist/lifecycle/deep-diff.d.ts.map +1 -1
- package/dist/lifecycle/deep-observe.d.ts +9 -1
- package/dist/lifecycle/deep-observe.d.ts.map +1 -1
- package/dist/lifecycle/disruption.d.ts +96 -0
- package/dist/lifecycle/disruption.d.ts.map +1 -0
- package/dist/lifecycle/gate-ledger.d.ts +33 -0
- package/dist/lifecycle/gate-ledger.d.ts.map +1 -0
- package/dist/lifecycle/git.d.ts +145 -21
- package/dist/lifecycle/git.d.ts.map +1 -1
- package/dist/lifecycle/index.d.ts +6 -0
- package/dist/lifecycle/index.d.ts.map +1 -1
- package/dist/lifecycle/lease.d.ts +113 -0
- package/dist/lifecycle/lease.d.ts.map +1 -0
- package/dist/lifecycle/replay.d.ts +2 -0
- package/dist/lifecycle/replay.d.ts.map +1 -1
- package/dist/lifecycle/scenario-eval.d.ts +42 -0
- package/dist/lifecycle/scenario-eval.d.ts.map +1 -0
- package/dist/lifecycle/scenario.d.ts +163 -0
- package/dist/lifecycle/scenario.d.ts.map +1 -0
- package/dist/lifecycle/symptoms.d.ts +63 -0
- package/dist/lifecycle/symptoms.d.ts.map +1 -0
- package/dist/lint/output-docs.d.ts +94 -0
- package/dist/lint/output-docs.d.ts.map +1 -0
- package/dist/lint/post-synth.d.ts +29 -0
- package/dist/lint/post-synth.d.ts.map +1 -1
- package/dist/lint/rules/__fixtures__/comp/comp003/pass/agent-turn.component.d.ts +11 -0
- package/dist/lint/rules/__fixtures__/comp/comp003/pass/agent-turn.component.d.ts.map +1 -0
- package/dist/lsp/lexicon-providers.d.ts +7 -0
- package/dist/lsp/lexicon-providers.d.ts.map +1 -1
- package/dist/op/activity-contract.d.ts +139 -0
- package/dist/op/activity-contract.d.ts.map +1 -0
- package/dist/op/builders.d.ts +42 -2
- package/dist/op/builders.d.ts.map +1 -1
- package/dist/op/converge-rule.d.ts +161 -0
- package/dist/op/converge-rule.d.ts.map +1 -0
- package/dist/op/generate-pipeline.d.ts +39 -0
- package/dist/op/generate-pipeline.d.ts.map +1 -0
- package/dist/op/index.d.ts +14 -0
- package/dist/op/index.d.ts.map +1 -1
- package/dist/op/local-executor.d.ts +7 -1
- package/dist/op/local-executor.d.ts.map +1 -1
- package/dist/op/op-verb-class.d.ts +42 -0
- package/dist/op/op-verb-class.d.ts.map +1 -0
- package/dist/op/operator.d.ts +128 -0
- package/dist/op/operator.d.ts.map +1 -0
- package/dist/op/step-output-ref.d.ts +187 -0
- package/dist/op/step-output-ref.d.ts.map +1 -0
- package/dist/op/types.d.ts +18 -1
- package/dist/op/types.d.ts.map +1 -1
- package/dist/provenance.d.ts +73 -3
- package/dist/provenance.d.ts.map +1 -1
- package/dist/runtime-adapter.d.ts +7 -1
- package/dist/runtime-adapter.d.ts.map +1 -1
- package/dist/serializer.d.ts +18 -0
- package/dist/serializer.d.ts.map +1 -1
- package/dist/testing.d.ts +23 -2
- package/dist/testing.d.ts.map +1 -1
- package/dist/toml.d.ts +40 -5
- package/dist/toml.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/audit/catalog.test.ts +1 -1
- package/src/audit/catalog.ts +75 -3
- package/src/audit/core.ts +9 -0
- package/src/audit/discover.ts +29 -2
- package/src/audit/fetch.test.ts +216 -3
- package/src/audit/fetch.ts +270 -59
- package/src/audit/report-html.ts +5 -2
- package/src/audit/report-model.ts +9 -0
- package/src/audit/report.test.ts +22 -0
- package/src/audit/report.ts +3 -2
- package/src/audit/rules-doc.ts +2 -0
- package/src/audit/secrets.test.ts +303 -0
- package/src/audit/secrets.ts +406 -0
- package/src/audit/wrangler.test.ts +230 -0
- package/src/audit/wrangler.ts +290 -0
- package/src/build.ts +8 -3
- package/src/cli/command-group.ts +1 -1
- package/src/cli/commands/__fixtures__/schemas/sarif-2.1.0.schema.json +2882 -0
- package/src/cli/commands/audit.test.ts +215 -1
- package/src/cli/commands/audit.ts +86 -17
- package/src/cli/commands/build.test.ts +167 -2
- package/src/cli/commands/build.ts +114 -23
- package/src/cli/handlers/build.ts +2 -0
- package/src/cli/handlers/components.test.ts +199 -1
- package/src/cli/handlers/components.ts +160 -3
- package/src/cli/handlers/graph.test.ts +20 -0
- package/src/cli/handlers/graph.ts +10 -1
- package/src/cli/handlers/lifecycle.test.ts +90 -0
- package/src/cli/handlers/lifecycle.ts +30 -5
- package/src/cli/handlers/op-progress.test.ts +202 -0
- package/src/cli/handlers/op-progress.ts +192 -0
- package/src/cli/handlers/operator.test.ts +255 -0
- package/src/cli/handlers/operator.ts +240 -0
- package/src/cli/handlers/run-client.test.ts +82 -0
- package/src/cli/handlers/run-client.ts +85 -2
- package/src/cli/handlers/run-report.test.ts +62 -0
- package/src/cli/handlers/run-report.ts +20 -58
- package/src/cli/handlers/run.test.ts +144 -0
- package/src/cli/handlers/run.ts +40 -18
- package/src/cli/handlers/scenario.test.ts +456 -0
- package/src/cli/handlers/scenario.ts +330 -0
- package/src/cli/handlers/search-drift.test.ts +263 -0
- package/src/cli/handlers/search.ts +150 -1
- package/src/cli/main.test.ts +23 -0
- package/src/cli/main.ts +81 -1
- package/src/cli/mcp/op-tools.ts +17 -6
- package/src/cli/mcp/resource-handlers.ts +13 -5
- package/src/cli/mcp/server.test.ts +265 -2
- package/src/cli/mcp/server.ts +84 -7
- package/src/cli/mcp/types.ts +27 -1
- package/src/cli/registry.ts +47 -3
- package/src/codegen/docs-rule-scanning.test.ts +42 -0
- package/src/codegen/docs-rule-scanning.ts +25 -2
- package/src/components/README.md +7 -0
- package/src/components/capability.ts +17 -2
- package/src/components/cli-support.test.ts +17 -0
- package/src/components/cli-support.ts +13 -1
- package/src/components/component-schema.test.ts +32 -0
- package/src/components/component.schema.json +6 -0
- package/src/components/component.test.ts +21 -0
- package/src/components/component.ts +15 -0
- package/src/components/driver.ts +12 -4
- package/src/components/run-progress.ts +9 -5
- package/src/components/verbs/index.ts +6 -1
- package/src/components/verbs/run-agent.test.ts +683 -0
- package/src/components/verbs/run-agent.ts +786 -0
- package/src/components/verbs/sign.test.ts +19 -0
- package/src/components/verbs/sign.ts +34 -2
- package/src/composite.ts +31 -2
- package/src/discovery/collect.ts +11 -2
- package/src/discovery/fold-import.test.ts +54 -0
- package/src/discovery/fold-import.ts +178 -38
- package/src/discovery/fold-rank.test.ts +197 -0
- package/src/discovery/fold-rank.ts +346 -0
- package/src/discovery/index.ts +16 -1
- package/src/discovery/param-deps.test.ts +118 -0
- package/src/discovery/param-deps.ts +170 -0
- package/src/fold/fold.test.ts +6 -2
- package/src/fold/fold.ts +184 -3
- package/src/fold/subset.test.ts +82 -19
- package/src/fold/subset.ts +79 -41
- package/src/lexicon-schema.ts +3 -0
- package/src/lexicon.ts +154 -2
- package/src/lifecycle/assert-live.test.ts +125 -0
- package/src/lifecycle/assert-live.ts +154 -0
- package/src/lifecycle/change-set.ts +35 -3
- package/src/lifecycle/converge-ledger.test.ts +199 -0
- package/src/lifecycle/converge-ledger.ts +179 -0
- package/src/lifecycle/deep-diff.test.ts +79 -1
- package/src/lifecycle/deep-diff.ts +23 -0
- package/src/lifecycle/deep-observe.ts +13 -2
- package/src/lifecycle/disruption.test.ts +186 -0
- package/src/lifecycle/disruption.ts +224 -0
- package/src/lifecycle/gate-ledger.test.ts +103 -0
- package/src/lifecycle/gate-ledger.ts +140 -0
- package/src/lifecycle/git.test.ts +430 -0
- package/src/lifecycle/git.ts +446 -84
- package/src/lifecycle/index.ts +6 -0
- package/src/lifecycle/lease.test.ts +343 -0
- package/src/lifecycle/lease.ts +270 -0
- package/src/lifecycle/replay.test.ts +25 -0
- package/src/lifecycle/replay.ts +11 -3
- package/src/lifecycle/scenario-eval.test.ts +199 -0
- package/src/lifecycle/scenario-eval.ts +158 -0
- package/src/lifecycle/scenario.test.ts +195 -0
- package/src/lifecycle/scenario.ts +321 -0
- package/src/lifecycle/symptoms.test.ts +116 -0
- package/src/lifecycle/symptoms.ts +126 -0
- package/src/lint/output-docs.test.ts +220 -0
- package/src/lint/output-docs.ts +204 -0
- package/src/lint/post-synth.test.ts +97 -0
- package/src/lint/post-synth.ts +45 -0
- package/src/lint/rules/__fixtures__/comp/comp003/pass/agent-turn.component.ts +26 -0
- package/src/lint/rules/comp/comp.test.ts +49 -1
- package/src/lint/rules/evl001-non-literal-expression.test.ts +8 -3
- package/src/lint/rules/evl001-non-literal-expression.ts +6 -6
- package/src/lsp/lexicon-providers.test.ts +44 -0
- package/src/lsp/lexicon-providers.ts +11 -1
- package/src/op/activity-contract.test.ts +180 -0
- package/src/op/activity-contract.ts +278 -0
- package/src/op/builders-exports.test.ts +17 -1
- package/src/op/builders.ts +59 -5
- package/src/op/converge-rule.test.ts +179 -0
- package/src/op/converge-rule.ts +311 -0
- package/src/op/generate-pipeline.test.ts +53 -0
- package/src/op/generate-pipeline.ts +99 -0
- package/src/op/index.ts +30 -0
- package/src/op/local-executor.test.ts +92 -0
- package/src/op/local-executor.ts +52 -10
- package/src/op/local-output.ts +1 -1
- package/src/op/op-verb-class.test.ts +126 -0
- package/src/op/op-verb-class.ts +115 -0
- package/src/op/operator.test.ts +346 -0
- package/src/op/operator.ts +213 -0
- package/src/op/step-output-ref.test.ts +334 -0
- package/src/op/step-output-ref.ts +453 -0
- package/src/op/types.ts +18 -1
- package/src/provenance.test.ts +151 -4
- package/src/provenance.ts +118 -4
- package/src/runtime-adapter.ts +31 -10
- package/src/serializer.ts +18 -0
- package/src/testing.test.ts +89 -2
- package/src/testing.ts +63 -3
- package/src/toml.test.ts +157 -384
- package/src/toml.ts +371 -5
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* assertLive (#1857) — the read half of the test harness (#1224):
|
|
3
|
+
* observation-backed assertions against a live deploy, for exactly one
|
|
4
|
+
* declared entity at a time. Same primitive teardown.ts's fallback path
|
|
5
|
+
* uses — `describeResources` — turned into a pass/throw instead of a
|
|
6
|
+
* would-delete set.
|
|
7
|
+
*
|
|
8
|
+
* The observation contract (#1089) draws a hard line between OBSERVED-ABSENT
|
|
9
|
+
* and NOT-OBSERVED: a declared entity the read could not cover is never the
|
|
10
|
+
* same as one confirmed missing. `assertLiveEntity` preserves that line by
|
|
11
|
+
* construction — NOT-OBSERVED throws {@link UnobservedAssertionError}, a type
|
|
12
|
+
* distinct from the {@link LiveAssertionError} an observed-absent, foreign,
|
|
13
|
+
* or status-mismatched verdict throws, so a caller can tell "could not tell"
|
|
14
|
+
* from "confirmed wrong" without parsing a message.
|
|
15
|
+
*
|
|
16
|
+
* Marker verification is best-effort by the same logic {@link
|
|
17
|
+
* ResourceMetadata.marker}'s own contract states: a lexicon with no marker
|
|
18
|
+
* channel on this read path (aws's thin `describeResources`, `ownership:
|
|
19
|
+
* "unknown"`) reports no marker at all, which is not the same claim as
|
|
20
|
+
* "foreign". Enforcing a match whenever the channel exists — a present
|
|
21
|
+
* mismatch, or `ownership: "foreign"` with no marker to show — catches the
|
|
22
|
+
* case the harness cares about (a same-named leftover from another env);
|
|
23
|
+
* an absent channel is passed through unverified rather than making every
|
|
24
|
+
* lexicon without one unusable.
|
|
25
|
+
*/
|
|
26
|
+
import { type UnobservedReason } from "../observation.js";
|
|
27
|
+
import type { ObservationLexicon, ResourceMetadata } from "../lexicon.js";
|
|
28
|
+
import type { OwnershipMarker } from "../ownership.js";
|
|
29
|
+
/**
|
|
30
|
+
* Thrown by {@link assertLiveEntity} for a confirmed failure: observed
|
|
31
|
+
* absent, a marker that names another stack/env, a resource confirmed
|
|
32
|
+
* foreign, or a status mismatch. Never thrown for NOT-OBSERVED — see {@link
|
|
33
|
+
* UnobservedAssertionError}.
|
|
34
|
+
*/
|
|
35
|
+
export declare class LiveAssertionError extends Error {
|
|
36
|
+
constructor(message: string);
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Thrown when the entity is NOT-OBSERVED (#1089) rather than confirmed
|
|
40
|
+
* present or absent. Kept as its own type, not a flag on {@link
|
|
41
|
+
* LiveAssertionError}: a suite (or a CI policy) that wants to fail loudly on
|
|
42
|
+
* "could not tell" but treat it differently from a confirmed miss can catch
|
|
43
|
+
* this one specifically.
|
|
44
|
+
*/
|
|
45
|
+
export declare class UnobservedAssertionError extends Error {
|
|
46
|
+
readonly entity: string;
|
|
47
|
+
readonly reason: UnobservedReason;
|
|
48
|
+
readonly detail?: string | undefined;
|
|
49
|
+
constructor(entity: string, reason: UnobservedReason, detail?: string | undefined);
|
|
50
|
+
}
|
|
51
|
+
export interface AssertLiveOptions {
|
|
52
|
+
/** Expected `ResourceMetadata.status`, where the lexicon reports one. Skipped when omitted. */
|
|
53
|
+
status?: string;
|
|
54
|
+
}
|
|
55
|
+
export interface AssertLiveEntityOptions extends AssertLiveOptions {
|
|
56
|
+
plugin: ObservationLexicon;
|
|
57
|
+
/** chant entity name — the key to assert on. */
|
|
58
|
+
name: string;
|
|
59
|
+
entityType: string;
|
|
60
|
+
props: Record<string, unknown>;
|
|
61
|
+
/** This lexicon's own built output for the deploy, or `""` when none was built. */
|
|
62
|
+
buildOutput: string;
|
|
63
|
+
environment: string;
|
|
64
|
+
/** This deploy's identity — the marker an observed resource is checked against. */
|
|
65
|
+
marker: OwnershipMarker;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Assert one declared entity is live: observed present in `environment`, not
|
|
69
|
+
* a confirmed-foreign resource, and — when `status` is given — reporting
|
|
70
|
+
* that status. Resolves to the entity's {@link ResourceMetadata} on success.
|
|
71
|
+
*
|
|
72
|
+
* Throws {@link UnobservedAssertionError} for NOT-OBSERVED. Throws {@link
|
|
73
|
+
* LiveAssertionError} for observed-absent, a confirmed-foreign identity, or a
|
|
74
|
+
* status mismatch.
|
|
75
|
+
*/
|
|
76
|
+
export declare function assertLiveEntity(opts: AssertLiveEntityOptions): Promise<ResourceMetadata>;
|
|
77
|
+
//# sourceMappingURL=assert-live.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"assert-live.d.ts","sourceRoot":"","sources":["../../src/lifecycle/assert-live.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH,OAAO,EAA6D,KAAK,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAClH,OAAO,KAAK,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AACvE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAEpD;;;;;GAKG;AACH,qBAAa,kBAAmB,SAAQ,KAAK;gBAC/B,OAAO,EAAE,MAAM;CAI5B;AAED;;;;;;GAMG;AACH,qBAAa,wBAAyB,SAAQ,KAAK;aAE/B,MAAM,EAAE,MAAM;aACd,MAAM,EAAE,gBAAgB;aACxB,MAAM,CAAC,EAAE,MAAM;gBAFf,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,gBAAgB,EACxB,MAAM,CAAC,EAAE,MAAM,YAAA;CAQlC;AAED,MAAM,WAAW,iBAAiB;IAChC,+FAA+F;IAC/F,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,uBAAwB,SAAQ,iBAAiB;IAChE,MAAM,EAAE,kBAAkB,CAAC;IAC3B,gDAAgD;IAChD,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC/B,mFAAmF;IACnF,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,mFAAmF;IACnF,MAAM,EAAE,eAAe,CAAC;CACzB;AAQD;;;;;;;;GAQG;AACH,wBAAsB,gBAAgB,CAAC,IAAI,EAAE,uBAAuB,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAwD/F"}
|
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
*/
|
|
15
15
|
import { type AttributeChange, type DiffLiveInput } from "./live-diff.js";
|
|
16
16
|
import { type UnobservedReason } from "../observation.js";
|
|
17
|
+
import { type Disruption } from "./disruption.js";
|
|
17
18
|
/**
|
|
18
19
|
* What the projection proposes for a single resource.
|
|
19
20
|
*
|
|
@@ -125,6 +126,22 @@ export interface ChangeSetEntry {
|
|
|
125
126
|
effectReason?: EffectFireReason;
|
|
126
127
|
/** Human-readable backing for `effectReason` (the digests that differ, the unresolved path). */
|
|
127
128
|
effectDetail?: string;
|
|
129
|
+
/**
|
|
130
|
+
* How much applying this change hurts (#1665) — in-place / rolling / replace
|
|
131
|
+
* / destroy / unknown. Set on `update` entries only: every other action
|
|
132
|
+
* carries its blast radius in the action itself.
|
|
133
|
+
*
|
|
134
|
+
* The verdict comes from the lexicon that owns the spec
|
|
135
|
+
* ({@link LexiconPlugin.classifyDisruption}), never from core, which has no
|
|
136
|
+
* per-provider replacement rules and must not grow any. `unknown` is the
|
|
137
|
+
* default and the only fallback — read it as "nobody could say", never as
|
|
138
|
+
* "probably in place".
|
|
139
|
+
*/
|
|
140
|
+
disruption?: Disruption;
|
|
141
|
+
/** The attribute paths that forced `disruption` (#1665). */
|
|
142
|
+
disruptionBecause?: string[];
|
|
143
|
+
/** Human-readable backing for `disruption` — the spec knowledge behind the call, or why there is none. */
|
|
144
|
+
disruptionDetail?: string;
|
|
128
145
|
}
|
|
129
146
|
export interface ChangeSet {
|
|
130
147
|
env: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"change-set.d.ts","sourceRoot":"","sources":["../../src/lifecycle/change-set.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AACH,OAAO,EAAY,KAAK,eAAe,EAAE,KAAK,aAAa,EAAE,MAAM,aAAa,CAAC;AACjF,OAAO,EAAwB,KAAK,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"change-set.d.ts","sourceRoot":"","sources":["../../src/lifecycle/change-set.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AACH,OAAO,EAAY,KAAK,eAAe,EAAE,KAAK,aAAa,EAAE,MAAM,aAAa,CAAC;AACjF,OAAO,EAAwB,KAAK,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAC7E,OAAO,EAAyC,KAAK,UAAU,EAAE,MAAM,cAAc,CAAC;AAEtF;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,MAAM,MAAM,YAAY,GAAG,QAAQ,GAAG,QAAQ,GAAG,QAAQ,GAAG,OAAO,GAAG,SAAS,GAAG,MAAM,GAAG,QAAQ,GAAG,YAAY,CAAC;AAEnH;;;;;;;;;;;GAWG;AACH,MAAM,MAAM,gBAAgB,GAAG,gBAAgB,GAAG,eAAe,GAAG,kBAAkB,CAAC;AAEvF;;;;GAIG;AACH,MAAM,MAAM,SAAS,GAAG,OAAO,GAAG,SAAS,GAAG,SAAS,CAAC;AAExD,MAAM,WAAW,cAAc;IAC7B;;;;OAIG;IACH,IAAI,EAAE,MAAM,CAAC;IACb,kDAAkD;IAClD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;;;OAKG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;;OAIG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,YAAY,CAAC;IACrB,kEAAkE;IAClE,QAAQ,EAAE;QACR,oCAAoC;QACpC,QAAQ,EAAE,OAAO,CAAC;QAClB,oCAAoC;QACpC,UAAU,EAAE,OAAO,CAAC;QACpB,qDAAqD;QACrD,IAAI,EAAE,OAAO,CAAC;QACd;;;;;WAKG;QACH,QAAQ,EAAE,OAAO,CAAC;KACnB,CAAC;IACF,6CAA6C;IAC7C,MAAM,CAAC,EAAE,eAAe,EAAE,CAAC;IAC3B,oDAAoD;IACpD,SAAS,EAAE,SAAS,CAAC;IACrB,gFAAgF;IAChF,gBAAgB,CAAC,EAAE,gBAAgB,CAAC;IACpC,gGAAgG;IAChG,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B;;;;;OAKG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,oGAAoG;IACpG,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;;;OAIG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,4DAA4D;IAC5D,YAAY,CAAC,EAAE,gBAAgB,CAAC;IAChC,gGAAgG;IAChG,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;;;;;;;;;OAUG;IACH,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB,4DAA4D;IAC5D,iBAAiB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC7B,0GAA0G;IAC1G,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,WAAW,SAAS;IACxB,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,cAAc,EAAE,CAAC;CAC3B;AAED;;;;;;;;;;GAUG;AACH,MAAM,WAAW,gBAAgB;IAC/B,qEAAqE;IACrE,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,aAAa,EAAE,OAAO,CAAC,EAAE,gBAAgB,GAAG,SAAS,CA6GvG;AAID,gCAAgC;AAChC,wBAAgB,SAAS,CAAC,EAAE,EAAE,SAAS,GAAG,MAAM,CAAC,YAAY,EAAE,MAAM,CAAC,CAarE;AAED;;;;;;;;;;;;;;GAcG;AACH,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,uEAAuE;AACvE,wBAAgB,cAAc,CAAC,EAAE,EAAE,SAAS,GAAG,cAAc,CAG5D;AAED,sEAAsE;AACtE,wBAAgB,eAAe,CAAC,EAAE,EAAE,SAAS,GAAG,MAAM,CAqDrD"}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
/** One rule's outcome within a tick. */
|
|
2
|
+
export interface ConvergeRuleOutcome {
|
|
3
|
+
ruleId: string;
|
|
4
|
+
/**
|
|
5
|
+
* What actually happened for this fired rule this tick. `"gated"` (#1485)
|
|
6
|
+
* is gate-as-fact: the dispatched op's own run hit a gate it can't clear
|
|
7
|
+
* on the local executor, and the tick records that as a terminal, durable
|
|
8
|
+
* fact — `gateName` names the gate — rather than treating it as a
|
|
9
|
+
* dispatch failure. Resolution is out-of-band (`chant approve <op>
|
|
10
|
+
* <gate>`, ./gate-ledger.ts, or a merged PR); the tick itself never
|
|
11
|
+
* blocks waiting for it.
|
|
12
|
+
*/
|
|
13
|
+
action: "ran" | "reported" | "skipped-budget" | "skipped-flap" | "gated";
|
|
14
|
+
/** The dispatched Op name, for `action: "ran"` or `"gated"`. */
|
|
15
|
+
op?: string;
|
|
16
|
+
/** The gate's signal name, for `action: "gated"`. */
|
|
17
|
+
gateName?: string;
|
|
18
|
+
/** The report reason, for `action: "reported"` (including a flap-damped rule's forced report) — and the human-readable explanation for `action: "gated"`. */
|
|
19
|
+
reason?: string;
|
|
20
|
+
}
|
|
21
|
+
/** One immutable converge-tick record. */
|
|
22
|
+
export interface ConvergeTickRecord {
|
|
23
|
+
/** Schema version, so an incompatible future shape is detected before being misread. */
|
|
24
|
+
version: 1;
|
|
25
|
+
/** The ConvergeOp's name (`OpConfig.name`). */
|
|
26
|
+
op: string;
|
|
27
|
+
env: string;
|
|
28
|
+
/** ISO-8601 timestamp, caller-supplied (same convention as `ReleaseRecord.timestamp` — library code never calls `Date.now()` internally). */
|
|
29
|
+
timestamp: string;
|
|
30
|
+
/** Every rule id whose predicate matched this tick, regardless of what action followed — the flap-damping input. */
|
|
31
|
+
firedRuleIds: string[];
|
|
32
|
+
/** Per-rule outcome, for every fired rule. */
|
|
33
|
+
outcomes: ConvergeRuleOutcome[];
|
|
34
|
+
/** Aggregate counts backing the tick's one log line. */
|
|
35
|
+
summary: {
|
|
36
|
+
drifted: number;
|
|
37
|
+
remediated: number;
|
|
38
|
+
reported: number;
|
|
39
|
+
skippedBudget: number;
|
|
40
|
+
skippedFlap: number;
|
|
41
|
+
unobserved: number;
|
|
42
|
+
adopted: number;
|
|
43
|
+
/** Rules whose dispatch hit a gate this tick (#1485) — a terminal, non-blocking fact; see `ConvergeRuleOutcome.action`'s doc. @default 0, so an older record without this field still reads as zero, not undefined. */
|
|
44
|
+
gated?: number;
|
|
45
|
+
};
|
|
46
|
+
/** The one human-readable log line this tick produced (issue: "one log line and one ledger record per tick"). */
|
|
47
|
+
log: string;
|
|
48
|
+
}
|
|
49
|
+
export type ConvergeTickRecordInput = Omit<ConvergeTickRecord, "version">;
|
|
50
|
+
/**
|
|
51
|
+
* Append one immutable tick record. Does not push to the remote — call
|
|
52
|
+
* `pushLifecycle` (./git.ts) afterward, same two-step shape every other
|
|
53
|
+
* ledger write here uses.
|
|
54
|
+
*
|
|
55
|
+
* Retries the whole read-modify-write cycle (#1485) on `RefCASConflictError`
|
|
56
|
+
* — `writeBlobToPath`'s ref write is CAS-guarded, so a concurrent writer to
|
|
57
|
+
* a *different* env's file on the same orphan branch (two operators ticking
|
|
58
|
+
* two environments at once is the ordinary case, not an edge case) can lose
|
|
59
|
+
* the race and needs to re-read the branch tip and retry, not fail the
|
|
60
|
+
* tick. Each retry re-reads `existing` fresh, so it always appends onto
|
|
61
|
+
* whatever the other writer just committed rather than reintroducing a stale
|
|
62
|
+
* read. Exhausting the budget re-throws the conflict — a real, sustained
|
|
63
|
+
* pile-up of writers is a signal worth surfacing, not silently swallowing.
|
|
64
|
+
*
|
|
65
|
+
* The baseline read must be `readPathSha` + `readBlobBySha` rather than
|
|
66
|
+
* `readBlobFromPath`, so the exact sha `existing` came from can be passed as
|
|
67
|
+
* `expectPriorPathSha`. See `writeBlobToPath` (./git.ts) for the race that
|
|
68
|
+
* closes.
|
|
69
|
+
*/
|
|
70
|
+
export declare function appendConvergeRecord(input: ConvergeTickRecordInput, opts?: {
|
|
71
|
+
cwd?: string;
|
|
72
|
+
}): Promise<{
|
|
73
|
+
commit: string;
|
|
74
|
+
record: ConvergeTickRecord;
|
|
75
|
+
}>;
|
|
76
|
+
/** Read every tick record for `environment`, oldest first. Malformed lines are skipped, not thrown on — a corrupted or hand-edited ledger degrades gracefully, the same stance `readReleaseLedger` takes. */
|
|
77
|
+
export declare function readConvergeLedger(environment: string, opts?: {
|
|
78
|
+
cwd?: string;
|
|
79
|
+
}): Promise<{
|
|
80
|
+
records: ConvergeTickRecord[];
|
|
81
|
+
malformed: number;
|
|
82
|
+
}>;
|
|
83
|
+
/**
|
|
84
|
+
* How many consecutive most-recent ticks (newest first) fired `ruleId`,
|
|
85
|
+
* stopping at the first tick where it did not — the count a rule's
|
|
86
|
+
* `flapThreshold` is compared against. `0` when the newest tick didn't fire
|
|
87
|
+
* it (including an empty ledger).
|
|
88
|
+
*/
|
|
89
|
+
export declare function consecutiveRuleFires(records: ConvergeTickRecord[], ruleId: string): number;
|
|
90
|
+
//# sourceMappingURL=converge-ledger.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"converge-ledger.d.ts","sourceRoot":"","sources":["../../src/lifecycle/converge-ledger.ts"],"names":[],"mappings":"AAmCA,wCAAwC;AACxC,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE,MAAM,CAAC;IACf;;;;;;;;OAQG;IACH,MAAM,EAAE,KAAK,GAAG,UAAU,GAAG,gBAAgB,GAAG,cAAc,GAAG,OAAO,CAAC;IACzE,gEAAgE;IAChE,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,qDAAqD;IACrD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,6JAA6J;IAC7J,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,0CAA0C;AAC1C,MAAM,WAAW,kBAAkB;IACjC,wFAAwF;IACxF,OAAO,EAAE,CAAC,CAAC;IACX,+CAA+C;IAC/C,EAAE,EAAE,MAAM,CAAC;IACX,GAAG,EAAE,MAAM,CAAC;IACZ,6IAA6I;IAC7I,SAAS,EAAE,MAAM,CAAC;IAClB,oHAAoH;IACpH,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,8CAA8C;IAC9C,QAAQ,EAAE,mBAAmB,EAAE,CAAC;IAChC,wDAAwD;IACxD,OAAO,EAAE;QACP,OAAO,EAAE,MAAM,CAAC;QAChB,UAAU,EAAE,MAAM,CAAC;QACnB,QAAQ,EAAE,MAAM,CAAC;QACjB,aAAa,EAAE,MAAM,CAAC;QACtB,WAAW,EAAE,MAAM,CAAC;QACpB,UAAU,EAAE,MAAM,CAAC;QACnB,OAAO,EAAE,MAAM,CAAC;QAChB,uNAAuN;QACvN,KAAK,CAAC,EAAE,MAAM,CAAC;KAChB,CAAC;IACF,iHAAiH;IACjH,GAAG,EAAE,MAAM,CAAC;CACb;AAED,MAAM,MAAM,uBAAuB,GAAG,IAAI,CAAC,kBAAkB,EAAE,SAAS,CAAC,CAAC;AAE1E;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAsB,oBAAoB,CACxC,KAAK,EAAE,uBAAuB,EAC9B,IAAI,CAAC,EAAE;IAAE,GAAG,CAAC,EAAE,MAAM,CAAA;CAAE,GACtB,OAAO,CAAC;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,kBAAkB,CAAA;CAAE,CAAC,CAqBzD;AAED,6MAA6M;AAC7M,wBAAsB,kBAAkB,CACtC,WAAW,EAAE,MAAM,EACnB,IAAI,CAAC,EAAE;IAAE,GAAG,CAAC,EAAE,MAAM,CAAA;CAAE,GACtB,OAAO,CAAC;IAAE,OAAO,EAAE,kBAAkB,EAAE,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,CAAC,CA0B/D;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,kBAAkB,EAAE,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAO1F"}
|
|
@@ -22,6 +22,7 @@
|
|
|
22
22
|
* interpolated property forever.
|
|
23
23
|
*/
|
|
24
24
|
import { type DeepNormalizationHooks, type NormalizedDeepObservation } from "../deep-observation.js";
|
|
25
|
+
import { type PathOrigin } from "../provenance.js";
|
|
25
26
|
import type { UnobservedResource } from "./live-diff.js";
|
|
26
27
|
import { type BaselineLexicon } from "./observation-baseline.js";
|
|
27
28
|
/**
|
|
@@ -61,6 +62,18 @@ export interface PropertyDrift {
|
|
|
61
62
|
* with no per-field ownership, which is every substrate but k8s.
|
|
62
63
|
*/
|
|
63
64
|
owner?: string;
|
|
65
|
+
/**
|
|
66
|
+
* What produced this path on the DECLARED side (#1443) — the counterpart of
|
|
67
|
+
* {@link owner}, and the reason the two are reported together: "owned live by
|
|
68
|
+
* `hpa-controller`, governed in source by the `tier` parameter" says where
|
|
69
|
+
* each half of a disagreement has to be fixed, which neither half says alone.
|
|
70
|
+
*
|
|
71
|
+
* Resolved by longest prefix from the entity's recorded path origins, so a
|
|
72
|
+
* field inside a keyed list element inherits the origin recorded for the
|
|
73
|
+
* list. Absent when the build recorded none — the run path, and a sandboxed
|
|
74
|
+
* child, have no expression to attribute (see `EntityProvenance.paths`).
|
|
75
|
+
*/
|
|
76
|
+
origin?: PathOrigin;
|
|
64
77
|
}
|
|
65
78
|
/** Property-level drift for one declared entity. */
|
|
66
79
|
export interface DeepEntityDrift {
|
|
@@ -88,6 +101,11 @@ export interface DeepDiffResult {
|
|
|
88
101
|
export interface DeclaredDeepEntity {
|
|
89
102
|
type: string;
|
|
90
103
|
properties: Record<string, unknown>;
|
|
104
|
+
/**
|
|
105
|
+
* The entity's recorded path origins (#1443), as `EntityProvenance.paths`.
|
|
106
|
+
* Omit for a build that recorded none.
|
|
107
|
+
*/
|
|
108
|
+
pathOrigins?: Record<string, PathOrigin>;
|
|
91
109
|
}
|
|
92
110
|
export interface DiffDeepInput {
|
|
93
111
|
/** Normalized declared property trees, keyed by chant entity name. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"deep-diff.d.ts","sourceRoot":"","sources":["../../src/lifecycle/deep-diff.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,OAAO,EAIL,KAAK,sBAAsB,EAC3B,KAAK,yBAAyB,EAC/B,MAAM,qBAAqB,CAAC;AAC7B,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AACtD,OAAO,EAAqB,KAAK,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAEjF;;;;;;;;;GASG;AACH,MAAM,MAAM,iBAAiB,GAAG,SAAS,GAAG,YAAY,GAAG,QAAQ,CAAC;AAEpE,qCAAqC;AACrC,MAAM,WAAW,aAAa;IAC5B,kEAAkE;IAClE,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,iBAAiB,CAAC;IACxB,gDAAgD;IAChD,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,+CAA+C;IAC/C,IAAI,CAAC,EAAE,OAAO,CAAC;IACf;;;;OAIG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB;;;;;;;;;OASG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"deep-diff.d.ts","sourceRoot":"","sources":["../../src/lifecycle/deep-diff.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,OAAO,EAIL,KAAK,sBAAsB,EAC3B,KAAK,yBAAyB,EAC/B,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAgB,KAAK,UAAU,EAAE,MAAM,eAAe,CAAC;AAC9D,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AACtD,OAAO,EAAqB,KAAK,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAEjF;;;;;;;;;GASG;AACH,MAAM,MAAM,iBAAiB,GAAG,SAAS,GAAG,YAAY,GAAG,QAAQ,CAAC;AAEpE,qCAAqC;AACrC,MAAM,WAAW,aAAa;IAC5B,kEAAkE;IAClE,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,iBAAiB,CAAC;IACxB,gDAAgD;IAChD,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,+CAA+C;IAC/C,IAAI,CAAC,EAAE,OAAO,CAAC;IACf;;;;OAIG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB;;;;;;;;;OASG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;;;;;;;;OAUG;IACH,MAAM,CAAC,EAAE,UAAU,CAAC;CACrB;AAED,oDAAoD;AACpD,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,aAAa,EAAE,CAAC;CAC1B;AAED,MAAM,WAAW,cAAc;IAC7B,iFAAiF;IACjF,OAAO,EAAE,eAAe,EAAE,CAAC;IAC3B;;;;OAIG;IACH,QAAQ,EAAE,eAAe,EAAE,CAAC;IAC5B,qDAAqD;IACrD,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,8EAA8E;IAC9E,UAAU,EAAE,kBAAkB,EAAE,CAAC;IACjC,0EAA0E;IAC1E,kBAAkB,EAAE,MAAM,EAAE,CAAC;CAC9B;AAED,sFAAsF;AACtF,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACpC;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;CAC1C;AAED,MAAM,WAAW,aAAa;IAC5B,sEAAsE;IACtE,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,kBAAkB,CAAC,CAAC;IAC7C,4EAA4E;IAC5E,IAAI,EAAE,yBAAyB,CAAC;IAChC,yEAAyE;IACzE,QAAQ,CAAC,EAAE,eAAe,CAAC;IAC3B;;;;;OAKG;IACH,KAAK,CAAC,EAAE,sBAAsB,CAAC;CAChC;AAED;;;GAGG;AACH,wBAAgB,QAAQ,CAAC,KAAK,EAAE,aAAa,GAAG,cAAc,CAwG7D;AAED,+DAA+D;AAC/D,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,cAAc,GAAG,MAAM,CAEjE"}
|
|
@@ -18,12 +18,20 @@
|
|
|
18
18
|
*/
|
|
19
19
|
import type { ObservationLexicon } from "../lexicon.js";
|
|
20
20
|
import { type DeepNormalizationHooks, type NormalizedDeepObservation } from "../deep-observation.js";
|
|
21
|
+
import type { PathOrigin } from "../provenance.js";
|
|
21
22
|
import { type DeepDiffResult } from "./deep-diff.js";
|
|
22
23
|
import type { BaselineLexicon } from "./observation-baseline.js";
|
|
23
|
-
/**
|
|
24
|
+
/**
|
|
25
|
+
* Declared entities for one lexicon, in the shape the observe paths pass around.
|
|
26
|
+
*
|
|
27
|
+
* `pathOrigins` (#1443) rides alongside `props` rather than being read off the
|
|
28
|
+
* entity, because callers rebuild this map as plain objects and the symbol-keyed
|
|
29
|
+
* provenance channel does not survive that copy.
|
|
30
|
+
*/
|
|
24
31
|
export type DeclaredEntities = Map<string, {
|
|
25
32
|
entityType: string;
|
|
26
33
|
props: Record<string, unknown>;
|
|
34
|
+
pathOrigins?: Record<string, PathOrigin>;
|
|
27
35
|
}>;
|
|
28
36
|
export interface DeepObserveOptions {
|
|
29
37
|
environment: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"deep-observe.d.ts","sourceRoot":"","sources":["../../src/lifecycle/deep-observe.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AACrD,OAAO,EAIL,KAAK,sBAAsB,EAE3B,KAAK,yBAAyB,EAC/B,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EAAqC,KAAK,cAAc,EAAE,MAAM,aAAa,CAAC;AACrF,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAE9D
|
|
1
|
+
{"version":3,"file":"deep-observe.d.ts","sourceRoot":"","sources":["../../src/lifecycle/deep-observe.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AACrD,OAAO,EAIL,KAAK,sBAAsB,EAE3B,KAAK,yBAAyB,EAC/B,MAAM,qBAAqB,CAAC;AAE7B,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EAAqC,KAAK,cAAc,EAAE,MAAM,aAAa,CAAC;AACrF,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAE9D;;;;;;GAMG;AACH,MAAM,MAAM,gBAAgB,GAAG,GAAG,CAChC,MAAM,EACN;IAAE,UAAU,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAAA;CAAE,CACjG,CAAC;AAEF,MAAM,WAAW,kBAAkB;IACjC,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,gBAAgB,CAAC;IAC3B,uDAAuD;IACvD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;4CAEwC;IACxC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,kFAAkF;IAClF,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;IAC3B,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED;;;GAGG;AACH,wBAAgB,qBAAqB,CACnC,KAAK,EAAE,QAAQ,CAAC,yBAAyB,CAAC,GACzC,yBAAyB,CAS3B;AAED;;;;;GAKG;AACH,wBAAsB,WAAW,CAC/B,MAAM,EAAE,kBAAkB,EAC1B,IAAI,EAAE,kBAAkB,GACvB,OAAO,CAAC,yBAAyB,CAAC,CA+BpC;AAED;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CACjC,QAAQ,EAAE,gBAAgB,EAC1B,IAAI,EAAE,yBAAyB,EAC/B,KAAK,CAAC,EAAE,sBAAsB,EAC9B,QAAQ,CAAC,EAAE,eAAe,GACzB,cAAc,CAoDhB;AAED,oFAAoF;AACpF,wBAAsB,kBAAkB,CACtC,MAAM,EAAE,kBAAkB,EAC1B,IAAI,EAAE,kBAAkB,GAAG;IAAE,QAAQ,CAAC,EAAE,eAAe,CAAA;CAAE,GACxD,OAAO,CAAC,cAAc,CAAC,CAGzB"}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Per-change disruption classification (#1665).
|
|
3
|
+
*
|
|
4
|
+
* The change set says WHAT a pending change is (`create`/`update`/`delete`/…).
|
|
5
|
+
* It says nothing about what applying it costs. An `update` that flips a tag
|
|
6
|
+
* and an `update` that rebuilds a database read identically, and the second one
|
|
7
|
+
* is the one that wakes somebody up.
|
|
8
|
+
*
|
|
9
|
+
* The knowledge that separates them is spec knowledge. CloudFormation's
|
|
10
|
+
* registry schema declares `createOnlyProperties` per type; Kubernetes' SSA
|
|
11
|
+
* schema knows which field changes roll a workload. Core owns neither, and
|
|
12
|
+
* hardcoding either here would put per-provider replacement rules in the tool
|
|
13
|
+
* — the same mistake `postSynthChecks` exists to avoid. So core defines the
|
|
14
|
+
* contract and the reporting, and the lexicon that compiled the spec supplies
|
|
15
|
+
* the answer, via {@link LexiconPlugin.classifyDisruption}.
|
|
16
|
+
*
|
|
17
|
+
* The invariant that makes the field trustworthy is that `unknown` is the
|
|
18
|
+
* default and the only fallback. No classifier, a classifier that says nothing
|
|
19
|
+
* about an entry, a classifier that throws, a classifier that returns a level
|
|
20
|
+
* outside the vocabulary — all of them land on `unknown`, never on `in-place`.
|
|
21
|
+
* A confident "this mutates in place" is only ever a lexicon's own claim.
|
|
22
|
+
*/
|
|
23
|
+
import type { AttributeChange } from "./live-diff.js";
|
|
24
|
+
import type { ChangeSet, ChangeSetEntry } from "./change-set.js";
|
|
25
|
+
/**
|
|
26
|
+
* How much applying one pending change hurts.
|
|
27
|
+
*
|
|
28
|
+
* - `in-place` — the provider mutates the existing resource. No new identity,
|
|
29
|
+
* no window where it is absent.
|
|
30
|
+
* - `rolling` — the resource survives, but its workload is replaced
|
|
31
|
+
* incrementally (a Deployment's pod template changing). Disruptive to what
|
|
32
|
+
* is running, not to the resource.
|
|
33
|
+
* - `replace` — a new resource is created and the old one removed. The
|
|
34
|
+
* physical id changes; anything holding the old one has to be updated.
|
|
35
|
+
* - `destroy` — replacement that removes the old resource FIRST. There is a
|
|
36
|
+
* window with nothing there, and whatever the old one held is gone.
|
|
37
|
+
* - `unknown` — nobody could say. The honest value, and the default: it is
|
|
38
|
+
* what a change gets when no lexicon classifies it, and it must never be
|
|
39
|
+
* read as "probably fine".
|
|
40
|
+
*/
|
|
41
|
+
export type Disruption = "in-place" | "rolling" | "replace" | "destroy" | "unknown";
|
|
42
|
+
/** Every level, most disruptive last — also the guard core validates a lexicon's answer against. */
|
|
43
|
+
export declare const DISRUPTION_LEVELS: readonly Disruption[];
|
|
44
|
+
/** One pending change put to a lexicon for classification. */
|
|
45
|
+
export interface DisruptionQuery {
|
|
46
|
+
/** The change set entry's `name` — the key a verdict comes back under. */
|
|
47
|
+
name: string;
|
|
48
|
+
/** Resource type, when the observation reported one. */
|
|
49
|
+
type?: string;
|
|
50
|
+
/** The attribute-level changes the entry carries. */
|
|
51
|
+
deltas: AttributeChange[];
|
|
52
|
+
}
|
|
53
|
+
/** A lexicon's answer for one query. */
|
|
54
|
+
export interface DisruptionVerdict {
|
|
55
|
+
disruption: Disruption;
|
|
56
|
+
/** The attribute paths that forced the verdict — empty or absent when none did. */
|
|
57
|
+
because?: string[];
|
|
58
|
+
/** One line of human-readable backing, naming the spec knowledge behind the call. */
|
|
59
|
+
detail?: string;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* The shape of {@link LexiconPlugin.classifyDisruption}. Keyed by query `name`;
|
|
63
|
+
* a name the lexicon says nothing about degrades to `unknown`, so a partial
|
|
64
|
+
* answer is a valid answer.
|
|
65
|
+
*/
|
|
66
|
+
export type DisruptionClassifier = (options: {
|
|
67
|
+
environment: string;
|
|
68
|
+
changes: DisruptionQuery[];
|
|
69
|
+
}) => Record<string, DisruptionVerdict> | Promise<Record<string, DisruptionVerdict>>;
|
|
70
|
+
/** The verdict every fallback path produces. */
|
|
71
|
+
export declare function unknownDisruption(detail: string): DisruptionVerdict;
|
|
72
|
+
/**
|
|
73
|
+
* Annotate one lexicon's change set with a disruption verdict per `update`.
|
|
74
|
+
*
|
|
75
|
+
* Only `update` entries are asked about: every other action already carries its
|
|
76
|
+
* blast radius in the action itself. Called once per lexicon, before the plan
|
|
77
|
+
* merges the change sets, so `classify` is always the lexicon that produced the
|
|
78
|
+
* entries — the only party that can map its own observation's attribute paths
|
|
79
|
+
* back onto spec properties.
|
|
80
|
+
*
|
|
81
|
+
* Returns a new change set; the input is not mutated.
|
|
82
|
+
*/
|
|
83
|
+
export declare function annotateDisruption(cs: ChangeSet, environment: string, classify?: DisruptionClassifier): Promise<ChangeSet>;
|
|
84
|
+
/** Count `update` entries per level. Entries with no verdict at all are not counted. */
|
|
85
|
+
export declare function summarizeDisruption(cs: ChangeSet): Record<Disruption, number>;
|
|
86
|
+
/** The most disruptive verdict in the set, or undefined when nothing was classified. */
|
|
87
|
+
export declare function worstDisruption(cs: ChangeSet): Disruption | undefined;
|
|
88
|
+
/**
|
|
89
|
+
* Warnings a plan should print on stderr — so a `--json` or `--report gitlab-mr`
|
|
90
|
+
* consumer, whose shape has no column for disruption, still hears about the
|
|
91
|
+
* expensive rows. Same discipline as the unobserved warning (#1089).
|
|
92
|
+
*/
|
|
93
|
+
export declare function disruptionNotices(cs: ChangeSet): string[];
|
|
94
|
+
/** Render one entry's verdict for the human plan, or "" when there is none. */
|
|
95
|
+
export declare function renderDisruption(entry: ChangeSetEntry): string;
|
|
96
|
+
//# sourceMappingURL=disruption.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"disruption.d.ts","sourceRoot":"","sources":["../../src/lifecycle/disruption.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AACnD,OAAO,KAAK,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAE9D;;;;;;;;;;;;;;;GAeG;AACH,MAAM,MAAM,UAAU,GAAG,UAAU,GAAG,SAAS,GAAG,SAAS,GAAG,SAAS,GAAG,SAAS,CAAC;AAEpF,oGAAoG;AACpG,eAAO,MAAM,iBAAiB,EAAE,SAAS,UAAU,EAMlD,CAAC;AAWF,8DAA8D;AAC9D,MAAM,WAAW,eAAe;IAC9B,0EAA0E;IAC1E,IAAI,EAAE,MAAM,CAAC;IACb,wDAAwD;IACxD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,qDAAqD;IACrD,MAAM,EAAE,eAAe,EAAE,CAAC;CAC3B;AAED,wCAAwC;AACxC,MAAM,WAAW,iBAAiB;IAChC,UAAU,EAAE,UAAU,CAAC;IACvB,mFAAmF;IACnF,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,qFAAqF;IACrF,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;;;GAIG;AACH,MAAM,MAAM,oBAAoB,GAAG,CAAC,OAAO,EAAE;IAC3C,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,eAAe,EAAE,CAAC;CAC5B,KAAK,MAAM,CAAC,MAAM,EAAE,iBAAiB,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAAC,CAAC;AAErF,gDAAgD;AAChD,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG,iBAAiB,CAEnE;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,kBAAkB,CACtC,EAAE,EAAE,SAAS,EACb,WAAW,EAAE,MAAM,EACnB,QAAQ,CAAC,EAAE,oBAAoB,GAC9B,OAAO,CAAC,SAAS,CAAC,CA0CpB;AAiBD,wFAAwF;AACxF,wBAAgB,mBAAmB,CAAC,EAAE,EAAE,SAAS,GAAG,MAAM,CAAC,UAAU,EAAE,MAAM,CAAC,CAY7E;AAED,wFAAwF;AACxF,wBAAgB,eAAe,CAAC,EAAE,EAAE,SAAS,GAAG,UAAU,GAAG,SAAS,CAOrE;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,EAAE,EAAE,SAAS,GAAG,MAAM,EAAE,CAkBzD;AAED,+EAA+E;AAC/E,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,cAAc,GAAG,MAAM,CAG9D"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/** One immutable gate-resolution record. */
|
|
2
|
+
export interface GateResolutionRecord {
|
|
3
|
+
/** Schema version, so an incompatible future shape is detected before being misread. */
|
|
4
|
+
version: 1;
|
|
5
|
+
/** The dispatched op the gate belongs to. */
|
|
6
|
+
op: string;
|
|
7
|
+
/** The gate's signal name (matches `ConvergeRuleOutcome.gateName`). */
|
|
8
|
+
gate: string;
|
|
9
|
+
/** Who resolved it — an actor name, the same convention `components release --actor` and `run signal --approver` use. */
|
|
10
|
+
resolvedBy: string;
|
|
11
|
+
/** ISO-8601 timestamp, caller-supplied (library code never calls `Date.now()` internally). */
|
|
12
|
+
timestamp: string;
|
|
13
|
+
/** Optional free-text context (e.g. a PR URL — "or a merged PR" is the issue's other resolution path; recording its link here keeps both paths visible from one ledger). */
|
|
14
|
+
note?: string;
|
|
15
|
+
}
|
|
16
|
+
export type GateResolutionInput = Omit<GateResolutionRecord, "version">;
|
|
17
|
+
/** Append one immutable gate-resolution record. Does not push to the remote — call `pushLifecycle` (./git.ts) afterward, same two-step shape every other ledger write here uses. Retries on `RefCASConflictError` the same way `appendConvergeRecord` does (./converge-ledger.ts) — a concurrent writer to a different op's/env's file on the same orphan branch is the ordinary case, not an edge case. The baseline read must be `readPathSha` + `readBlobBySha` rather than `readBlobFromPath`, so the exact sha `existing` came from can be passed as `expectPriorPathSha` — see `writeBlobToPath` (./git.ts) for the race that closes. */
|
|
18
|
+
export declare function appendGateResolution(input: GateResolutionInput, opts?: {
|
|
19
|
+
cwd?: string;
|
|
20
|
+
}): Promise<{
|
|
21
|
+
commit: string;
|
|
22
|
+
record: GateResolutionRecord;
|
|
23
|
+
}>;
|
|
24
|
+
/** Read every gate-resolution record for `op`, oldest first. Malformed lines are skipped, not thrown on, the same graceful-degradation stance `readConvergeLedger` takes. Returns `[]` (never throws) when `op` has no resolutions recorded yet. */
|
|
25
|
+
export declare function readGateResolutions(op: string, opts?: {
|
|
26
|
+
cwd?: string;
|
|
27
|
+
}): Promise<{
|
|
28
|
+
records: GateResolutionRecord[];
|
|
29
|
+
malformed: number;
|
|
30
|
+
}>;
|
|
31
|
+
/** The most recent resolution for `gate` recorded after `sinceIso` (a gated tick's own timestamp) — what `chant operator status` uses to tell a resolved gate from a still-pending one. `undefined` when no such resolution exists. */
|
|
32
|
+
export declare function latestResolutionSince(records: GateResolutionRecord[], gate: string, sinceIso: string): GateResolutionRecord | undefined;
|
|
33
|
+
//# sourceMappingURL=gate-ledger.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gate-ledger.d.ts","sourceRoot":"","sources":["../../src/lifecycle/gate-ledger.ts"],"names":[],"mappings":"AA4CA,4CAA4C;AAC5C,MAAM,WAAW,oBAAoB;IACnC,wFAAwF;IACxF,OAAO,EAAE,CAAC,CAAC;IACX,6CAA6C;IAC7C,EAAE,EAAE,MAAM,CAAC;IACX,uEAAuE;IACvE,IAAI,EAAE,MAAM,CAAC;IACb,yHAAyH;IACzH,UAAU,EAAE,MAAM,CAAC;IACnB,8FAA8F;IAC9F,SAAS,EAAE,MAAM,CAAC;IAClB,4KAA4K;IAC5K,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,MAAM,mBAAmB,GAAG,IAAI,CAAC,oBAAoB,EAAE,SAAS,CAAC,CAAC;AAMxE,+mBAA+mB;AAC/mB,wBAAsB,oBAAoB,CACxC,KAAK,EAAE,mBAAmB,EAC1B,IAAI,CAAC,EAAE;IAAE,GAAG,CAAC,EAAE,MAAM,CAAA;CAAE,GACtB,OAAO,CAAC;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,oBAAoB,CAAA;CAAE,CAAC,CAqB3D;AAED,oPAAoP;AACpP,wBAAsB,mBAAmB,CACvC,EAAE,EAAE,MAAM,EACV,IAAI,CAAC,EAAE;IAAE,GAAG,CAAC,EAAE,MAAM,CAAA;CAAE,GACtB,OAAO,CAAC;IAAE,OAAO,EAAE,oBAAoB,EAAE,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,CAAC,CA0BjE;AAED,uOAAuO;AACvO,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,oBAAoB,EAAE,EAC/B,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,MAAM,GACf,oBAAoB,GAAG,SAAS,CASlC"}
|
package/dist/lifecycle/git.d.ts
CHANGED
|
@@ -1,26 +1,6 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Write a blob to an arbitrary `<environment>/<filename>` path on the orphan
|
|
3
|
-
* branch, preserving every other env/file entry already on the branch.
|
|
4
|
-
*
|
|
5
|
-
* Pipeline: hash-object → mktree → commit-tree → update-ref. Factored out of
|
|
6
|
-
* `writeSnapshot` so the release ledger (#568, epic #551 "Build & deploy
|
|
7
|
-
* observability") can reuse the identical git-plumbing path for a different
|
|
8
|
-
* filename (`releases.jsonl`) under the same env directory, rather than a
|
|
9
|
-
* parallel storage mechanism.
|
|
10
|
-
*
|
|
11
|
-
* Exported (not just used internally) so ./build-ledger-store.ts (#609) can
|
|
12
|
-
* reuse this exact plumbing for a top-level directory that isn't really an
|
|
13
|
-
* "environment" (`_builds`, keyed by manifest digest rather than env name) —
|
|
14
|
-
* a build archive is promoted by digest across environments, never owned by
|
|
15
|
-
* one, so it belongs in its own digest-keyed namespace on the same orphan
|
|
16
|
-
* branch rather than duplicated per env. The parameter is still named
|
|
17
|
-
* `environment` because it is literally the first path segment / root-tree
|
|
18
|
-
* entry name this function's tree-building logic groups by; callers outside
|
|
19
|
-
* this module that pass a non-env value (like `_builds`) are relying on that
|
|
20
|
-
* generic behavior, not on any env-specific semantics.
|
|
21
|
-
*/
|
|
22
1
|
export declare function writeBlobToPath(environment: string, filename: string, content: string, commitMessage: string, opts?: {
|
|
23
2
|
cwd?: string;
|
|
3
|
+
expectPriorPathSha?: string | null;
|
|
24
4
|
}): Promise<string>;
|
|
25
5
|
/**
|
|
26
6
|
* Read a blob from an arbitrary `<environment>/<filename>` path on the orphan
|
|
@@ -32,6 +12,16 @@ export declare function writeBlobToPath(environment: string, filename: string, c
|
|
|
32
12
|
export declare function readBlobFromPath(environment: string, filename: string, opts?: {
|
|
33
13
|
cwd?: string;
|
|
34
14
|
}): Promise<string | null>;
|
|
15
|
+
/**
|
|
16
|
+
* Read the blob SHA stored at `<environment>/<filename>` on the orphan branch,
|
|
17
|
+
* or `null` if absent. Sibling of `readBlobFromPath` returning the
|
|
18
|
+
* content-address rather than the content. A read-modify-write ledger append
|
|
19
|
+
* pairs this with {@link readBlobBySha} to pin its baseline read to an exact
|
|
20
|
+
* sha, then passes that sha as `writeBlobToPath`'s `expectPriorPathSha`.
|
|
21
|
+
*/
|
|
22
|
+
export declare function readPathSha(environment: string, filename: string, opts?: {
|
|
23
|
+
cwd?: string;
|
|
24
|
+
}): Promise<string | null>;
|
|
35
25
|
/**
|
|
36
26
|
* Storage key for a snapshot on the orphan branch. Single-stack projects key by
|
|
37
27
|
* lexicon (`<env>/<lexicon>.json`, unchanged). A multi-stack project (see
|
|
@@ -81,6 +71,20 @@ export declare function readSnapshotAt(environment: string, lexicon: string, ref
|
|
|
81
71
|
* Returns the new orphan-branch commit SHA — the caller still owns pushing
|
|
82
72
|
* via `pushLifecycle` under the same concurrent-write lease `writeSnapshot`
|
|
83
73
|
* uses.
|
|
74
|
+
*
|
|
75
|
+
* Retries the whole read-modify-append cycle on `RefCASConflictError`
|
|
76
|
+
* (#1959 finding 1), the same shape `appendConvergeRecord`
|
|
77
|
+
* (./converge-ledger.ts) and `appendGateResolution` (./gate-ledger.ts) use
|
|
78
|
+
* for their own append-only ledgers: `writeBlobToPath`'s own retry only
|
|
79
|
+
* absorbs a conflict caused by some *other* env/file changing — a conflict
|
|
80
|
+
* on this exact `releases.jsonl` (e.g. two deploys to the same env racing)
|
|
81
|
+
* needs `existing` re-read fresh so the appended line list is rebuilt onto
|
|
82
|
+
* whatever the other writer just committed, not silently dropped by
|
|
83
|
+
* retrying with a blob computed from a stale read.
|
|
84
|
+
*
|
|
85
|
+
* The baseline read must be `readPathSha` + `readBlobBySha` rather than
|
|
86
|
+
* `readBlobFromPath`, so the exact sha `existing` came from can be passed as
|
|
87
|
+
* `expectPriorPathSha`. See `writeBlobToPath` for the race that closes.
|
|
84
88
|
*/
|
|
85
89
|
export declare function appendReleaseRecordLine(environment: string, recordJson: string, opts?: {
|
|
86
90
|
cwd?: string;
|
|
@@ -166,6 +170,126 @@ export declare function pushLifecycle(opts?: {
|
|
|
166
170
|
export declare function fetchLifecycle(opts?: {
|
|
167
171
|
cwd?: string;
|
|
168
172
|
}): Promise<boolean>;
|
|
173
|
+
/**
|
|
174
|
+
* Thrown by {@link updateRefCAS}/{@link deleteRefCAS} when `ref` no longer
|
|
175
|
+
* points at the `oldValue` the caller last observed — another writer moved
|
|
176
|
+
* it concurrently. Deliberately a distinct type from a generic git failure so
|
|
177
|
+
* callers (a lease acquire, a retried ledger append) can tell "I lost a race"
|
|
178
|
+
* from "git itself failed" and react differently to each.
|
|
179
|
+
*/
|
|
180
|
+
export declare class RefCASConflictError extends Error {
|
|
181
|
+
readonly ref: string;
|
|
182
|
+
readonly expected: string | null;
|
|
183
|
+
constructor(ref: string, expected: string | null, stderr: string);
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* Thrown by {@link updateRefCAS}/{@link deleteRefCAS} when the ref update
|
|
187
|
+
* failed because git found a stale `.lock` file already sitting next to the
|
|
188
|
+
* ref (#1959 finding 2) — what a `chant operator`/`chant approve`/etc.
|
|
189
|
+
* process leaves behind when it is killed (SIGKILL, OOM, `kill -9`) mid-write,
|
|
190
|
+
* *before* `git update-ref`'s own lockfile-then-rename completes. This is
|
|
191
|
+
* exactly the crash this feature must recover from, and it is NOT a CAS
|
|
192
|
+
* conflict: nobody else actually holds the ref (no other writer is racing,
|
|
193
|
+
* the previous one is simply dead), so it must never be misread as "someone
|
|
194
|
+
* else updated it first" — see `./lease.ts`'s `acquireLease`, which used to
|
|
195
|
+
* (before this fix) read this as "lease held by someone else" and quietly
|
|
196
|
+
* back off forever, since the dead process's lock file never goes away on
|
|
197
|
+
* its own.
|
|
198
|
+
*/
|
|
199
|
+
export declare class StaleLockError extends Error {
|
|
200
|
+
readonly ref: string;
|
|
201
|
+
readonly lockPath: string;
|
|
202
|
+
constructor(ref: string, lockPath: string, stderr: string);
|
|
203
|
+
}
|
|
204
|
+
/** Read the SHA `ref` currently points to, or `null` if it doesn't exist. Works for any ref, not just the lifecycle branch. */
|
|
205
|
+
export declare function readRefSha(ref: string, opts?: {
|
|
206
|
+
cwd?: string;
|
|
207
|
+
}): Promise<string | null>;
|
|
208
|
+
/**
|
|
209
|
+
* Compare-and-swap update of an arbitrary ref. `oldValue` is the SHA the
|
|
210
|
+
* caller last observed the ref at, or `null` to assert the ref does not yet
|
|
211
|
+
* exist (git's own convention: an empty `<oldvalue>` argument to
|
|
212
|
+
* `update-ref` means "must not exist"). Throws {@link RefCASConflictError}
|
|
213
|
+
* when the ref genuinely moved since `oldValue` was read, {@link
|
|
214
|
+
* StaleLockError} when a leftover lock file from a killed process is
|
|
215
|
+
* blocking the write, or a plain `Error` for anything else — never silently
|
|
216
|
+
* overwrites, and never misclassifies one failure as another (#1959 finding
|
|
217
|
+
* 2; see {@link classifyRefFailure}).
|
|
218
|
+
*/
|
|
219
|
+
export declare function updateRefCAS(ref: string, newValue: string, oldValue: string | null, opts?: {
|
|
220
|
+
cwd?: string;
|
|
221
|
+
}): Promise<void>;
|
|
222
|
+
/**
|
|
223
|
+
* Compare-and-swap delete of an arbitrary ref — `oldValue` is required (no
|
|
224
|
+
* "delete unconditionally" escape hatch here) so releasing a lease you no
|
|
225
|
+
* longer hold can never delete someone else's newer one. Same failure
|
|
226
|
+
* classification as {@link updateRefCAS} (#1959 finding 2).
|
|
227
|
+
*/
|
|
228
|
+
export declare function deleteRefCAS(ref: string, oldValue: string, opts?: {
|
|
229
|
+
cwd?: string;
|
|
230
|
+
}): Promise<void>;
|
|
231
|
+
/**
|
|
232
|
+
* Write arbitrary content as a git blob object — no tree, no commit, no ref
|
|
233
|
+
* update. The building block a CAS ref's value can point at directly: a
|
|
234
|
+
* lease record (`./lease.ts`) has no meaningful "tree of files", so its ref
|
|
235
|
+
* targets a blob SHA rather than a commit the way `writeBlobToPath`'s tree-
|
|
236
|
+
* building pipeline does.
|
|
237
|
+
*/
|
|
238
|
+
export declare function writeBlob(content: string, opts?: {
|
|
239
|
+
cwd?: string;
|
|
240
|
+
}): Promise<string>;
|
|
241
|
+
/** Read a blob's raw content by its SHA (whatever object a ref points at directly). Returns `null` when the object doesn't exist locally. */
|
|
242
|
+
export declare function readBlobBySha(sha: string, opts?: {
|
|
243
|
+
cwd?: string;
|
|
244
|
+
}): Promise<string | null>;
|
|
245
|
+
/**
|
|
246
|
+
* Push one arbitrary ref (e.g. a lease ref) to the remote, guarded the same
|
|
247
|
+
* way {@link pushLifecycle} guards the ledger branch: `--force-with-lease`
|
|
248
|
+
* keyed to the remote SHA last observed locally, so a concurrent push from a
|
|
249
|
+
* second machine is rejected rather than silently clobbered. Plain `--force`
|
|
250
|
+
* underneath that lease — a lease ref's value is a bare blob SHA, not a
|
|
251
|
+
* commit descending from the previous one, so there is no "fast-forward" to
|
|
252
|
+
* preserve, only the CAS the lease guard already provides.
|
|
253
|
+
*
|
|
254
|
+
* Returns `false` (never throws) when no remote is configured — a
|
|
255
|
+
* remote-less project's lease is local-only by construction (see
|
|
256
|
+
* `./lease.ts`'s module doc), or when the push itself is rejected (the
|
|
257
|
+
* caller re-reads and retries; see `acquireLease`).
|
|
258
|
+
*/
|
|
259
|
+
export declare function pushRef(ref: string, opts?: {
|
|
260
|
+
cwd?: string;
|
|
261
|
+
}): Promise<boolean>;
|
|
262
|
+
/**
|
|
263
|
+
* Fetch one arbitrary remote ref into a local ref of a possibly *different*
|
|
264
|
+
* name (#1959 finding 3). `+` forces the update even when it isn't a
|
|
265
|
+
* fast-forward (a lease ref's new value is rarely a descendant of its old
|
|
266
|
+
* one). Returns `false` (never throws) when no remote is configured.
|
|
267
|
+
*
|
|
268
|
+
* The `localRef !== remoteRef` shape exists so a read path can observe what
|
|
269
|
+
* the remote currently holds without ever touching a local ref another code
|
|
270
|
+
* path treats as CAS-authoritative — see {@link fetchRef}'s doc and
|
|
271
|
+
* `./lease.ts`'s `readLease`, which fetches into a side tracking ref
|
|
272
|
+
* (`refs/chant/lease-remote/<op>`) for exactly this reason.
|
|
273
|
+
*/
|
|
274
|
+
export declare function fetchRefInto(remoteRef: string, localRef: string, opts?: {
|
|
275
|
+
cwd?: string;
|
|
276
|
+
}): Promise<boolean>;
|
|
277
|
+
/**
|
|
278
|
+
* Fetch one arbitrary ref from remote into the same local ref name.
|
|
279
|
+
*
|
|
280
|
+
* **Caution for a read path (#1959 finding 3):** this force-overwrites
|
|
281
|
+
* `ref` locally (`+ref:ref`) — safe for a ref only a CAS write path ever
|
|
282
|
+
* mutates locally between fetches, but NOT safe to call from a plain read
|
|
283
|
+
* before every read if some other local writer (in the same clone) might be
|
|
284
|
+
* mid-write: fetching here would force the local ref back to whatever the
|
|
285
|
+
* remote last had, clobbering a just-written, not-yet-pushed local value out
|
|
286
|
+
* from under it. `./lease.ts`'s `readLease` used to do exactly that; it now
|
|
287
|
+
* uses {@link fetchRefInto} against a side tracking ref instead. Prefer
|
|
288
|
+
* `fetchRefInto` for any new read-before-decide path.
|
|
289
|
+
*/
|
|
290
|
+
export declare function fetchRef(ref: string, opts?: {
|
|
291
|
+
cwd?: string;
|
|
292
|
+
}): Promise<boolean>;
|
|
169
293
|
/**
|
|
170
294
|
* Get the current HEAD commit SHA of the main working branch.
|
|
171
295
|
*/
|