Files
weatherreporter/docs/roadmap/implementation.md

911 lines
46 KiB
Markdown

# 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 risk and
the default remediation order, not confidence; dependency prerequisites may
place a lower-priority consolidation mechanism before the P1 correction that
depends on it. 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-14, 16-21, 24-37 | `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 | 38-43 | `AUD-059` through `AUD-062`, `AUD-064`, `AUD-065`, and `AUD-066` | Accepted now |
| P3: behavior-preserving consolidation and cleanup | 15, 22-23, 44-52 | `AUD-039`, `AUD-067` through `AUD-072` | Accepted now; Stages 15 and 22-23 run early because P1 corrections depend on them |
| P4: documentation lifecycle and audit retirement | 53-56 | `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 Keys And Overrides Explicit
- Findings: `AUD-004`, `AUD-006`, `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; 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: focused config and CLI tests, followed by the standard
repository commands.
### Stage 3: Make Secret Loading Atomic
- Findings: `AUD-007`.
- Affected areas: configuration loading, secret-directory application, load
failure state, and focused configuration tests.
- Work: stage secret values and apply them to the returned configuration only
after the complete load and validation sequence succeeds.
- Locked behavior: secret precedence, configured secret-directory discovery,
environment independence, actionable errors, and redaction remain unchanged.
- Documentation owners: `docs/config.md` only if the observable load contract
needs clarification.
- Exit commands: focused config tests plus
`GOWORK=off go test -race -count=1 ./internal/config`, followed by the
standard repository commands.
### Stage 4: 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 5: Propagate Process Interrupt Cancellation
- Findings: `AUD-008`.
- Affected areas: `cmd/weatherreporter`, action contexts, CLI wiring, and
interrupt/cancellation tests.
- Work: convert operating-system interrupts into action-context cancellation
and verify active generation, batch, and comparison workflows observe it.
- Locked behavior: command/flag ownership, structured summary shapes, stream
separation, and one executor per action remain unchanged.
- Documentation owners: `docs/cli.md`, `docs/operations.md`, and
`docs/internal/cli.md` if signal behavior needs clarification.
- Exit commands: `GOWORK=off go test -race -count=1 ./internal/cli
./internal/app ./cmd/weatherreporter`, then the standard repository commands.
### Stage 6: Correct CLI Preflight, Coverage, And Visible Contracts
- Findings: `AUD-009`, `AUD-010`, `AUD-074`.
- Affected areas: `internal/cli`, executor construction, assembled CLI tests,
help text, and CLI documentation.
- Work: 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, cancellation from Stage 5, and one executor per action remain
unchanged.
- Documentation owners: `docs/cli.md` and `docs/internal/cli.md`.
- Exit commands: focused CLI/app tests, both root and comparison help commands,
then the standard repository commands.
### Stage 7: Validate Weather API Endpoints And Retry Classification
- Findings: `AUD-011`, `AUD-015`.
- Affected areas: Weather API configuration and adapter construction, warmup
retry classification, local HTTP fixtures, and focused tests.
- Work: accept only supported endpoint forms 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`,
and `docs/internal/collect.md` as applicable.
- Exit commands: focused configuration, adapter, and collection tests, then the
standard repository commands.
### Stage 8: Bound And Redact Weather API Diagnostics
- Findings: `AUD-012`, `AUD-013`.
- Affected areas: Weather API response reading, non-success error projection,
size limits, local HTTP fixtures, and focused adapter tests.
- Work: replace upstream response text with bounded safe diagnostics and reject
rather than silently truncate oversized bodies.
- Locked behavior: HTTP status classification, source-local error context,
cancellation, and offline tests remain intact.
- Documentation owners: `docs/integrations/weatherapi.md` and
`docs/internal/collect.md` if observable limits or diagnostics change.
- Exit commands: focused boundary-size and malicious-response adapter tests,
then the standard repository commands.
### Stage 9: Require Usable Hourly Period Bounds
- Findings: `AUD-014`.
- Affected areas: Weather API hourly decoding, normalized hourly data,
required-source validation, fixtures, and focused tests.
- Work: reject required hourly products whose periods do not contain usable
time bounds before they enter collection and derivation.
- Locked behavior: required/optional source policy, source provenance,
chronological selection, and valid hourly fixtures remain unchanged.
- Documentation owners: `docs/integrations/weatherapi.md`,
`docs/internal/weather-data.md`, and `docs/internal/collect.md`.
- Exit commands: focused weather-data, adapter, and collection tests, then the
standard repository commands.
### Stage 10: Correct Civil-Time Windows And Daily Run Identity
- Findings: `AUD-002`, `AUD-003`.
- Affected areas: `internal/timeutil`, Daily report identity, DST and run-ID
tests, and report-registry documentation.
- Work: construct configured clocks as local civil times across both DST
transitions and add durable protection for Daily run-ID uniqueness.
- Locked behavior: half-open selection, civil-day report periods, rolling
Hourly elapsed time, and source-period identity remain unchanged.
- Documentation owners: `docs/internal/report-registry.md`.
- Exit commands: focused time/report tests with both DST transitions, then the
standard repository commands.
### Stage 11: Preserve Units And Overnight Alert Coverage
- Findings: `AUD-016`, `AUD-017`.
- Affected areas: `internal/forecast`, `internal/facts`, metric fallback
values, overnight dayparts, alerts, and focused tests.
- Work: preserve units in fallback values and include alerts over the complete
overnight interval.
- Locked behavior: half-open overlap semantics, chronological ordering, source
periods, and valid US-customary results remain unchanged.
- Documentation owners: `docs/internal/forecast-derivation.md` and
`docs/internal/facts.md`.
- Exit commands: focused forecast/facts tests with metric and overnight cases,
then the standard repository commands.
### Stage 12: Validate Precipitation And Ice Classification
- Findings: `AUD-018`, `AUD-019`.
- Affected areas: precipitation-domain validation, weather-text
classification, derived summaries, and focused forecast/facts tests.
- Work: reject precipitation probabilities outside the percentage domain and
classify ordinary icy wording consistently.
- Locked behavior: valid percentage handling, summary ordering, and existing
weather-condition categories remain unchanged.
- Documentation owners: `docs/internal/forecast-derivation.md` and
`docs/internal/facts.md`.
- Exit commands: focused forecast/facts boundary tests, then the standard
repository commands.
### Stage 13: 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 14: 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 15: 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 16: 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 15'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 17: 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 18: Harden Prompt-Debug Redaction
- Findings: `AUD-034`.
- Affected areas: `internal/promptdebug`, Promptkit debug callbacks, endpoint
redaction, and adversarial content tests.
- Work: redact common credential aliases and URL credential forms from every
explicit debug artifact and error projection.
- 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 redaction tests, then the
standard repository commands.
### Stage 19: Make Prompt-Debug Filesystem Traversal Race-Resistant
- Findings: `AUD-035`.
- Affected areas: `internal/promptdebug`, secure directory and file creation,
Promptkit debug callbacks, and adversarial filesystem tests.
- Work: replace pathname check/use gaps with a race-resistant secure traversal
and creation strategy while preserving atomic replacement and actionable
failures.
- Locked behavior: Stage 18 redaction, explicit opt-in, `0700` directories,
`0600` files, deterministic references, containment, and ordinary concurrent
execution remain unchanged.
- 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 20: Enforce Generated-Text Identity And Shape
- Findings: `AUD-036`, `AUD-037`.
- Affected areas: generated-text catalog, decoders, schemas, typed validators,
and focused tests.
- Work: require report-specific schema/template pairs; reject case-variant
properties that schemas reject.
- Locked behavior: typed normalization, exact registered identities, schema
copy isolation, and valid generated content remain unchanged.
- Documentation owners: `docs/internal/generatedtext.md` and template docs.
- Exit commands: focused generated-text and promptassets tests, then the
standard repository commands.
### Stage 21: Bound Generated Content And Diagnostics
- Findings: `AUD-038`.
- Affected areas: generated-text decoders and typed validators, schemas,
Promptkit result handling, safe error projection, and boundary tests.
- Work: bound prose, arrays, total generated content, and diagnostic context
before allocation or normal error projection.
- Locked behavior: Stage 20 identity/shape enforcement, typed normalization,
valid generated content, and content-safe normal summaries 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 at and around
every limit, then the standard repository commands.
### Stage 22: Establish The Prepared Metadata Authority
- Findings: `AUD-069`.
- Affected areas: briefing metadata construction, prepared reports, identity
and timing values, and focused app/briefing tests.
- Work: define one prepared identity/timing authority, populate it at the
preparation boundary, and lock its equivalence to current valid output.
- 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`.
- Exit commands: focused briefing and app tests, then the standard repository
commands.
### Stage 23: Migrate Prepared Metadata Projections
- Findings: none; this completes the remediation begun in Stage 22.
- Affected areas: prompt metadata projection, render-context inputs, superseded
parallel fields, and focused prompt/render tests.
- Work: route prompt and render projections through Stage 22's authority, then
remove or narrow superseded fields without changing serialized YAML or
rendered Markdown.
- Locked behavior: Stage 22's authority, 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 24: Enforce Render Identity And Empty-Section Behavior
- Findings: `AUD-040`, `AUD-042`.
- Affected areas: render-context builders, Today templates/partials, and
focused context/rendering tests.
- Work: reject conflicting report identities and suppress or replace a Today
daypart section that has no rows or fallback.
- 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, then the
standard repository commands.
### Stage 25: Prevent Generated Prose From Impersonating Markdown Structure
- Findings: `AUD-041`.
- Affected areas: generated prose insertion, Markdown templates/partials,
renderer policy, and adversarial rendering tests.
- Work: define and enforce the smallest content-handling rule that prevents
generated prose from creating structure that impersonates deterministic
report sections.
- Locked behavior: repository templates remain Markdown owners, deterministic
facts remain authoritative, ordinary generated prose remains readable, 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 with
adversarial headings and related Markdown constructs, then the standard
repository commands.
### Stage 26: Move Prompt Compatibility Checks Before Collection
- Findings: `AUD-043`.
- Affected areas: application prompt inspection and preparation,
generated-text catalog preflight, collection ordering, and app tests.
- Work: validate catalog compatibility before collection or other expensive
report work begins.
- 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 and generatedtext tests proving failure ordering,
then the standard repository commands.
### Stage 27: Reconcile Prompt Execution Provenance
- Findings: `AUD-044`.
- Affected areas: prompt inspection, prepared execution values, callbacks,
completed execution results, schema validation, and app tests.
- Work: reconcile inspected, prepared, callback, completed, and schema
identities before accepting generated output.
- Locked behavior: Stage 26 preflight ordering, one inspection/preparation,
profile precedence, immutable execution copies, and partial 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 with mismatched
provenance at each boundary, then the standard repository commands.
### Stage 28: Preflight Single-Report Temporary Names
- Findings: `AUD-046`.
- Affected areas: app output planning, bounded temporary naming, destination
validation, directory creation, and focused filesystem tests.
- Work: detect temporary-name and basename limits during preflight without
leaving newly created directories after failure.
- Locked behavior: destination selection, same-directory atomic visibility,
final filenames, and existing regular-file preservation remain unchanged.
- Documentation owners: `docs/operations.md` and app orchestration internals if
preflight behavior needs clarification.
- Exit commands: focused fileutil/app/CLI long-name tests, then the standard
repository commands.
### Stage 29: Make Single-Report Publication Type-Safe And Cancelable
- Findings: `AUD-045`, `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
from Stage 28; 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 30: Validate Distributor Endpoints Before Publication
- Findings: `AUD-048`.
- Affected areas: Distributor configuration validation, app preflight,
endpoint construction, and focused config/app tests.
- Work: reject unsupported endpoint forms before report publication.
- 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`, and Distributor
integration docs.
- Exit commands: focused config and app preflight tests, then the standard
repository commands.
### Stage 31: Bound Distributor Diagnostics And Exercise The HTTP Boundary
- Findings: `AUD-049`, `AUD-050`, `AUD-052`.
- Affected areas: Distributor adapter, pinned client interaction, response
reading and classification, local HTTP tests, and safe batch diagnostics.
- Work: bound response reads; redact or classify remote text before normal
results; and exercise the real production HTTP boundary with a local server.
- Locked behavior: Stage 30 endpoint validation, exactly-once upload/status
mapping, published-file source selection, token redaction, and adapter-local
dependency types remain unchanged.
- Documentation owners: `docs/operations.md`,
`docs/internal/distributor-adapter.md`, and Distributor integration docs.
- Exit commands: focused distributor/app tests including oversized and
malicious response bodies, then the standard repository commands.
### Stage 32: 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 33: 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 34: Preflight Comparison Sibling Names
- Findings: `AUD-057`.
- Affected areas: comparison destination planning, staging and backup sibling
naming, parent directory creation, and focused filesystem tests.
- Work: validate derived sibling-name constraints during preflight and fail
without leaving residual directories.
- Locked behavior: exact target selection, sibling staging, broad-target
rejection, and valid destination names remain unchanged.
- Documentation owners: comparison publication internals and operations if
preflight behavior needs clarification.
- Exit commands: focused comparison/app long-name tests, then the standard
repository commands.
### Stage 35: Honor Cancellation At Comparison Replacement Commit
- Findings: `AUD-055`.
- Affected areas: comparison replacement transaction, cancellation
linearization, rollback, and deterministic filesystem tests.
- Work: honor cancellation after moving the prior bundle but before installing
the replacement, restoring or retaining the prior bundle according to the
transaction's recovery rules.
- Locked behavior: Stage 34 preflight, post-move authorization, no forced
destructive cleanup, rollback, and committed-new-bundle truth remain.
- Documentation owners: comparison bundle/publication docs and operations.
- Exit commands: focused comparison/app cancellation tests plus
`GOWORK=off go test -race -count=1 ./internal/comparison ./internal/app`,
then the standard repository commands.
### Stage 36: Represent Comparison Backup Recovery Truthfully
- Findings: `AUD-056`.
- Affected areas: comparison backup cleanup, publication result/error state,
app/CLI recovery projection, and deterministic filesystem tests.
- Work: distinguish a complete retained recovery bundle from a partially
removed backup and report the actual recoverable state without deleting the
committed new bundle.
- Locked behavior: post-move authorization, rollback, no forced destructive
cleanup, Stage 35 cancellation behavior, 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 37: 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 38: 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 39: 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 40: 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 41: Remove The Redundant Weather Warmup Fetch
- Findings: `AUD-065`.
- Affected areas: Weather API warmup and current-conditions acquisition,
retry semantics from Stage 7, request counts, and adapter/collection tests.
- Work: reuse the successful warmup response or remove the redundant warmup so
current conditions are not fetched and decoded twice.
- Locked behavior: source-local validation/errors, exact source order,
required/optional policy, Stage 7 retry policy, and context cancellation
remain authoritative.
- Documentation owners: Weather API integration and collection internals if
operational request behavior changes materially.
- Exit commands: focused request-count and retry tests, then the standard
repository commands.
### Stage 42: Acquire Independent Weather Sources Concurrently
- Findings: none; this completes the efficiency remediation begun in Stage 41.
- Affected areas: Weather API bundle acquisition, request-result aggregation,
provenance ordering, cancellation, and adapter/collection tests.
- Work: execute independent source requests concurrently and merge their
results in one deterministic source order.
- Locked behavior: Stage 41 current-response handling, source-local
validation/errors, exact source order, required/optional policy, Stage 7
retry policy, and context cancellation remain authoritative.
- Documentation owners: Weather API integration and collection internals if
operational request behavior changes materially.
- Exit commands: focused latency, deterministic-order, failure, and
cancellation tests plus
`GOWORK=off go test -race -count=1 ./internal/adapters/weatherapi
./internal/collect`, then standard commands.
### Stage 43: 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
Stages 34-36 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 44: 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 45: Define One Fact Requirement Vocabulary
- Findings: `AUD-070`.
- Affected areas: module requirement vocabulary, current briefing definitions,
identity/category metadata, and focused module/briefing tests.
- Work: define each requirement's identity and category once, preserve each
module's explicit requirement list, and lock equivalence with current valid
compositions.
- 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 and briefing catalog tests, then the standard
repository commands.
### Stage 46: Migrate Fact Availability And Constructor Validation
- Findings: none; this completes the remediation begun in Stage 45.
- Affected areas: availability predicates, briefing constructors, legacy
switches, configuration validation, and focused tests.
- Work: route availability and constructor validation through Stage 45's
requirement vocabulary and remove superseded policy implementations.
- Locked behavior: all current compositions, supported reports, missing-data
policy, availability, and diagnostic identity remain unchanged.
- Documentation owners: module and briefing internals if ownership changes.
- Exit commands: focused module/briefing/config tests, then the standard
repository commands.
### Stage 47: 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 6 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 48: Retire Dormant Prompt And Generated-Text Surfaces
- Findings: `AUD-072`.
- Affected areas: unused prompt YAML loading/saving, normalized generated JSON
returns, and their sole-purpose tests and documentation.
- Work: verify these prompt/generated-text compatibility surfaces still have no
production owner, then remove them. If a production consumer appears, stop
and replace this retirement sequence with a separately approved contract.
- Locked behavior: normal Build/Validate/MarshalYAML, report publication,
comparison data packages, prompt debugging, typed normalization, and all
workflows remain unchanged.
- Documentation owners: prompt-input and generated-text internal documents;
remove stale descriptions rather than documenting retired APIs.
- Exit commands: graph/text caller checks, focused promptinput/generatedtext
tests, then the standard repository commands.
### Stage 49: Retire Dormant Weather Persistence Helpers
- Findings: none; this continues the dormant-surface remediation begun in
Stage 48.
- Affected areas: Weather API bundle saving, the JSON atomic helper if it
becomes orphaned, and sole-purpose tests and documentation.
- Work: verify these persistence helpers still have no workflow owner, then
remove them and any helper made unreachable by that removal. If a production
consumer appears, stop and seek a separately approved contract.
- Locked behavior: weather collection, normalized in-memory bundles, prompt
debugging, operator-owned publication, and all workflows remain unchanged.
- Documentation owners: weather-data and collection internals where stale
persistence claims exist.
- Exit commands: graph/text caller checks, focused weatherapi/weatherdata/
fileutil tests, then the standard repository commands.
### Stage 50: Retire Dormant Module And Forecast Compatibility Exports
- Findings: none; this continues the dormant-surface remediation begun in
Stage 48.
- Affected areas: module snapshot compatibility implications, unused forecast
threshold exports, and sole-purpose tests and documentation.
- Work: verify the identified exports still have no production owner, then
remove them without broadening the supported compatibility contract. If a
production consumer appears, stop and seek a separately approved contract.
- Locked behavior: current module snapshots, real forecast decisions, prompt
exports, report rendering, and all workflows remain unchanged.
- Documentation owners: module, briefing, and forecast internals where stale
compatibility claims exist.
- Exit commands: graph/text caller checks, focused module/briefing/forecast
tests, then the standard repository commands.
### Stage 51: Narrow Dormant Alert Envelope Copies
- Findings: none; this completes the dormant-surface remediation begun in
Stage 48.
- Affected areas: unused full alert-envelope copies, retained alert item
provenance, and sole-purpose tests and documentation.
- Work: remove unconsumed alert-envelope data while retaining exactly the item
and provenance values required by current facts, briefing, and report paths.
If a production consumer appears, stop and seek a separately approved
contract.
- Locked behavior: alert selection, alert item provenance, briefing digests,
report rendering, and all workflows remain unchanged.
- Documentation owners: weather-data, facts, and briefing internals where the
narrowed value is described.
- Exit commands: graph/data-flow checks plus focused weatherdata/facts/
briefing tests, then the standard repository commands.
### Stage 52: 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 53: 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 54: 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 55: Verify Remediation Completion And Durable Ownership
- Findings: none; this is the roadmap lifecycle gate.
- Prerequisite: Stages 1-54 are complete and every referenced finding's tests
and canonical documentation have landed.
- Affected areas: every remediation completion note, canonical documentation
owner, audit finding, retained decision, and incoming audit-document link.
- Work: verify every finding is resolved, superseded, or explicitly moved to a
newly approved roadmap; verify durable rationale lives with its canonical
owner; and produce a concise removal checklist for the temporary audit plan,
ledger, and remediation roadmap. Do not remove those records in this stage.
- 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: verify every stage/finding mapping and completion note;
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`.
### Stage 56: Retire The Completed Audit Records
- Findings: none; this is the final documentation lifecycle change.
- Prerequisite: Stage 55 has verified completion and supplied the exact removal
and link-repair checklist.
- Affected areas: `docs/roadmap/audit.md`, `audit-plan.md`, this roadmap, and
their incoming links.
- Work: apply Stage 55's checklist, repair incoming navigation, and remove the
temporary audit plan, ledger, and remediation roadmap without changing
executable behavior or historical records.
- Locked behavior: documentation lifecycle only; durable current contracts and
rationale remain with their canonical owners, and ADRs and release notes are
unchanged.
- Documentation owners: only the navigation or durable owner files identified
by Stage 55.
- Exit commands: repository link/fence and secret-pattern checks;
`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. A stage that
begins a multi-stage remediation sequence must not mark its finding resolved
until the final continuation stage succeeds. Do not copy implemented contracts
into this roadmap. When all work is complete, follow Stages 55 and 56 rather
than retaining this file as a parallel reference.