AUR-583: architecture guards cover internal/
Measured before (base 64a8bfc1, then main 9c685fde with AUR-581)
internal/gateimportedinternal/renderin six files (analysisdata.go, dtrack.go, policy.go, result.go, scanner.go, sources.go) forrender.AuditFinding,AuditException,AnalysisDataAudit;internal/render/audit.goimportedinternal/configforPolicyDigest(policyDir, *config.Config)andconfig.DefaultConfigPath.internal/config/dtrack.goimportedinternal/dtrackforAsClientThresholds(only caller:internal/gate/dtrack.go, which runsdtrack.Run) and forValidateHost(parse-time refusal of an insecure host).internal/configdoes not rundtrack.Runitself.internal/config/wrap.goimportsinternal/llm.WrapProviderWithWarningshas no production caller after AUR-579, butconfig.WrapProvideris still called by finished acceptance scripts and tests:tests/acceptance/AUR-452.sh,AUR-468.sh,AUR-479.sh;tests/unit/AUR-452.go,AUR-468.go,AUR-479.go;tests/integration/AUR-468.go,AUR-479.go;internal/review/prompt_golden_test.go;internal/config/provider_pending_test.go. Comments naming it live incmd/aurumcode/policygate.go,review_cache.go,main.goandaur513_test.go(outside this card's paths).ApplyCentralPolicycopied each section by hand (124 lines); a new field ofConfigwas, by omission, the repository's.- Contributors wrote
*res = dand restoredReason/Trail/AnalysisDataby hand;MergeDTrackGateduplicatedResult.Merge.FoldSourcesno longer existed. len(text)/4in internal/prompt/estimator.go, internal/llm/estimator.go and internal/context/skills/skills.go; skill front matter parsed by hand (skills.go,parseFrontMatter/yamlScalar/yamlList).renderSlot(internal/prompt/slots.go) panicked on a template error.- The 150-line and card-name guards covered only
cmd/aurumcode. The exit ladder guard recognized onlyexit*identifiers; the engine guard only string literals. No function ofinternal/orpkg/exceeded 150 lines (measured with go/ast).
What changed
internal/gate/facts(facts.go):AuditFinding,AuditException,AnalysisDataAudit(same fields and JSON tags).internal/renderkeeps them as type aliases, so its API and the serialized audit are unchanged;internal/gateusesfacts.*and no longer importsrender. (A first version put them inpkg/types; moved becausepkgis outside the card's paths.)config.(*Config).PolicyDigest(policyDir)(internal/config/policydigest.go) holds the digest, nil-safe;render.PolicyDigest(policyDir, PolicySource)takes any value with that method (a typed or untyped nil gives ""), sorenderno longer importsconfigand callers are unchanged.- The Dependency-Track threshold conversion moved to
internal/gate/dtrack.go(clientThresholds);configkeeps onlydtrack.ValidateHost, declared as a symbol exception in the layer table. internal/config/governance.go:governedSections(key, rule) in warning order,reviewPolicyFields/reviewRepositoryFields,qualityGateSections.ApplyCentralPolicywalks the table (14 lines;GenerateReviewWithContextis 21).governance_test.goreflects overConfig,ReviewConfigandQualityGatesConfigand fails for an unclassified field, a classification of a field that does not exist, or a double classification.gate.Contributor.Apply(ctx, run, prior Result) (Result, error): each contributor returns its partial decision andPipeline.Runmerges it (Result.Merge, which now also carries anAnalysisDatafact).MergeDTrackGateremoved. The policy-skills partial clears its reason (the run's reason is already in the result), so no reason is joined twice.tokens.Estimate(internal/llm/tokens) is the one heuristic;prompt.HeuristicEstimator,llm.heuristicTokens(never below 1, as before) andskills.EstimateTokensdelegate to it.- Skill front matter is decoded with
gopkg.in/yaml.v3(already a dependency): a list, a block list or a comma-separated scalar; unknown keys ignored; malformed YAML is an error naming the file (fail closed; it used to be read leniently). renderSlotnever panics: a failed slot renders a NUL-delimited failure mark;BuildPromptandFixedOverheadTokensrefuse a prompt that carries one, with the slot name and cause. Signatures (and the anchors finished acceptance scripts edit) are unchanged.docs/architecture.md: new "Layers" table (the test's source), the configuration-section and contributor extension points, the guard list.cmd/aurumcode/structure_test.go:TestImportsFollowLayerTable(reads the table; a file exception or symbol exception that matches nothing fails),TestNoFunctionExceedsLineLimitAnywhereandTestNoProductionFileNamedByCardAnywhereover cmd, internal and pkg,TestReviewSourcesReturnNoGateExitCode(named constants, anygate.Exit*selector, the literal value ofgate.ExitFindings; literals 1 and 2 stay legal because each early exit keeps its own code),TestNoEngineBranchInGateOrCmdByAnyName(literal, named constant, map key, index).
Proof
All in the shared container (.board/bin/go-shared).
go vet ./... && go test -p 1 ./...: rc=0.bash tests/acceptance/AUR-583.sh all:AUR-583/all/pass. Mutations, each compiling and RED by assertion:- MUT-001 (
internal/gate/result.goimports render):internal/gate/result.go imports internal/render (internal/gate must not import internal/render). - MUT-002 (
Telemetry string yaml:"telemetry"in Config):Config.telemetry has no central-policy classification. - MUT-003 (150 lines into ApplyCentralPolicy):
functions over 150 lines: internal/config/central.go: ApplyCentralPolicy (164). - MUT-004 (
return 3, trueinprReview.generateReview):review sources returning a gate exit code ... [review_pr_generate.go:65 prReview.generateReview]. - MUT-005 (
map[string]int{mutEngine: 1}withconst mutEngine = "semgrep"in gate):../../internal/gate/result.go: an engine name as a map key. - AC-004: the audit/SARIF/report tests (AUR-521, AUR-568, AUR-577) pass, and
the 17 tutorials were re-run with this tree's image
(
AURUMCODE_TUT_IMAGE=aurum-tutoriais:aur583);run.sh --checkpasses for every one againstexpected/recorded before the refactor, which was not re-recorded. Theout/diffs are timestamps, the analysis-data tag and the interleaving of stdout and stderr, which differs between two runs of the same image. - Regression aceites, each rc=0: AUR-521, 565, 570, 576, 577, 578, 579, 580,
581 end in
all/pass; AUR-568 ends inAUR-568/all/ok; AUR-561..564 end in their last mutation line (AC-002-MUT-001/ok).
Left out
config ↛ llm:wrap.gostays (file exception in the table) until the finished acceptance scripts above stop callingconfig.WrapProvider.internal/gatestill receives*config.Config(inRunand several sources); narrowing it is a rewrite of the gate's inputs, not done here.