Skip to content

feat(account): close the page with what authGD last pushed - #42

Merged
guarzo merged 3 commits into
mainfrom
worktree-account-closing-beat
Aug 3, 2026
Merged

feat(account): close the page with what authGD last pushed#42
guarzo merged 3 commits into
mainfrom
worktree-account-closing-beat

Conversation

@guarzo

@guarzo guarzo commented Aug 3, 2026

Copy link
Copy Markdown
Owner

The account page ended on a control and a disclaimer. It now ends on what authGD
is actually doing on the member's behalf, and then on the artwork.

LAST PUSHED  UTC ──────────────────────────────
STANDINGS   12m ago   next 22:05
MAP         38m ago   next 22:10
DISCORD     ○ NOT LINKED

Reviewer focus: the data source changed from the brief

The plan was to aggregate per-character state. All three candidate sources are
wrong in the same direction — they report "never" for members who are being
synced correctly:

  • contact_sync_state is keyed by the FLYGD character whose contact list is
    written. A blue or green member is the content of that push, never a target,
    so their rows are structurally absent.
  • wanderer_acl_observation is delete-and-replace. A character legitimately off
    the ACL has no row, indistinguishable from a job that never ran.
  • audit_log records role changes. "Last changed" is not "last checked".

So each row reads sync_run for its job, which is true for every member
regardless of tier. partial counts as pushed; failed does not, so a broken
job visibly stops advancing rather than reporting freshness it did not deliver.
Rationale is in the PUSH_JOBS doc comment.

No N+1: three indexed lookups issued concurrently, ordered by serial id to
match the (job_type, id desc) index, following the precedent in
services/health.ts.

Other decisions

  • Cron schedules: the brief said lift them into src/config.ts, and this PR
    originally did. Sync: promote the answer, collapse the evidence #47 landed src/core/schedules.ts for the same reason (the
    admin sync page renders cadence from what the worker registers), so on rebase
    that became the single source and the src/config.ts copy was dropped rather
    than shipped alongside it. The dependency-free next-occurrence helper (12 unit
    tests) now lives in that same module, under formatCadence: that says how
    often a job runs, this says when it runs next. src/worker/queues.ts is
    unchanged from main.
  • Absolute next-check times (next 22:05) in UTC, the timezone EVE schedules are
    already read in.
  • Discord gets a distinct "not linked" state, which is not the same as "the job
    has not run".
  • The whole section is omitted with zero characters linked: three "not yet run"
    rows would read as a broken system rather than an empty one.
  • Crew manifest column CONTACTS → STANDINGS.
  • Closing artwork is lander-moon.webp, 1120×711 cut from the master at its
    alpha bounding box and drawn at 560px — a derivative cut for the size it is
    drawn at, per PRODUCT.md principle 5, not a scaled-down master or a decorative
    crop.

Known inconsistency, not fixed here

The top notice ("First sync has not run yet") and the crew-manifest STANDINGS
cells both key off per-character contactSyncResult — the same structurally-null
field described above — so they can read "not yet run" while LAST PUSHED reports
a recent push. Same defect, different surfaces, out of scope for this PR.

Verification

  • npx tsc --noEmit — clean
  • npx prettier --check . — all files match
  • npx eslint . — 0 errors, 5 warnings (all pre-existing-style no-img-element)
  • npx vitest run — 367 passed (48 files)
  • npx playwright test — 21 passed

@coderabbitai

coderabbitai Bot commented Aug 3, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

You’ve reached a temporary PR review limit under our Fair Usage Limits Policy.

Your recent review volume is higher than typical usage, so adaptive limits are currently applied.

Next review available in: 9 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 5539d387-b3c1-472d-a812-82ee11a16fba

📥 Commits

Reviewing files that changed from the base of the PR and between 4e7a7f3 and ae09bf4.

📒 Files selected for processing (8)
  • e2e/account.spec.ts
  • public/brand/lander-moon.webp
  • src/app/account/page.tsx
  • src/app/globals.css
  • src/core/schedules.ts
  • src/services/account-view.ts
  • tests/account-view.test.ts
  • tests/schedules.test.ts
📝 Walkthrough

Walkthrough

The account view now calculates per-service push telemetry from sync runs and cron schedules. The account page displays last and next push times for standings, map, and Discord, updates the contacts heading to “Standings,” and adds closing artwork. Tests cover schedule parsing, status selection, and account states.

Changes

Account Push Telemetry

Layer / File(s) Summary
Cron schedule parsing and occurrence calculation
src/core/schedules.ts, tests/schedules.test.ts
Cron expressions now support validated wildcards, steps, ranges, lists, and UTC next-occurrence calculation. Tests cover validation, rollovers, DST, impossible dates, and worker schedules.
Account-view push status aggregation
src/services/account-view.ts, tests/account-view.test.ts
The account view now exposes per-job push status. Successful and partial sync runs provide the latest timestamp, while cron schedules provide the next check.
Account-page telemetry and presentation
src/app/account/page.tsx, src/app/globals.css, public/brand/lander-moon.webp
The page renders standings, map, and Discord push states, handles unlinked and never-run states, renames the contacts column, and adds responsive closing artwork.
Account-page end-to-end coverage
e2e/account.spec.ts
End-to-end tests cover the Standings heading and Last pushed states, including omission when no character is linked.

Estimated code review effort: 4 (Complex) | ~45 minutes

Possibly related PRs

  • guarzo/authGD#1: Extends the same account page, account-view service, and account-view tests.
  • guarzo/authGD#2: Relates to the sync-run telemetry and synchronization infrastructure used by this change.
  • guarzo/authGD#11: Extends the same account-page styling and visual system.

Poem

A rabbit checks the cron at dawn,
Three push trails glow before the morn.
“Not yet run” rests soft and clear,
The moon now closes the page with cheer.
Hop, sync, and schedule onward! 🐇

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed The title clearly identifies the account-page change that adds last-pushed telemetry.
Description check ✅ Passed The description explains the change, rationale, verification, and known inconsistency, so it is mostly complete despite missing explicit template headings.
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch worktree-account-closing-beat
✨ Simplify code
  • Create PR with simplified code
  • Commit simplified code in branch worktree-account-closing-beat

Comment @coderabbitai help to get the list of available commands.

@guarzo
guarzo force-pushed the worktree-account-closing-beat branch 2 times, most recently from 0a0622e to 4e7a7f3 Compare August 3, 2026 22:30

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 9

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@e2e/account.spec.ts`:
- Around line 146-156: Make the relative-time check in the account page test
deterministic by freezing the test clock or asserting an acceptable bounded
range around the 12-minute fixture age. Update the expectation associated with
the “Last pushed” heading and pushed locator while preserving validation of the
rendered relative time.
- Around line 154-160: Update the assertions around the pushed telemetry rows to
locate each row by its <dt> label, then verify the expected <dd> values for
standings, map, and Discord individually. Replace the broad pushed-container
text checks and first-match cadence assertion with row-scoped checks that
validate each surface’s configured next occurrence, using the existing pushed
locator as the test scope.

In `@src/app/account/page.tsx`:
- Around line 307-315: Replace the native img element in the closing section of
the account page with next/image, preserving its source, dimensions, alt text,
and loading behavior while adding an appropriate sizes value for responsive
image selection. Retain the native element only if this deployment cannot use
the Next.js image optimizer.

In `@src/app/globals.css`:
- Around line 1425-1438: Update the push status-column rule for .push > time and
.push > .st to use a fixed flex basis of 8ch rather than only min-width,
ensuring all status values reserve the same width and the “next HH:mm” column
aligns consistently across rows.

In `@src/core/schedules.ts`:
- Around line 98-104: Update the cron parsing loop around part.split("/") to
capture all slash-separated segments and reject any part containing more than
one slash before parsing spec and stepRaw. Preserve the existing validation for
non-numeric and zero step values, while ensuring inputs such as "*/5/2" throw an
unsupported-cron-step error.

In `@src/services/account-view.ts`:
- Around line 59-90: Cache the account-independent database results used by
getPushStatus with a short revalidation window and no account-specific key,
while keeping now outside the cached computation so nextCheckAt is calculated
against the current request time. Preserve the existing per-job query semantics
and returned PushStatus shape.
- Around line 82-85: Update getPushStatus around the nextOccurrence call to
defensively resolve JOB_CRON[jobType]. Catch missing or unsupported cadence
errors and set PushStatus.nextCheckAt to null, while preserving the calculated
occurrence for valid expressions so account rendering continues without
throwing.

In `@tests/account-view.test.ts`:
- Around line 140-148: Strengthen the test “takes the newest run per job,
keeping the three independent” by adding a later-inserted, higher-id run whose
finishedAt is earlier than the existing contacts run, so id ordering and
finishedAt ordering disagree. Update the expected contacts lastPushedAt
assertion to confirm getPushStatus selects that higher-id row while leaving the
other job and never-ran assertions unchanged.

In `@tests/schedules.test.ts`:
- Around line 79-141: Add a test within the nextOccurrence suite that supplies a
cron expression restricting both day-of-month and day-of-week, with an instant
covering a date matching only one restriction before the date matching both.
Assert the returned occurrence satisfies both fields, thereby pinning the
documented intersection semantics rather than standard cron union behavior.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 665195fb-32c2-4bd8-bbb9-a7b32737d89d

📥 Commits

Reviewing files that changed from the base of the PR and between d4fb44b and 4e7a7f3.

📒 Files selected for processing (8)
  • e2e/account.spec.ts
  • public/brand/lander-moon.webp
  • src/app/account/page.tsx
  • src/app/globals.css
  • src/core/schedules.ts
  • src/services/account-view.ts
  • tests/account-view.test.ts
  • tests/schedules.test.ts

Comment thread e2e/account.spec.ts Outdated
Comment thread e2e/account.spec.ts Outdated
Comment thread src/app/account/page.tsx
Comment thread src/app/globals.css
Comment thread src/core/schedules.ts
Comment thread src/services/account-view.ts
Comment thread src/services/account-view.ts
Comment thread tests/account-view.test.ts
Comment thread tests/schedules.test.ts
guarzo added 3 commits August 3, 2026 18:57
The account page ended on a control and a disclaimer, leaving the member
without the one thing they came to check: whether the system has actually
acted for them, and when it will look again.

Adds a "Last pushed" telemetry block — standings, map, Discord — each with
a relative last-push time and the next scheduled check in UTC, and closes
the page on Faoble's lander cresting the lunar horizon.

Sourcing note: the timestamps come from sync_run, not from per-character
state. contact_sync_state is keyed by the FLYGD character being written,
so a blue or green member has no rows and would read "never run" forever;
wanderer_acl_observation is a delete-and-replace snapshot where "not on the
ACL" is indistinguishable from "not yet run"; audit_log records role
*changes*, and "last changed" is not "last checked". The job's own
completion is the only answer that is true for every tier.

- SCHEDULES lifted into src/config.ts so the worker's cadence and the
  cadence shown to members cannot silently diverge
- src/core/schedule.ts: a small pure next-occurrence helper over the cron
  grammar we actually use, throwing loudly on anything outside it
- crew manifest column renamed Contacts -> Standings, matching the language
  the rest of the page uses
Adds e2e coverage for the three states the section can be in: a surface
that has pushed, one that is scheduled but has never run, and a Discord
row with nothing linked at all. Plus the zero-character case, where the
section is absent rather than showing three empty rows.

Also centres the closing artwork with a margin. The global reset makes
images block-level, so the text-align on the wrapper was silently doing
nothing and the lander sat flush left.
- reject a second cron step ("*/5/2") instead of dropping the tail
- degrade an unknown or unparseable JOB_CRON entry to a null next-check
  rather than throwing and taking the account page down
- reserve the state column in rem, not ch: ch resolves per element
  font-size and the two branches render at different sizes, so the
  "next" column did not actually line up
- scope the e2e push assertions per row and assert the alignment
- pin newest-by-id (not max(finished_at)) and the dom+dow intersection
@guarzo
guarzo force-pushed the worktree-account-closing-beat branch from e9d9308 to ae09bf4 Compare August 3, 2026 22:57
@guarzo
guarzo merged commit e60f60e into main Aug 3, 2026
5 checks passed
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.

1 participant