24 KiB
Repository Audit Ledger
Status: In progress; Stages 1-2 complete.
This temporary roadmap document is the evidence ledger for the staged audit defined by the audit plan. It records audit evidence and status, not implemented product behavior. Current contracts remain with the canonical owners identified by the documentation policy.
Executive Summary
Stage 1 established a clean, reproducible baseline. The repository-wide test suite, CLI help check, formatting check, and vet check all pass. Stage 2 found that the implemented package graph and principal workflows follow the intended dependency direction and assigned ownership. It recorded one low-severity candidate finding for unused internal persistence helpers left outside the documented stateless workflows. Subsystem conclusions and final disposition remain pending the later stages.
Baseline Metadata
| Item | Recorded baseline |
|---|---|
| Audit date | 2026-08-12 (UTC) |
| Commit | e7c7262404ba0e8e74009ed840d38f7a0142b347 (Add audit workflow plan) |
| Expected commit from audit plan | 151c536cb91ebedb6039270b752bae219dfe33d0 (Add comparison diagnostics to the future roadmap) |
| Baseline difference | The audit uses the current main, one commit ahead of the expected commit. The intervening commit adds the audit workflow plan used to conduct this audit. |
| Branch | main |
| Initial worktree | Clean; git status --porcelain=v1 produced no entries before the audit ledger was created. |
| Go toolchain | go version go1.26.5 linux/amd64; go env GOVERSION reported go1.26.5. |
| Module | gitea.maximumdirect.net/eric/weatherreporter; module file /home/eric/Workspace/weatherreporter/go.mod; go 1.26. |
| Workspace context | Module mode with no go.work; go env GOWORK was empty and the repository contains only ./go.mod. |
| Graph project | home-eric-Workspace-weatherreporter |
| Graph refresh | Refreshed from the baseline checkout in moderate mode without a persisted artifact: 2,674 nodes and 11,572 edges. The indexer excluded docs, examples, embedded-asset directories, and test-data directories, so their inventories below come from tracked files rather than the graph. |
| Baseline exclusions | None. There were no pre-existing worktree changes. |
| Environmental limitations | None encountered. Validation was deterministic and offline. |
Scope And Inventory
Stage 1 inventories the checked-out repository without judging subsystem correctness or test sufficiency. The repository has 219 tracked files. Its Go inventory contains 24 packages, 83 non-test source files, and 50 test files.
Go Packages And Files
| Package directory | Production .go files |
_test.go files |
|---|---|---|
cmd/weatherreporter |
1 | 0 |
internal/adapters/distributor |
1 | 1 |
internal/adapters/promptkit |
1 | 1 |
internal/adapters/weatherapi |
1 | 1 |
internal/app |
10 | 11 |
internal/briefing |
21 | 6 |
internal/buildinfo |
1 | 0 |
internal/cli |
4 | 5 |
internal/collect |
1 | 1 |
internal/comparison |
2 | 2 |
internal/config |
7 | 2 |
internal/facts |
1 | 1 |
internal/fileutil |
1 | 1 |
internal/forecast |
3 | 1 |
internal/generatedtext |
8 | 7 |
internal/module |
1 | 1 |
internal/promptassets |
1 | 1 |
internal/promptdebug |
1 | 1 |
internal/promptexec |
2 | 1 |
internal/promptinput |
1 | 1 |
internal/report |
8 | 1 |
internal/reporttemplate |
2 | 1 |
internal/timeutil |
3 | 2 |
internal/weatherdata |
1 | 1 |
| Total | 83 | 50 |
Fixtures
Nine tracked fixtures are present:
internal/adapters/weatherapi/testdata/alerts.jsoninternal/adapters/weatherapi/testdata/convective_outlooks.jsoninternal/adapters/weatherapi/testdata/current.jsoninternal/adapters/weatherapi/testdata/discussion.jsoninternal/adapters/weatherapi/testdata/hourly.jsoninternal/adapters/weatherapi/testdata/narrative.jsoninternal/adapters/weatherapi/testdata/observations.jsoninternal/adapters/weatherapi/testdata/weather_story.jsoninternal/forecast/testdata/daily_bundle.json
Embedded Assets
The three //go:embed declarations cover 26 tracked assets:
- one SPC definition file under
internal/briefing/assets/; - three Promptkit profiles, ten prompt files, and four generated-text schemas
under
internal/promptassets/assets/; and - four report templates and four template partials under
internal/reporttemplate/templates/.
The exact embedding owners are
internal/briefing/spc_convective_outlook_definitions.go,
internal/promptassets/promptassets.go, and
internal/reporttemplate/reporttemplate.go.
Canonical Documents And Maintained Examples
There are 38 tracked, non-roadmap canonical documents and three maintained example files. The canonical inventory is:
- product and maintainer references:
README.md,docs/cli.md,docs/config.md,docs/development.md,docs/operations.md,docs/release.md, anddocs/templates.md; - policies:
docs/policy/architecture.md,docs/policy/documentation.md, anddocs/policy/testing.md; - architecture decisions:
docs/adr/0001-stateless-execution.md; - integration contracts:
docs/integrations/comparison-bundle.md,docs/integrations/promptkit.md,docs/integrations/weatherapi.md, and the three documents underdocs/integrations/distributor/; - internal documents: all 17 tracked documents under
docs/internal/; and - release notes: the four tracked documents under
docs/releases/.
The maintained examples are examples/config.yml,
examples/minimal-config.yml, and
examples/weather-light-local-profile.yml. Roadmaps are coordination records,
not canonical current-state documents; the four pre-existing roadmap files are
therefore outside the canonical count.
Baseline Validation
| Command | Result | Evidence |
|---|---|---|
go test ./... |
Pass | Exit 0. All 24 packages were evaluated; 22 package test suites passed and cmd/weatherreporter plus internal/buildinfo reported no test files. |
go run ./cmd/weatherreporter --help |
Pass | Exit 0. Help printed usage for help, version, four report generators, two batch commands, and comparison. |
git diff --check |
Pass | Exit 0 with no output on the clean pre-ledger baseline. |
go vet ./... |
Pass | Exit 0 with no diagnostics. |
Supplementary baseline commands were git rev-parse HEAD,
git rev-list --left-right --count 151c536...HEAD,
git status --porcelain=v1, git branch --show-current, go version,
go env GOVERSION GOMOD GOWORK GO111MODULE, go list ./..., tracked-file
inventory commands, graph index refresh, and graph architecture inspection.
Stage Coverage
| Stage | Scope | Status |
|---|---|---|
| 1 | Establish the baseline and audit ledger | Complete |
| 2 | Audit architecture and dependency direction | Complete |
| 3 | Audit report identity and time foundations | Pending |
| 4 | Audit configuration, secrets, and validation | Pending |
| 5 | Audit CLI parsing, wiring, and output contracts | Pending |
| 6 | Audit weather data acquisition and collection | Pending |
| 7 | Audit forecast and fact derivation | Pending |
| 8 | Audit module contracts, registry, and source-facing briefing modules | Pending |
| 9 | Audit derived, planning, formatting, and SPC briefing modules | Pending |
| 10 | Audit prompt inputs, assets, and neutral execution contracts | Pending |
| 11 | Audit Promptkit adaptation and secure prompt debugging | Pending |
| 12 | Audit generated-text validation and catalog contracts | Pending |
| 13 | Audit render contexts, templates, and Markdown rendering | Pending |
| 14 | Audit application preparation and prompt preflight | Pending |
| 15 | Audit single-report generation and atomic output | Pending |
| 16 | Audit batch orchestration and Distributor notification | Pending |
| 17 | Audit comparison contracts and transactional publication | Pending |
| 18 | Audit comparison execution and CLI integration | Pending |
| 19 | Audit test hermeticity and execution hygiene | Pending |
| 20 | Audit test risk coverage and ownership | Pending |
| 21 | Audit test durability, duplication, and maintenance cost | Pending |
| 22 | Audit cross-cutting efficiency and complexity | Pending |
| 23 | Audit cross-cutting refactoring and deduplication opportunities | Pending |
| 24 | Audit documentation coherence and executable contracts | Pending |
| 25 | Run dynamic robustness and final diagnostic validation | Pending |
| 26 | Verify, consolidate, and triage findings | Pending |
| 27 | Produce the remediation roadmap and close the audit | Pending |
Risk-To-Test Coverage
Stage 1 records where tests exist but does not infer sufficiency from package counts or a passing suite. Assigned stages will replace these pending entries with evidence about meaningful risks, test ownership, gaps, and duplication.
| Risk area | Current test owner or evidence source | Audit stage | Coverage assessment |
|---|---|---|---|
| Architecture and dependency direction | Assembled app and CLI tests; graph traces | 2 | Sufficient at the architectural boundary: direct imports are acyclic, external dependency types remain adapter-local, and representative workflow ordering and publication boundaries have focused tests. AUD-001 records unused persistence APIs that do not participate in normal execution. |
| Report identity, periods, dates, and timezones | internal/report, internal/timeutil |
3 | Pending |
| Configuration, validation, and secrets | internal/config |
4 | Pending |
| CLI parsing, output, and exit behavior | internal/cli |
5 | Pending |
| Weather transport and normalized collection | internal/adapters/weatherapi, internal/collect, internal/weatherdata |
6 | Pending |
| Forecast and fact derivation | internal/forecast, internal/facts |
7 | Pending |
| Module and briefing contracts | internal/module, internal/briefing |
8-9 | Pending |
| Prompt inputs, embedded assets, and execution contracts | internal/promptinput, internal/promptassets, internal/promptexec |
10 | Pending |
| Promptkit boundary and sensitive debug output | internal/adapters/promptkit, internal/promptdebug |
11 | Pending |
| Generated-text validation | internal/generatedtext |
12 | Pending |
| Render contexts and templates | internal/generatedtext, internal/reporttemplate |
13 | Pending |
| Prompt preflight and prepared inputs | internal/app |
14 | Pending |
| Single-report publication and preservation | internal/app, internal/fileutil |
15 | Pending |
| Batch partial success and notification | internal/app, internal/adapters/distributor |
16 | Pending |
| Comparison identity and transactional publication | internal/comparison |
17 | Pending |
| Comparison concurrency and CLI behavior | internal/app, internal/cli |
18 | Pending |
| Hermeticity, execution hygiene, portfolio coverage, and durability | Repository-wide suite | 19-21 | Pending |
| Cross-cutting efficiency and maintainability | Graph metrics plus focused tests | 22-23 | Pending |
| Documentation and executable-contract coherence | Canonical documents, code, schemas, templates, examples | 24 | Pending |
| Dynamic robustness and diagnostic checks | Repository-wide deterministic checks | 25 | Pending |
Findings
AUD-001: Unused persistence helpers remain after the stateless redesign
- Stage: 2
- Status: candidate
- Severity: low
- Confidence: high
- Category: architecture
- Area:
internal/promptinput.Save,internal/adapters/weatherapi.SaveBundle, andinternal/fileutil.WriteJSONAtomic - Evidence: Graph inbound traces show
promptinput.Savehas no callers,weatherapi.SaveBundleis called only byTestSaveBundle, andfileutil.WriteJSONAtomicis called only bySaveBundleand its focused test. Repository text search found no documentation or other call sites. Representative generate, batch, comparison, and collection traces do not reach any of these helpers.promptinput.SaveandSaveBundlewrite intermediate prompt input or normalized weather data to arbitrary paths, while normal publication usesfileutil.WriteFileAtomicfor selected Markdown andcomparison.Publishfor selected bundles. - Contract at risk: The architecture policy and ADR 0001 define normal execution as an in-memory stateless transformation whose durable files are operator-selected report outputs, comparison bundles, or explicitly requested secure prompt debugging.
- Impact: These unreachable exported functions do not create state during current workflows, but they retain an unsupported persistence surface and low-value tests that can invite accidental reintroduction of intermediate artifacts or require maintenance despite having no product caller.
- Recommendation: Remove the two unused domain/adapter save functions, remove
WriteJSONAtomicif it then has no production use, and delete or consolidate tests that protect only those retired APIs. - Test implications:
TestSaveBundleandTestWriteJSONAtomicprotect unused persistence mechanisms;promptinput.Savehas no focused test. Preserve tests forWriteFileAtomic, normal report publication, comparison publication, and explicit prompt-debug writes. - Validation: Graph and text searches show no remaining production references
to the retired helpers;
go test ./...passes; normal output, comparison, and debug-publication tests remain unchanged and pass. - Related findings: none
- Remediation reference: pending
Retained Decisions
RET-001: Keep the application package as the explicit composition owner
The package import graph, outbound traces from GenerateDetailed,
RunBatchDetailed, and compareDetailed, and their focused tests were
inspected. internal/app has deliberately broad outbound dependencies because
it sequences project-owned domain, collection, execution, publication, and
notification contracts; those dependencies do not point back into app. Splitting
that fan-out merely to reduce a graph metric would obscure workflow ownership.
Reconsider only if a second composition owner emerges or a coherent workflow
can move behind a narrower contract without duplicating ordering policy.
RET-002: Keep external dependencies behind repository-owned contracts
Production import and data-flow inspection found Promptkit imports only in
internal/adapters/promptkit and Distributor imports only in
internal/adapters/distributor. The Promptkit adapter implements
promptexec.Executor; Weather API collection returns weatherdata.Bundle;
and Distributor results are translated before application and CLI summaries.
This explicit translation prevents dependency types and sensitive diagnostics
from becoming application contracts. Reconsider only when an upstream type is
intentionally adopted as a public repository contract with corresponding
architecture and compatibility changes.
RET-003: Keep publication mechanisms separate by artifact contract
Filesystem-write discovery and call traces were inspected for single reports,
comparison bundles, and secure prompt debugging. fileutil.WriteFileAtomic
owns one-file replacement, comparison.Publish owns guarded transactional
directory replacement and recovery, and promptdebug owns secure explicit
diagnostic files. Their shared use of temporary paths and rename operations is
mechanical similarity, while their authorization, permissions, commit, and
recovery semantics differ materially. Reconsider common abstraction only if
multiple artifact kinds acquire the same complete transaction contract.
RET-004: Keep collection as a narrow application-facing seam
The app.Collector contract, collect.Run, the Weather API adapter boundary,
and focused collection tests were inspected. Although collect.Run is small,
it keeps adapter creation and error context out of orchestration and gives app
tests a dependency-neutral deterministic seam. Reconsider if collection gains
no additional policy and an equally narrow project-owned adapter contract can
replace it without leaking transport construction into app.
Open Questions
No Stage 1 open questions or unexplained baseline failures remain.
Stage 2 routed these investigation leads without treating graph metrics or an unusual edge as findings:
internal/configimportsinternal/briefingto use module definitions while validating report-module options. Stages 4, 8, and 23 should determine whether this remains the smallest single-owner validation path or creates avoidable registry coupling.- The graph identifies
internal/cli.Run,internal/app.RunBatchDetailed, andinternal/app.compareDetailedas relatively complex orchestration paths. Their ownership and top-level ordering are coherent; Stages 5, 16, 18, 22, and 23 should assess their local behavior and maintainability rather than inferring a finding from metrics.
Stage Log
Stage 1: Establish The Baseline And Audit Ledger
- Status: Complete.
- Scope reviewed: repository identity, worktree state, Go module and workspace context, graph identity, tracked package/source/test/fixture/asset/document inventory, and required baseline validation.
- Exclusions: none beyond the stage boundary; no production code, tests, dependencies, examples, or canonical documents were changed.
- Result: the audit is tied to exact commit
e7c7262; the expected-baseline difference is explained; every required baseline command passes; and all later stages remain pending. - Findings: none.
- Retained decisions: none.
- Open questions: none.
Stage 2: Audit Architecture And Dependency Direction
- Status: Complete.
- Scope reviewed:
cmd/weatherreporter, production import boundaries for all 24 Go packages, principal call and data-flow paths, external adapter containment, project-owned interfaces, publication boundaries, filesystem writes, ADR 0001, focused orchestration tests, and the architecture policy. - Exclusions: Detailed report/time, configuration, CLI, weather, domain, module, prompt, rendering, comparison, and notification correctness remains assigned to Stages 3-18. Cross-cutting complexity, deduplication, and full documentation coherence remain assigned to Stages 22-24.
Boundary Accounting
| Normative boundary or invariant | Implementation owner and evidence | Disposition |
|---|---|---|
| Binary entry and CLI ownership | cmd/weatherreporter.main calls cli.Run; internal/cli owns action parsing, config loading, executor construction, and bounded result output. Graph traces place app calls below action resolution. |
Matches policy. |
| Configuration ownership | internal/config owns defaults, YAML loading, normalization, secrets, and validation. CLI loads config and passes effective values down; app does not parse config files. |
Matches policy; the config-to-briefing validation edge is routed to Stages 4, 8, and 23. |
| Application orchestration | GenerateDetailed, RunBatchDetailed, and compareDetailed sequence preflight, collection, preparation, execution, publication, and notification through repository-owned values and interfaces. No lower package imports app. |
Matches policy; retained as RET-001. |
| Report and domain ownership | report, timeutil, weatherdata, forecast, facts, module, briefing, promptinput, generatedtext, and reporttemplate form one-way deterministic dependencies below app. |
Matches policy at package level; local rules remain for Stages 3 and 7-13. |
| Prompt execution boundary | promptexec.Executor is dependency-neutral. CLI constructs the Promptkit adapter once per action, app consumes only promptexec requests/results, and the prepared-report data flow supplies curated serialized module packages. |
Matches policy; retained as RET-002. |
| Weather API boundary | App calls its Collector interface; the production implementation delegates through collect.Run to adapters/weatherapi.FetchBundle, which returns normalized weatherdata.Bundle. Production HTTP imports occur only in external adapters. |
Matches policy; retained as RET-004. |
| Distributor boundary | App owns notification timing and repository request/result types; distributorNotifier translates them to adapter-local types and the adapter alone imports the Distributor dependency. Comparison exposes no notifier path. |
Matches policy. |
| Prompt preflight and curated inputs | Generate inspects the exact prompt/profile before collectWeather; batch inspects all candidates before its one collection; comparison inspects prompt and all profiles before collection, then calls prepareReport once. Data-flow traces reach promptinput.Build and MarshalYAML, not raw bundle serialization into Promptkit. |
Matches policy at workflow level; detailed checks remain for Stages 10, 11, 14, and 18. |
| Single output and notification order | publishPromptReport checks context, calls fileutil.WriteFileAtomic, records the path, and only then calls notifyReport. Focused tests cover pre-publication preservation and notification ordering. |
Matches policy; publication split retained as RET-003. |
| Batch output and notification order | RunBatchDetailed validates every planned path before sequential execution, suppresses item notification, continues across item failures, and calls notifyBatch only after the loop. Focused tests cover preflight, partial failure, and notification-after-publication. |
Matches policy at workflow level; detailed review remains for Stage 16. |
| Comparison publication | App preflights before external work and again before publication. internal/comparison owns bundle validation, guarded replacement, staging, commit, restoration, and cleanup results. The comparison request has no notifier and the trace does not reach Distributor. |
Matches policy at workflow level; detailed review remains for Stages 17-18. |
| Stateless execution | Normal traces retain preparation and execution values in memory. Production filesystem writes are limited to selected Markdown publication, selected comparison bundles, explicit prompt-debug capture, and the unreachable helpers in AUD-001; no cache, workspace, history, receipt, or resume owner appears in the package graph. |
Matches normal-runtime policy; AUD-001 records the unused persistence surface. |
| Dependency cycles and direction | The compiler-derived direct-import inventory is acyclic. Entry packages point inward, adapters do not import app/CLI, domain packages do not import orchestration, and no external dependency type appears outside its production adapter. | Matches policy. |
Commands And Evidence
- Refreshed graph project
home-eric-Workspace-weatherreporterin moderate mode. The graph's branch identity remains production baselinee7c7262; Stage 1's intervening commit changes only this excluded audit document. - Used graph architecture views for structure, dependencies, entry points, hotspots, boundaries, layers, and clusters; queried the graph schema and direct import edges.
- Used graph search, snippets, inbound/outbound call traces, and data-flow
traces for
main,cli.Run,GenerateDetailed,RunBatchDetailed,compareDetailed,prepareReport,executePreparedProfile,collect.Run, all three external adapters,publishPromptReport,comparison.PlanDestination,comparison.Publish, and Distributor notification. - Used compiler-derived
go listdirect imports to separate production edges from test-only graph edges and confirm the build has no import cycle. - Used graph-augmented code search to inventory external dependency imports, HTTP ownership, and production filesystem writes. A bounded text search confirmed the unused persistence helpers have no documentation or hidden non-code callers.
- Ran
go test ./internal/app ./internal/cli ./internal/collect ./internal/comparison ./internal/adapters/... ./internal/fileutil ./internal/promptdebug ./internal/promptexec; all focused packages passed. - Findings:
AUD-001. - Retained decisions:
RET-001,RET-002,RET-003, andRET-004. - Open questions: the two leads recorded above are routed to their assigned later stages.