Skip to content

docs(readme): recapture the daily entry, reports and sales screenshots - #865

Merged
mforce merged 1 commit into
mainfrom
docs/readme-screenshots
Sep 14, 2026
Merged

mforce merged 1 commit into
mainfrom
docs/readme-screenshots

Conversation

@mforce

@mforce mforce commented Sep 14, 2026

Copy link
Copy Markdown
Owner

Why

The README's four screenshots were captured on 2026-09-02, before #781 rebuilt both dashboard charts and #791 changed the capture tiles, and nobody recaptured. Three of the four are refreshed here from a sim stack rebuilt at main (6c83c5c), reset and reseeded per the capture procedure in tools/simulation/ui/README.md.

Scope

  • docs/images/daily-entry.png, docs/images/reports.png, docs/images/sales.png: recaptured by npm run screenshots.
  • Not included: docs/images/dashboard.png. Its capture fails the spec's own guard (screenshots.spec.ts:108, bar heights must vary) because on the simulation fixture every one of the last 14 days is a partial day: the fixture carries 102 flocks and only two file entries, so no day is complete, the complete-day peak is null, and every bar is a 2% floor stub with no average. That is the honest picture of the fixture, and it is not a picture for the README. The dashboard image therefore stays at its 2026-09-02 state until the fixture or the partial-day rule changes; see the discussion on the PR.

Blast Radius

Documentation only. The image job skips (#782); the tracked-file pin guard and GitGuardian still run.

Verification

  • bash tools/simulation/reset.sh at main: up, migrated, seeded (fingerprint 8987971d), verified.
  • npm run screenshots: 3 passed, 1 failed (dashboard, as above), and the three passing captures are the files in this diff.

@coderabbitai

coderabbitai Bot commented Sep 14, 2026 •

Copy link
Copy Markdown

Important

Review skipped

Review was skipped due to path filters

⛔ Files ignored due to path filters (3)
  • docs/images/daily-entry.png is excluded by !**/*.png
  • docs/images/reports.png is excluded by !**/*.png
  • docs/images/sales.png is excluded by !**/*.png

CodeRabbit blocks several paths by default. You can override this behavior by explicitly including those paths in the path filters. For example, including **/dist/** will override the default block on the dist directory, by removing the pattern from both the lists.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Advanced

Run ID: b5b3705b-6968-4d91-bd95-40e7f64d211c

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@mforce

mforce commented Sep 14, 2026

Copy link
Copy Markdown
Owner Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Sep 14, 2026 •

Copy link
Copy Markdown
⚠️ Action not completed

No files to review.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@mforce

mforce commented Sep 14, 2026

Copy link
Copy Markdown
Owner Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Sep 14, 2026 •

Copy link
Copy Markdown
⚠️ Action not completed

Already reviewed the last commit. Use @coderabbitai full review to rerun a review of the entire changeset.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@mforce
mforce merged commit f18e336 into main Sep 14, 2026
16 checks passed
@mforce
mforce deleted the docs/readme-screenshots branch September 14, 2026 13:59
mforce added a commit that referenced this pull request Sep 14, 2026
## Why

`docs/images/dashboard.png` is the one README image #865 could not
refresh. Its capture fails the spec's own guard (`screenshots.spec.ts`,
bar heights must vary) because on the simulation fixture every day in
the window is a **partial** day: the fixture seeds ~100 catalog flocks
for the picker (#627) which are placed, active and never file, so every
day owes a count nobody filed, `DayStripData.max` is null, and all
fourteen bars render as the 2% floor stub. #865 states that gap and
leaves the image at its 2026-09-02 state, which predates #781's bar
strip and #791.

The product rule is right and the fixture's counts are pinned by the
picker-paging specs, k6 and the e2e suite. So the fixture stays as it is
and the **capture** moves: the sim stack now carries a second, small
farm seeded with the demo profile, and the dashboard image is taken from
that.

Closes nothing — no issue exists. It follows from #865's stated gap.

## Scope

**`seed --profile demo --farm-code <slug>`** (`SeedCliCommand`,
`DemoDataSeeder`). The code is resolved by slug exactly as
`rename-account` and the lifecycle verbs resolve theirs
(`AccountSlugLookup`), after the migrate and before the seed; an unknown
code exits 1 naming `list-accounts`. `DemoDataSeeder.SeedAsync` takes
the target account as an explicit `Guid?` parameter, never ambient state
— `TenantContext` is single-assignment, so a seeder reading the tenant
instead of setting it could only run where somebody else had already
resolved one. Default behaviour is unchanged: every existing caller
passes nothing and gets `SeedDefaults.AccountId`. `--profile simulation`
**refuses** the flag: its manifest, its cast emails and the counts k6
and the e2e suite pin are all default-farm facts, so honouring it would
need a second decision, not a parameter.

Two things came along with that file. Every stderr path in the verb now
routes through one sanitizing sink (#560) instead of two of five,
because the shape where only the messages that quote argv get fixed is
the shape `rename-account` was corrected out of. And the demo seeder's
prerequisite messages no longer say "the default account", which stopped
being true.

**The sim harness** (#370 — all three files considered, and it says so
below). `reset.sh` provisions `readme-farm` with `provision-account`,
rotates its Owner off the printed one-time password onto a stable one,
demo-seeds it, and preflights that the farm is signable and holds the
demo fixture's three flocks. The timezone passed is
`Simulation__TimeZoneId`, not a literal, so the two farms on one stack
cannot end up on different clocks.

- The stable password is generated in `bootstrap.sh` beside
`SIM_ADMIN_PASSWORD` and read back by `reset.sh`, **mirroring the
existing pattern** rather than minting one in `reset.sh`. Generating it
in `reset.sh` would produce a new credential on every reset and leave
`.sim-cast.json` describing the previous one.
- It lands in `.sim-cast.json` under a top-level `readmeFarm` key,
outside the `cast` array, because every entry there signs into
`default-farm` and a driver iterating the cast must not have to ask
which farm each member belongs to.
- The rotation block is now **one shell function with two callers**
rather than two copies of a credential-rotation block.
- Re-running converges. `reset.sh`'s own flow never reaches the
already-exists branch (`down -v` ran at the top), but
`provision-account`'s duplicate behaviour is *not* a no-op like
`bootstrap-admin`'s — it exits 1 with `Provision.SlugTaken*` and prints
no password — so the branch checks the stable credential still signs in
and carries on, and fails loudly on any other failure.
- `verify-harness.sh` fails closed on a missing or blank `README_*`
value and on a cast file that predates the `readmeFarm` key.
- **`docker-compose.sim.yml` needs no change**, and that is a considered
answer rather than an omission: the `README_*` vars carry no `__`,
exactly like `SIM_ADMIN_*`, so they are script-level values `reset.sh`
greps out of `.env.sim` and never app configuration. Nothing new reaches
the container's `environment:` block. For the same reason there is no
`src/Cluckwork.AppHost/Program.cs` change under #565 — no new required
config key exists.

**The e2e suite.** `cast.ts` exposes `readmeFarmOwner()`, whose return
type widens `farmCode` from optional to required; `signIn` and the API
sign-in helper take the code from the member, falling back to
`default-farm`, so every persona written before this one is untouched.
Only the dashboard capture uses it.

**Docs.** `AGENTS.md`, `tools/simulation/README.md` ("Two farms on this
stack" + the `.env.sim` parameter row + the `reset.sh` chain),
`tools/simulation/ui/README.md`, and the dev-database runbook. **No
GLOSSARY or Help change**, deliberately: no user-visible concept changed
— the flag is an operator CLI argument and the second farm exists only
inside the sim harness.

## Blast Radius

`seed --profile demo` with no flag behaves exactly as before, which is
what every existing caller does. `--profile simulation` gains one
refusal on an argument nothing passes today. Per #394 the write contract
is unchanged, so no caller under `tools/simulation/k6/` or `specs/`
needed a change; the one Playwright caller that did (`signIn`) is in
this diff, and `session-races.spec.ts`'s own hardcoded `default-farm` is
correct as written because it drives a sim-cast persona.

The `readme-farm` account exists only in a throwaway `cluckwork-sim`
database. A regenerated `.env.sim`/`.sim-cast.json` is required — run
`bootstrap.sh --force`, then `reset.sh`; `verify-harness.sh` says so by
name if you forget.

Two capture fixes ride along. The #780 readout assertion moved **below**
the screenshot, because focusing a day leaves a focus ring and a readout
balloon that `capture()`'s blur does not dismiss, and the first capture
published both. And the `1280x1180` frame is now held open by the
**Owner's sidebar** (its content ends at 1164px, measured on the
rendered page) rather than by the main column, which on this farm ends
at 700px — anything shorter clips the navigation mid-list. The comment
in `playwright.screenshots.config.ts` says so, because the visible empty
space below the panels otherwise invites a shrink that breaks the
sidebar.

## Verification

Everything below ran in the worktree, against the real stack.

- `dotnet build Cluckwork.sln` — 0 warnings, 0 errors.
- `bash tools/simulation/bootstrap.sh --force` then `bash
tools/simulation/reset.sh` — up, migrated, both farms seeded, all four
preflights green, and the temporary password redacted on both
provisioning paths (checked in the log).
- `cd tools/simulation/ui && npm ci && npm run screenshots` — **4
passed**, including the dashboard capture whose guard fails on the
simulation fixture. `npm run typecheck` clean.
- `SeedCommandTests` (8, up from 5) plus `SimulationSeedCommandTests` —
11 passed. Registry readers found by grepping
`CliDispatcher.Commands|ProcessRoles.OneShotVerbs` under `tests/` rather
than from memory: `CliDispatcherTests`, `OneShotVerbMinimalConfigTests`,
`ProcessRoleRegistryTests`, run with `DemoSeedTests` and
`DemoSeedActorTests` — 29 passed.
- Both `PostgresImagePin_IsOneIdenticalString*` guards run before the
markdown was committed — 2 passed.
- **Mutation-checked, not asserted.** Reverting the CLI's account
routing to `SeedAsync()` turns
`SeedCommand_Demo_WithFarmCode_SeedsThatFarmAndLeavesTheDefaultEmpty`
red. Deleting `readmeFarm` from the cast file, and blanking its
password, each fail `verify-harness.sh` with exit 1; so does a blank
`README_OWNER_EMAIL` in `.env.sim`.
- The new seed test runs against **its own Postgres**, not the class
fixture's, and that is the assertion rather than tidiness: "nothing
landed under the default farm" is only meaningful on a database no
sibling `[Fact]` has demo-seeded, and xUnit guarantees no order within a
class.
- `dotnet test Cluckwork.sln` — result in a comment below.

The `RealSourceTree_AllBypassesAreAllowListed` guard fired on the
`SeedAsync` signature change, which is #632's registry working: the
entry is keyed by the enclosing symbol including its parameters, so
adding one demanded a re-read. The justification is re-written rather
than re-pinned — the `AccountId` predicate on those pre-`tenant.Resolve`
queries is now the caller's account rather than always
`SeedDefaults.AccountId`, and the bypass is still what lets the
preflight see the target farm at all.

## Two judgment calls worth a reviewer's eye

1. **The function is `readmeFarmOwner()`, not `readmeFarm()`.** It
returns a persona, like `owner()` and `restrictedWorker()` beside it,
and `readmeFarm()` reads as though it returns the farm.
2. **The farm name was truncated and is now fixed.** "Meadowlark Farm"
ellipsised to "Meadowlark F…" at the sidebar's 244px; commit 71f95ad
names the farm "Meadowlark" (`README_FARM_NAME` in `bootstrap.sh`) and
recaptures the image after a full reset. The comment below carries the
new capture.

## Screenshot

Before and after below. Same screen, same 1280x1180 frame; the before is
the committed image this PR replaces.

![Before: the committed dashboard image, captured 2026-09-02 on the
simulation fixture, showing the pre-#781 line
chart](https://github.com/user-attachments/assets/aac876b5-49e7-4f91-bcba-6252c01360aa)

![After: the same screen captured from the demo-seeded readme-farm, with
the #781 bar strip showing seven partial and seven complete days, the
average reference line, Avg 803.1 / Peak 822, and one No entry
tile](https://github.com/user-attachments/assets/b24ea479-80bf-46d5-ab6d-2b39bfa98e63)


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

- **New Features**
- The demo seed command can now target a specific farm with `--farm-code
<slug>`.
  - Unknown farm codes return a clear error and guidance.
  - Simulation profiles explicitly reject the farm-selection option.

- **Bug Fixes**
- Sign-in and simulation tooling now correctly support members of
non-default farms.

- **Documentation**
- Updated runbooks and simulation guidance describe multi-farm seeding
and screenshot workflows.

- **Tests**
- Added coverage for targeted seeding, invalid farm codes, and
unsupported simulation options.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: mforce <cleyva@clvc.net>
mforce pushed a commit that referenced this pull request Sep 16, 2026
🤖 I have created a release *beep* *boop*
---


## [0.1.2](v0.1.1...v0.1.2)
(2026-09-16)


### Features

* **data:** standardize business record chronology
([#820](#820))
([6231b31](6231b31))
* **infra:** optional leader-lease endpoint for pooled deploys
([#869](#869))
([e9bc6a7](e9bc6a7))
* **sim:** seed a second farm for the README dashboard capture
([#867](#867))
([de407c6](de407c6))
* **web:** adopt MUI, themed from the farm palette tokens
([#674](#674))
([#860](#860))
([6c83c5c](6c83c5c))
* **web:** convert Daily entry to MUI, field-first on the phone
([#888](#888))
([b66f8b8](b66f8b8))
* **web:** convert the Dashboard and app shell to MUI
([#829](#829))
([#883](#883))
([2e94277](2e94277))
* **web:** retire the Slack-blue link colour for ink + a rule underline
([#884](#884))
([c08f9d8](c08f9d8))
* **web:** serve a per-request CSP nonce so Emotion's styles apply under
style-src 'self'
([#874](#874))
([ba4e6f3](ba4e6f3))
* **web:** visual language theme overrides for the MUI revamp
([#864](#864))
([#882](#882))
([0bb6b73](0bb6b73))
* **web:** whole-app MUI baseline, theme policy guard and the
[#740](#740) phone action rule
([#823](#823))
([#871](#871))
([af565e4](af565e4))


### Bug fixes

* **auth:** fail closed on unresolved flock-scope actors
([#787](#787))
([#868](#868))
([16d0350](16d0350))
* **auth:** make farm configuration owner-only
([#870](#870))
([42f9036](42f9036))
* **e2e:** repoint the canary at the markup two PRs replaced
([#844](#844))
([18b45dc](18b45dc))
* **i18n:** tl glossary uses the standard passive of ilagay
([#813](#813))
([20dec10](20dec10)),
closes [#738](#738)
* **sim:** stop the k6-baseline EXIT trap masking a clean run as failed
([#838](#838))
([f5ec96f](f5ec96f))
* **web:** declare the rule tokens the Dashboard reads, and guard
undeclared custom properties
([#885](#885))
([5bead1f](5bead1f))


### Performance

* **ci:** start the serialized integration collection first
([#861](#861))
([1dcc7f6](1dcc7f6)),
closes [#839](#839)


### Documentation

* **auth:** record the OAuth 2.1 decision for MCP authentication
([#801](#801))
([0510854](0510854))
* **designs:** MUI revamp design doc, component map, layout system, IA
([#862](#862))
([da49481](da49481))
* **readme:** recapture the daily entry, reports and sales screenshots
([#865](#865))
([f18e336](f18e336))
* **specs:** correct the sales_order_items column list in §10.5
([#812](#812))
([afe4a02](afe4a02)),
closes [#737](#737)

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

Co-authored-by: cluckwork-lockfix[bot] <309265648+cluckwork-lockfix[bot]@users.noreply.github.com>
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