@go-to-k/cdkd 0.284.50 → 0.284.51

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/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import { $n as setAwsClients, Bt as DiffCalculator, Cr as normalizeAwsError, Gt as TemplateParser, Jn as clearBucketRegionCache, Jt as S3StateBackend, Kn as AssemblyReader, Kt as LockManager, Qn as resetAwsClients, Sr as isCdkdError, W as IAMRoleProvider, Wt as DagBuilder, Xn as AwsClients, Yn as resolveBucketRegion, Zn as getAwsClients, Zt as AssetPublisher, br as SynthesisError, er as AssetError, et as CloudControlProvider, ir as DependencyError, mr as ProvisioningError, nr as ConfigError, q as ProviderRegistry, r as DeployEngine, tr as CdkdError, ur as LockError, wn as Synthesizer, xr as formatError, yr as StateError } from "./deploy-engine-tBUjmzHn.js";
1
+ import { $n as setAwsClients, Bt as DiffCalculator, Cr as normalizeAwsError, Gt as TemplateParser, Jn as clearBucketRegionCache, Jt as S3StateBackend, Kn as AssemblyReader, Kt as LockManager, Qn as resetAwsClients, Sr as isCdkdError, W as IAMRoleProvider, Wt as DagBuilder, Xn as AwsClients, Yn as resolveBucketRegion, Zn as getAwsClients, Zt as AssetPublisher, br as SynthesisError, er as AssetError, et as CloudControlProvider, ir as DependencyError, mr as ProvisioningError, nr as ConfigError, q as ProviderRegistry, r as DeployEngine, tr as CdkdError, ur as LockError, wn as Synthesizer, xr as formatError, yr as StateError } from "./deploy-engine-Dnp730rc.js";
2
2
  import { n as getLogger, r as setLogger, t as ConsoleLogger } from "./logger-zRrlbaQt.js";
3
3
 
4
4
  export { AssemblyReader, AssetError, AssetPublisher, AwsClients, CdkdError, CloudControlProvider, ConfigError, ConsoleLogger, DagBuilder, DependencyError, DeployEngine, DiffCalculator, IAMRoleProvider, LockError, LockManager, ProviderRegistry, ProvisioningError, S3StateBackend, StateError, SynthesisError, Synthesizer, TemplateParser, clearBucketRegionCache, formatError, getAwsClients, getLogger, isCdkdError, normalizeAwsError, resetAwsClients, resolveBucketRegion, setAwsClients, setLogger };
@@ -1,7 +1,7 @@
1
- import { $ as startInterruptWatch, $n as setAwsClients, $t as WorkGraph, A as renderStatefulReason, An as resolveCaptureObservedState, At as redactSecretsForState, B as exportAliasCollisionScrubWarning, Bn as findLargeInlineResources, Bt as DiffCalculator, C as isFinalSnapshotError, Cn as getDockerImageBySourceHash, Cr as normalizeAwsError, Ct as TEMPLATE_SOURCED_RULES, D as extractDeploymentEventError, Dn as getLegacyStateBucketName, Dr as isThrottlingError, Dt as isSingleDynamicReferenceToken, E as makeCanonicalizePropertiesFn, En as getDefaultStateBucketName, Er as isRetryableTransientError, Et as errorCauseChain, F as green, Fn as stateBucketExistenceConfirmed, Ft as s3BucketDomainName, G as collectInlinePolicyNamesManagedBySiblings, Gn as derivePartitionAndUrlSuffix, Gt as TemplateParser, H as secretBearingStateKeyWarning, Hn as expectedOwnerParam, Ht as describeTypeWithThrottleRetry, I as red, In as warnDeprecatedNoPrefixCliFlag, It as s3BucketDualStackDomainName, J as findActionableSilentDrops, Jt as S3StateBackend, K as clearOnUpdateRemoval, Kn as AssemblyReader, Kt as LockManager, L as yellow, Ln as CFN_TEMPLATE_BODY_LIMIT, Lt as s3BucketRegionalDomainName, M as bold, Mn as resolveStateBucketWithDefault, Mt as classifyReplaySecretRegion, N as cyan, Nn as resolveStateBucketWithDefaultAndSource, Nt as producerRegionsFromState, O as MULTI_REGION_RECREATE_BLOCKED_TYPES, On as resolveApp, Or as markNonRetryable, Ot as maskSecretsInError, P as gray, Pn as resolveUseCdkBootstrapAssets, Pt as s3BucketArn, Q as isInterruptedWaitError, Qn as resetAwsClients, Qt as stringifyValue, R as collectDeclaredOutputNames, Rn as CFN_TEMPLATE_URL_LIMIT, Rt as s3BucketWebsiteUrl, S as createPreDeleteFinalSnapshot, Sn as AssetManifestLoader, St as STATE_SOURCED_READBACK_RULES, T as unsupportedFinalSnapshotError, Tn as synthesisStatusMessage, Tr as isMarkedNonRetryable, Tt as dynamicReferenceTokens, U as stateKeySecretExposure, Un as PARTITION_TABLE, Ut as withRetry, V as isExportAliasCollision, Vn as uploadCfnTemplate, Vt as INTRINSIC_KEYS, W as IAMRoleProvider, Wn as canonicalizeRegion, Wt as DagBuilder, X as beginCommandInterruptScope, Xn as AwsClients, Xt as shouldRetainResource, Y as findSilentDropProperties, Yn as resolveBucketRegion, Yt as rebuildClientForBucketRegion, Z as endCommandInterruptScope, Zn as getAwsClients, Zt as AssetPublisher, _ as computeImplicitDeleteEdges, _n as formatDockerLoginError, _r as StackHasActiveImportsError, _t as replayWarn, a as DeploymentEventsStore, an as stripControlChars, ar as DeployCancelledError, at as carriesDynamicReference, b as buildFinalSnapshotIdentifier, bn as runDockerForeground, bt as requireConfigString, c as replayFailedOperations, cn as ensureAssetStorage, cr as LocalMigrateError, ct as refStateLookupFromResource, d as updatePartialReason, dn as readBootstrapMarkerBody, dr as MissingCdkCliError, dt as resolveExplicitPhysicalId, en as buildAssetRedirectMap, et as CloudControlProvider, f as UNSPECIFIED_SKIP_REASON, fn as validateAssetBucketName, fr as NestedStackChildDirectDestroyError, ft as assertRegionMatch, g as IMPLICIT_DELETE_DEPENDENCIES, gn as dockerSpawnEnvWithSensitive, gr as ResourceUpdateNotSupportedError, gt as readConfigString, h as maskingRetryLogger, hn as buildDockerImage, hr as ResourceTimeoutError, ht as configStringRefusal, i as DeploymentEventsReader, in as escapeRegExp, it as IntrinsicFunctionResolver, j as formatResourceLine, jn as resolveSkipPrefix, jt as scrubResourceRecord, k as isStatefulRecreateTargetSync, kn as resolveAutoAssetStorage, kt as maskSecretsInText, l as replayRollback, ln as getBootstrapMarkerKey, lr as LocalStartServiceError, lt as WAFv2WebACLProvider, m as withResourceDeadline, mn as buildDenyExternalAccessPolicy, mr as ProvisioningError, mt as configBooleanRefusal, n as DEFAULT_RESOURCE_WARN_AFTER_MS, nn as loadPublishableAssetManifest, nt as disableInstanceApiTermination, o as planFailedOps, on as AssetModeResolver, or as DynamicReferenceRegionAmbiguousError, ot as cfnRefValueFromPhysicalId, p as deleteSkipReason, pn as validateContainerRepoName, pr as PartialFailureError, pt as coerceCfnBoolean, q as ProviderRegistry, qn as processStackMessages, qt as displaySafe, r as DeployEngine, rn as rewriteTemplateAssetReferences, rr as CrossAccountSecretRefusalError, rt as isTerminationProtectionPropagationError, s as planRollback, sn as BOOTSTRAP_MARKER_PREFIX, sr as LocalInvokeBuildError$1, st as getAccountInfo, t as DEFAULT_RESOURCE_TIMEOUT_MS, tn as createAssetRedirectResolver, tr as CdkdError, tt as slowCcOperationTimeoutMs, u as updatePartialMessage, un as parseBootstrapMarker, ut as normalizeAwsTagsToCfn, v as ATOMIC_FINAL_SNAPSHOT_TYPES, vn as getDockerCmd, vr as StackTerminationProtectionError, vt as requireConfigArray, w as refusesFinalSnapshot, wn as Synthesizer, wr as withErrorHandling, wt as createSecretMasker, x as ccRoutedFinalSnapshotError, xn as runDockerStreaming, xt as STATE_SOURCED_CROSS_GENERATION_RULES, y as PRE_DELETE_SNAPSHOT_TYPES, yn as partitionSensitiveEnv, yt as requireConfigObject, z as collectPublishedOutputNames, zn as MIGRATE_TMP_PREFIX, zt as applyRoleArnIfSet } from "./deploy-engine-tBUjmzHn.js";
1
+ import { $ as startInterruptWatch, $n as setAwsClients, $t as WorkGraph, A as renderStatefulReason, An as resolveCaptureObservedState, At as redactSecretsForState, B as exportAliasCollisionScrubWarning, Bn as findLargeInlineResources, Bt as DiffCalculator, C as isFinalSnapshotError, Cn as getDockerImageBySourceHash, Cr as normalizeAwsError, Ct as TEMPLATE_SOURCED_RULES, D as extractDeploymentEventError, Dn as getLegacyStateBucketName, Dr as isThrottlingError, Dt as isSingleDynamicReferenceToken, E as makeCanonicalizePropertiesFn, En as getDefaultStateBucketName, Er as isRetryableTransientError, Et as errorCauseChain, F as green, Fn as stateBucketExistenceConfirmed, Ft as s3BucketDomainName, G as collectInlinePolicyNamesManagedBySiblings, Gn as derivePartitionAndUrlSuffix, Gt as TemplateParser, H as secretBearingStateKeyWarning, Hn as expectedOwnerParam, Ht as describeTypeWithThrottleRetry, I as red, In as warnDeprecatedNoPrefixCliFlag, It as s3BucketDualStackDomainName, J as findActionableSilentDrops, Jt as S3StateBackend, K as clearOnUpdateRemoval, Kn as AssemblyReader, Kt as LockManager, L as yellow, Ln as CFN_TEMPLATE_BODY_LIMIT, Lt as s3BucketRegionalDomainName, M as bold, Mn as resolveStateBucketWithDefault, Mt as classifyReplaySecretRegion, N as cyan, Nn as resolveStateBucketWithDefaultAndSource, Nt as producerRegionsFromState, O as MULTI_REGION_RECREATE_BLOCKED_TYPES, On as resolveApp, Or as markNonRetryable, Ot as maskSecretsInError, P as gray, Pn as resolveUseCdkBootstrapAssets, Pt as s3BucketArn, Q as isInterruptedWaitError, Qn as resetAwsClients, Qt as stringifyValue, R as collectDeclaredOutputNames, Rn as CFN_TEMPLATE_URL_LIMIT, Rt as s3BucketWebsiteUrl, S as createPreDeleteFinalSnapshot, Sn as AssetManifestLoader, St as STATE_SOURCED_READBACK_RULES, T as unsupportedFinalSnapshotError, Tn as synthesisStatusMessage, Tr as isMarkedNonRetryable, Tt as dynamicReferenceTokens, U as stateKeySecretExposure, Un as PARTITION_TABLE, Ut as withRetry, V as isExportAliasCollision, Vn as uploadCfnTemplate, Vt as INTRINSIC_KEYS, W as IAMRoleProvider, Wn as canonicalizeRegion, Wt as DagBuilder, X as beginCommandInterruptScope, Xn as AwsClients, Xt as shouldRetainResource, Y as findSilentDropProperties, Yn as resolveBucketRegion, Yt as rebuildClientForBucketRegion, Z as endCommandInterruptScope, Zn as getAwsClients, Zt as AssetPublisher, _ as computeImplicitDeleteEdges, _n as formatDockerLoginError, _r as StackHasActiveImportsError, _t as replayWarn, a as DeploymentEventsStore, an as stripControlChars, ar as DeployCancelledError, at as carriesDynamicReference, b as buildFinalSnapshotIdentifier, bn as runDockerForeground, bt as requireConfigString, c as replayFailedOperations, cn as ensureAssetStorage, cr as LocalMigrateError, ct as refStateLookupFromResource, d as updatePartialReason, dn as readBootstrapMarkerBody, dr as MissingCdkCliError, dt as resolveExplicitPhysicalId, en as buildAssetRedirectMap, et as CloudControlProvider, f as UNSPECIFIED_SKIP_REASON, fn as validateAssetBucketName, fr as NestedStackChildDirectDestroyError, ft as assertRegionMatch, g as IMPLICIT_DELETE_DEPENDENCIES, gn as dockerSpawnEnvWithSensitive, gr as ResourceUpdateNotSupportedError, gt as readConfigString, h as maskingRetryLogger, hn as buildDockerImage, hr as ResourceTimeoutError, ht as configStringRefusal, i as DeploymentEventsReader, in as escapeRegExp, it as IntrinsicFunctionResolver, j as formatResourceLine, jn as resolveSkipPrefix, jt as scrubResourceRecord, k as isStatefulRecreateTargetSync, kn as resolveAutoAssetStorage, kt as maskSecretsInText, l as replayRollback, ln as getBootstrapMarkerKey, lr as LocalStartServiceError, lt as WAFv2WebACLProvider, m as withResourceDeadline, mn as buildDenyExternalAccessPolicy, mr as ProvisioningError, mt as configBooleanRefusal, n as DEFAULT_RESOURCE_WARN_AFTER_MS, nn as loadPublishableAssetManifest, nt as disableInstanceApiTermination, o as planFailedOps, on as AssetModeResolver, or as DynamicReferenceRegionAmbiguousError, ot as cfnRefValueFromPhysicalId, p as deleteSkipReason, pn as validateContainerRepoName, pr as PartialFailureError, pt as coerceCfnBoolean, q as ProviderRegistry, qn as processStackMessages, qt as displaySafe, r as DeployEngine, rn as rewriteTemplateAssetReferences, rr as CrossAccountSecretRefusalError, rt as isTerminationProtectionPropagationError, s as planRollback, sn as BOOTSTRAP_MARKER_PREFIX, sr as LocalInvokeBuildError$1, st as getAccountInfo, t as DEFAULT_RESOURCE_TIMEOUT_MS, tn as createAssetRedirectResolver, tr as CdkdError, tt as slowCcOperationTimeoutMs, u as updatePartialMessage, un as parseBootstrapMarker, ut as normalizeAwsTagsToCfn, v as ATOMIC_FINAL_SNAPSHOT_TYPES, vn as getDockerCmd, vr as StackTerminationProtectionError, vt as requireConfigArray, w as refusesFinalSnapshot, wn as Synthesizer, wr as withErrorHandling, wt as createSecretMasker, x as ccRoutedFinalSnapshotError, xn as runDockerStreaming, xt as STATE_SOURCED_CROSS_GENERATION_RULES, y as PRE_DELETE_SNAPSHOT_TYPES, yn as partitionSensitiveEnv, yt as requireConfigObject, z as collectPublishedOutputNames, zn as MIGRATE_TMP_PREFIX, zt as applyRoleArnIfSet } from "./deploy-engine-Dnp730rc.js";
2
2
  import { a as getLiveRenderer, c as PATTERN_B_RESOURCE_TYPES, d as generateResourceNameWithFallback, f as getCurrentStackName, h as withStackName, i as runStackBuffered, m as withSkipPrefix, n as getLogger, o as PATTERN_B_NAME_OPTIONS, s as PATTERN_B_NAME_PROPERTIES, u as generateResourceName } from "./logger-zRrlbaQt.js";
3
- import { t as getCdkdVersion } from "./version-pYF8nPNw.js";
4
- import { t as ASGProvider } from "./asg-provider-tVXU-L28.js";
3
+ import { t as getCdkdVersion } from "./version-CJG_PFNb.js";
4
+ import { t as ASGProvider } from "./asg-provider-CynKJdi4.js";
5
5
  import { AsyncLocalStorage } from "node:async_hooks";
6
6
  import { createHash, randomBytes, randomUUID } from "node:crypto";
7
7
  import { CopyObjectCommand, CreateBucketCommand, DeleteBucketAnalyticsConfigurationCommand, DeleteBucketCommand, DeleteBucketCorsCommand, DeleteBucketEncryptionCommand, DeleteBucketIntelligentTieringConfigurationCommand, DeleteBucketInventoryConfigurationCommand, DeleteBucketLifecycleCommand, DeleteBucketMetricsConfigurationCommand, DeleteBucketOwnershipControlsCommand, DeleteBucketPolicyCommand, DeleteBucketReplicationCommand, DeleteBucketTaggingCommand, DeleteBucketWebsiteCommand, DeleteObjectsCommand, GetBucketAccelerateConfigurationCommand, GetBucketCorsCommand, GetBucketEncryptionCommand, GetBucketLifecycleConfigurationCommand, GetBucketLocationCommand, GetBucketLoggingCommand, GetBucketNotificationConfigurationCommand, GetBucketOwnershipControlsCommand, GetBucketPolicyCommand, GetBucketReplicationCommand, GetBucketTaggingCommand, GetBucketVersioningCommand, GetBucketWebsiteCommand, GetObjectCommand, GetObjectLockConfigurationCommand, GetPublicAccessBlockCommand, HeadBucketCommand, ListBucketAnalyticsConfigurationsCommand, ListBucketIntelligentTieringConfigurationsCommand, ListBucketInventoryConfigurationsCommand, ListBucketMetricsConfigurationsCommand, ListObjectVersionsCommand, ListObjectsV2Command, NoSuchBucket, PutBucketAccelerateConfigurationCommand, PutBucketAnalyticsConfigurationCommand, PutBucketCorsCommand, PutBucketEncryptionCommand, PutBucketIntelligentTieringConfigurationCommand, PutBucketInventoryConfigurationCommand, PutBucketLifecycleConfigurationCommand, PutBucketLoggingCommand, PutBucketMetricsConfigurationCommand, PutBucketNotificationConfigurationCommand, PutBucketOwnershipControlsCommand, PutBucketPolicyCommand, PutBucketReplicationCommand, PutBucketTaggingCommand, PutBucketVersioningCommand, PutBucketWebsiteCommand, PutObjectCommand, PutObjectLockConfigurationCommand, PutPublicAccessBlockCommand, S3Client, S3ServiceException } from "@aws-sdk/client-s3";
@@ -65809,6 +65809,10 @@ var DriftDetectedError = class DriftDetectedError extends CdkdError {
65809
65809
  * a partially-failed `--revert` still exits 2 through `PartialFailureError`) --
65810
65810
  * those modes report per-resource refusals on their own paths, and changing them
65811
65811
  * would alter what a remediation run means, which is not what this closes.
65812
+ * Issue [#2208](https://github.com/go-to-k/cdkd/issues/2208) re-examined that
65813
+ * scoping and KEPT it: what those modes owed was not this exit code but an
65814
+ * honest SENTENCE, since their no-drift line claimed a clean bill of health for
65815
+ * a stack they had not read. See {@link incompleteRemediationMessage}.
65812
65816
  *
65813
65817
  * WHAT DOES NOT TRIGGER IT: a stack whose properties reference
65814
65818
  * `{{resolve:ssm-secure:...}}` still exits 0. Those properties genuinely are not
@@ -65903,6 +65907,171 @@ function outcomeExitSignal(outcome) {
65903
65907
  });
65904
65908
  }
65905
65909
  /**
65910
+ * What {@link incompleteRemediationMessage} says about each reason, and WHICH
65911
+ * CLAIM it is allowed to make about it.
65912
+ *
65913
+ * An exhaustive `Record`, for the same reason {@link notComparedReason} is one:
65914
+ * adding a cause must be a COMPILE ERROR here rather than falling into an
65915
+ * `else` that describes it as something it is not. The first cut of this
65916
+ * function had that `else`, and it was worse than a wrong default -- it
65917
+ * described any unknown cause as a dynamic-reference problem, while
65918
+ * {@link outcomeExitSignal} deliberately routes every NEW cause to the
65919
+ * incomplete side. The two together meant the next cause added would be
65920
+ * reported, at once, to the widest audience and under the wrong name. Carrying
65921
+ * `kind` in the SAME record rather than a second one beside it means a new
65922
+ * reason cannot be given a phrase while quietly inheriting a claim.
65923
+ *
65924
+ * `kind` exists because one blanket tail overclaimed. The line used to end
65925
+ * `..., so cdkd does not know whether they drifted`, which is true of a
65926
+ * throttled read and FALSE of a `Custom::*` resource -- for that one, issue
65927
+ * [#323](https://github.com/go-to-k/cdkd/issues/323)'s position is that drift is
65928
+ * not APPLICABLE, not that cdkd is uncertain. A stack with one throttle and five
65929
+ * `Custom::S3AutoDeleteObjects` would have claimed uncertainty about all six.
65930
+ *
65931
+ * The insertion ORDER is the order the phrases are emitted in, so the line is
65932
+ * deterministic without a second list to keep in sync: "not compared at all"
65933
+ * first, then the partial ones, then the two structural reasons.
65934
+ *
65935
+ * The wording splits on "was ANY of it compared", which is the same split the
65936
+ * human report's `NOT fully compared` heading makes -- a `readFailed` resource
65937
+ * is not "partially" anything.
65938
+ */
65939
+ const UNCOMPARED_REASONS = {
65940
+ readFailed: {
65941
+ kind: "unknown",
65942
+ phrase: "not compared AT ALL: the read or comparison failed"
65943
+ },
65944
+ refused: {
65945
+ kind: "unknown",
65946
+ phrase: "only PARTIALLY compared: cdkd refused to resolve a dynamic reference their state records"
65947
+ },
65948
+ unresolvedToken: {
65949
+ kind: "unknown",
65950
+ phrase: "only PARTIALLY compared: their state records a `{{resolve:...}}` spelling cdkd resolves for nobody, which no re-run can clear"
65951
+ },
65952
+ unsupported: {
65953
+ kind: "byDesign",
65954
+ phrase: "not compared AT ALL: their provider does not support drift detection yet"
65955
+ },
65956
+ skipped: {
65957
+ kind: "byDesign",
65958
+ phrase: "not compared AT ALL: cdkd does not drift-check the type"
65959
+ }
65960
+ };
65961
+ /**
65962
+ * The sentence lead each {@link UncomparedKind} group is reported under.
65963
+ *
65964
+ * Exhaustive for the same reason the record above is, and SEPARATE from it
65965
+ * because the lead is per GROUP while the phrase is per reason: writing the
65966
+ * claim into each phrase would put five copies of two sentences in the file,
65967
+ * and five copies is how two of them come to disagree.
65968
+ *
65969
+ * Insertion order is emit order, and `unknown` comes first deliberately: it is
65970
+ * the half the user can do something about.
65971
+ */
65972
+ const UNCOMPARED_KIND_LEADS = {
65973
+ unknown: "cdkd does not know whether these drifted",
65974
+ byDesign: "Not drift-checked by cdkd at all, which is a coverage limit rather than uncertainty"
65975
+ };
65976
+ /**
65977
+ * How many resources across every report ended UNCOMPARED, per reason.
65978
+ *
65979
+ * The `notCompared` population is read through {@link notComparedOutcomes} --
65980
+ * the single spelling both renderings already share -- and the other two come
65981
+ * from an exhaustive `matchOutcome`, so a new outcome variant cannot join the
65982
+ * "nothing to say about it" side by omission. That is the same guarantee
65983
+ * {@link outcomeExitSignal} carries at the exit code, applied to the count.
65984
+ */
65985
+ function uncomparedTally(reports) {
65986
+ const tally = /* @__PURE__ */ new Map();
65987
+ const bump = (reason) => {
65988
+ tally.set(reason, (tally.get(reason) ?? 0) + 1);
65989
+ };
65990
+ for (const report of reports) {
65991
+ for (const { cause } of notComparedOutcomes(report)) bump(cause);
65992
+ for (const outcome of report.outcomes) matchOutcome(outcome, {
65993
+ drifted: () => {},
65994
+ clean: () => {},
65995
+ notCompared: () => {},
65996
+ unsupported: () => bump("unsupported"),
65997
+ skipped: () => bump("skipped")
65998
+ });
65999
+ }
66000
+ return tally;
66001
+ }
66002
+ /**
66003
+ * The lines `--accept` / `--revert` print INSTEAD of `No drift detected --
66004
+ * nothing to accept.` when the run found no drift but did not manage to compare
66005
+ * everything ([issue #2208](https://github.com/go-to-k/cdkd/issues/2208)).
66006
+ *
66007
+ * MESSAGE-ONLY, and the EXIT CODE deliberately stays `0`. The remediation
66008
+ * modes' exit codes are a documented user contract -- #2108 scoped its `2` to
66009
+ * detection-only mode on purpose, and {@link DriftComparisonIncompleteError}'s
66010
+ * note says why: "changing them would alter what a remediation run means".
66011
+ * Nothing about that reasoning expired. The defect this closes is entirely in
66012
+ * what the run REPORTS: `--accept` / `--revert` already correctly leave an
66013
+ * uncompared resource alone (both iterate the drifted outcomes only, asserted
66014
+ * in `tests/unit/cli/drift-per-resource-failure.test.ts`), so the state and AWS
66015
+ * are right and only the sentence is wrong. Making the remediation path exit
66016
+ * non-zero would break the CI of everyone running `cdkd drift --accept` over a
66017
+ * stack that hits a throttle, to fix a wording problem.
66018
+ *
66019
+ * What the lines have to carry, since the exit code will not carry it: that the
66020
+ * comparison was INCOMPLETE (never that no drift was detected), HOW MANY
66021
+ * resources were not compared and WHY, WHICH of those cdkd is actually
66022
+ * uncertain about, and the pointer to the detection-only run, which is the mode
66023
+ * whose exit code does report it (`2`).
66024
+ *
66025
+ * THE TRIGGER AND THE COUNT ARE DIFFERENT POPULATIONS, deliberately, and
66026
+ * collapsing them is the defect review round 1 found here.
66027
+ *
66028
+ * - The TRIGGER is `anyIncomplete`, i.e. {@link outcomeExitSignal}'s
66029
+ * `incomplete`. It is narrow on purpose: a stack whose ONLY uncompared
66030
+ * resource holds a `{{resolve:ssm-secure:...}}` token must not start
66031
+ * shouting on every run about a comparison no action of the user's can ever
66032
+ * complete -- the same CI-forever hazard that cause is kept out of the exit
66033
+ * code on.
66034
+ * - The COUNT and the LABELS, once the line is triggered, cover EVERY
66035
+ * uncompared resource, each named by its own reason (see
66036
+ * {@link uncomparedTally}). A resource that was not compared was not
66037
+ * compared, whatever the reason, and counting only the clearable ones
66038
+ * printed `1 of 3` on a stack the report a few lines above called
66039
+ * `2 resource(s) NOT fully compared` -- two lines disagreeing about one
66040
+ * run, with the newer and quieter one being the one written to stop a
66041
+ * command from being quietly reassuring.
66042
+ *
66043
+ * WHAT `N` AND `M` ARE, stated because the alternatives are all defensible and
66044
+ * silence about the choice is what made the first cut wrong. `M` is the total
66045
+ * number of resource outcomes, and `N` is every one of them that was not
66046
+ * compared -- so `unsupported` and `skipped` land in `N`, WITH their own
66047
+ * phrase, rather than sitting only in the denominator where they would inflate
66048
+ * `M` and go unnamed. On a remediation path, erring LOUD is the correct
66049
+ * direction. Note this makes `N` deliberately WIDER than the report's
66050
+ * `NOT fully compared` heading, which counts the reference / read population
66051
+ * only and reports `drift unknown` separately: the question this line answers
66052
+ * is #2154's, "was everything actually compared", not "how many entries are in
66053
+ * that block". What being in `N` does NOT buy is a uniform claim about the
66054
+ * resource -- see {@link UNCOMPARED_REASONS}'s `kind`, and see
66055
+ * {@link UncomparedReason} for why counting a `skipped` resource here is not a
66056
+ * reversal of #323's silence.
66057
+ */
66058
+ function incompleteRemediationMessage(reports, mode) {
66059
+ const tally = uncomparedTally(reports);
66060
+ const total = reports.reduce((n, report) => n + report.outcomes.length, 0);
66061
+ const uncompared = [...tally.values()].reduce((a, b) => a + b, 0);
66062
+ const kinds = Object.keys(UNCOMPARED_KIND_LEADS);
66063
+ const reasons = Object.keys(UNCOMPARED_REASONS);
66064
+ const groups = kinds.flatMap((kind) => {
66065
+ const parts = reasons.filter((reason) => UNCOMPARED_REASONS[reason].kind === kind && (tally.get(reason) ?? 0) > 0).map((reason) => `${tally.get(reason)} ${UNCOMPARED_REASONS[reason].phrase}`);
66066
+ return parts.length === 0 ? [] : [`${UNCOMPARED_KIND_LEADS[kind]} — ${parts.join("; ")}.`];
66067
+ });
66068
+ return [
66069
+ `Comparison INCOMPLETE — nothing to ${mode}, and that is NOT a clean bill of health: ${uncompared} of ${total} resource(s) could not be compared.`,
66070
+ ...groups,
66071
+ `Re-run 'cdkd drift' without --${mode} to see which resources and why — a detection-only run exits 2 while a comparison is incomplete.`
66072
+ ];
66073
+ }
66074
+ /**
65906
66075
  * `cdkd drift [<stack>...]` command implementation.
65907
66076
  *
65908
66077
  * Three operating modes (mutually exclusive):
@@ -65979,6 +66148,10 @@ async function driftCommand(stacks, options) {
65979
66148
  return;
65980
66149
  }
65981
66150
  if (!drifted) {
66151
+ if (anyIncomplete) {
66152
+ for (const line of incompleteRemediationMessage(reports, options.accept ? "accept" : "revert")) logger.info(line);
66153
+ return;
66154
+ }
65982
66155
  logger.info(options.accept ? "No drift detected — nothing to accept." : "No drift detected — nothing to revert.");
65983
66156
  return;
65984
66157
  }
@@ -87059,4 +87232,4 @@ function buildProgram() {
87059
87232
 
87060
87233
  //#endregion
87061
87234
  export { buildProgram };
87062
- //# sourceMappingURL=program-CMiO_i__.js.map
87235
+ //# sourceMappingURL=program-DjH_cfVU.js.map