stamp: retire the HCL rewrite and module_prefix; refusal registry re-measured (#644) - #944
Merged
Conversation
The inventory this unit works from, taken at 22d9a3f before anything was deleted. WHAT THE RULING RETIRES (issue #644, ruled 2026-09-04 in #831/#825: "the stamp is retired, not split"; HANDOFF "The order" item 3). 1. The HCL rewrite in stamp.Stamp - internal/live/stamp/stamp.go (2633), perinstance.go (358), sharedbody.go (143) and 21 test files that drive it (10,285 test lines). Entry points: Stamp, Request, Result, Schemas, Skip, SkipReason and its 30-odd constants, Untagged, Stamped. Callers, all of them already dead on the default path since CHOUDOUFU_NODE_RESOLVE flipped on 2026-08-25: internal/command/live_plan.go statelessStamp (gated off at #451), statelessStampGaps, statelessNeedsDiscovery, recordBackedNeedsDiscoveryBlocks internal/command/live_mode.go the same pass on the apply path internal/command/live_policy.go statelessPolicyUntagMap and the stampRes half of statelessPolicyReport internal/live/check ALREADY off it (#454's nodestamp.go); uses only the summaries, the registry and UnmarkedDiscoveryDetail tools/refusal-probe/cause.go uses only UnmarkedDiscoveryDetail and SummaryUnmarkedApply 2. module_prefix - markers.ModulePrefixAttr / ModulePrefixRef / ModulePrefix, the evaluator arms in internal/configs/static_scope.go and internal/tofu/evaluate.go, lint's RuleReservedSymbol that reserves the symbol, and the two internal/live/passthrough refusals that describe the static evaluator refusing it. Sole writer was stamp.go's modulePrefixTemplate. Landed in a later commit on this branch. 3. LayerStamp's refusals - five of the eight retire (NoConfig, NoEstateName, NoSchemas, SharedBody, MarkerUncheckable); three stay, because internal/live/check's node-path port and internal/live/projection still raise them. refusals.go carries the per-entry reason. WHAT STAYS, AND WHY - The static evaluator does NOT retire. HANDOFF item 3 is explicit and #934 already made internal/live/staticeval the one copy; stamp's five copies (evalStatic, staticValue, staticString, staticCount, staticForEachKeys) die with stamp.go rather than being migrated. - UnmarkedDiscoveryDetail (moved to unmarked.go) and its rendered-sentence tests: two live callers, and the sentences are what an operator reads. - The taggability pin (taggability_test.go, taggability_live_test.go, taggability_survey_test.go, the 30 stamp_cohort_*_test.go files). It pins which admitted types have a settable tags map, which is the question the NODE path's markers.TagSurface asks per instance, and internal/live/harness/burndown.go cites the chain by name. - markerlessdocs_test.go and markeronlysplit_test.go: identity/row-gen guards that never called Stamp. WHAT THIS COMMIT CHANGES BEHAVIOURALLY, on the CHOUDOUFU_NODE_RESOLVE=0 opt-out only (the default path is byte-identical, because every deleted call was already gated off): - declared_tagged = "untag"'s marker suppression had no node-path equivalent and so has been inert since 2026-08-25; its unreachable implementation is deleted and named in live_policy.go's own comment. - statelessStampGaps' "Unstamped marker-only resource" plan-time error and its #364 record-backed downgrade go with it; the node path never raised either. internal/live/check still reports the same finding offline. Reference: refusal-probe -schemas at 22d9a3f over the 228-entry corpus reads sites 8247, instances 4632, blocked 193. Unmarked apply of a marker-only resource: 55 sites. Re-measured after the deletion. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018QSftBd7j3Dp4mnB6feRKL
…644) The symbol existed for exactly one reader, and that reader is gone. tofu.marker_module_prefix (markers.ModulePrefixAttr) was this fork's one addition to the language's terraform/tofu object. Issue #378 added it because a module call's several instances share ONE *hclsyntax.Body for a resource's tags argument, so no literal tofu-address in that body is right for all of them - the module-instance segment had no expression the language could interpolate, the way count.index and each.key cover a repeated resource. The HCL rewrite wrote a template over it. The node-path writer (projection.NodeResolver.AdjustConfigValue) is handed one concrete addrs.AbsResourceInstance and its already-evaluated configuration value, so it writes the escaped instance address as a plain string. There is no shared body, no template, and nothing left that reads the symbol. Deleted: internal/live/markers/modulemarker.go ModulePrefixAttr, ModulePrefixRef, ModulePrefix internal/configs/static_scope.go the GetTerraformAttr arm and its two refusals internal/configs/static_evaluator.go WithModuleInstance and the moduleInstance/moduleInstanceSet pair, which existed only to make that arm answerable internal/tofu/evaluate.go the plan-time arm internal/live/lint/reserved_symbol.go RuleReservedSymbol, the whole rule internal/live/passthrough/refusals.go the two "Marker module prefix" passthrough entries live/e2e/limits/reserved-symbol/ the rule's fixture Checked before deleting, as issue #644 asks: internal/live/lint/ module_instance_eval.go (#580) does NOT use WithModuleInstance. It rebuilds a child's var.* closure per instance through identity.ChildModuleRepetitionData and configs.StaticEvaluator's repetition axis, neither of which this commit touches. The static evaluator itself does not retire - HANDOFF "The order" item 3 is explicit, and #934 already made internal/live/staticeval the one copy. Retiring the reservation is not a loss of protection. Its whole purpose was to keep a FORK-ADDED symbol out of a configuration's hands; with the symbol gone, a configuration naming tofu.marker_module_prefix gets stock OpenTofu's own "Unsupported attribute", which is both the correct answer and the portable one. Keeping the rule would have meant refusing a configuration for naming an attribute that no longer exists. TestIdentityGolden: 0 identities changed, 0 added, 1 removed. The one removed row is live/e2e/limits/reserved-symbol's aws_s3_bucket.reserved, CONCRETE, "tofu-stateless-limits-reserved-symbol", bucket=tofu-stateless-limits-reserved-symbol - the fixture deleted above. The golden was edited by hand rather than with -update, and the test verifies the whole file including its body digest, so the result is byte-identical to what -update would have produced. Pins updated with the reason: identityGoldenPinInstances 1107 -> 1106, identityGoldenPinDirs 624 -> 623, classes CONCRETE 607 -> 606, identityGoldenPinBodyDigest, and HANDOFF.md's figure table. Regenerated: live/LIMITATIONS.md (`go run ./tools/limits-gen`), 223 refusals -> 215, 28 lint rules -> 27. Hand-written prose that described the retired mechanism was rewritten rather than deleted, in LIMITATIONS.md's "Behavioral limits", live/MARKERS.md and site/content/docs/use/compatibility.md: what a keyed module's marker IS did not change, only how it comes to be written. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018QSftBd7j3Dp4mnB6feRKL
Deleting the HCL rewrite left the opt-out with no marker writer at all.
Before this branch, CHOUDOUFU_NODE_RESOLVE=0 selected two things at once:
the static identity path AND internal/live/stamp's configuration rewrite.
The flag's own doc comment says so. With the rewrite gone, an opted-out run
would have wired neither writer - ConfigValueAdjuster nil, no stamping
anywhere - and created every resource with no tofu-estate and no
tofu-address on it. Silently, and unrecoverably for any instance a marker
is the only handle on. That is HANDOFF's "never write a wrong marker"
pointed at the write side, and it is not something this unit is allowed to
introduce as a side effect of a deletion.
So the two halves are separated. [projection.NodeResolver] is constructed
and populated for every run and installed as tofu.ConfigValueAdjuster
unconditionally; the flag now governs only what it always named, whether
identity RESOLUTION goes through tofu.ResourceIdentityResolver. The fields
only the identity path reads (RecordStore, MarkerIndex, NoSourceCreate,
Unowned) are set either way and are simply never read by an opted-out run,
because it never installs the method that reads them.
Two call sites keyed off "resolver != nil" as a stand-in for the flag and
had to move to nodeResolveEnabled(), because that expression is now always
true:
- live_plan.go's identity.DowngradeForNodeResolution. Caught by
TestLivePlan_identityFatal's own opt-out subtest going from exit 1 to
exit 0: the static evaluator's "Identity argument not set" stopped
being fatal and the run planned a CREATE for an instance nothing had
identified. Exactly the failure that subtest exists to catch, caught
by it. live_mode.go's copy already read r.nodeResolve and was right.
- live_plan.go's recordShrinkStore (#388 edge 3), whose whole contract
is that a flag-off run sees a byte-identical marker-sweep demand.
TestStatelessBegin_nodeResolveOptOut is rewritten to pin the new contract
on both sides - identity path off, writer on - and it asserts the writer by
VALUE (resolver.Estate is populated) rather than by presence, because
AdjustConfigValue writes nothing when Estate is empty and a constructed
but unpopulated resolver would stamp exactly as little as no resolver at
all. Proved red: re-gating the population block on r.nodeResolve fails it
with "the resolver was constructed but never given an estate name".
go test ./internal/command/: ok, 65.6s.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018QSftBd7j3Dp4mnB6feRKL
TestGodocCitationsResolve (internal/live/docrefs) named ten of them: [stamp.Stamp] x7, [stamp.Request], [stamp.SkipReason.Unknown] x2, all in internal/live/check, all pointing at symbols this branch deleted. Rewritten rather than mechanically de-bracketed, because each was doing real work in its comment: nodestamp.go's own doc comment is #454's argument for why the port reports the same thing the rewrite did, and it now reads as the record of a completed retirement instead of a pending one. catalog.go's LayerStamp comment names [nodeStampDiagnostics] as what actually computes the section. stamp.go's syntheticStampEstate argument - that a synthetic estate name cannot manufacture a marker-conflict finding - is unchanged in substance and now cites the functions that implement it. stamp_gate_test.go's #230 invariant now cites nodeStampUnmarkedApply's !hasSchema arm, which is where the rule lives. go test ./internal/live/...: ok. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018QSftBd7j3Dp4mnB6feRKL
The one exemption in nodeStampUnmarkedApply had no test of its own once the stamp package's went with the engine. A resource whose instances can only be found by their ownership marker is refused when its type has nowhere to write one. identity.DiscoveryUniqueName is exempt: AWS itself refuses to issue the name the configuration states twice, so the object is findable in a listing with no marker, and refusing it would refuse every apply of the population GitHub issue #272 admitted. internal/live/check's port (nodestamp.go, #454) implements the exemption - `mustStamp := !disco.Cause.BindsByName()` - and until now the only test that would have caught its removal was internal/live/stamp's TestUnmarkedDiscoveryDetail_uniqueNameIsNotRefused, which drove the deleted HCL-rewrite engine. TestStampGate_UniqueNameCauseIsExemptFromTheUnmarkedApplyRefusal is that guard, on the surviving path, asserted on the rendered finding rather than on a predicate. Its negative control is in the same fixture, the same run and the SAME TYPE: two aws_cloudfront_cache_policy instances, one stating its documented account-unique name (cause UNIQUE_NAME, must not be refused) and one omitting it (the provider mints the whole identity, must be refused). One schema serves both, so the only difference between them is the cause resolution assigned - a port that stopped reading the cause fails the first assertion and one that stopped refusing anything fails the second. Proved red: forcing `mustStamp := true` fails it with the exempt resource's own site quoted. Restored, it is green. The first draft used aws_cloudfront_origin_access_control as the negative control (the type TestStampGate_GenuinelyUntaggableTypeStillRefuses uses) and the control never fired: that type is markerless-vetoed at LayerLint and never reaches the stamp layer at all. The test said so rather than passing, which is why the control is there. TestIdentityGolden: 2 ADDED rows, 0 changed, 0 removed - the fixture's two instances, both NEEDS_DISCOVERY, both rendering nothing, which is what a server-assigned type renders in this sweep. Combined with the removal in de01425d29, this branch's net golden movement is 1107 -> 1108 instances and 624 -> 624 directories, 0 identities changed. Pins and HANDOFF.md updated with both halves named; the golden itself was edited by hand, never with -update, and the test verifies the file including its body digest. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018QSftBd7j3Dp4mnB6feRKL
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The shared-layer re-measure of the core set has NOT been run. No
gauntlet run, no emulator, no change tolive/gauntlet.jsonor therendered progress pages, on the maintainer's instruction mid-unit. This PR
is the code half of #644 only, and it must not merge as progress until the
core set is re-measured by the nightly or a later pass. Everything below is
measured with instruments that need no cloud.
Closes the code half of #644.
The unit
Issue #644, ruled 2026-09-04 in the refactor-1500 epic (#831, see #825):
the stamp is retired, not split, once the
live_plan.gosplit (#819) hasmerged. #819 is closed. HANDOFF "The order" item 3 names the three pieces:
the HCL-rewriting stamp,
module_prefix, and LayerStamp's refusals - andsays explicitly that the static evaluator does not retire.
929 insertions, 12,109 deletions across 59 files; the stamp package
itself goes from 15,758 lines across 62 files to 5,593 across 39.
Inventory: what the ruling retires
1. The HCL rewrite.
internal/live/stamp/stamp.go(2633),perinstance.go(358),sharedbody.go(143), and the 21 test files thatdrive them.
Stamp,Request,Result,Schemas,Skip,SkipReasonand its constants,
Untagged,Stamped, and the wholestampertype:markerObject,addressExpr,forEachLookupAddressExpr,splitAddressMarker,templateChunkMarkers,chunkCount,slotExpr,tagsWrite,mergeEntries,verify/verifyValue,mustStamp,unstampable/unstampableAt,privateBody,moduleResources,childExpansion. Every one of them was already dead on the default path:#451 gated the pass off entirely when
CHOUDOUFU_NODE_RESOLVEis on, whichit has been by default since 2026-08-25.
Its five copies of the config-subset evaluator (
evalStatic,staticValue,staticString,staticCount,staticForEachKeys) die withit rather than migrating to
internal/live/staticeval- the copies #934deliberately left for this unit.
Callers, all updated:
live_plan.gostatelessStampstatelessMarkerEstate- the warnings onlylive_plan.gostatelessStampGapslive_plan.gostatelessNeedsDiscovery,recordBackedNeedsDiscoveryBlockslive_mode.golive_policy.gostatelessPolicyUntagMap,statelessPolicyReport'sstampResdeclared_tagged = "untag"'s released keysinternal/live/checknodestamp.go)UnmarkedDiscoveryDetailtools/refusal-probe/cause.goUnmarkedDiscoveryDetail,SummaryUnmarkedApply2.
module_prefix.markers.ModulePrefixAttr/ModulePrefixRef/ModulePrefix(internal/live/markers/modulemarker.go); theGetTerraformAttrarms ininternal/configs/static_scope.goandinternal/tofu/evaluate.go;configs.StaticEvaluator.WithModuleInstanceand the
moduleInstance/moduleInstanceSetpair that existed only to makethat arm answerable; lint's
RuleReservedSymbol(
internal/live/lint/reserved_symbol.go) and its fixture; the twointernal/live/passthrough"Marker module prefix" entries.The symbol existed for exactly one reader. A module call's several instances
share one
*hclsyntax.Body, so #378 wrote a template over${tofu.marker_module_prefix}because a configuration rewrite had no otherway to produce a different address per instance.
NodeResolver.AdjustConfigValueis handed one concreteaddrs.AbsResourceInstanceand writes the escaped address as a plainstring.
Read before deleting, as the issue asks:
internal/live/lint/module_instance_eval.go(#580) does not use
WithModuleInstance. It rebuilds a child'svar.*closure per instance through
identity.ChildModuleRepetitionDataand thestatic evaluator's repetition axis, neither of which this PR touches.
Retiring the reservation is not a loss of protection: its purpose was to
keep a fork-added symbol out of a configuration's hands, and with the symbol
gone a configuration naming it gets stock OpenTofu's own "Unsupported
attribute", which is both correct and portable. Keeping the rule would mean
refusing a configuration for naming an attribute that does not exist.
3. LayerStamp's refusals. Five of eight retire, three stay:
No configuration to stampRequeststruct. There is noRequest.No estate name to stamp withNo provider schemas for marker stampingTwo resources share one configuration body*hclsyntax.Body(#280). The node path is called once per concrete instance with its own value and rewrites no body; structurally absent, not merely unmeasured.Ownership marker could not be checkedOwnership marker conflict, an agreeing one is a no-op.Ownership marker conflictinternal/live/projection(SummaryMarkerConflict, matched text by construction) and surfaced under LayerStamp by check's port.Ownership markers not stampednodeStampUnmarkedApply, and bystatelessMarkerEstate's three no-estate warnings.Unmarked apply of a marker-only resourcenodeStampUnmarkedApply. 55 corpus sites.The registry stays in
internal/live/stampunderRaisedByStamp, becausethat is the layer a reader of
live/LIMITATIONS.mdlooks the refusal upunder.
refusals.gocarries the per-entry account above.What stays, and why
is the estate-wide demand computation live-import, live-mv, live-check,
discovery and the instruments all consume.
UnmarkedDiscoveryDetail(moved tounmarked.go) and itsrendered-sentence tests. Two live callers, and the sentences are what an
operator reads.
discoverycause_test.gonow drives it directly instead ofthrough the deleted engine, keeping every wording assertion.
taggability_test.go,taggability_live_test.go,taggability_survey_test.goand the 30stamp_cohort_*_test.gofiles. It pins which admitted types have asettable tags map, which is the same question the node writer's
markers.TagSurfaceasks per instance, andinternal/live/harness/burndown.gocites the chain by name.markerlessdocs_test.goandmarkeronlysplit_test.gonever calledStampat all.What this removes that was not already dead
Two things, both already inert on the default path before this PR, both
named rather than dropped quietly:
declared_tagged = "untag"'s marker suppression. It lived only inthe HCL rewrite (
stamp.Request.PolicyUntag), and the node writer has noequivalent, so it stopped happening on 2026-08-25 when
CHOUDOUFU_NODE_RESOLVEdefaulted on. The view'sUntaggedsection hasbeen empty for a fortnight. Porting it to
AdjustConfigValueis realwork with its own decision (a per-instance withhold, not a per-block one)
and is not this issue's;
live_policy.gocarries the note.statelessStampGaps' plan-time "Unstamped marker-only resource"error and its foundation: a universal per-instance record, so every type stock supports is admitted and rung is a metric #364 record-backed downgrade. The node path never raised
either.
internal/live/checkstill reports the same finding offline, atthe same 55 sites.
The safety fix this deletion forced
Deleting the rewrite left
CHOUDOUFU_NODE_RESOLVE=0with no markerwriter at all -
ConfigValueAdjusternil, nothing stamping, everyresource created with no
tofu-estateand notofu-address. Silently. Theflag used to select two things at once, and only one of them still exists.
So the halves are separated (619a1f8):
NodeResolveris built,populated and installed as
tofu.ConfigValueAdjusterfor every run; theflag governs only what it always named, whether identity resolution goes
through
tofu.ResourceIdentityResolver. Two call sites usedresolver != nilas a stand-in for the flag and had to move tonodeResolveEnabled(), because that expression is now always true:identity.DowngradeForNodeResolution. Caught byTestLivePlan_identityFatal's own opt-out subtest going exit 1 -> exit 0:the static "Identity argument not set" stopped being fatal and the run
planned a CREATE for an instance nothing had identified. Exactly the
failure that subtest exists to catch, caught by it.
recordShrinkStore(foundation: the plan-node seam - identity resolved and markers stamped at NodePlannableResourceInstance from stock's evaluated values; the static evaluator and the HCL stamp retire #388 edge 3), whose contract is that a flag-off runsees a byte-identical marker-sweep demand.
Five-row table
=0would have had no marker writerdeclared_tagged = "untag"has no node-path equivalentThe generic rule, and how many types it reaches
Zero hand-wired type names were added or removed in control flow. The
retired mechanism was never per type:
mustStampreadsidentity.DiscoveryCause, taggability readsmarkers.Taggable/markers.TagSurfaceoff the provider schema, and the module-prefix templatewas a property of module expansion, not of any resource type. The rule
that replaces the whole thing - "write the marker from the instance address
you already have" - reaches every admitted type: 1,699 rows in
identity.DefaultTable, of which the taggable population is what thesurviving pin in
taggability_test.gocovers.live/derivation_guard_test.go's registry is unchanged, and correctlyso: it excludes
_test.gofiles, and every type literal this PR deletes oradds is in a test fixture or a pinned test table. Verified green.
Refusal registry, re-measured
refusal-probe -schemas -allow-partial-corpus, both runs in this worktree,before at
22d9a3f099and after at0baf59209a.The issue's baseline of
sites 10363, instances 4912, blocked 203at5f2402e95adoes not reproduce, and not because of this change: thecorpus manifest has moved since (228 entries reachable here, against the
250/259 the older figures were taken over, and 5 manifest sources whose
globs match a repository root with no top-level configuration). The new
baseline, measured at
22d9a3f099before a line was deleted, issites 8247, instances 4632, blocked 193, 228 entries. Both runs arepartial in the identical way, which is what
-diffchecks before it willcompare them.
Per entry, not aggregate - all 27, no entry got worse and none moved at
all:
The eight registry entries this PR deletes measured zero sites in the
before run and so appear in neither column: the five stamp caller-error
and rewrite-mechanism refusals,
reserved-symbol, and the twoMarker module prefixpassthrough entries.Unmarked apply of a marker-only resource- the one nonzero stamp entry - is unchanged at 55, which is thenumber that had to hold.
live/LIMITATIONS.mdregenerated (go run ./tools/limits-gen): 223refusals -> 215, 28 lint rules -> 27.
TestIdentityGolden
It moved, by exactly two operations, and neither is a changed identity.
0 identities changed across the branch. Never
-update: the golden wasedited by hand and the test verifies the whole file including its body
digest, so the result is byte-identical to what
-updatewould havewritten.
1 removed:
live/e2e/limits/reserved-symbolaws_s3_bucket.reserved,CONCRETE,
tofu-stateless-limits-reserved-symbol,bucket=tofu-stateless-limits-reserved-symbol. That directory existed onlyto give
RuleReservedSymbolsomething to refuse; the rule retires, andTestLimitsDirsMatchTablerequires everylive/e2e/limitsdirectory to mapto a rule, so the fixture goes with it. A bucket's identity is its own
bucketargument, which the retired symbol never touched.2 added:
internal/live/check/testdata/stamp-uniquename-exemptaws_cloudfront_cache_policy.exemptand.refused, both NEEDS_DISCOVERY,both rendering nothing - which is what a server-assigned type renders
in this sweep, and the point of the fixture is that the two differ by
cause, not by identity.
Net: instances 1107 -> 1108, dirs 624 -> 624, CONCRETE 607 -> 606,
NEEDS_DISCOVERY 411 -> 413. Pins, the body digest and HANDOFF.md's figure
table all updated with the reason attached.
Assertions on rendered identities, never on a predicate
internal/live/stamp/discoverycause_test.gokeeps every one of itssentence assertions on the string
UnmarkedDiscoveryDetailreturns, oneper
identity.DiscoveryCause, including the "six distinct sentences"check that catches a switch falling through.
TestStampGate_UniqueNameCauseIsExemptFromTheUnmarkedApplyRefusal(new)asserts on the rendered finding, not on
BindsByName(). It replacesthe exemption half of the deleted
TestUnmarkedDiscoveryDetail_uniqueNameIsNotRefused, which had been theonly test that would have caught the exemption's removal.
forcing
mustStamp := trueinnodeStampUnmarkedApplyfails theexemption test with the exempt resource's own site quoted; re-gating the
resolver population on
r.nodeResolvefailsTestStatelessBegin_nodeResolveOptOutwith "the resolver was constructedbut never given an estate name".
The exemption test's first draft used
aws_cloudfront_origin_access_controlas its negative control and the control never fired - that type is
markerless-vetoed at LayerLint and never reaches the stamp layer. The test
said so rather than passing green, which is why the control is now the same
type on both sides: two
aws_cloudfront_cache_policyinstances, one statingits documented account-unique name and one omitting it, one schema serving
both, so the only difference is the cause.
Tests
TestGodocCitationsResolvecaught ten citations naming deleted symbols andthey were rewritten rather than de-bracketed (e070707).
Reproduce
Not done, and why
maintainer mid-run.
live/gauntlet.jsonand every rendered progress pageare untouched on this branch. The board line is whatever
7841ac337f(gauntlet: carry plan_approval to the remaining 25 estates so stage 12 can be flipped active #903's 27-estate re-measure withplan_approvalactive)plus
d8d7c84e87(gauntlet: reference-ec2-vpc day2_crash regressed; destroying a deposed object records no tombstone, so its lingering tag is a second claimant #938'sreference-ec2-vpc/day2_crashfail -> pass)left it at; this PR moves neither, and no claim about it is made here.
Do not merge this as progress until that re-measure runs.
declared_tagged = "untag"'s node-path port, above.🤖 Generated with Claude Code
https://claude.ai/code/session_018QSftBd7j3Dp4mnB6feRKL