diff --git a/docs/roadmap/audit-remediation.md b/docs/roadmap/audit-remediation.md new file mode 100644 index 0000000..85fd6b2 --- /dev/null +++ b/docs/roadmap/audit-remediation.md @@ -0,0 +1,603 @@ +# Repository Audit Remediation Roadmap + +Status: Ready for implementation. + +## Purpose And Authority + +This roadmap translates the confirmed findings in the +[repository audit ledger](audit.md) into dependency-ordered implementation +stages. The ledger owns discovery evidence and final finding disposition. This +document owns remediation scope, ordering, locked behavior, verification, and +completion state until the work is finished. + +All 74 confirmed findings are accepted for remediation. None is priority- +deferred and none requires a separate product or architecture decision before +work can begin. Four rejected standalone findings remain consolidated into +their confirmed owners and are not separate work items. + +This roadmap describes future work. Until an individual stage is implemented, +canonical current-state documentation and executable behavior remain +authoritative. + +## Implementation Rules + +Every stage must: + +- read `docs/development.md`, all files under `docs/policy/`, this roadmap, and + the task-specific canonical documents identified below; +- implement only its listed findings and prerequisites; +- preserve the architecture policy's stateless pipeline, adapter boundaries, + curated prompt boundary, operator-owned outputs, comparison ordering, and + notification rules unless the stage explicitly corrects that contract; +- add durable tests at the narrowest stable boundary and avoid duplicating + behavior already owned elsewhere; +- update every listed canonical documentation owner in the same change as an + implemented contract change; +- use deterministic, offline, credential-free tests and synthetic fixtures; +- run `gofmt` on changed Go files, the stage's focused commands, + `GOWORK=off go test -count=1 ./...`, and `git diff --check`; and +- commit the completed stage separately when the implementing prompt requests + commits. + +Stages affecting concurrent execution, cancellation, filesystem mutation, or +process-global state must also run the affected packages with `-race`. No stage +may weaken a safety invariant merely to make a test pass. + +## Priority And Finding Allocation + +Each confirmed finding appears exactly once below. Priority describes +remediation order, not confidence; every listed finding has high confidence. + +| Priority | Stages | Findings | Decision | +| --- | --- | --- | --- | +| P0: generated forecast integrity | 1 | `AUD-029`, `AUD-030`, `AUD-031`, `AUD-033` | Accepted now | +| P1: security, correctness, and data integrity | 2-22 | `AUD-002` through `AUD-021` excluding rejected `AUD-022`; `AUD-023` through `AUD-028`; `AUD-034` through `AUD-038`; `AUD-040` through `AUD-058`; `AUD-073`, `AUD-074`, `AUD-077`, and `AUD-078` | Accepted now | +| P2: deterministic test and operational quality | 23-27 | `AUD-059` through `AUD-062`, `AUD-064`, `AUD-065`, and `AUD-066` | Accepted now | +| P3: behavior-preserving consolidation and cleanup | 28-32 | `AUD-039`, `AUD-067` through `AUD-072` | Accepted now | +| P4: documentation lifecycle and audit retirement | 33-35 | `AUD-075` and `AUD-076`; final audit-record retirement | Accepted now | + +Rejected `AUD-001`, `AUD-022`, and `AUD-032` are represented only through +`AUD-072`; rejected `AUD-063` is represented only through `AUD-039`. + +## Remediation Stages + +### Stage 1: Correct The Curated Prompt Package Contract + +- Findings: `AUD-029`, `AUD-030`, `AUD-031`, `AUD-033`. +- Affected areas: `internal/promptinput`, shared embedded prompt assets, and + focused prompt-input/prompt-asset tests. +- Work: remove raw transport-shaped warning details from provider input; make + shared prompt paths match serialized YAML; describe regional versus point- + matched hazard products accurately; and cover stanza serialization failure. +- Locked behavior: deterministic category/stanza order, exact prompt identity, + safe normal diagnostics, and byte-stable valid YAML remain unchanged. +- Documentation owners: `docs/internal/prompt-input.md` and + `docs/integrations/promptkit.md` if their implemented contract changes. +- Exit commands: focused tests for `./internal/promptinput` and + `./internal/promptassets`, then the standard repository commands. + +### Stage 2: Make Configuration Validation Atomic And Explicit + +- Findings: `AUD-004`, `AUD-006`, `AUD-007`, `AUD-078`. +- Affected areas: `internal/config`, report-key lookup, timezone parsing, + maintained examples, and configuration tests. +- Work: reject unsupported missing-source keys; make programmatic report + overrides obey the same presence semantics as loaded configuration; apply + secrets only after the complete load succeeds; and document accepted report- + key normalization and numeric-offset bounds. +- Locked behavior: file/CLI precedence, inactive-integration policy, exact + command-name lookup, and secret redaction remain unchanged. +- Documentation owners: `docs/config.md` and maintained examples only where + executable behavior requires them. +- Exit commands: `GOWORK=off go test -race -count=1 ./internal/config + ./internal/cli`, followed by the standard repository commands. + +### Stage 3: Require Complete Single-Report Notification Identity + +- Findings: `AUD-005`. +- Affected areas: Distributor notification configuration, bundle-ID rendering, + and focused config/app tests. +- Work: reject enabled single-report notification configurations that can + produce blank required identity fields before report work begins. +- Locked behavior: inactive notification settings remain optional; configured + templates and publication-before-notification ordering remain intact. +- Documentation owners: `docs/config.md`, `docs/operations.md`, and Distributor + integration docs if accepted values or failures change. +- Exit commands: focused config and app notification tests, then the standard + repository commands. + +### Stage 4: Correct CLI Cancellation, Preflight, And Visible Contracts + +- Findings: `AUD-008`, `AUD-009`, `AUD-010`, `AUD-074`. +- Affected areas: `cmd/weatherreporter`, `internal/cli`, assembled CLI tests, + help text, and CLI documentation. +- Work: propagate process interrupts through action contexts; validate report + dates before executor construction; add representative generate and batch + result/exit tests; and align help/internal guidance with quiet, date, and + comparison behavior. +- Locked behavior: command/flag ownership, structured summary shapes, stream + separation, and one executor per action remain unchanged. +- Documentation owners: `docs/cli.md` and `docs/internal/cli.md`. +- Exit commands: `GOWORK=off go test -race -count=1 ./internal/cli + ./internal/app ./cmd/weatherreporter`, both root and comparison help commands, + then the standard repository commands. + +### Stage 5: Harden The Weather API Transport Boundary + +- Findings: `AUD-011`, `AUD-012`, `AUD-013`, `AUD-014`, `AUD-015`. +- Affected areas: Weather API configuration/adapter, normalized hourly data, + local HTTP fixtures, and collection tests. +- Work: accept only supported endpoint forms; bound and redact non-success + diagnostics; reject rather than truncate oversized bodies; require usable + hourly time bounds; and retry warmup only for transient failures. +- Locked behavior: all eight source contracts, checked-empty optional products, + cancellation, provenance, and offline testing remain intact. +- Documentation owners: `docs/config.md`, + `docs/integrations/weatherapi.md`, `docs/internal/weather-data.md`, and + `docs/internal/collect.md` as applicable. +- Exit commands: focused adapter/collection tests including boundary-size and + cancellation cases, then the standard repository commands. + +### Stage 6: Correct Civil-Time And Forecast Derivation Boundaries + +- Findings: `AUD-002`, `AUD-003`, `AUD-016`, `AUD-017`, `AUD-018`, `AUD-019`. +- Affected areas: `internal/timeutil`, `internal/report`, `internal/forecast`, + `internal/facts`, and their focused tests. +- Work: construct configured clocks as local civil times across DST; protect + Daily run-ID uniqueness; preserve units in fallback values; include the full + overnight alert interval; reject invalid precipitation percentages; and + classify ordinary icy wording consistently. +- Locked behavior: half-open selection, chronological ordering, rolling Hourly + elapsed time, and source-period identity remain unchanged. +- Documentation owners: `docs/internal/report-registry.md`, + `docs/internal/forecast-derivation.md`, and `docs/internal/facts.md`. +- Exit commands: focused time/report/forecast/facts tests with both DST + transitions and metric cases, then the standard repository commands. + +### Stage 7: Correct Source-Facing Briefing Module Semantics + +- Findings: `AUD-020`, `AUD-021`. +- Affected areas: briefing module option validation, weather-story construction, + module registry tests, and normalized source fixtures. +- Work: make accepted AFD option shapes constructible and omit semantically + empty weather stories instead of publishing false availability. +- Locked behavior: report support, default compositions, checked-empty alerts, + and ordered module snapshots remain unchanged. +- Documentation owners: `docs/internal/module.md` and + `docs/internal/briefing.md`. +- Exit commands: focused briefing/module tests, then the standard repository + commands. + +### Stage 8: Correct Derived Briefing Language And Ranking + +- Findings: `AUD-023`, `AUD-026`, `AUD-027`. +- Affected areas: derived daily summaries, outdoor-window scoring, temperature + band wording, and briefing tests. +- Work: label apparent temperature accurately; include snow, ice, and fog in + outdoor-window ranking; and preserve negative-zero temperature meaning. +- Locked behavior: deterministic ranking, Today-only planning scope, and + existing module/schema identities remain unchanged. +- Documentation owners: `docs/internal/briefing.md` and prompt-facing field + documentation if names or meaning change. +- Exit commands: focused briefing tests with metric, subzero, and hazard cases, + then the standard repository commands. + +### Stage 9: Establish One Daypart Canonicalization Mechanism + +- Findings: `AUD-067`. +- Affected areas: duplicated canonical-key helpers in briefing and + generated-text packages plus their behavior tests. +- Work: establish one domain-owned canonical key contract and route both + current consumers through it without changing accepted ASCII behavior. +- Locked behavior: display labels, report-specific semantic roles, ordering, + and current valid output remain unchanged. +- Documentation owners: focused internal briefing/generated-text docs only if + ownership needs explanation. +- Exit commands: focused briefing and generated-text tests, then the standard + repository commands. + +### Stage 10: Correct Daypart Identity, Collision, And Display Behavior + +- Findings: `AUD-024`, `AUD-025`, `AUD-073`. +- Affected areas: derived daypart summaries, planning builders, display + capitalization, configuration fixtures, and rendering tests. +- Work: reject canonical-key collisions; use configured identities consistently + across planning; and make non-ASCII display capitalization rune-safe. +- Locked behavior: Stage 9's canonical identity remains separate from display + text; stable ordering and default dayparts remain unchanged. +- Documentation owners: `docs/config.md`, `docs/internal/briefing.md`, and + generated-text/template docs if visible labels change. +- Exit commands: focused config/briefing/generated-text/reporttemplate tests, + then the standard repository commands. + +### Stage 11: Refresh The Official SPC Definition Asset + +- Findings: `AUD-028`. +- Affected areas: embedded SPC category definitions, source attribution, and + risk-digest tests. +- Work: reconcile descriptions with the current authoritative SPC table and + record a durable source/review mechanism without changing risk thresholds + accidentally. +- Locked behavior: deterministic category ordering, threshold selection, and + overlap logic remain unchanged unless current official semantics require an + explicit reviewed correction. +- Documentation owners: `docs/internal/briefing.md` or another single + canonical maintainer owner for the external definition source. +- Exit commands: focused briefing asset/risk tests, then the standard + repository commands. + +### Stage 12: Secure Prompt-Debug Redaction And Filesystem Traversal + +- Findings: `AUD-034`, `AUD-035`. +- Affected areas: `internal/promptdebug`, Promptkit debug callbacks, endpoint + redaction, filesystem operations, and adversarial tests. +- Work: redact common credential aliases and URL credential forms; replace + pathname check/use gaps with a race-resistant secure creation strategy. +- Locked behavior: debug remains explicit opt-in with `0700` directories, + `0600` files, deterministic references, and no sensitive normal output. +- Documentation owners: `docs/operations.md` and + `docs/integrations/promptkit.md`. +- Exit commands: focused promptdebug/Promptkit tests plus + `GOWORK=off go test -race -count=1 ./internal/promptdebug + ./internal/adapters/promptkit ./internal/app`, then standard commands. + +### Stage 13: Enforce Generated-Text Identity, Shape, And Size + +- Findings: `AUD-036`, `AUD-037`, `AUD-038`. +- Affected areas: generated-text catalog, decoders, schemas, typed validators, + Promptkit result handling, and focused tests. +- Work: require report-specific schema/template pairs; reject case-variant + properties that schemas reject; and bound prose, arrays, and diagnostic + context before allocation or normal error projection. +- Locked behavior: typed normalization, exact registered identities, schema + copy isolation, and valid generated content remain unchanged. +- Documentation owners: `docs/internal/generatedtext.md`, template docs, and + Promptkit integration limits where externally relevant. +- Exit commands: focused generated-text/promptassets/app tests including limit + boundaries, then the standard repository commands. + +### Stage 14: Establish One Prepared Metadata Authority + +- Findings: `AUD-069`. +- Affected areas: briefing metadata construction, prepared reports, prompt + metadata projection, render-context inputs, and focused app/briefing tests. +- Work: establish one prepared identity/timing source and narrow projections + without changing serialized YAML or rendered Markdown. +- Locked behavior: prompt and output bytes for valid fixtures, immutable + prepared inputs, and module ordering remain unchanged. +- Documentation owners: `docs/internal/prepared-report.md`, + `docs/internal/briefing.md`, and `docs/internal/prompt-input.md`. +- Exit commands: focused briefing/app/promptinput/generatedtext tests, then the + standard repository commands. + +### Stage 15: Enforce Render Identity And Markdown Structure + +- Findings: `AUD-040`, `AUD-041`, `AUD-042`. +- Affected areas: render-context builders, repository templates/partials, + generated prose insertion, and rendering tests. +- Work: reject conflicting report identities; prevent dynamic prose from + impersonating deterministic Markdown structure; and suppress or replace an + empty Today daypart section. +- Locked behavior: repository templates remain Markdown owners, deterministic + facts remain authoritative, and normal section order remains unchanged. +- Documentation owners: `docs/templates.md`, + `docs/internal/generatedtext.md`, and `docs/internal/reporttemplate.md`. +- Exit commands: focused generated-text/reporttemplate/app tests including + adversarial heading content, then the standard repository commands. + +### Stage 16: Move Prompt Compatibility And Provenance Checks Before Work + +- Findings: `AUD-043`, `AUD-044`. +- Affected areas: application prompt inspection/preparation/execution, + generated-text catalog preflight, provenance values, and app tests. +- Work: validate catalog compatibility before collection and reconcile + inspected, prepared, callback, completed, and schema identities before + accepting generated output. +- Locked behavior: one inspection/preparation, profile precedence, immutable + execution copies, and partial execution result ownership remain unchanged. +- Documentation owners: `docs/internal/prepared-report.md`, + `docs/internal/app-orchestration.md`, and Promptkit integration docs. +- Exit commands: focused app/promptexec/generatedtext tests, then the standard + repository commands. + +### Stage 17: Make Single-Report Publication Type-Safe And Cancelable + +- Findings: `AUD-045`, `AUD-046`, `AUD-047`. +- Affected areas: `internal/fileutil`, app output planning/publication, + destination error projection, and filesystem tests. +- Work: reject non-regular final destinations; use bounded temporary naming + without leaving new directories on precommit failure; and check cancellation + at the rename linearization point. +- Locked behavior: same-directory atomic visibility, preservation of prior + regular files, restrictive new-file mode, truthful committed paths, and + notification-after-publication remain unchanged. +- Documentation owners: `docs/operations.md`, architecture policy if an + invariant needs clarification, and app orchestration internals. +- Exit commands: focused fileutil/app/CLI filesystem tests plus + `GOWORK=off go test -race -count=1 ./internal/fileutil ./internal/app + ./internal/cli`, then standard commands. + +### Stage 18: Bound And Validate The Distributor Adapter Boundary + +- Findings: `AUD-048`, `AUD-049`, `AUD-050`, `AUD-052`. +- Affected areas: Distributor config validation, repository adapter, pinned + client interaction, local HTTP tests, and safe batch diagnostics. +- Work: reject unsupported endpoints before publication; bound response reads; + redact or classify remote text before normal results; and exercise the real + production HTTP boundary with a local server. +- Locked behavior: exactly-once upload/status mapping, published-file source + selection, token redaction, and dependency types remaining adapter-local. +- Documentation owners: `docs/config.md`, `docs/operations.md`, + `docs/internal/distributor-adapter.md`, and Distributor integration docs. +- Exit commands: focused config/distributor/app tests including oversized and + malicious response bodies, then the standard repository commands. + +### Stage 19: Preserve Batch Cancellation As A Distinct Outcome + +- Findings: `AUD-051`. +- Affected areas: batch orchestration, result/error types, CLI projection, and + cancellation tests. +- Work: stop starting later reports after cancellation and preserve + cancellation separately from independent report failures and notification + state. +- Locked behavior: collect once, deterministic planned order, continuation + after non-cancellation failures, report-only counters, and all-success + notification gating remain unchanged. +- Documentation owners: `docs/cli.md`, `docs/operations.md`, and + `docs/internal/app-orchestration.md`. +- Exit commands: focused app/CLI tests plus + `GOWORK=off go test -race -count=1 ./internal/app ./internal/cli`, then + standard commands. + +### Stage 20: Tighten Comparison Manifest Compatibility + +- Findings: `AUD-053`, `AUD-054`. +- Affected areas: comparison JSON decoding, manifest/logical-bundle validation, + filename helpers, and compatibility tests. +- Work: reject duplicate and case-variant fields and require each successful + report path to equal the canonical ordinal/profile filename. +- Locked behavior: current schema version, deterministic encoding/hashing, + flat exact file set, ordered profiles, and bounded recognition errors remain. +- Documentation owners: `docs/integrations/comparison-bundle.md` and + `docs/internal/comparison-publication.md`. +- Exit commands: focused comparison compatibility tests, then the standard + repository commands. + +### Stage 21: Make Comparison Replacement Cancellation And Recovery Truthful + +- Findings: `AUD-055`, `AUD-056`, `AUD-057`. +- Affected areas: comparison planning/publication, backup cleanup/result state, + sibling naming, app/CLI recovery projection, and filesystem tests. +- Work: honor cancellation before replacement commit; distinguish a complete + retained recovery bundle from a partially removed backup; and fail long-name + constraints during preflight without residual directories. +- Locked behavior: post-move authorization, rollback, no forced destructive + cleanup, committed-new-bundle truth, and actionable recovery paths remain. +- Documentation owners: comparison bundle/publication docs, operations, and + CLI result docs where state representation changes. +- Exit commands: focused comparison/app/CLI tests plus + `GOWORK=off go test -race -count=1 ./internal/comparison ./internal/app + ./internal/cli`, then standard commands. + +### Stage 22: State Executor Concurrency And Preserve Profile Failures + +- Findings: `AUD-058`, `AUD-077`. +- Affected areas: `promptexec.Executor` contract, comparison execution/result + aggregation, Promptkit adapter, app fakes, and CLI tests. +- Work: document and test concurrent-call substitutability and preserve + already-completed profile failures when later command cancellation occurs. +- Locked behavior: one shared executor, one goroutine per explicit profile, + provider-owned capacity, joined workers, selection ordering, and no + Distributor notification remain unchanged. +- Documentation owners: Promptkit integration and comparison execution/app + orchestration internals. +- Exit commands: focused promptexec/Promptkit/app/CLI tests plus + `GOWORK=off go test -race -count=1 ./internal/adapters/promptkit + ./internal/app ./internal/cli`, then standard commands. + +### Stage 23: Make Tests Independent Of Ambient Host State + +- Findings: `AUD-059`, `AUD-060`. +- Affected areas: Promptkit credential tests and symlink tests in app, + promptdebug, and comparison packages. +- Work: explicitly control the credential environment and treat inability to + create symlinks as a tested capability prerequisite rather than product + failure. +- Locked behavior: real supported-host symlink safety assertions and missing- + credential behavior remain fully protected. +- Documentation owners: testing policy only if supported-platform policy is + deliberately changed; normally none. +- Exit commands: focused packages under scrubbed and ordinary environments, + race-enabled focused tests, then standard commands. + +### Stage 24: Remove Redundant Assertions And Production Test Waits + +- Findings: `AUD-061`, `AUD-062`. +- Affected areas: briefing SPC tests, collection wrapper tests, Distributor + polling tests, and narrow timing seams. +- Work: remove the private-constant assertion while retaining observable risk + behavior; inject only the wait controls necessary to avoid production delays + in deterministic tests. +- Locked behavior: production retry/poll intervals and observable SPC policy + remain unchanged. +- Documentation owners: none unless a contributor-facing test seam warrants a + focused internal note. +- Exit commands: focused briefing/collect/distributor tests with repeated runs, + then the standard repository commands. + +### Stage 25: Make Comparison Test Failure Cleanup Total + +- Findings: `AUD-064`. +- Affected areas: comparison execution test barriers and worker cleanup in + `internal/app` tests. +- Work: release and join workers on timeout, early completion, duplicate start, + and every diagnostic exit without weakening liveness detection. +- Locked behavior: production comparison scheduling and five-second deadlock + diagnostics remain unchanged. +- Documentation owners: none. +- Exit commands: repeat focused comparison-execution tests and run them with + `-race`, then the standard repository commands. + +### Stage 26: Remove Redundant Weather Fetches And Safe Serialization + +- Findings: `AUD-065`. +- Affected areas: Weather API bundle acquisition, request-result aggregation, + provenance ordering, cancellation, and adapter/collection tests. +- Work: reuse or remove the discarded warmup current response and execute + independent source requests concurrently through one deterministic merge. +- Locked behavior: source-local validation/errors, exact source order, + required/optional policy, retry policy after Stage 5, and context cancellation + remain authoritative. +- Documentation owners: Weather API integration and collection internals if + operational request behavior changes materially. +- Exit commands: focused latency/request-count and cancellation tests plus + `GOWORK=off go test -race -count=1 ./internal/adapters/weatherapi + ./internal/collect`, then standard commands. + +### Stage 27: Eliminate Repeated Comparison Bundle Reads + +- Findings: `AUD-066`. +- Affected areas: comparison recognition/planning/publication and app + comparison preflight. +- Work: pass or cache only the recognition evidence needed to avoid four full + reads while retaining reauthorization at every mutation boundary. +- Locked behavior: early rejection, exact file/type validation, post-move + authorization, deterministic hashes, and concurrent destination safety after + Stage 21 remain unchanged. +- Documentation owners: comparison publication internals if ownership or + transaction phases change. +- Exit commands: focused read-count and adversarial replacement tests plus + `GOWORK=off go test -race -count=1 ./internal/comparison ./internal/app`, then + standard commands. + +### Stage 28: Consolidate Distributor Template Parsing + +- Findings: `AUD-068`. +- Affected areas: single and batch notification template rendering and config + tests. +- Work: extract one private grammar/parser with typed callbacks while + preserving each template family's variable allowlist and error context. +- Locked behavior: accepted syntax, rejected malformed forms, exact rendering, + and single-versus-batch policy remain unchanged. +- Documentation owners: none unless the user-visible grammar changes, which is + outside this behavior-preserving stage. +- Exit commands: focused config tests, then the standard repository commands. + +### Stage 29: Centralize Fact Requirement Policy + +- Findings: `AUD-070`. +- Affected areas: module requirement vocabulary, briefing definitions, + availability checks, constructor validation, and tests. +- Work: define requirement identity/category/predicate once while leaving each + module's requirement list and missing-data policy explicit. +- Locked behavior: all current compositions, supported reports, availability, + and diagnostic identity remain byte-for-byte or semantically unchanged. +- Documentation owners: module and briefing internals if ownership changes. +- Exit commands: focused module/briefing/config tests, then the standard + repository commands. + +### Stage 30: Consolidate CLI Report-Date Policy + +- Findings: `AUD-071`. +- Affected areas: generate/comparison flag registration and date resolution, + CLI parser/action tests, and private CLI descriptors. +- Work: establish one private report-date policy/resolver used by both actions + after Stage 4 has locked corrected behavior. +- Locked behavior: accepted flags, required/default dates, action-specific + errors, and request types remain unchanged. +- Documentation owners: none unless implementation reveals a current contract + mismatch; CLI docs remain authoritative. +- Exit commands: focused CLI parser/action tests and help commands, then the + standard repository commands. + +### Stage 31: Retire Dormant Compatibility And Persistence Surfaces + +- Findings: `AUD-072`. +- Affected areas: unused prompt YAML loading/saving, Weather API bundle saving, + JSON atomic helper if orphaned, module snapshot compatibility implication, + forecast threshold exports, full alert envelope copies, normalized generated + JSON returns, and sole-purpose tests/docs. +- Work: remove the no-owner surfaces identified by the audit. If an actual + production consumer appears before implementation, stop this stage and + replace the retirement with a separately approved narrow contract; do not + retain speculative compatibility. +- Locked behavior: normal Build/Validate/MarshalYAML, report publication, + comparison bundles, prompt debugging, alert item provenance, real forecast + decisions, typed normalization, and all workflows remain unchanged. +- Documentation owners: affected focused internal documents; remove stale + descriptions rather than documenting retired APIs. +- Exit commands: graph/text caller checks showing no remaining references, + focused affected package tests, then the standard repository commands. + +### Stage 32: Consolidate Generated-Text Test Ownership + +- Findings: `AUD-039`. +- Affected areas: generated-text day-style and render-context tests, + promptassets schema tests, and reporttemplate tests. +- Work: keep one shared semantic suite plus thin report-identity cases; put + schema ownership in promptassets and Markdown ownership in reporttemplate; + retain one real typed-context render integration. +- Locked behavior: every public validator identity, distinct Hourly behavior, + schema/type agreement, typed projection, template semantics, and composition + remain protected. +- Documentation owners: none. +- Exit commands: focused promptassets/generatedtext/reporttemplate tests, then + the standard repository commands. + +### Stage 33: Reconcile Stale Internal Implementation Guides + +- Findings: `AUD-075`. +- Affected areas: forecast derivation, collection, report registry, and prompt- + input internal guides plus incoming links. +- Work: replace nonexistent API/flow/test claims with concise descriptions of + the implemented owners and link to canonical contracts instead of duplicating + volatile details. +- Locked behavior: documentation-only; no executable contract changes. +- Documentation owners: the four affected `docs/internal/` files and + `docs/development.md` only if task routing changes. +- Exit commands: repository link/fence checks, focused test inventories used to + verify claims, `GOWORK=off go test -count=1 ./...`, and `git diff --check`. + +### Stage 34: Retire Completed Comparison Roadmaps + +- Findings: `AUD-076`. +- Affected areas: `docs/roadmap/profile-comparison.md`, + `docs/roadmap/implementation.md`, and all incoming links. +- Work: verify useful implemented contracts have one durable canonical owner, + repair incoming navigation, then remove the completed roadmaps so they no + longer duplicate current behavior. +- Locked behavior: documentation lifecycle only; no code, tests, dependencies, + schemas, or current contracts change. +- Documentation owners: CLI, operations, comparison integration/publication, + comparison execution, Promptkit integration, architecture, and development + docs only where an incoming link or missing durable fact requires correction. +- Exit commands: repository link/fence checks, both CLI help commands, + `GOWORK=off go test -count=1 ./...`, and `git diff --check`. + +### Stage 35: Close Remediation And Retire Audit Records + +- Findings: none; this is the roadmap lifecycle gate. +- Prerequisite: Stages 1-34 are complete and every referenced finding's tests + and canonical documentation have landed. +- Affected areas: `docs/roadmap/audit.md`, `audit-plan.md`, this roadmap, and + incoming links. +- Work: verify every finding is resolved, superseded, or explicitly moved to a + newly approved roadmap; move any durable rationale to its canonical owner; + verify no active work or incoming link depends on these coordination files; + then remove the temporary audit plan, ledger, and this roadmap in the final + lifecycle change. +- Locked behavior: documentation lifecycle only; do not rewrite historical + ADRs or release notes and do not create a second current-state reference. +- Documentation owners: all durable owners touched by earlier stages, solely + to fill a demonstrated ownership gap. +- Exit commands: repository link/fence and secret-pattern checks; all focused + stage exits; `GOWORK=off go test -count=1 ./...`, + `GOWORK=off go test -race -count=1 ./...`, both CLI help commands, + `GOWORK=off go vet ./...`, and `git diff --check`. + +## Completion Tracking + +Update a stage heading or add a concise completion note only after its code, +tests, canonical documentation, and exit commands pass together. Do not copy +implemented contracts into this roadmap. When all work is complete, follow +Stage 35 rather than retaining this file as a parallel reference. diff --git a/docs/roadmap/audit.md b/docs/roadmap/audit.md index c0dd0b3..cd2984c 100644 --- a/docs/roadmap/audit.md +++ b/docs/roadmap/audit.md @@ -1,7 +1,6 @@ # Repository Audit Ledger -Status: In progress; Stages 1-24 and 26 complete. Stage 25 was interrupted -before its evidence was recorded. +Status: Complete; all 27 planned stages complete. This temporary roadmap document is the evidence ledger for the staged audit defined by [the audit plan](audit-plan.md). It records audit evidence and @@ -222,6 +221,81 @@ retained decision, and no high-impact uncertainty requires a supplemental investigation stage. Remediation acceptance, priority, and implementation sequencing remain exclusively Stage 27 work. +Stage 27 accepted all 74 confirmed findings for implementation and allocated +each exactly once across the dependency-ordered +[audit remediation roadmap](audit-remediation.md). No confirmed finding is +priority-deferred or blocked on a separate product/architecture decision. The +roadmap places generated-forecast integrity, security, correctness, data +integrity, destructive operations, and cancellation before efficiency, +behavior-preserving consolidation, test cleanup, and roadmap retirement. The +discovery audit changed only its temporary roadmap documents. + +## Final Audit Summary + +### Overall Assessment + +Weatherreporter's architecture is coherent: dependency direction is acyclic, +external dependencies remain adapter-local, the normal workflow is stateless, +deterministic facts and repository templates remain authoritative, and the +default test suite is offline and repeatable. The audit nevertheless found two +high-severity shared-prompt defects that can systematically misdirect every +generated report, 43 medium-severity correctness/security/reliability/ +compatibility/efficiency gaps, and 29 low-severity confirmed maintenance, +documentation, testing, cleanup, or edge-case gaps. Four low-severity entries +were rejected only as standalone duplicates and consolidated into broader +confirmed owners. + +The highest remediation risks are prompt/data-package disagreement and +overstated hazard locality, sensitive or unbounded upstream diagnostics, +prompt-debug pathname races, Markdown structural injection, destructive output +target handling, comparison replacement/recovery truthfulness, and lost +cancellation or failure identity. The suite passes because many findings are +missing adversarial boundary cases or incorrect-but-current contracts rather +than ordinary happy-path breakage. + +### Reviewed Scope And Exclusions + +The audit covered all production and test packages, command paths, +configuration and maintained examples, embedded prompt/profile/schema/template +assets, normalized weather acquisition and derivation, briefing modules, +Promptkit and Distributor adapters, generated-text validation/rendering, +single/batch/comparison orchestration, filesystem publication, test quality, +dependency/complexity history, and all current, historical, policy, internal, +integration, release, and roadmap documentation inventoried by Stage 1. + +It did not call live Weather API, Promptkit-provider, or Distributor services; +use real credentials or private infrastructure; prove power-loss durability; +define an unsupported-platform promise; perform production remediation; change +dependencies; rewrite canonical current-state contracts to legitimize defects; +or prepare a release. Those exclusions preserve deterministic offline audit +evidence and the architecture's stated boundaries. + +### Prioritized Finding Summary + +| Priority | Finding set | Assessment and disposition | +| --- | --- | --- | +| P0 | `AUD-030`, `AUD-031` | Two high-severity prompt-contract defects. Accepted first because they affect shared instructions for all generated reports. | +| P1 | Medium security, correctness, reliability, compatibility, cancellation, and destructive-publication findings | Forty-three medium findings accepted before efficiency or cleanup. Their package-level tests must protect malformed input, safe diagnostics, cancellation linearization, recovery state, and visible result truth. | +| P2 | Low-severity correctness/security edges plus deterministic test and operational quality | Accepted after the P0/P1 contract fixes, except where a low finding is a prerequisite mechanism for a related correctness fix. | +| P3 | `AUD-039`, `AUD-067` through `AUD-072` | Behavior-preserving consolidation and dormant-surface retirement accepted after the behavior they touch is corrected and locked by tests. | +| P4 | `AUD-075`, `AUD-076`, and audit-record retirement | Documentation lifecycle work accepted last, after implemented contracts have durable canonical owners. | + +The remediation roadmap's allocation table and 35 stages are the authoritative +finding-to-stage mapping. All 74 confirmed findings are accepted now; none is +deferred and none requires a prerequisite decision. Rejected `AUD-001`, +`AUD-022`, and `AUD-032` flow only through `AUD-072`; rejected `AUD-063` flows +only through `AUD-039`. + +### Final Validation Summary + +The clean final checkout passed uncached default tests, repository-wide race +tests, three shuffled repetitions, vet, root CLI help, and whitespace checks. +Diagnostic coverage was 79.4% of statements; it was used to inspect weak +critical branches rather than as a target, and `coverage.out` was removed. +Focused adversarial evidence and narrow test seams support the confirmed +correctness and safety findings. No generated artifact, unexplained failure, +candidate status, deferred finding, or unresolved scope question remains. + ## Baseline Metadata | Item | Recorded baseline | @@ -371,9 +445,9 @@ inventory commands, graph index refresh, and graph architecture inspection. | 22 | Audit cross-cutting efficiency and complexity | Complete | | 23 | Audit cross-cutting refactoring and deduplication opportunities | Complete | | 24 | Audit documentation coherence and executable contracts | Complete | -| 25 | Run dynamic robustness and final diagnostic validation | Pending | +| 25 | Run dynamic robustness and final diagnostic validation | Complete | | 26 | Verify, consolidate, and triage findings | Complete | -| 27 | Produce the remediation roadmap and close the audit | Pending | +| 27 | Produce the remediation roadmap and close the audit | Complete | ## Risk-To-Test Coverage @@ -405,7 +479,7 @@ with evidence about meaningful risks, test ownership, gaps, and duplication. | Cross-cutting efficiency | Graph metrics, workflow traces, and focused latency/allocation diagnostics | 22 | Partly insufficient. Fixed-size registries, service-sized derivation, template parsing, batch composition, and ordinary profile fan-out are proportionate. `AUD-065` records one redundant Weather API request plus serial independent source fetches; `AUD-066` records repeated full comparison-bundle reads during replacement. | | Cross-cutting maintainability | Graph similarity, change history, caller traces, and focused structural review | 23 | Partly insufficient. `AUD-067` through `AUD-073` identify duplicated canonicalization/template/date/requirement policy, parallel metadata authority, dormant internal surfaces, and unsafe duplicate capitalization. Important report, prompt-curation, safety-copy, validation, and orchestration similarities remain explicit under `RET-053` through `RET-058`. | | Documentation and executable-contract coherence | Canonical documents, code, schemas, templates, examples | 24 | Partly insufficient. `AUD-074` through `AUD-078` record CLI/help drift, stale internal flow/API/test claims, completed-roadmap duplication, an implicit concurrent-executor requirement, and incomplete configuration normalization/bounds. Other volatile identities and maintained examples match their executable owners; linked summaries, historical release notes, and the accepted ADR remain appropriately distinct. | -| Dynamic robustness and diagnostic checks | Repository-wide deterministic checks | 25 | Pending | +| Dynamic robustness and diagnostic checks | Repository-wide deterministic checks | 25 | Sufficient for audit closure. Uncached, race-enabled, and three shuffled test runs passed; vet and CLI help passed; coverage remained 79.4% and exposed no additional consequential unowned branch. The diagnostic artifact was removed. | | Finding verification and triage | All findings, retained decisions, routed questions, validation records, and coverage entries | 26 | Complete. Seventy-four findings are confirmed and four duplicate standalone entries are rejected into their named root-cause owners. No candidate or deferred status remains; all confirmed entries retain actionable test implications and validation criteria. | ## Findings @@ -452,7 +526,8 @@ with evidence about meaningful risks, test ownership, gaps, and duplication. consolidated under `AUD-072`; a separate recommendation would split one ownership decision without changing its priority or validation. - Related findings: `AUD-072` -- Remediation reference: pending +- Remediation reference: Not applicable; consolidated into `AUD-072` and + Remediation Stage 31. ### AUD-002: Clock windows shift on daylight-saving transition days @@ -489,7 +564,7 @@ with evidence about meaningful risks, test ownership, gaps, and duplication. implementation and passes when transition-day boundaries retain their configured local clocks; focused `timeutil` and `forecast` suites pass. - Related findings: none -- Remediation reference: pending +- Remediation reference: Remediation Stage 6. ### AUD-003: Daily run-ID uniqueness lacks a focused contract test @@ -527,7 +602,7 @@ with evidence about meaningful risks, test ownership, gaps, and duplication. with the invariant intact, report and multi-Daily batch tests pass and `plannedReportsByRunID` receives unique keys. - Related findings: none -- Remediation reference: pending +- Remediation reference: Remediation Stage 6. ### AUD-004: Unsupported missing-source keys are silently accepted @@ -565,7 +640,7 @@ with evidence about meaningful risks, test ownership, gaps, and duplication. and pass when validation rejects keys that cannot affect optional-source policy; focused config and Weather API policy tests remain green. - Related findings: none -- Remediation reference: pending +- Remediation reference: Remediation Stage 2. ### AUD-005: Single-report notification identities may render blank @@ -601,7 +676,7 @@ with evidence about meaningful risks, test ownership, gaps, and duplication. and pass when all active rendered identities are nonblank; focused config, app notification, and Distributor adapter tests pass. - Related findings: none -- Remediation reference: pending +- Remediation reference: Remediation Stage 3. ### AUD-006: Constructed report overrides depend on inaccessible presence flags @@ -641,7 +716,7 @@ with evidence about meaningful risks, test ownership, gaps, and duplication. construction today and passes when loaded and constructed forms yield the same overrides and validation result. - Related findings: none -- Remediation reference: pending +- Remediation reference: Remediation Stage 2. ### AUD-007: Failed configuration loads can leave secrets applied @@ -676,7 +751,7 @@ with evidence about meaningful risks, test ownership, gaps, and duplication. - Validation: Both failure cases leave the environment exactly as it was before loading; successful overwrite and single-line-ending behavior remain intact. - Related findings: none -- Remediation reference: pending +- Remediation reference: Remediation Stage 2. ### AUD-008: Process interrupts do not cancel active workflows @@ -715,7 +790,7 @@ with evidence about meaningful risks, test ownership, gaps, and duplication. when available, and leaves the existing destination intact; ordinary help, version, and successful exits are unchanged. - Related findings: `AUD-010` -- Remediation reference: pending +- Remediation reference: Remediation Stage 4. ### AUD-009: Generate validates report dates after constructing its executor @@ -754,7 +829,7 @@ with evidence about meaningful risks, test ownership, gaps, and duplication. constructing an executor or emitting a partial summary; valid requests still construct exactly one executor. - Related findings: `AUD-007`, `AUD-010` -- Remediation reference: pending +- Remediation reference: Remediation Stage 4. ### AUD-010: Assembled non-comparison CLI result paths lack durable tests @@ -795,7 +870,7 @@ with evidence about meaningful risks, test ownership, gaps, and duplication. selection, or failure return status break a focused CLI test, while internal app refactors that preserve request/result contracts require no CLI edits. - Related findings: `AUD-008`, `AUD-009` -- Remediation reference: pending +- Remediation reference: Remediation Stage 4. ### AUD-011: Unsupported Weather API URL schemes fail only at transport @@ -830,7 +905,7 @@ with evidence about meaningful risks, test ownership, gaps, and duplication. - Validation: Unsupported schemes fail before Weather API or Promptkit work; ordinary HTTP test servers and configured HTTPS URLs remain accepted. - Related findings: none -- Remediation reference: pending +- Remediation reference: Remediation Stage 5. ### AUD-012: Weather API failures expose upstream response bodies @@ -866,7 +941,7 @@ with evidence about meaningful risks, test ownership, gaps, and duplication. - Validation: Normal failure output is bounded and marker-free for warmup and source requests, with existing actionable and retry tests still passing. - Related findings: `AUD-013` -- Remediation reference: pending +- Remediation reference: Remediation Stage 5. ### AUD-013: The Weather API response limit silently truncates bodies @@ -902,7 +977,7 @@ with evidence about meaningful risks, test ownership, gaps, and duplication. complete at-limit response remains readable and response bodies always close. - Related findings: `AUD-012` -- Remediation reference: pending +- Remediation reference: Remediation Stage 5. ### AUD-014: Required hourly periods can lack usable time bounds @@ -938,7 +1013,7 @@ with evidence about meaningful risks, test ownership, gaps, and duplication. - Validation: Every accepted required hourly period has a usable half-open time range, and existing valid fixtures still normalize unchanged. - Related findings: none -- Remediation reference: pending +- Remediation reference: Remediation Stage 5. ### AUD-015: Weather API warmup retries permanent HTTP failures @@ -969,7 +1044,7 @@ with evidence about meaningful risks, test ownership, gaps, and duplication. - Validation: Warmup retries only the documented transient classes and fails permanent statuses immediately with endpoint/status context. - Related findings: none -- Remediation reference: pending +- Remediation reference: Remediation Stage 5. ### AUD-016: Metric fallback values lose their unit during daypart derivation @@ -1011,7 +1086,7 @@ with evidence about meaningful risks, test ownership, gaps, and duplication. wind decisions and unambiguous summary values; all immediate derived-fact consumers retain correct units. - Related findings: none -- Remediation reference: pending +- Remediation reference: Remediation Stage 6. ### AUD-017: Overnight dayparts omit alerts that begin after midnight @@ -1045,7 +1120,7 @@ with evidence about meaningful risks, test ownership, gaps, and duplication. - Validation: Every wrapping daypart includes all and only alerts overlapping its full period, while daily alert summaries retain civil-day boundaries. - Related findings: `AUD-002` -- Remediation reference: pending +- Remediation reference: Remediation Stage 6. ### AUD-018: Invalid precipitation percentages flow into derived summaries @@ -1079,7 +1154,7 @@ with evidence about meaningful risks, test ownership, gaps, and duplication. and malformed source behavior is deterministic and visible under the chosen source-failure policy. - Related findings: `AUD-014` -- Remediation reference: pending +- Remediation reference: Remediation Stage 6. ### AUD-019: Ordinary “icy” forecast text does not set the ice indicator @@ -1108,7 +1183,7 @@ with evidence about meaningful risks, test ownership, gaps, and duplication. - Validation: Representative icy descriptions set the ice indicator without broadening matches to unrelated words. - Related findings: none -- Remediation reference: pending +- Remediation reference: Remediation Stage 6. ### AUD-020: Pointer-shaped AFD options pass validation but fail construction @@ -1147,7 +1222,7 @@ with evidence about meaningful risks, test ownership, gaps, and duplication. builder in a usable canonical form, and invalid shapes still fail during preflight. - Related findings: `AUD-006` -- Remediation reference: pending +- Remediation reference: Remediation Stage 7. ### AUD-021: Empty weather-story data is published as available @@ -1183,7 +1258,7 @@ with evidence about meaningful risks, test ownership, gaps, and duplication. policy or are omitted, while a usable story emits `Available: true` with its structured fields intact. - Related findings: none -- Remediation reference: pending +- Remediation reference: Remediation Stage 7. ### AUD-022: Module snapshots accept unsupported schema versions @@ -1219,7 +1294,8 @@ with evidence about meaningful risks, test ownership, gaps, and duplication. retained as part of the broader no-owner decision in `AUD-072`; hardening it independently would add a contract for a surface the repository may retire. - Related findings: `AUD-072` -- Remediation reference: pending +- Remediation reference: Not applicable; consolidated into `AUD-072` and + Remediation Stage 31. ### AUD-023: Apparent temperature is published as heat index @@ -1257,7 +1333,7 @@ with evidence about meaningful risks, test ownership, gaps, and duplication. retain an accurately named value; focused briefing and downstream schema or render tests pass. - Related findings: `AUD-016` -- Remediation reference: pending +- Remediation reference: Remediation Stage 8. ### AUD-024: Normalized daypart keys can silently overwrite summaries @@ -1291,7 +1367,7 @@ with evidence about meaningful risks, test ownership, gaps, and duplication. - Validation: Every accepted daypart maps to one distinct output entry, and every collision is rejected before prompt construction. - Related findings: `AUD-025` -- Remediation reference: pending +- Remediation reference: Remediation Stage 10. ### AUD-025: Planning applies configurable daypart identities inconsistently @@ -1327,7 +1403,7 @@ with evidence about meaningful risks, test ownership, gaps, and duplication. classification, and unsupported role configurations fail explicitly rather than degrading to fallback prose. - Related findings: `AUD-024` -- Remediation reference: pending +- Remediation reference: Remediation Stage 10. ### AUD-026: Outdoor-window ranking ignores snow, ice, and fog @@ -1360,7 +1436,7 @@ with evidence about meaningful risks, test ownership, gaps, and duplication. - Validation: None of the supported hazard-only periods is described as quiet, and best/worst selection reflects the documented relative policy. - Related findings: `AUD-019` -- Remediation reference: pending +- Remediation reference: Remediation Stage 8. ### AUD-027: Subzero temperatures are rendered as positive zero-degree bands @@ -1391,7 +1467,7 @@ with evidence about meaningful risks, test ownership, gaps, and duplication. - Validation: Every negative input produces unambiguously below-zero wording, and band indices remain monotonic from colder to warmer values. - Related findings: `AUD-016` -- Remediation reference: pending +- Remediation reference: Remediation Stage 8. ### AUD-028: Embedded official SPC category descriptions have drifted @@ -1432,7 +1508,7 @@ with evidence about meaningful risks, test ownership, gaps, and duplication. authoritative revision, and repository-authored summaries are labeled as such; asset and briefing tests pass. - Related findings: none -- Remediation reference: pending +- Remediation reference: Remediation Stage 11. ### AUD-029: Raw source warnings cross the curated prompt boundary @@ -1471,7 +1547,7 @@ with evidence about meaningful risks, test ownership, gaps, and duplication. transport/provenance fields; ordinary warning meaning and existing deterministic YAML tests remain intact. - Related findings: none -- Remediation reference: pending +- Remediation reference: Remediation Stage 1. ### AUD-030: The shared prompt instructs nonexistent briefing paths @@ -1508,7 +1584,7 @@ with evidence about meaningful risks, test ownership, gaps, and duplication. current serialized package and a category move or prompt-path regression fails one focused compatibility test. - Related findings: none -- Remediation reference: pending +- Remediation reference: Remediation Stage 1. ### AUD-031: The shared prompt overstates SPC product locality @@ -1546,7 +1622,7 @@ with evidence about meaningful risks, test ownership, gaps, and duplication. treat regional or non-containing SPC material as point-local, while still requiring locally relevant digest facts to lead the report. - Related findings: `AUD-030` -- Remediation reference: pending +- Remediation reference: Remediation Stage 1. ### AUD-032: The exported YAML loader accepts malformed package shapes @@ -1587,7 +1663,8 @@ with evidence about meaningful risks, test ownership, gaps, and duplication. identify a real consumer—so prescribing strict decoding first has insufficient cost-benefit evidence. - Related findings: `AUD-072` -- Remediation reference: pending +- Remediation reference: Not applicable; consolidated into `AUD-072` and + Remediation Stage 31. ### AUD-033: Stanza serialization failures lack a focused contract test @@ -1622,7 +1699,7 @@ with evidence about meaningful risks, test ownership, gaps, and duplication. - Validation: The focused test fails if conversion errors lose stanza context or are swallowed, and deterministic successful serialization remains green. - Related findings: `AUD-043` -- Remediation reference: pending +- Remediation reference: Remediation Stage 1. ### AUD-034: Prompt-debug credential redaction misses common aliases and URL forms @@ -1662,7 +1739,7 @@ with evidence about meaningful risks, test ownership, gaps, and duplication. - Validation: Every supported debug projection is allowlisted, adversarial marker tests find no value leak, and normal summaries remain content-free. - Related findings: none -- Remediation reference: pending +- Remediation reference: Remediation Stage 12. ### AUD-035: Prompt-debug symlink checks can be raced before writes @@ -1701,7 +1778,7 @@ with evidence about meaningful risks, test ownership, gaps, and duplication. originally validated root handle across component swaps; attempted redirection fails closed without an external file or partial target. - Related findings: none -- Remediation reference: pending +- Remediation reference: Remediation Stage 12. ### AUD-036: The generated-text catalog accepts a known pair for the wrong report @@ -1740,7 +1817,7 @@ with evidence about meaningful risks, test ownership, gaps, and duplication. - Validation: Every current definition resolves once, and swapping any two known pairs fails during lookup before prompt inspection or provider work. - Related findings: none -- Remediation reference: pending +- Remediation reference: Remediation Stage 13. ### AUD-037: Typed decoding accepts property names rejected by the schema @@ -1778,7 +1855,7 @@ with evidence about meaningful risks, test ownership, gaps, and duplication. - Validation: A corpus of canonical, missing, added, case-varied, duplicate, null, and wrong-type fields produces compatible schema and Go decisions. - Related findings: none -- Remediation reference: pending +- Remediation reference: Remediation Stage 13. ### AUD-038: Generated prose and decoder diagnostics have no size boundary @@ -1821,7 +1898,7 @@ with evidence about meaningful risks, test ownership, gaps, and duplication. normalization/rendering, and no malformed provider value can make normal error text exceed the documented diagnostic bound. - Related findings: none -- Remediation reference: pending +- Remediation reference: Remediation Stage 13. ### AUD-039: Generated-text tests duplicate semantic and rendered-output ownership @@ -1867,7 +1944,7 @@ with evidence about meaningful risks, test ownership, gaps, and duplication. schema/type disagreement, required-field regression, or normalization change, and report-template tests fail only for template/render behavior. - Related findings: `AUD-037`, `AUD-063` -- Remediation reference: pending +- Remediation reference: Remediation Stage 32. ### AUD-040: Render contexts accept conflicting report identities @@ -1911,7 +1988,7 @@ with evidence about meaningful risks, test ownership, gaps, and duplication. metadata stanza that disagrees with the canonical context input; all four normal prepared contexts still render. - Related findings: `AUD-036` -- Remediation reference: pending +- Remediation reference: Remediation Stage 15. ### AUD-041: Dynamic prose can impersonate deterministic Markdown sections @@ -1956,7 +2033,7 @@ with evidence about meaningful risks, test ownership, gaps, and duplication. owned nodes create report headings and deterministic list structure, and adversarial dynamic strings remain text within their authorized slots. - Related findings: `AUD-038` -- Remediation reference: pending +- Remediation reference: Remediation Stage 15. ### AUD-042: Today can render a daypart heading with no rows or fallback @@ -1988,7 +2065,7 @@ with evidence about meaningful risks, test ownership, gaps, and duplication. - Validation: The Daypart Forecast heading is always followed by at least one row or the explicit fallback, and mixed rows retain their existing order. - Related findings: none -- Remediation reference: pending +- Remediation reference: Remediation Stage 15. ### AUD-043: Generated-text compatibility is validated after collection @@ -2031,7 +2108,7 @@ with evidence about meaningful risks, test ownership, gaps, and duplication. ordinary, batch, and comparison preflight, while each valid definition is resolved once and no model execution occurs on later preparation failures. - Related findings: `AUD-036` -- Remediation reference: pending +- Remediation reference: Remediation Stage 16. ### AUD-044: Execution provenance is accepted without reconciliation @@ -2079,7 +2156,7 @@ with evidence about meaningful risks, test ownership, gaps, and duplication. inspected prompt hash and selected profile/backend/model in results and debug artifacts. - Related findings: `AUD-036`, `AUD-037`, `AUD-040` -- Remediation reference: pending +- Remediation reference: Remediation Stage 16. ### AUD-045: Single-report publication replaces non-regular destinations @@ -2120,7 +2197,7 @@ with evidence about meaningful risks, test ownership, gaps, and duplication. the documented symlink policy; non-regular objects retain their type and identity with zero collector, executor, or notifier calls. - Related findings: none -- Remediation reference: pending +- Remediation reference: Remediation Stage 17. ### AUD-046: Valid long output names fail through the temporary-name pattern @@ -2164,7 +2241,7 @@ with evidence about meaningful risks, test ownership, gaps, and duplication. and a failed publication leaves neither a partial file nor an app-created empty directory under the documented lifecycle. - Related findings: none -- Remediation reference: pending +- Remediation reference: Remediation Stage 17. ### AUD-047: Cancellation is not checked at the publication linearization point @@ -2206,7 +2283,7 @@ with evidence about meaningful risks, test ownership, gaps, and duplication. rename succeeds, results truthfully report publication regardless of later notification outcome. - Related findings: `AUD-038` -- Remediation reference: pending +- Remediation reference: Remediation Stage 17. ### AUD-048: Unsupported Distributor endpoint forms fail only after publication @@ -2247,7 +2324,7 @@ with evidence about meaningful risks, test ownership, gaps, and duplication. production upload client; rejected endpoint forms perform no collection, report generation, publication, or notification. - Related findings: `AUD-005`, `AUD-011` -- Remediation reference: pending +- Remediation reference: Remediation Stage 18. ### AUD-049: Distributor response text crosses into normal batch diagnostics @@ -2287,7 +2364,7 @@ with evidence about meaningful risks, test ownership, gaps, and duplication. normal notification results or CLI output, while conflict, status, and local identity remain actionable. - Related findings: `AUD-012`, `AUD-034` -- Remediation reference: pending +- Remediation reference: Remediation Stage 18. ### AUD-050: Distributor response bodies have no size boundary @@ -2323,7 +2400,7 @@ with evidence about meaningful risks, test ownership, gaps, and duplication. - Validation: Memory use is bounded independently of remote body length and oversized responses fail with a stable safe diagnostic. - Related findings: `AUD-013`, `AUD-038`, `AUD-049` -- Remediation reference: pending +- Remediation reference: Remediation Stage 18. ### AUD-051: Mid-batch cancellation is flattened into ordinary report failures @@ -2367,7 +2444,7 @@ with evidence about meaningful risks, test ownership, gaps, and duplication. shared context termination stops new work and remains identifiable at every application and CLI boundary. - Related findings: `AUD-008`, `AUD-047` -- Remediation reference: pending +- Remediation reference: Remediation Stage 19. ### AUD-052: Distributor adapter tests bypass the production HTTP boundary @@ -2405,7 +2482,7 @@ with evidence about meaningful risks, test ownership, gaps, and duplication. repository-to-dependency HTTP path, and each remaining fake has a boundary behavior that the local server cannot express efficiently. - Related findings: `AUD-049`, `AUD-050` -- Remediation reference: pending +- Remediation reference: Remediation Stage 18. ### AUD-053: Comparison recognition accepts ambiguous manifest fields @@ -2444,7 +2521,7 @@ with evidence about meaningful risks, test ownership, gaps, and duplication. - Validation: Only exact, unique schema property names reach `Manifest.Validate` and no ambiguous manifest can authorize replacement. - Related findings: `AUD-037` -- Remediation reference: pending +- Remediation reference: Remediation Stage 20. ### AUD-054: Manifest validation does not enforce canonical profile report names @@ -2485,7 +2562,7 @@ with evidence about meaningful risks, test ownership, gaps, and duplication. - Validation: Every published and recognized successful report path is exactly reproducible from the manifest's ordered profile identity. - Related findings: none -- Remediation reference: pending +- Remediation reference: Remediation Stage 20. ### AUD-055: Replacement ignores cancellation after moving the prior bundle @@ -2525,7 +2602,7 @@ with evidence about meaningful risks, test ownership, gaps, and duplication. rename either leaves or restores the exact prior destination and cannot return a committed replacement. - Related findings: `AUD-008`, `AUD-047`, `AUD-051` -- Remediation reference: pending +- Remediation reference: Remediation Stage 21. ### AUD-056: Cleanup errors can leave an invalid retained backup @@ -2567,7 +2644,7 @@ with evidence about meaningful risks, test ownership, gaps, and duplication. - Validation: Every cleanup failure reports the actual surviving state; only a complete recognized old bundle is called a retained backup. - Related findings: none -- Remediation reference: pending +- Remediation reference: Remediation Stage 21. ### AUD-057: Long comparison destinations fail through derived sibling names @@ -2604,7 +2681,7 @@ with evidence about meaningful risks, test ownership, gaps, and duplication. - Validation: Every preflighted basename can create both sibling forms, and a pre-commit failure leaves only the documented parent-directory state. - Related findings: `AUD-046` -- Remediation reference: pending +- Remediation reference: Remediation Stage 21. ### AUD-058: Late cancellation overwrites completed profile failures @@ -2649,7 +2726,7 @@ with evidence about meaningful risks, test ownership, gaps, and duplication. cancellation category; result order and no-publication behavior remain unchanged under the race detector. - Related findings: `AUD-044`, `AUD-051` -- Remediation reference: pending +- Remediation reference: Remediation Stage 22. ### AUD-059: Missing-credential test depends on the ambient environment @@ -2685,7 +2762,7 @@ with evidence about meaningful risks, test ownership, gaps, and duplication. inspection, provider-call count, error category, or test outcome, and the full scrubbed/default suites continue to pass. - Related findings: none -- Remediation reference: pending +- Remediation reference: Remediation Stage 23. ### AUD-060: Symlink tests assume host creation capability @@ -2725,7 +2802,7 @@ with evidence about meaningful risks, test ownership, gaps, and duplication. hosts report narrowly explained skips rather than setup failures; other filesystem and race tests remain unchanged. - Related findings: `AUD-035` -- Remediation reference: pending +- Remediation reference: Remediation Stage 23. ### AUD-061: SPC policy constants have a redundant implementation-coupled test @@ -2757,7 +2834,7 @@ with evidence about meaningful risks, test ownership, gaps, and duplication. outcome, while replacing the constants with an equivalent implementation requires no test edit. - Related findings: none -- Remediation reference: pending +- Remediation reference: Remediation Stage 24. ### AUD-062: Two integration tests pay production retry and polling intervals @@ -2794,7 +2871,7 @@ with evidence about meaningful risks, test ownership, gaps, and duplication. production-sized sleep, and the suite's cancellation/timeout tests still detect a wait mechanism that ignores context. - Related findings: none -- Remediation reference: pending +- Remediation reference: Remediation Stage 24. ### AUD-063: Render-context tests duplicate template output ownership @@ -2838,7 +2915,8 @@ with evidence about meaningful risks, test ownership, gaps, and duplication. Keeping two remediation entries would create overlapping edits and two validation plans for one consolidation boundary. - Related findings: `AUD-039` -- Remediation reference: pending +- Remediation reference: Not applicable; consolidated into `AUD-039` and + Remediation Stage 32. ### AUD-064: Comparison test failure exits can leave workers blocked @@ -2873,7 +2951,7 @@ with evidence about meaningful risks, test ownership, gaps, and duplication. diagnosis and leaves no blocked comparison workers under the race detector or a goroutine-leak probe. - Related findings: `AUD-058` -- Remediation reference: pending +- Remediation reference: Remediation Stage 25. ### AUD-065: Weather collection duplicates one source and serializes independent requests @@ -2919,7 +2997,7 @@ with evidence about meaningful risks, test ownership, gaps, and duplication. than their sum; existing normalized fixture output and failure policy remain byte-for-byte or semantically unchanged as appropriate. - Related findings: `AUD-013`, `AUD-015` -- Remediation reference: pending +- Remediation reference: Remediation Stage 26. ### AUD-066: Comparison replacement repeatedly rereads complete bundles @@ -2964,7 +3042,7 @@ with evidence about meaningful risks, test ownership, gaps, and duplication. deliberate commit authorization without rereading any artifact inside a scan; recognized and adversarial bundles retain their current outcomes. - Related findings: `AUD-038`, `AUD-053`, `AUD-055` -- Remediation reference: pending +- Remediation reference: Remediation Stage 27. ### AUD-067: Daypart key canonicalization has two independent owners @@ -3004,7 +3082,7 @@ with evidence about meaningful risks, test ownership, gaps, and duplication. snapshot, prompt, and render boundaries; current default keys and rendered ordering remain unchanged. - Related findings: `AUD-024`, `AUD-025` -- Remediation reference: pending +- Remediation reference: Remediation Stage 9. ### AUD-068: Distributor single and batch templates duplicate one parser @@ -3040,7 +3118,7 @@ with evidence about meaningful risks, test ownership, gaps, and duplication. malformed inputs retain their actionable field names, and a parser mutation is detected once rather than by copied syntax suites. - Related findings: none -- Remediation reference: pending +- Remediation reference: Remediation Stage 28. ### AUD-069: Preparation retains parallel metadata authorities and unused render surfaces @@ -3089,7 +3167,7 @@ with evidence about meaningful risks, test ownership, gaps, and duplication. impossible or rejected, and template contexts contain no unused complete fact bundle. - Related findings: `AUD-029`, `AUD-040`, `AUD-063` -- Remediation reference: pending +- Remediation reference: Remediation Stage 14. ### AUD-070: Fact requirement policy spans constants, declarations, and switches @@ -3132,7 +3210,7 @@ with evidence about meaningful risks, test ownership, gaps, and duplication. requirements fail at registry creation, and existing omit/empty/error results remain unchanged for all reports. - Related findings: none -- Remediation reference: pending +- Remediation reference: Remediation Stage 29. ### AUD-071: Generate and comparison repeat report-date policy at four sites @@ -3172,7 +3250,7 @@ with evidence about meaningful risks, test ownership, gaps, and duplication. resolved dates for all four reports, and no duplicated report-kind switch remains in their date path. - Related findings: `AUD-009` -- Remediation reference: pending +- Remediation reference: Remediation Stage 30. ### AUD-072: Dormant internal compatibility and persistence surfaces have no workflow owner @@ -3226,7 +3304,7 @@ with evidence about meaningful risks, test ownership, gaps, and duplication. reference, prompt YAML and rendered reports remain unchanged, alert source hashes still cover accepted payloads, and the repository suite passes. - Related findings: `AUD-001`, `AUD-022`, `AUD-032`, `AUD-038`, `AUD-039` -- Remediation reference: pending +- Remediation reference: Remediation Stage 31. ### AUD-073: Duplicate capitalization helpers disagree on Unicode safety @@ -3261,7 +3339,7 @@ with evidence about meaningful risks, test ownership, gaps, and duplication. label remains valid UTF-8 with its first rune capitalized, and only one capitalization implementation remains. - Related findings: `AUD-024`, `AUD-025`, `AUD-067` -- Remediation reference: pending +- Remediation reference: Remediation Stage 10. ### AUD-074: CLI help and internal guidance disagree with action behavior @@ -3305,7 +3383,7 @@ with evidence about meaningful risks, test ownership, gaps, and duplication. run, and comparison failed-result tests remain silent under `--quiet`; and CLI internals name all three action families. - Related findings: `AUD-010`, `AUD-071` -- Remediation reference: pending +- Remediation reference: Remediation Stage 4. ### AUD-075: Internal guides describe nonexistent APIs, flows, and tests @@ -3353,7 +3431,7 @@ with evidence about meaningful risks, test ownership, gaps, and duplication. caller, every claimed focused behavior is discoverable in the listed test package, and internal-document links still resolve. - Related findings: `AUD-001`, `AUD-003`, `AUD-072` -- Remediation reference: pending +- Remediation reference: Remediation Stage 33. ### AUD-076: Completed comparison roadmaps duplicate current contracts @@ -3399,7 +3477,7 @@ with evidence about meaningful risks, test ownership, gaps, and duplication. command, artifact, and lifecycle contract; active roadmaps contain only future or audit coordination work; all repository links resolve. - Related findings: none -- Remediation reference: pending +- Remediation reference: Remediation Stage 34. ### AUD-077: Concurrent executor substitutability is only implicit @@ -3441,7 +3519,7 @@ with evidence about meaningful risks, test ownership, gaps, and duplication. call requirement, the Promptkit adapter remains race-clean, and single-report executors retain unchanged behavior. - Related findings: `AUD-058` -- Remediation reference: pending +- Remediation reference: Remediation Stage 22. ### AUD-078: Configuration normalization and timezone bounds are underdocumented @@ -3486,7 +3564,7 @@ with evidence about meaningful risks, test ownership, gaps, and duplication. accepted, representative out-of-range offsets are rejected, and the configuration reference agrees with focused parser tests. - Related findings: none -- Remediation reference: pending +- Remediation reference: Remediation Stage 2. ## Retained Decisions @@ -6001,16 +6079,50 @@ remediation is intentionally left to Stage 27. - Open questions: none; remediation and dynamic-validation leads are routed above without changing later-stage scope. +### Stage 25: Run Dynamic Robustness And Final Diagnostic Validation + +- Status: Complete. +- Scope reviewed: the complete default suite and CLI help path, race-enabled + execution, three shuffled repetitions, vet, statement coverage, critical + weak branches, whitespace validity, and worktree artifact cleanup. +- Exclusions: no live service, real credential, production mutation, or + remediation was introduced. Coverage remained diagnostic rather than a + percentage target. + +#### Commands And Evidence + +- Ran `GOWORK=off go test -count=1 ./...`; all packages passed. +- Ran `GOWORK=off go test -race -count=1 ./...`; all packages passed with no + race report. +- Ran `GOWORK=off go test -shuffle=on -count=3 ./...`; all three shuffled + repetitions passed with no order-dependent or intermittent failure. +- Ran `GOWORK=off go vet ./...` and + `GOWORK=off go run ./cmd/weatherreporter --help`; both passed. +- Ran `GOWORK=off go test -coverprofile=coverage.out ./...` and inspected the + function/package report. Total statement coverage was 79.4%. Lower coverage + remained concentrated in thin production wrappers, defensive accessors, + report/time helpers, and dormant surfaces already owned by `AUD-003`, + `AUD-052`, and `AUD-072`; no additional consequential unowned branch became + a finding. +- Ran `git diff --check`; it passed. Removed `coverage.out` and verified no + generated diagnostic artifact remained. +- Findings: none new. Dynamic execution strengthened the existing evidence for + the test, cancellation, concurrency, diagnostic-boundary, and publication + findings without changing their ownership. +- Retained decisions: all existing decisions remained consistent with the + dynamic results. +- Open questions: none. + ### Stage 26: Verify, Consolidate, And Triage Findings - Status: Complete. - Scope reviewed: all 78 candidate findings, all 61 retained decisions, every routed open question, finding-specific validation and test implications, the stage-coverage table, and every risk-to-test coverage entry. -- Exclusions: Stage 25 remains pending because its interrupted results were not - promoted into audit evidence. No production code, test code, canonical - documentation, implementation priority, acceptance decision, or remediation - sequence was changed; those remain Stage 27 work. +- Exclusions: no production code, test code, canonical documentation, + implementation priority, acceptance decision, or remediation sequence was + changed; those remain Stage 27 work. Stage 25's interrupted evidence was + rerun and recorded during final audit closure rather than inferred. #### Final Disposition @@ -6081,3 +6193,51 @@ directly established. rejected as standalone duplicates. - Retained decisions: `RET-001` through `RET-061` revalidated. - Open questions: none. + +### Stage 27: Produce The Remediation Roadmap And Close The Audit + +- Status: Complete. +- Scope reviewed: all 74 confirmed findings, all 61 retained decisions, final + coverage and risk matrices, discovery exclusions, repository-wide validation, + canonical documentation ownership, dependency ordering, one-prompt stage + sizing, and roadmap lifecycle requirements. +- Exclusions: no finding was remediated; no production code, tests, + dependencies, embedded assets, maintained examples, canonical current-state + documents, ADRs, or release notes changed. + +#### Acceptance And Allocation + +- Accepted all 74 confirmed findings for implementation. None was priority- + deferred, and the evidence was sufficient to choose a corrective direction + without a separate product or architecture decision. +- Created `docs/roadmap/audit-remediation.md` with 35 independently executable + stages. Each stage names its findings, affected areas, work, locked behavior, + test expectations, canonical documentation owners, and exit commands. +- Allocated every confirmed finding exactly once. Correctness, security, data + integrity, destructive operations, cancellation, and compatibility precede + efficiency, behavior-preserving refactoring, test cleanup, and documentation + retirement. Refactors that must preserve behavior have their own stages + after related behavioral fixes. +- Kept the four rejected standalone findings out of the allocation: `AUD-001`, + `AUD-022`, and `AUD-032` remain consolidated into `AUD-072`; `AUD-063` + remains consolidated into `AUD-039`. +- Recorded a final lifecycle gate that removes temporary audit records only + after remediation is complete and useful contracts/rationale live with their + durable canonical owners. + +#### Final Verification + +- Re-ran and recorded the complete Stage 25 command set on the current checkout + to close the previously interrupted evidence gap. All commands passed, + coverage remained 79.4%, and `coverage.out` was removed. +- Verified mechanically that all 78 ledger entries have final statuses, every + confirmed finding has one remediation-stage reference, rejected entries have + no independent remediation assignment, and the roadmap allocation contains + each confirmed ID exactly once. +- Ran repository link/reference checks for the new roadmap, `git diff --check`, + and worktree-scope checks. Only `docs/roadmap/audit.md` and + `docs/roadmap/audit-remediation.md` changed during Stage 27. +- Findings: no new audit findings. +- Retained decisions: `RET-001` through `RET-061` remain valid and are encoded + as locked behavior or reconsideration constraints where relevant. +- Open questions and unresolved scope gaps: none.