AGENTS.md · git:20261021.a1c9089 · 2026-10-21 · sha256 da05f833b3b36ae8
AGENTS.md git:20261021.a1c9089A
Immutable. This exact content never changes and is served at /api/v1/blob/da05f833b3b36ae8.
# Wikipedia-AI-Skills — Agent Instructions
Loaded automatically by pi in every session in this repo. See
`CONTRIBUTING.md` for the full contributor guide; this file is the binding
short version.
## PR-first workflow (hard rule)
All changes to `main` go through a pull request. Branch protection enforces
this server-side (6 required CI checks, no reviews); follow it even when you
could bypass it.
1. Start from up-to-date `main`: `git checkout main && git pull --ff-only origin main`
2. Create a branch: `git checkout -b <scope>/<change>` (e.g. `feat/my-skill`, `fix/toolforge`, `docs/agents-md`)
3. Commit with conventional style: `feat|fix|docs|ci|chore(<scope>): <summary>`
4. Push the branch, then `gh pr create` — the template
(`.github/PULL_REQUEST_TEMPLATE.md`) auto-applies; fill in summary,
what/why, and how it was tested
5. `gh pr checks --watch` — all 6 checks must pass before merging
6. Merge with `gh pr merge --merge --delete-branch`
Direct pushes to `main` are admin-bypass only, reserved for emergencies
(e.g. CI outage blocking a hotfix). If you bypass, say so explicitly in the
commit/PR.
## Remote state — query it, never infer it from local refs (hard rule)
`git log origin/main..HEAD` proves exactly one thing: *not merged into main*. It
says nothing about whether a branch was pushed, whether a PR exists, or what its
checks and review state are.
Learned the hard way: asked whether a commit had been pushed, an agent ran
`git log origin/main..HEAD`, saw the commit absent from `main`, and reported it as
"exists only on a local branch — awaiting its own PR/push". The branch was pushed
and had an **open PR with green CI**. A stale local `origin/*` is the usual cause.
- **Fetch first** (`git fetch origin`), or ask `gh` — those queries hit the API and
cannot be stale.
- **Branch pushed?** `git ls-remote --heads origin`.
- **PR exists / open / merged?** `gh pr list`, `gh pr view <n>`.
- **Checks / mergeable?** `gh pr checks <n>`,
`gh pr view <n> --json mergeable,mergeStateStatus`.
- **State the method with the claim.** "No PR in `gh pr list`" is checkable; "it
isn't pushed" is a guess dressed as a fact. If you have not queried the remote,
say so instead of asserting.
- **Absence is not evidence.** A local branch can exist with no PR; an open PR can
exist for a branch you never fetched; and because this repo deletes branches on
merge (`--delete-branch`), a missing branch says nothing about whether its PR
merged — use `gh pr view <n> --json state,mergedAt`.
## Consult the library before probing (hard rule)
This repo **is** the knowledge base for Wikimedia-adjacent work. Before writing a probe, a request,
or any claim about a Wikimedia-hosted endpoint, route, model or schema:
1. `grep -r "<model-or-endpoint>" .claude/skills/` and read the matching `references/` file.
2. Probe live only when the library does not answer, or to re-verify a `last_verified` date.
Learned the hard way (2026-10-21): the merged reference
`.claude/skills/wikimedia-ml-services/references/clef-flash-decision-models.md` (PR #100, merged
2026-10-16) documents that decision models 404 on the chat route and answer on `:predict`. Five days
later an adjacent task probed the chat route, got the documented 404, and reported a live model as
"not exposed — unexplained, worth asking the ML team". **A contradiction between a live probe and
this repo is a signal to re-read the repo, not a finding to publish.**
**Harness note for contributors:** `skill_discovery_hints` is a pi/opencode convention and is not
read by every harness — the Hermes harness selects skills on `description` alone. Trigger words
therefore belong in the `description`. A useful CI check would assert that each skill's hint
keywords appear in its description; until then, keep the description load-bearing.
## Skill contributions
For new or changed skills (`.claude/skills/<name>/`):
- **New skills:** pass the 7-question candidacy filter
(`docs/design-philosophy.md` §2) and record the verdict in the PR
- **Register:** `README.md` (skill table + "What can I do" table),
`ROADMAP.md` ("Published skills"), and run
`python3 scripts/refresh-url-registry.py --new-only` for any new URLs —
CI's Skill Registration Check enforces the first two
- **Tests:** add mock-based tests under `tests/` for new scripts/assets;
run `python3 -m pytest tests/ -q`. The suite is green (3 skips are
optional-dependency guards); tests marked `@pytest.mark.slow` make real API
calls and skip on HTTP 429/network drops via `run_live()` from
`tests/live_calls.py` — a skip there is CI throttling, not a failure
- **Freshness:** bump `last_verified` in the frontmatter of any changed
SKILL.md
- **Verify before pushing skill changes** (all offline, all must pass):
`python3 scripts/verify-links.py && python3 scripts/verify-freshness.py \
&& python3 scripts/verify-snippets.py && python3 scripts/verify-commands.py \
&& python3 scripts/verify-api.py && python3 scripts/verify-mul-labels.py \
&& python3 scripts/verify-script-guards.py`
## API etiquette (summary)
Every request to Wikimedia/Wikimedia-adjacent hosts needs a descriptive
User-Agent (`$WIKIMEDIA_USER_AGENT`), 429/403 handling, and ≥1s pacing
**when running outside Toolforge/WMCS** (rate limiting is not enforced on
bots in Toolforge/WMCS — see the Wikitech Robot policy) — see the global
AGENTS.md and the `wikimedia-api-access` skill for details.
## Local tooling
- Githooks (pre-push tooling-reference check): `./setup-hooks.sh`
- The 6 required CI checks: `check-skill-registration`,
`check-conftest-auto-discovery`, `check-roadmap-mentions`, `verify`,
`validate-tooling`, `tests` — they run on every PR unconditionally