Skip to content

docs(agents): make AGENTS.md the shared contract for every executor (branches, delivery, forbidden ops, acceptance, repo constraints) #662

Description

@jasonhnd

Why

More kinds of executors now work in this repository: local agents, cloud agents, and project-level supervisors. Most of them read only AGENTS.md at the repository root — they cannot see any personal or machine-level instructions. Today AGENTS.md (86 lines on preview 66ec643e) covers canonical documents, hard rules, Vercel read-only commands, and a short verification block, but it does not say:

  • who may merge into preview and main, and that executors never merge;
  • that one Issue maps to one PR and what the PR description must contain;
  • which operations are forbidden (force-push, branch deletion, CI/deploy config edits, live GA4 setup, global tool upgrades);
  • the full acceptance chain CI actually runs (the Playwright step and the REQUIRE_BUILT_ARTIFACTS step are missing), that there is no lint script, and why the PUBLIC_* analytics variables must be unset;
  • repository constraints that were only known to supervisors: public copy is Japanese-only and owner-signed, independence / data-source wording, the 1440 / 768 / 375 check, production-crawl limits, score rounding, toolchain pins.

It also still says "Design v1.0"; the canon is Design v1.2 (docs/Design.md line 3).

Revision 2026-09-25 (after review of PR #663)

The independent review of PR #663 found four problems in this Issue's target text (the executor followed it faithfully). All four were verified and the appendix below is corrected:

  1. Merge authority conflicted with docs/WORKFLOW.md / CONTRIBUTING.md ("human merge") and omitted the merge preconditions. Fixed in the table (preconditions added; main = owner, merge commit) and by aligning those two lines (new step 3).
  2. unset PUBLIC_* is not enough: the build also reads .env* files. Measured on preview with a copy of .env.local: unset only → the production gtag snippet is still emitted; explicit empty exports → no tracker markup and vercel.json CSP hashes identical to CI. PUBLIC_CF_BEACON_TOKEN and PUBLIC_GOOGLE_ADS_ID (read in src/layouts/BaseLayout.astro) are added.
  3. The chain lacked bun x playwright install --with-deps chromium (CI runs it before the suite; playwright.config.ts says the browser binary is not a package dependency).
  4. docs/TOOLCHAIN.md §10.1's e2e row is outdated; AGENTS.md now says so and points to the acceptance commands.

Evidence (checked 2026-09-25 on preview 66ec643e)

Command Result
bun install --frozen-lockfile OK
bun run test 1725 pass / 0 fail
bun run typecheck OK
bun run build OK
REQUIRE_BUILT_ARTIFACTS=1 bun test scripts/home-css-loading.test.ts src/site/models-built.test.ts OK
bun run verify:gates OK
bun run check:docs-links OK
bun x playwright test --reporter=line 356 passed, 26 skipped, 0 failed
git diff --exit-code clean
grep -c '"lint' package.json 0 — there is no lint script

Facts cited by the new text, all verified on preview: --gutter and --content-max in src/lib/canonical-css.ts (lines 114–120); CI step Enforce preview-to-main promotion at .github/workflows/ci.yml:26; Playwright baseURL / webServer.url on port 4321 (playwright.config.ts:41,51); displayed-value banding and unrounded averaging in docs/CONSENSUS_SCORE.md / docs/DATA_ARCHITECTURE.md; independence and data-source wording on /about, /compliance, src/lib/og-renderers/_frame.ts.

やること

  1. Branch docs/agents-contract from the latest origin/preview.

  2. Replace the whole content of AGENTS.md with the target text in the appendix below, verbatim (copy it exactly; do not reword, reorder, or add). Compared with the current file it:

    • keeps every existing section and sentence;
    • adds one paragraph under the title (the "shared contract" paragraph);
    • changes "Design v1.0" to "Design v1.2" in Hard rules;
    • inserts new sections Branches and merge authority, Delivery: one Issue, one PR, Forbidden operations, Acceptance commands (replaces the old Verification section and keeps its Cursor Cloud paragraph), Repository-specific constraints, Autonomy;
    • moves Operational commands (read-only) to the end, unchanged.
  3. Align the two older contract lines that still say "human merge" for PRs into preview (owner decision 2026-09-21: preview merges are delegated to the supervisor; main promotion stays with the owner). Replace exactly these lines and nothing else:
    docs/WORKFLOW.md (標準フロー, step 5, third bullet). Replace this whole line (it starts with three spaces):

    - `quality`(GitHub UI では `CI / quality`)と `Vercel` が成功し、review conversation がすべて解決してから human merge する。
    

    with:

    - `quality`(GitHub UI では `CI / quality`)と `Vercel` が成功し、review conversation がすべて解決してから、監督者(オーナー、またはオーナーが `preview` への merge を委任した監督 agent)が diff と独立レビューを確認して merge する。実装担当(executor)は merge しない。
    

    CONTRIBUTING.md (ブランチと Pull Request, step 4). Replace this whole line:

  4. Repository checks の rollout 完了後は quality(GitHub UI では CI / quality)と Vercel を通し、review conversation をすべて解決してから human merge を行う。

    
    with:
    
    ```text
    
  5. Repository checks の rollout 完了後は quality(GitHub UI では CI / quality)と Vercel を通し、review conversation をすべて解決してから、監督者(オーナー、またはオーナーが preview への merge を委任した監督 agent)が diff と独立レビューを確認して merge する。実装担当は merge しない。main への promotion はオーナー本人が承認して merge する。

    
    The lines inside the `text` blocks are exact file content (no escaping). Easiest: `python3 -c` with `str.replace` on each file, asserting the old line occurs exactly once.
    Leave `docs/WORKFLOW.md`'s promotion section (「Owner が production 反映を承認して human merge する」) unchanged.
    
  6. Do not edit any other file except CHANGELOG.md: under ## [Unreleased] → ### Changed (create the heading only if absent), add as the first bullet:
    - **AGENTS.md is now the shared contract for every executor** — branches and merge authority, one Issue / one PR delivery, forbidden operations, the full acceptance chain (no lint script exists), and repository constraints (Japanese-only owner-signed copy, independence wording, 1440/768/375, production-crawl limits, score rounding, toolchain pins). Design canon reference corrected to v1.2.

  7. Verify:

    diff AGENTS.md <(gh issue view 662 --json body -q .body | sed -n '/^<!-- AGENTS.md BEGIN -->$/,/^<!-- AGENTS.md END -->$/p' | sed '1,2d;$d' | sed '$d')   # must be empty; if the extraction is awkward, compare by eye section by section and say so in the PR
    bun run check:docs-links
    git diff --stat origin/preview      # only AGENTS.md, CHANGELOG.md, docs/WORKFLOW.md, CONTRIBUTING.md
    grep -c "human merge" docs/WORKFLOW.md CONTRIBUTING.md   # WORKFLOW 1 (promotion only), CONTRIBUTING 0
    grep -n "Design v1.2" AGENTS.md     # present
    grep -c "Design v1.0" AGENTS.md     # 0
  8. Commit, push, open the PR against preview with Closes #662 on the first line, the verification output, and a note of anything you were unsure about.

やらないこと

  • Do not reword the target text, fix its style, or add sections. If you believe something in it is factually wrong, keep the text as given and explain the problem in the PR description.
  • Do not change docs/TOOLCHAIN.md or any other file besides AGENTS.md, CHANGELOG.md, and the two single lines in step 3.
  • Do not add model names, credentials, tokens, or personal paths.
  • No force-push, no merge, no push to preview / main, no branch deletion.

Acceptance

  • AGENTS.md equals the appendix text byte for byte (trailing newline included).
  • git diff --stat origin/preview lists only AGENTS.md, CHANGELOG.md, docs/WORKFLOW.md (1 line), CONTRIBUTING.md (1 line).
  • bun run check:docs-links passes (all new links resolve: docs/CONSENSUS_SCORE.md, docs/DATA_ARCHITECTURE.md, docs/EDGE_SECURITY.md, docs/INCIDENT_RUNBOOK.md, docs/TOOLCHAIN.md, docs/WORKFLOW.md, docs/Design.md, docs/DESIGN_CONFORMANCE.md, CONTRIBUTING.md).
  • PR base preview, first line Closes #662, verification output pasted.
  • quality green.

Appendix — target AGENTS.md (verbatim)

# AGENTS.md

Guidance for coding agents (Claude Code / Codex / Gemini CLI / Grok) working in
this repository.

This file is the shared contract for **every** executor that works here —
local agents, cloud agents, and project-level supervisors alike. Many of them
cannot read any instructions outside this repository, so everything an
executor must obey is written here or in the documents linked below. When this
file and a brief disagree, stop and say so in the PR instead of guessing.

## Canonical documents

- [`docs/WORKFLOW.md`](docs/WORKFLOW.md) — development workflow, branch roles,
  promotion, and the Vercel operation authority boundary. Read it before
  non-trivial work.
- [`docs/TOOLCHAIN.md`](docs/TOOLCHAIN.md) — canonical pins for Bun / Node /
  Astro / Vercel planes. Do not guess versions.
- [`docs/Design.md`](docs/Design.md) — UI/UX canon: colour tokens, type scale,
  heading levels, page classes, spacing, breakpoints, contrast contract.
  **Read §0 (a 40-line quick card) before touching any CSS, markup, or visual
  copy.** Do not guess a font size or a colour — every value is a token.
- [`docs/DESIGN_CONFORMANCE.md`](docs/DESIGN_CONFORMANCE.md) — per-surface
  migration ledger. Tells you which surfaces the Design gates enforce on, what
  the next migration step is, and the completion checklist for each surface.
- [`CONTRIBUTING.md`](CONTRIBUTING.md) — PR flow and required verification.

## Hard rules

- Repository records (Issues, PRs, commit messages, `docs/`) are written in
  English or Japanese only.
- Base PRs on `preview`. Never target `main` directly; `preview → main`
  promotion is owner-approved.
- Vercel access (MCP `https://mcp.vercel.com` and the authenticated CLI)
  carries owner-level permissions:
  - Read/diagnose freely: deployment status, build logs, usage, analytics,
    firewall overview, alert listings.
  - Owner approval required before any state change: promote / rollback /
    redeploy, env vars, firewall rules and `publish`, rolling-release config,
    alias / domain / DNS / project settings, and any `vercel api` write
    (POST / PATCH / PUT / DELETE).
  - Never use firewall Challenge actions — they block AI crawlers and break
    the GEO policy ([`docs/EDGE_SECURITY.md`](docs/EDGE_SECURITY.md)).
    Rate-limit exceeded action is `log` or `deny` (429) only.
- Score batches are append-only; never overwrite existing runs.
- Do not commit secrets or generated `dist-astro/`.
- UI work follows [`docs/Design.md`](docs/Design.md) (Design v1.2):
  - No raw `font-size`, `color`, `padding`, `border-radius`, or `z-index` in
    page CSS. Use the `var(--*)` tokens.
  - No `!important` on `font-size`. Heading variants branch on
    `body[data-page-class]` inside `canonical-css.ts` (§4.9).
  - No `:root{}` in a page `<style>` (§18.4).
  - Serif is Display / H1 / H2 only. H3 and below are sans (§4.4). Minimum
    font size site-wide is 12px (§4.2).
  - Every new page belongs to a page class (§6.5).
  - Adding a scale step, a role, or a token means updating `docs/Design.md`
    **first** (§19.4). A version bump is owner-approved — an agent must never
    revise the canon on its own (§20.6).
  - Before starting a surface migration, read its row in
    [`docs/DESIGN_CONFORMANCE.md`](docs/DESIGN_CONFORMANCE.md); when finished,
    update that row in the same PR.

## Branches and merge authority

| Branch | Role | Who may push | Who may merge into it |
| --- | --- | --- | --- |
| `preview` | Integration branch. Every topic branch starts from the latest `origin/preview`; every PR targets it. | Nobody pushes directly. | The supervisor — the owner, or a supervising agent the owner has delegated `preview` merges to — after reading the diff and an independent review, with `quality` and `Vercel` successful and all review conversations resolved. Never the executor. |
| `main` | Vercel production. | Nobody pushes directly. | Only a promotion PR with head=`preview`, merged by the owner (a human) after explicitly approving that promotion, using a merge commit. CI enforces the head rule (`Enforce preview-to-main promotion` in `.github/workflows/ci.yml`). |
| topic branch | One Issue, one focused change. | The executor assigned to that Issue. | — |

- `pre.mirai-shigoto.com` is the preview **alias**, not a branch. There is no
  `pre` branch.
- `preview` is not the default branch, so `Closes #N` in a PR does **not**
  auto-close the Issue on merge. The supervisor closes it after merging.
- Start from the latest `preview`: `git fetch origin && git switch -c <branch> origin/preview`.
  If `preview` moves while your PR is open and GitHub reports a conflict or
  "not up to date", run `git fetch origin && git merge origin/preview`,
  resolve, and push normally. Do not rebase a branch that is already pushed.

## Delivery: one Issue, one PR

1. Work only from an Issue. If there is no Issue, there is no PR.
2. One Issue maps to exactly one PR (unless the Issue itself splits the work).
3. Commit after every completed step, with a conventional English message
   (`feat:`, `fix:`, `docs:`, `chore:`, `ci:`, …).
4. The PR description contains, in this order:
   - `Closes #N` on the first line;
   - what changed, mapped to the Issue's steps;
   - the real output of every verification command you ran;
   - anything not done, deviations from the Issue, and open questions.
5. Stop after opening the PR (and after pushing any follow-up commits the
   Issue asks for). Review and merging are someone else's job.

## Forbidden operations

Unless the Issue explicitly says otherwise, an executor must never:

- force-push (`--force`, `--force-with-lease`, `-f`) or rewrite pushed history;
- delete branches (local or remote) or delete files outside the Issue's scope;
- merge, close, or reopen PRs; close or edit Issues;
- push to `preview` or `main`, or open a PR whose base is `main`;
- change CI or deployment configuration: `.github/workflows/**`,
  `vercel.json` (except the CSP hashes that `bun run build` regenerates —
  commit those only when the Issue's change explains them), `.cursor/**`,
  `.vercelignore`, `bunfig.toml`, `astro.config.mjs`;
- run any Vercel state change (see Hard rules), or the live GA4 setup under
  `analytics/` (`setup`, `setup:check`, `discover`, `oauth-init`) — only
  `node analytics/setup-ga4.mjs --dry-run` is credential-free;
- upgrade globally installed tools (e.g. `bun upgrade`). If an Issue needs a
  specific tool version, install it into a private directory and put it
  first on `PATH` for your commands.

## Acceptance commands

Run these from the repository root before opening a PR. All of them were
confirmed to pass on `preview` (`66ec643e`, 2026-09-25):

```bash
export PUBLIC_GA4_MEASUREMENT_ID='' PUBLIC_X_PIXEL_ID='' PUBLIC_META_PIXEL_ID=''
export PUBLIC_CF_BEACON_TOKEN='' PUBLIC_GOOGLE_ADS_ID=''
bun install --frozen-lockfile
bun run test          # read the "N pass" / "N fail" lines, not only the last line
bun run typecheck
bun run build
REQUIRE_BUILT_ARTIFACTS=1 bun test scripts/home-css-loading.test.ts src/site/models-built.test.ts
bun run verify:gates
bun x playwright install --with-deps chromium   # the browser binary is not a package dependency
bun x playwright test --reporter=line           # the CI "rendered-output checks" step
git diff --exit-code
```

- Docs-only changes still require `bun run check:docs-links`.
- There is **no lint script** in this repository. Do not invent one; the
  gates above (`verify:gates`, `check:*`) are the static checks.
- Override the `PUBLIC_*` analytics variables with **empty values** before
  building, as above. Unsetting them is not enough: the build also reads
  `.env*` files (for example `.env.local`), which can supply production IDs.
  With an ID present the build emits tracker blocks, which changes the CSP
  hashes written into `vercel.json` and sends local test traffic to
  production analytics.
- Playwright uses port 4321 (fixed in `playwright.config.ts`); do not run two
  suites on the same machine at the same time.
- CI (`quality`) runs this acceptance chain on Ubuntu, including the
  Chromium installation and the Playwright suite.

On a Cursor Cloud Agent, `.cursor/install.sh` provisions this toolchain at
checkout. What that VM can and cannot verify on its own — e2e, scoring
providers, and everything that needs a Vercel deployment — is
[`docs/TOOLCHAIN.md`](docs/TOOLCHAIN.md) §10. Its e2e row in §10.1 is
outdated: CI does run Playwright, and the analytics specs skip themselves
when the build carries no GA4 markup. Follow the acceptance commands above
for rendered-output checks.

## Repository-specific constraints

- **Public copy is Japanese only.** The site dropped its English UI in v1.4.0;
  do not add English UI strings or a language switcher.
- **Public Japanese copy is owner-signed.** Page text, meta descriptions, OG
  card text, and other visitor-facing Japanese must be used exactly as quoted
  in the Issue. Do not write, rephrase, or "improve" public Japanese copy on
  your own; if the Issue does not quote the string, stop and ask in the PR.
- **Independence and data-source wording.** The site is an independent,
  unofficial analysis (see `/about`, `/compliance`, and the OG card frame).
  Do not add wording that implies affiliation with, or endorsement by, the
  Ministry of Health, Labour and Welfare (jobtag), JILPT, or any model vendor.
  Changes to `/compliance`, `/privacy`, attribution, or licence text need
  owner-signed wording in the Issue.
- **Design, all three widths.** Any layout or typography change is checked at
  1440 / 768 / 375 px before the PR. Column padding uses only `var(--gutter)`
  and widths only `--content-max` (`src/lib/canonical-css.ts`); new pages
  must not define their own spacing values.
- **Scores and data.** Score batches are append-only. The consensus-score
  rules live in [`docs/CONSENSUS_SCORE.md`](docs/CONSENSUS_SCORE.md) and the
  rounding rules in [`docs/DATA_ARCHITECTURE.md`](docs/DATA_ARCHITECTURE.md):
  bands, colours, and tier words follow the displayed one-decimal value,
  while averages are computed from the unrounded values.
- **Production traffic.** Never crawl or poll the production domain
  `mirai-shigoto.com` from a script: platform DDoS mitigation will challenge
  your IP, and a challenge that reaches real crawlers breaks the GEO policy.
  Full-URL checks go to `pre.mirai-shigoto.com` or a deployment alias, with
  concurrency ≤ 4, once.
- **Toolchain pins** ([`docs/TOOLCHAIN.md`](docs/TOOLCHAIN.md)): keep
  `bun.lock` at `lockfileVersion: 1`; do not add `engines.node`; do not add
  `@astrojs/vercel`; keep `@vercel/og` pinned to exactly `1.0.1`
  (1.0.2 / 1.0.3 abort on import).

## Autonomy

Complete the work autonomously. Do not stop to ask questions — nobody will
answer. (自律的に完了させること。途中で止まって質問しないこと。誰も答えない。)

## Operational commands (read-only)

Free to run without approval, per the authority boundary in
[`docs/WORKFLOW.md`](docs/WORKFLOW.md):

- `vercel alerts --ai` — check unresolved production alerts at session start.
- `vercel ls` / `vercel inspect <url> --logs` — deployment states, build logs.
- `vercel usage --group-by project` — cost attribution.
- `vercel firewall overview` — WAF / rate-limit / attack-mode state.

Incident procedures and the platform-state ledger live in
[`docs/INCIDENT_RUNBOOK.md`](docs/INCIDENT_RUNBOOK.md). Every state-changing
command there is owner-approval-gated.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    delivery:unitloopcoder work unitdocumentationImprovements or additions to documentationrisk:lowlow risk work itemtier:2tier 2 work item

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions