docs: move what lived only in agent memory into the repo
Four lessons were known to one agent's private notes and to nobody else. They now live where every agent reads: how Gitea Actions differs from GitHub Actions, the owner's decision to refresh unreachable sources by hand rather than relax the robots gate, how to look at the built app in a headless browser and its traps, and one command per shell call. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
2da7f20905
commit
08bbba65ff
@@ -110,6 +110,25 @@ bun test --test-name-pattern "year-less"
|
||||
BASE_PATH=/gacha-event-tracker/ bun run build
|
||||
```
|
||||
|
||||
**Looking at the built app.** UI work is checked in a real browser, not reasoned about. Build the
|
||||
shell without touching the feed — `bun run build:css && bun run build:js && bun run build:static` —
|
||||
and serve it with `PORT=<port> bun run serve.ts`. Drive a headless Chrome with `puppeteer-core`
|
||||
installed in a scratch directory, never in the project (`zod` is the only runtime dependency); on
|
||||
the owner's machine the browser is `/usr/bin/google-chrome-stable`. Traps that have each cost a
|
||||
cycle:
|
||||
|
||||
- **Use a fresh, distinctive port for every rebuild**, and stop your own server by its PID. The shell
|
||||
is cached cache-first (PRD F14), so the same origin serves the *previous* bundle after a rebuild;
|
||||
a new origin has no service worker at all. Other sessions may be serving on nearby ports — never
|
||||
`pkill -f serve.ts`.
|
||||
- **Reach a state through `localStorage`, then reload.** `gacha-tracker:v1:prefs` with
|
||||
`onboarded: true` skips first run; `view` is `"soon"` (the list) or `"timeline"` — anything else
|
||||
falls back to the default. Wait for something the view renders, not for `networkidle0`, which
|
||||
returns before React mounts.
|
||||
- **Read text with `textContent`.** Eyebrows are uppercased in CSS, so `innerText` returns
|
||||
`TODAY'S DAILIES` and a wait for `Today's dailies` never ends.
|
||||
- **Keep total capture scale at or below about 3×**; above it sticky panes rasterise blank.
|
||||
|
||||
**`build:js` passes `--production`, and that flag is load-bearing.** Without it Bun bundles React's
|
||||
*development* build: 566 KB rather than 344 KB (164 KB vs 103 KB gzipped), every element creation
|
||||
validated at runtime, and `StrictMode` double-invoking effects — which in this app means
|
||||
@@ -378,6 +397,15 @@ same reason `uma.moe` was declined below — and unlike `uma.moe` we would be do
|
||||
`robots.txt` was welcoming, which makes it worse, not better. The legitimate options are to run the
|
||||
refresh from an address game8 will serve, or to find those games another source.
|
||||
|
||||
**When CI cannot reach a source but the owner's own machine can, the owner refreshes by hand** —
|
||||
`bun run refresh`, then commits the snapshots as `chore(data): refresh source snapshots`. Asked on
|
||||
2026-08-17 whether to add a recorded-robots-policy override for `reverse1999.fandom.com`, whose
|
||||
`/robots.txt` refused a datacenter address, the owner declined the machinery and took the manual
|
||||
route. So register such a source normally, write down why CI cannot fetch it, and say plainly that
|
||||
refreshing it is a manual run. Do not propose header shaping, a proxy or a robots override: a
|
||||
`skipped_robots` outcome is only a warning and never touches the failure streak, so the source costs
|
||||
a warning line per cycle and nothing else.
|
||||
|
||||
**CI moved to a Gitea runner on 2026-09-16, which is the first of those two options — and its result
|
||||
is not yet known.** A different address is exactly the variable this failure turns on, so the nine
|
||||
game8 sources may now refresh on schedule, or may not. Nothing here should be rewritten on the
|
||||
@@ -1034,6 +1062,10 @@ to an open page). Four things hold it up:
|
||||
test and existence in a script run from a full checkout, as `scripts/check-changelog.ts` does.
|
||||
To see what the image sees, copy the Dockerfile's `COPY` list into a scratch directory, link
|
||||
`node_modules`, and run the suite there.
|
||||
- **One command per shell call when someone is approving them.** A call that runs an edit, `git add`
|
||||
and `git commit` chained with `&&` is one approve-or-deny decision over three actions: the edit
|
||||
cannot be inspected before the commit lands, and the transcript hides the diff at the moment it is
|
||||
approved. Read-only commands may share a call; a commit never rides along with anything.
|
||||
- **Only ever commit your own work.** Stage the files you changed, by path, and nothing else. The
|
||||
working tree may already hold edits, untracked fixtures or a half-finished experiment that someone
|
||||
else — the user, or another agent — put there and has not decided about yet; `git add -A`, `git
|
||||
|
||||
@@ -228,6 +228,27 @@ gates and publish it, while `.github/workflows/ci.yml` builds and deploys to Git
|
||||
only needs to build and serve, not refresh data sources; the scheduled refresh and container image
|
||||
publishing run exclusively on Gitea Actions.
|
||||
|
||||
**Gitea Actions is GitHub-Actions-compatible, not GitHub Actions.** That compatibility makes
|
||||
GitHub-shaped answers look right and then fail in specific places, so ask what *Gitea* does before
|
||||
changing CI, the registry or secrets. The directory name `.github/` is not evidence of which forge
|
||||
runs a workflow: Gitea reads `.gitea/workflows/` natively, and `test/refresh.test.ts` asserts on the
|
||||
workflow files by path. The divergences found so far, each one paid for once:
|
||||
|
||||
- **The registry does not take the Actions token.** A Gitea package belongs to a user or org, not a
|
||||
repository, so `secrets.GITHUB_TOKEN` carries no authority over it and `permissions: packages:
|
||||
write` authorises nothing. The image push logs in with an access token with the *package* scope,
|
||||
stored as `REGISTRY_TOKEN` — the comments in `.gitea/workflows/ci.yml` carry the detail.
|
||||
- **`uses:` takes full URLs** (`https://github.com/actions/checkout@v4`); a bare reference resolves
|
||||
against the instance's `DEFAULT_ACTIONS_URL`.
|
||||
- **No `gh` CLI on the runner.** `refresh.yml` dispatches `ci.yml` through Gitea's REST API
|
||||
(`${{ github.server_url }}/api/v1`) with `curl`.
|
||||
- **A push made with the Actions token *does* trigger workflows**, unlike on GitHub, which suppresses
|
||||
them. `refresh.yml` dispatches `ci.yml` anyway, and the per-ref concurrency group absorbs the
|
||||
duplicate.
|
||||
- **No Pages.** Gitea's deploy artefact is the container image, built without `BASE_PATH`; Pages is
|
||||
the GitHub mirror's job alone.
|
||||
- **Gitea push-mirrors to GitHub** — see `AGENTS.md` § Conventions on pushing.
|
||||
|
||||
### Hosting under a subpath
|
||||
|
||||
Assets resolve against a `<base href>` substituted at build time, the feed URL resolves against
|
||||
|
||||
Reference in New Issue
Block a user