Update the today report template
This commit is contained in:
@@ -1,424 +0,0 @@
|
||||
# Today Report Roadmap
|
||||
|
||||
## Purpose
|
||||
|
||||
This roadmap defines the target state and implementation work needed to add a
|
||||
new independent generated-text-template `today` report.
|
||||
|
||||
The report is not implemented yet. Current report behavior remains documented
|
||||
outside `docs/roadmap/`.
|
||||
|
||||
## Intent
|
||||
|
||||
Today should be an independent generated-text-template report focused on the
|
||||
current local civil day. It should mirror the implemented Tomorrow Report
|
||||
structure, but its valid period, identity, prompt, template, schema, workspace
|
||||
paths, distributor identity, and deterministic planning module should use
|
||||
`today`.
|
||||
|
||||
This is a clean, separate report addition:
|
||||
|
||||
- `today` becomes a new canonical current-day generated-text report ID.
|
||||
- The existing `daily_today` report remains independent for now.
|
||||
- The existing public `daily` command remains independent for now.
|
||||
- `weatherreporter generate today` and `weatherreporter generate daily` must
|
||||
not be aliases for each other.
|
||||
- Morning batch should use `today`, not `daily_today`.
|
||||
- New Today artifacts use the `today` artifact group and report ID.
|
||||
- Existing historical `daily_today` workspace artifacts do not need migration.
|
||||
|
||||
The next planned feature will rewrite the `daily` command/report in the same
|
||||
style as Today and Tomorrow. Do not pre-solve that future work in this roadmap.
|
||||
|
||||
## Locked Decisions
|
||||
|
||||
- `today` is independent of `daily_today`.
|
||||
- `generate today` is independent of `generate daily`.
|
||||
- No command compatibility aliases between `today` and `daily`.
|
||||
- No config-key compatibility aliases between `reports.today` and
|
||||
`reports.daily` / `reports.daily_today`.
|
||||
- Morning batch includes `today`.
|
||||
- Morning batch should not include `daily_today` once Today is implemented.
|
||||
- `today` needs its own deterministic planning module analogous to
|
||||
`TomorrowPlanning`.
|
||||
- Add a new public `generate today` command.
|
||||
- Do not reuse the Tomorrow prompt, template, schema, report ID, artifact group,
|
||||
or planning stanza for Today.
|
||||
- Do not attempt to migrate old workspace artifacts.
|
||||
|
||||
## Target Report Shape
|
||||
|
||||
Today should render from deterministic current-day facts plus structured prose
|
||||
from Scriptorium:
|
||||
|
||||
```markdown
|
||||
# Today's Weather
|
||||
|
||||
**Forecast date:** Friday, May 29, 2026
|
||||
**Updated:** Friday, May 29, 2026 at 8:30 AM
|
||||
|
||||
<GeneratedText summary>
|
||||
|
||||
## Daypart Forecast
|
||||
|
||||
- **Morning:** <deterministic daypart line>
|
||||
- **Midday:** <deterministic daypart line>
|
||||
- **Afternoon:** <deterministic daypart line>
|
||||
- **Evening:** <deterministic daypart line>
|
||||
|
||||
## Precipitation Timing
|
||||
|
||||
- **10:00 AM** to **1:00 PM**: Precipitation is expected during this period.
|
||||
The peak precipitation chance is 70% at 11:00 AM.
|
||||
- <optional GeneratedText precipitation_timing>
|
||||
|
||||
## Forecast Discussion
|
||||
|
||||
<GeneratedText forecast_discussion paragraphs>
|
||||
```
|
||||
|
||||
The precipitation section should render only when precipitation windows exist
|
||||
for the current-day valid period. The deterministic daypart forecast should
|
||||
follow the same module-driven presentation approach used by Tomorrow.
|
||||
|
||||
The title should be stable and explicit: `Today's Weather`.
|
||||
|
||||
## Report Identity
|
||||
|
||||
Add a report definition with:
|
||||
|
||||
- report ID: `today`
|
||||
- public generate command: `today`
|
||||
- prompt ID: `weather.today_generated_text`
|
||||
- generation mode: `generated_text_template`
|
||||
- template ID: `today`
|
||||
- generated-text schema ID: `today`
|
||||
- artifact group: `today`
|
||||
- batch output name: `today.md`
|
||||
- prior compatibility: Today only
|
||||
- comparison strategy: same valid local date
|
||||
- valid period: current local civil day in the effective report timezone,
|
||||
`[00:00, next 00:00)`
|
||||
|
||||
Keep the existing `daily_today` report definition independent unless the future
|
||||
Daily rewrite roadmap removes or replaces it.
|
||||
|
||||
Command and config resolution must remain distinct:
|
||||
|
||||
- `generate today` resolves to report ID `today`.
|
||||
- `generate daily` resolves to the existing daily report ID.
|
||||
- `reports.today` config overrides apply only to report ID `today`.
|
||||
- `reports.daily` and `reports.daily_today` config overrides continue to apply
|
||||
only to the existing daily report while that report exists.
|
||||
|
||||
## Batch Behavior
|
||||
|
||||
Morning batch should include Today in the position currently occupied by Daily
|
||||
Today.
|
||||
|
||||
Target morning order:
|
||||
|
||||
1. `today`
|
||||
2. `three_day`
|
||||
3. `weekend`, when existing weekend rules include it
|
||||
|
||||
Existing Sunday behavior should remain equivalent except with Today replacing
|
||||
Daily Today in the batch: scheduled Sunday morning should include `today` and
|
||||
`three_day`, and should skip `weekend`.
|
||||
|
||||
Evening batch behavior is unchanged and should continue to include `tomorrow`.
|
||||
Hourly remains excluded from scheduled batches unless a later roadmap changes
|
||||
that.
|
||||
|
||||
The existing `daily` command/report may remain available for manual generation,
|
||||
but it is no longer the morning batch current-day product once Today is
|
||||
implemented.
|
||||
|
||||
## GeneratedText Contract
|
||||
|
||||
Today should use the same structured prose shape as Tomorrow:
|
||||
|
||||
```json
|
||||
{
|
||||
"summary": "string",
|
||||
"forecast_discussion": ["string"],
|
||||
"precipitation_timing": "string",
|
||||
"confidence": "string"
|
||||
}
|
||||
```
|
||||
|
||||
Required:
|
||||
|
||||
- `summary`
|
||||
- `forecast_discussion`
|
||||
|
||||
Optional:
|
||||
|
||||
- `precipitation_timing`
|
||||
- `confidence`
|
||||
|
||||
Validation should match Tomorrow semantics:
|
||||
|
||||
- reject malformed JSON and unknown fields
|
||||
- reject trailing JSON values
|
||||
- trim `summary`, `precipitation_timing`, and `confidence`
|
||||
- trim each `forecast_discussion` paragraph
|
||||
- drop blank discussion paragraphs
|
||||
- require at least one nonblank discussion paragraph
|
||||
- return canonical normalized JSON with the same public field names
|
||||
|
||||
Add a dedicated prompt asset for the source prompt text if prompt assets are
|
||||
maintained locally:
|
||||
|
||||
- `internal/reporttemplate/prompts/today.generated_text.md`
|
||||
|
||||
Scriptorium registration remains out of band. Weatherreporter should invoke the
|
||||
Today prompt by prompt ID and pass the data package as it does for other
|
||||
generated-text reports.
|
||||
|
||||
## Template Context
|
||||
|
||||
Add dedicated Today types under `internal/generatedtext`, rather than reusing
|
||||
Tomorrow types directly. The shape should mirror Tomorrow so template behavior
|
||||
stays explicit and testable:
|
||||
|
||||
```go
|
||||
type TodayRenderContext struct {
|
||||
Report TodayReportContext
|
||||
GeneratedText Today
|
||||
Modules TodayTemplateModules
|
||||
Collected facts.CollectedFacts
|
||||
Derived facts.DerivedFacts
|
||||
}
|
||||
```
|
||||
|
||||
`TodayReportContext` should include:
|
||||
|
||||
- `Title`, exactly `Today's Weather`
|
||||
- `ForecastDate`
|
||||
- `ForecastDateLabel`, for example `Friday, May 29, 2026`
|
||||
- `ForecastDayName`, for example `Friday`
|
||||
- `GeneratedAt`
|
||||
- `GeneratedAtLabel`
|
||||
- `ValidPeriod`
|
||||
- `Timezone`
|
||||
|
||||
`TodayTemplateModules` should expose the categories the Today template needs:
|
||||
|
||||
- `Metadata`
|
||||
- `CurrentConditions`
|
||||
- `HourlyForecast`
|
||||
- `DerivedDailySummary`
|
||||
- `DerivedDaypartSummaries`
|
||||
- ordered daypart rows
|
||||
- `PrecipTiming`
|
||||
- `AlertDigest`
|
||||
- `SPCConvectiveOutlooks`
|
||||
- `AreaForecastDiscussion`
|
||||
- `SPCConvectiveDiscussion`
|
||||
- `WeatherStory`
|
||||
- `TodayPlanning`
|
||||
|
||||
Today may share private helper functions with Tomorrow render-context
|
||||
construction when the helper represents identical mechanics, such as snapshot
|
||||
lookup or daypart row ordering. Do not expose Tomorrow-specific types through
|
||||
the Today template context.
|
||||
|
||||
## Module Composition
|
||||
|
||||
The default module composition should mirror Tomorrow where the same facts are
|
||||
useful for the current-day report, with a Today-specific planning module:
|
||||
|
||||
- `metadata`
|
||||
- `current_conditions`
|
||||
- `narrative_forecast`
|
||||
- `derived_daily_summary`
|
||||
- `derived_daypart_summaries`
|
||||
- `precip_timing`
|
||||
- `alert_digest`
|
||||
- `spc_convective_outlooks`
|
||||
- `area_forecast_discussion`
|
||||
- `spc_convective_discussion`
|
||||
- `weather_story`
|
||||
- `outdoor_windows`
|
||||
- `hourly_forecast`
|
||||
- `today_planning`
|
||||
|
||||
Keep module outputs deterministic and prompt-facing. Do not add prose-only Go
|
||||
fields unless the template needs a structured fact that cannot be expressed from
|
||||
existing module data.
|
||||
|
||||
## Today Planning Module
|
||||
|
||||
Add a Today-specific deterministic planning module:
|
||||
|
||||
- module ID: `today_planning`
|
||||
- stanza name: `today_planning`
|
||||
- options type: `TodayPlanningOptions`
|
||||
- output type: `TodayPlanningModule`
|
||||
- supported report: `today`
|
||||
|
||||
The module should be analogous to `TomorrowPlanning`, but current-day oriented.
|
||||
It should not reuse the public `TomorrowPlanningModule` type or
|
||||
`tomorrow_planning` stanza.
|
||||
|
||||
Recommended initial fields:
|
||||
|
||||
- `morning_readiness`
|
||||
- `commute_school_workday_concerns`
|
||||
- `outdoor_planning`
|
||||
- `late_day_change_watch`
|
||||
|
||||
The exact field names may be adjusted during implementation if tests and docs
|
||||
make a better shape clear, but the module must remain deterministic and
|
||||
current-day specific. Private helper functions may be shared with Tomorrow
|
||||
planning when the underlying logic is truly identical.
|
||||
|
||||
## Implementation Plan
|
||||
|
||||
1. Add Today report identity.
|
||||
- Add `report.Today`.
|
||||
- Keep the existing `report.DailyToday` active for now.
|
||||
- Add command-name support for `today`.
|
||||
- Do not change the `daily` command mapping in this roadmap.
|
||||
- Add config-key support for `today`.
|
||||
- Do not change `reports.daily` or `reports.daily_today` mapping in this
|
||||
roadmap.
|
||||
- Add a report definition with generated-text-template identity fields.
|
||||
- Add current-local-civil-day valid-period resolution.
|
||||
- Update report tests for ID, prompt ID, artifact group, command mapping,
|
||||
config key mapping, batch order, and valid period.
|
||||
|
||||
2. Add Today planning module.
|
||||
- Add `module.TodayPlanning`.
|
||||
- Add `TodayPlanningOptions`.
|
||||
- Add `TodayPlanningModule` and builder under `internal/briefing`.
|
||||
- Register it in the default module registry for `report.Today`.
|
||||
- Add tests for output shape, supported report, unsupported reports, and
|
||||
empty/fallback behavior.
|
||||
|
||||
3. Add Today generated-text validation and schema.
|
||||
- Add `generatedtext.Today`.
|
||||
- Add `ValidateToday`.
|
||||
- Add `today.generated_text.schema.json`.
|
||||
- Add generated-text validation tests matching Tomorrow coverage.
|
||||
|
||||
4. Add Today template and render context.
|
||||
- Add `today.md.tmpl`.
|
||||
- Add `TodayRenderContext`, `TodayReportContext`, and
|
||||
`TodayTemplateModules`.
|
||||
- Add `BuildTodayRenderContext`.
|
||||
- Use the internal snapshot lookup helper for module extraction.
|
||||
- Add render-context and template tests for populated and omitted optional
|
||||
modules.
|
||||
|
||||
5. Register Today in generated-text and embedded asset catalogs.
|
||||
- Add a generated-text catalog entry.
|
||||
- Add reporttemplate template/schema map entries if the current asset
|
||||
lookup still uses explicit maps.
|
||||
- Extend catalog completeness tests.
|
||||
- Add unsupported schema/template combination coverage if needed.
|
||||
|
||||
6. Integrate app, CLI, config, batches, and distributor workflows.
|
||||
- Ensure `weatherreporter generate today` resolves and runs through the
|
||||
generated-text-template workflow.
|
||||
- Ensure `weatherreporter generate daily` remains the existing daily
|
||||
workflow and does not resolve to Today.
|
||||
- Ensure morning batch uses `today` instead of `daily_today`.
|
||||
- Persist raw generated text, structured run result, normalized generated
|
||||
text, render context, Markdown report, metadata, and optional output copy.
|
||||
- Ensure distributor notification uses the managed Today Markdown report
|
||||
path and Today template values.
|
||||
- Ensure report metadata, RunID, artifact paths, data-package paths, batch
|
||||
output names, and distributor template variables use `today`.
|
||||
|
||||
7. Update implemented documentation after code changes.
|
||||
- Update `docs/cli.md`, `docs/config.md`, `docs/operations.md`,
|
||||
`docs/templates.md`, `docs/internal/report-registry.md`,
|
||||
`docs/internal/generatedtext.md`, `docs/internal/reporttemplate.md`,
|
||||
`docs/internal/module.md`, `docs/internal/app-orchestration.md`, and
|
||||
maintained examples as needed.
|
||||
- Non-roadmap docs must describe only the implemented Today behavior after
|
||||
the code changes land.
|
||||
- Keep `daily` and `today` documented as distinct commands/reports.
|
||||
|
||||
## Test Plan
|
||||
|
||||
Add or update tests for:
|
||||
|
||||
- report registry membership for both `today` and existing `daily_today`
|
||||
- `today` command-name resolution to `today`
|
||||
- `daily` command-name resolution remaining independent from `today`
|
||||
- config-key resolution for `reports.today`
|
||||
- config-key resolution for `reports.daily` and `reports.daily_today`
|
||||
remaining independent from `reports.today`
|
||||
- morning batch order with `today`, `three_day`, and conditional `weekend`
|
||||
- Sunday morning batch skip behavior with `today`
|
||||
- current-day valid period in the configured timezone
|
||||
- generated-text unknown fields, trailing JSON, missing required fields, blank
|
||||
fields, paragraph trimming, and canonical output
|
||||
- generated-text catalog completeness
|
||||
- template/schema asset lookup
|
||||
- render context labels, module extraction, nil optional modules, Today
|
||||
planning extraction, and daypart ordering
|
||||
- Today planning module output and supported-report validation
|
||||
- app workflow artifacts for `generate today`
|
||||
- `generate daily` remains separate from `generate today`
|
||||
- optional `--out` copy behavior
|
||||
- distributor template values and managed report notification source
|
||||
- CLI parser support for `generate today`
|
||||
- config report module overrides for `reports.today`
|
||||
|
||||
Suggested validation:
|
||||
|
||||
```sh
|
||||
go test ./internal/report ./internal/generatedtext ./internal/reporttemplate
|
||||
go test ./internal/briefing ./internal/module
|
||||
go test ./internal/app ./internal/cli ./internal/config
|
||||
go test ./...
|
||||
go run ./cmd/weatherreporter --help
|
||||
git diff --check
|
||||
```
|
||||
|
||||
## Documentation Updates After Implementation
|
||||
|
||||
Update implemented docs only after the code exists:
|
||||
|
||||
- `docs/cli.md`: document `generate today` and keep `generate daily`
|
||||
documented as a separate existing command.
|
||||
- `docs/config.md`: document `reports.today` module overrides separately from
|
||||
existing daily report overrides.
|
||||
- `docs/operations.md`: document Today artifact paths, morning batch behavior,
|
||||
and distributor upload identity.
|
||||
- `docs/templates.md`: document Today template variables.
|
||||
- `docs/internal/report-registry.md`: document Today report identity and its
|
||||
independence from Daily Today.
|
||||
- `docs/internal/generatedtext.md`: document Today generated-text schema and
|
||||
validation behavior.
|
||||
- `docs/internal/reporttemplate.md`: document Today template assets.
|
||||
- `docs/internal/module.md`: document `today_planning`.
|
||||
- `docs/internal/app-orchestration.md`: document Today workflow only if it
|
||||
differs from the generic generated-text-template flow.
|
||||
|
||||
## Ambiguities Addressed
|
||||
|
||||
- Independence: `today` is separate from `daily_today`; it does not replace the
|
||||
existing report definition in this roadmap.
|
||||
- Command behavior: `generate today` and `generate daily` are not aliases.
|
||||
- Config behavior: `reports.today` is not an alias for `reports.daily` or
|
||||
`reports.daily_today`.
|
||||
- Batch behavior: morning batch includes `today` instead of `daily_today`.
|
||||
- Planning module: Today has its own deterministic planning module.
|
||||
- Artifact identity: new Today artifacts and distributor values use `today`.
|
||||
- Historical artifacts: old `daily_today` workspace files are not migrated.
|
||||
|
||||
## Open Decisions
|
||||
|
||||
No open decisions remain that block implementation.
|
||||
|
||||
Future decisions that should not be resolved in this roadmap:
|
||||
|
||||
- How the future rewritten `daily` command/report should relate to `today`.
|
||||
- Whether the future Daily rewrite removes or retires `daily_today`.
|
||||
- Whether old `daily_today` workspace artifacts should ever receive a migration
|
||||
or inspection compatibility layer.
|
||||
@@ -203,14 +203,12 @@ func TestBuildTodayRenderContext(t *testing.T) {
|
||||
"# Today's Weather",
|
||||
"**Forecast date:** Monday, June 15, 2026",
|
||||
"Today starts quiet, then showers become more likely later in the day.",
|
||||
"Currently, it is 58°F and clear.",
|
||||
"Currently, it is 58°F and clear. It feels like 57°F, with a relative humidity of 61% and winds from the northwest at 9 mph.",
|
||||
"- **Morning:** Partly cloudy, with temperatures in the low 60s.",
|
||||
"- **Afternoon:** Showers, with temperatures in the mid 70s. Chance of precipitation is 70%.",
|
||||
"## Precipitation Timing",
|
||||
"- **3:00 PM** to **6:00 PM**: Precipitation is expected during this period. The peak precipitation chance is 70% at 3:00 PM.",
|
||||
"The most likely rain window is from midafternoon into early evening.",
|
||||
"## Planning Notes",
|
||||
"- Take sunglasses early.",
|
||||
"Morning conditions should stay mostly dry.",
|
||||
"Rain chances increase during the afternoon as deeper moisture arrives.",
|
||||
} {
|
||||
@@ -225,9 +223,11 @@ func TestBuildTodayRenderContext(t *testing.T) {
|
||||
"- **Morning:**",
|
||||
"- **Afternoon:**",
|
||||
"## Precipitation Timing",
|
||||
"## Planning Notes",
|
||||
"## Forecast Discussion",
|
||||
})
|
||||
if strings.Contains(text, "## Planning Notes") || strings.Contains(text, "- Take sunglasses early.") || strings.Contains(text, "Forecast details are limited") {
|
||||
t.Fatalf("rendered template included removed Today template content:\n%s", text)
|
||||
}
|
||||
}
|
||||
|
||||
func TestBuildTodayRenderContextAllowsOmittedOptionalModules(t *testing.T) {
|
||||
@@ -250,7 +250,7 @@ func TestBuildTodayRenderContextAllowsOmittedOptionalModules(t *testing.T) {
|
||||
t.Fatalf("Render() error = %v", err)
|
||||
}
|
||||
text := string(rendered)
|
||||
for _, unwanted := range []string{"## Current Conditions", "## Precipitation Timing", "## Planning Notes"} {
|
||||
for _, unwanted := range []string{"## Current Conditions", "## Precipitation Timing", "## Planning Notes", "Forecast details are limited"} {
|
||||
if strings.Contains(text, unwanted) {
|
||||
t.Fatalf("rendered template included %q without module data:\n%s", unwanted, text)
|
||||
}
|
||||
@@ -493,8 +493,12 @@ func testTodaySnapshot(t *testing.T) module.Snapshot {
|
||||
ID: module.CurrentConditions,
|
||||
StanzaName: string(module.CurrentConditions),
|
||||
Value: briefing.CurrentConditionsModule{
|
||||
ConditionTextLower: "clear",
|
||||
TemperatureF: intPtr(58),
|
||||
ConditionTextLower: "clear",
|
||||
TemperatureF: intPtr(58),
|
||||
ApparentTemperatureF: intPtr(57),
|
||||
RelativeHumidityPercent: intPtr(61),
|
||||
WindSpeedMph: intPtr(9),
|
||||
WindDirectionText: "northwest",
|
||||
},
|
||||
},
|
||||
{
|
||||
|
||||
@@ -35,11 +35,14 @@ func TestTodayTemplateLookup(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatalf("Template() error = %v", err)
|
||||
}
|
||||
for _, want := range []string{"# {{ .Report.Title }}", "**Forecast date:**", "## Current Conditions", "## Daypart Forecast", "## Planning Notes", "## Forecast Discussion"} {
|
||||
for _, want := range []string{"# {{ .Report.Title }}", "**Forecast date:**", "## Current Conditions", "## Daypart Forecast", "## Forecast Discussion"} {
|
||||
if !strings.Contains(source, want) {
|
||||
t.Fatalf("template missing %q:\n%s", want, source)
|
||||
}
|
||||
}
|
||||
if strings.Contains(source, "## Planning Notes") {
|
||||
t.Fatalf("template includes Planning Notes section:\n%s", source)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSchemaLookup(t *testing.T) {
|
||||
@@ -365,8 +368,12 @@ func TestRenderToday(t *testing.T) {
|
||||
},
|
||||
Modules: testTodayModules{
|
||||
CurrentConditions: &testCurrentConditions{
|
||||
ConditionTextLower: "clear",
|
||||
TemperatureF: intPtr(58),
|
||||
ConditionTextLower: "clear",
|
||||
TemperatureF: intPtr(58),
|
||||
ApparentTemperatureF: intPtr(57),
|
||||
RelativeHumidityPercent: intPtr(61),
|
||||
WindDirectionText: "northwest",
|
||||
WindSpeedMph: intPtr(9),
|
||||
},
|
||||
Dayparts: []testTomorrowDaypart{
|
||||
{
|
||||
@@ -393,6 +400,12 @@ func TestRenderToday(t *testing.T) {
|
||||
MentionPrecipitation: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
Key: "evening",
|
||||
Summary: testDaypartSummary{
|
||||
DisplayName: "Evening",
|
||||
},
|
||||
},
|
||||
},
|
||||
PrecipTiming: &testPrecipTiming{
|
||||
PrecipitationWindows: []testPrecipWindow{
|
||||
@@ -414,14 +427,11 @@ func TestRenderToday(t *testing.T) {
|
||||
"**Forecast date:** Monday, June 15, 2026",
|
||||
"**Updated:** Monday, June 15, 2026 at 7:14 AM",
|
||||
"Today starts dry before showers return later in the day.",
|
||||
"Currently, it is 58°F and clear.",
|
||||
"Currently, it is 58°F and clear. It feels like 57°F, with a relative humidity of 61% and winds from the northwest at 9 mph.",
|
||||
"- **Morning:** Sunny, with temperatures rising from the upper 50s to the upper 60s.",
|
||||
"- **Afternoon:** Showers, with temperatures in the upper 70s. Chance of precipitation is 70%.",
|
||||
"- **3:00 PM** to **6:00 PM**: Precipitation is expected during this period. The peak precipitation chance is 70% at 3:00 PM.",
|
||||
"A few showers may linger into early evening.",
|
||||
"## Planning Notes",
|
||||
"- Morning weather looks routine.",
|
||||
"- Watch late-day shower timing.",
|
||||
"Clouds increase after sunrise.",
|
||||
"Rain chances peak during the afternoon.",
|
||||
} {
|
||||
@@ -436,9 +446,13 @@ func TestRenderToday(t *testing.T) {
|
||||
"- **Morning:**",
|
||||
"- **Afternoon:**",
|
||||
"## Precipitation Timing",
|
||||
"## Planning Notes",
|
||||
"## Forecast Discussion",
|
||||
})
|
||||
for _, unwanted := range []string{"## Planning Notes", "Morning weather looks routine.", "Watch late-day shower timing.", "- **Evening:**", "Forecast details are limited"} {
|
||||
if strings.Contains(text, unwanted) {
|
||||
t.Fatalf("rendered template included %q:\n%s", unwanted, text)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestRenderTomorrowOmitsPrecipitationTimingWithoutWindows(t *testing.T) {
|
||||
|
||||
@@ -5,12 +5,14 @@
|
||||
|
||||
{{ .GeneratedText.Summary }}
|
||||
|
||||
{{ with .Modules.CurrentConditions }}{{ $current := . }}## Current Conditions
|
||||
Currently, {{ with .TemperatureF }}it is {{ . }}°F{{ with $current.ConditionTextLower }} and {{ . }}{{ end }}{{ else }}{{ with .ConditionTextLower }}conditions are {{ . }}{{ else }}latest current conditions are available{{ end }}{{ end }}.
|
||||
{{ with .Modules.CurrentConditions }}
|
||||
## Current Conditions
|
||||
{{ with .TemperatureF }}Currently, it is {{ . }}°F{{ with $.Modules.CurrentConditions.ConditionTextLower }} and {{ . }}{{ end }}.{{ else }}{{ with .ConditionText }}Currently, it is {{ . }}.{{ else }}Current conditions are unavailable.{{ end }}{{ end }}{{ with .ApparentTemperatureF }} It feels like {{ . }}°F{{ with $.Modules.CurrentConditions.RelativeHumidityPercent }}, with a relative humidity of {{ . }}%{{ end }}{{ with $.Modules.CurrentConditions.WindDirectionText }} and winds from the {{ . }}{{ with $.Modules.CurrentConditions.WindSpeedMph }} at {{ . }} mph{{ end }}{{ end }}.{{ else }}{{ with .RelativeHumidityPercent }} Relative humidity is {{ . }}%.{{ end }}{{ with .WindDirectionText }} Winds are from the {{ . }}{{ with $.Modules.CurrentConditions.WindSpeedMph }} at {{ . }} mph{{ end }}.{{ end }}{{ end }}
|
||||
|
||||
{{ end }}## Daypart Forecast
|
||||
{{ with .Modules.Dayparts }}{{ range . }}{{ $daypart := . }}- **{{ if .Summary.DisplayName }}{{ .Summary.DisplayName }}{{ else }}{{ .Key }}{{ end }}:** {{ with .Summary.DominantConditionDisplay }}{{ . }}{{ else }}{{ with .Summary.DominantCondition }}{{ . }}{{ else }}Forecast details are limited{{ end }}{{ end }}{{ if eq .Summary.TemperatureTrend "rising" }}{{ with .Summary.TemperatureStartPhraseF }}, with temperatures rising from the {{ . }}{{ with $daypart.Summary.TemperatureEndPhraseF }} to the {{ . }}{{ end }}{{ end }}{{ else if eq .Summary.TemperatureTrend "falling" }}{{ with .Summary.TemperatureStartPhraseF }}, with temperatures falling from the {{ . }}{{ with $daypart.Summary.TemperatureEndPhraseF }} to the {{ . }}{{ end }}{{ end }}{{ else if eq .Summary.TemperatureTrend "peaking" }}{{ with .Summary.TemperaturePeakPhraseF }}, with temperatures peaking in the {{ . }}{{ end }}{{ else }}{{ with .Summary.TemperatureSteadyPhraseF }}, with temperatures in the {{ . }}{{ else }}{{ with .Summary.TemperaturePhraseF }}, with temperatures in the {{ . }}{{ end }}{{ end }}{{ end }}.{{ if .Summary.MentionPrecipitation }}{{ with .Summary.MaxPopPercent }} Chance of precipitation is {{ . }}%.{{ end }}{{ end }}
|
||||
{{ end }}{{ else }}- No daypart forecast details are available.
|
||||
{{ end }}
|
||||
## Daypart Forecast
|
||||
{{ with .Modules.Dayparts }}{{ range . }}{{ $daypart := . }}{{ if or .Summary.DominantConditionDisplay .Summary.DominantCondition }}- **{{ if .Summary.DisplayName }}{{ .Summary.DisplayName }}{{ else }}{{ .Key }}{{ end }}:** {{ with .Summary.DominantConditionDisplay }}{{ . }}{{ else }}{{ with .Summary.DominantCondition }}{{ . }}{{ end }}{{ end }}{{ if eq .Summary.TemperatureTrend "rising" }}{{ with .Summary.TemperatureStartPhraseF }}, with temperatures rising from the {{ . }}{{ with $daypart.Summary.TemperatureEndPhraseF }} to the {{ . }}{{ end }}{{ end }}{{ else if eq .Summary.TemperatureTrend "falling" }}{{ with .Summary.TemperatureStartPhraseF }}, with temperatures falling from the {{ . }}{{ with $daypart.Summary.TemperatureEndPhraseF }} to the {{ . }}{{ end }}{{ end }}{{ else if eq .Summary.TemperatureTrend "peaking" }}{{ with .Summary.TemperaturePeakPhraseF }}, with temperatures peaking in the {{ . }}{{ end }}{{ else }}{{ with .Summary.TemperatureSteadyPhraseF }}, with temperatures in the {{ . }}{{ else }}{{ with .Summary.TemperaturePhraseF }}, with temperatures in the {{ . }}{{ end }}{{ end }}{{ end }}.{{ if .Summary.MentionPrecipitation }}{{ with .Summary.MaxPopPercent }} Chance of precipitation is {{ . }}%.{{ end }}{{ end }}
|
||||
{{ end }}{{ end }}{{ else }}- No daypart forecast details are available.
|
||||
{{ end }}
|
||||
|
||||
{{ with .Modules.PrecipTiming }}{{ with .PrecipitationWindows }}
|
||||
@@ -20,13 +22,7 @@ Currently, {{ with .TemperatureF }}it is {{ . }}°F{{ with $current.ConditionTex
|
||||
{{ end }}{{ with $.GeneratedText.PrecipitationTiming }}
|
||||
{{ . }}
|
||||
{{ end }}
|
||||
{{ end }}{{ end }}{{ with .Modules.TodayPlanning }}{{ if or .MorningReadiness .CommuteSchoolWorkdayConcerns .OutdoorPlanning .LateDayChangeWatch }}
|
||||
## Planning Notes
|
||||
{{ with .MorningReadiness }}{{ range . }}- {{ . }}
|
||||
{{ end }}{{ end }}{{ with .CommuteSchoolWorkdayConcerns }}{{ range . }}- {{ . }}
|
||||
{{ end }}{{ end }}{{ with .OutdoorPlanning }}{{ range . }}- {{ . }}
|
||||
{{ end }}{{ end }}{{ with .LateDayChangeWatch }}{{ range . }}- {{ . }}
|
||||
{{ end }}{{ end }}{{ end }}{{ end }}
|
||||
{{ end }}{{ end }}
|
||||
## Forecast Discussion
|
||||
{{ range .GeneratedText.ForecastDiscussion }}
|
||||
{{ . }}
|
||||
|
||||
Reference in New Issue
Block a user