Skip to content

Build Toward the Whole: phillies-wire - #38

Open
DaveHomeAssist wants to merge 8 commits into
mainfrom
law/build-toward-the-whole
Open

DaveHomeAssist wants to merge 8 commits into
mainfrom
law/build-toward-the-whole

Conversation

@DaveHomeAssist

Copy link
Copy Markdown
Owner

Applies the Build Toward the Whole patch series.

Commits

  • Persist canonical schedule, audit, and calendar in the archive snapshot
  • Make the accuracy scorecard report only the checks that actually ran
  • Run the accuracy export after render so it inspects this run's HTML
  • Report a no recipient run as skipped and keep the delivery reason
  • Remove three American League clubs from the National League table
  • Source factcheck team id, API base, and team codes from the shared tables
  • Derive every absolute site URL from one SITE_URL in config.mjs

Gate

npm test — lint OK, 25/25 test files pass — passing locally on this branch.

Not for merge yet.

The publish workflow deploys site/ and then commits generated artifacts back
to main, but the git add list omitted data/phillies-2026.json,
data/phillies-2026-audit.json, data/phillies-2026-overrides.json, and
calendar/phillies-2026-all.ics. render.mjs regenerates all of them every run,
so the deployed site carried a current schedule while the branch copy, which
the docs call the repo owned source of truth, stayed at its 2026-06-28 state.
That is the same class of drift already fixed for accuracy.json in issue 011.

Add the four paths to the persist step and pin the full list with a
reliability test so a future generated artifact cannot silently fork the
checkout from the deploy again.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01656XvdqNAVojSPQBtLZAAt
Two findings in factcheck.mjs, one subsystem, one commit.

The recap source check read recap.final_score and recap.starter_line, fields
that no pipeline stage writes. crawl.mjs publishes the most recent final as
meta.last_final (date, game_pk, runs, opponent) and the visible recap result
as sections.recap.content.result, so the documented "previous day final vs MLB
box score" check compared nothing in production. reconcileRecap now reads
those real fields, the schedule lookup targets the date and gamePk the payload
names instead of calendar yesterday, a doubleheader without a gamePk is left
unchecked rather than guessed, and the legacy free text fields still work.

buildAccuracyReport defaulted every published claim to verdict "accurate", so
the dashboard showed "27 of 28 claims verified" when only the five standings
rows had been compared with the MLB API. runSourceChecks now returns a
coverage map for the groups it compared (standings, record, recap), the report
carries that map, and a claim is accurate only when its group was covered and
no finding contradicted it. Everything else stays unverifiable and is labelled
as shown, not verified. The verify.mjs gate is unchanged: it fails on
inaccurate claims, and unverifiable claims never block.

Verified end to end on a scratch copy: the live pipeline exits 0, coverage
reports standings, record, and recap true, and the scorecard now reads 9 of
29 claims verified instead of 27 of 28.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01656XvdqNAVojSPQBtLZAAt
run.mjs called factcheck.mjs --export-accuracy before render.mjs. The
export's deterministic HTML checks (template token leak, duplicated weather
strip, dead dashboard slots) therefore read the previous run's
phillies-wire-output.html, or nothing at all on a fresh CI checkout where
that file is gitignored, so the scorecard could never carry a pipeline
integrity finding for the edition it described. README and HANDOFF said the
export runs after render.

Move the export stage between render and verify in both the daily and live
stage lists. factcheck.mjs now mirrors the report into site/ when render has
built it, so the verify.mjs root and site equality gate still holds and
verify still gates on the report before deploy. Pinned by a reliability test
and confirmed on a scratch copy: crawl, render, export, verify all exit 0 and
the two report copies are byte identical.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01656XvdqNAVojSPQBtLZAAt
deliver.mjs wrote state "sent" with delivered 0 when there was nobody to
send to, so the delivery signal claimed a send that never happened.
writeDeliveryStatus also dropped the reason run.mjs and deliver.mjs passed
in, while scripts/health-check.mjs prints that field, so the consumer read a
key the producer never wrote.

A run with no recipients now records state "skipped" with a reason, the
missing SMTP credentials path records its reason too, and writeDeliveryStatus
persists a non empty reason string. Keys are unchanged for the existing
success shape, and the health check and the workflow delivery gate only act
on required failed or partial states, so no gate behaviour changes.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01656XvdqNAVojSPQBtLZAAt
shared/phillies-schedule.mjs derives the "interleague" and "division" tags on
every canonical schedule row from a static NATIONAL_LEAGUE set. That set
listed 108 (LAA), 133 (ATH), and 136 (SEA), which are American League, so
those series never received the interleague tag. The Season at a Glance
splits and any schedule filter that reads tags were off for them. The set
now holds exactly the 15 National League ids, and a test pins AL, non East
NL, and NL East opponents to the tags they must carry.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01656XvdqNAVojSPQBtLZAAt
…bles

config.mjs is documented as the single source of truth for TEAM_ID and the
MLB API base, and shared/phillies-schedule.mjs owns the team id to
abbreviation table, but factcheck.mjs carried private copies of all three
(a literal 143, a literal statsapi URL, and a five entry id to code map).
Import them instead so the fact checker and the canonical schedule cannot
disagree on a team code or an endpoint. Behaviour is unchanged: the standings
reconciliation still resolves the same five NL East rows, confirmed by the
test suite and a scratch pipeline run with coverage.standings true.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01656XvdqNAVojSPQBtLZAAt
config.mjs is documented as the single source for constants, but the public
origin was copied into render.mjs, email-render.mjs, scripts/health-check.mjs,
and factcheck.mjs. The factcheck copy still pointed at the retired
davehomeassist.github.io root, so the accuracy report's source links and the
Notion row named a different site than the sitemap, RSS feed, JSON-LD, and
email. Add DEFAULT_SITE_URL and SITE_URL (with the existing
PHILLIES_WIRE_BASE_URL override, trailing slash stripped) to config.mjs and
import it everywhere. Output is unchanged for the default origin, confirmed
by a scratch pipeline run and the local health check.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01656XvdqNAVojSPQBtLZAAt
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.
To continue using code reviews, add credits to your account and enable them for code reviews in your settings.

The repository-scan (Trivy) gate fails on nodemailer 9.0.5, which carries
GHSA-2x7j-588g-ccc2: quadratic O(n^2) time complexity in addressparser
allows a remote denial of service. The advisory names 9.1.0 as the fixed
version.

main carries the same pinned 9.0.5, so this is not drift introduced by the
Build Toward the Whole series; main's last scheduled scan ran 2026-09-07,
before the advisory was published, and would fail the same check today.

Stay inside the 9.x major rather than moving to 10.x, so the delivery path
in deliver.mjs is unchanged. npm test passes with 9.1.0 installed: lint OK
across 55 files, 25/25 test files pass, including delivery-status and
deliver-failure-isolation.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants