AGENTS.md · git:20260926.6fe8f2d · 2026-09-26 · sha256 ab621e825620b140
AGENTS.md git:20260926.6fe8f2dA
Immutable. This exact content never changes and is served at /api/v1/blob/ab621e825620b140.
# AGENTS.md : gplay
Public Go CLI for the Google Play Developer API: one static binary for CI and AI agents, replacing Fastlane `supply`. Distributed via Homebrew (`PollyGlot/homebrew-tap`) and releases; agent skills live in the sibling repo `PollyGlot/google-play-cli-skills`.
## Glossary
Canonical terms live in `CONTEXT.md`; use them verbatim, no synonyms. The core five:
- **Edit**: the API's transactional unit; implicit (per-command) by default, explicit via `gplay edits begin/commit`, pinned in `.gplay/edit-<package>.json`.
- **Account**: a locally registered service-account credential; exactly one active at a time.
- **Project**: repo-local package pin in `.gplay/config.json` (package only, never an Account).
- **Listing**: per-locale store text (title/descriptions/video); release notes and images are separate resources.
- **Track / release**: where a build ships; `production` releases default to `draft` unless `--complete`/`--staged` (ADR-0002).
## Commandes
- The CLI is self-documenting: run `gplay <cmd> --help` to confirm the interface before coding.
- To check an API method's shape, `grep docs/discovery/paths.txt` or `jq` the snapshot; query it, it is too large to read whole.
- Design authority: `docs/DESIGN.md` (auth precedence, exit codes, output, edit lifecycle); **scope authority is the GitHub issue tracker** (`type:prd` / `type:slice` for planned work, `type:parking` for deferred, queried with `gh issue list`), with `docs/COVERAGE.md` as the method-level view (generated by `make coverage-update` from `internal/apiregistry`, never hand-edited); surprising decisions: `docs/adr/`.
## Vérifier
- Gate before every PR: `make check`, the required CI checks run locally (`make format` fixes what its format step rejects; `make install-hooks` runs it on pre-push).
- Tests stay offline: mock with a `testRoundTripper` (`http.RoundTripper`) injected as `&http.Client{Transport: ...}`; a test that reaches the network is wrong.
- New leaf command: classify it. Unlabelled means frozen Public contract (ADR-0010/0042); mark `kernel.Experimental(...)` at registration if its flags may still change. The registry test in `cmd/gplay` fails on unclassified leaves.
- To prove a command **behaves** as advertised, build this worktree and drive the
offline path: `b=$(mktemp -d)/gplay && go build -o "$b" ./cmd/gplay && "$b" schema --list`
(then `auth list`, `<cmd> --help`). Two traps: `--version` does not exist (it is
the `version` subcommand), and a pipe masks the exit code (`gplay tracks list`
returns 2 alone, 0 when piped into `head`). The local `verify` skill, when
present, adds evidence capture.
## Les pièges de ce repo
- Never write an API URL by hand: call `apiregistry.Resolve(<method id>)` for the verb and URL template, and add the method to `internal/apiregistry` if it is missing (`archgate_test.go` there fails on any literal API path under `internal/play/` or `commands/`, `internal/play/gcs` excepted).
- Hand-roll every Developer API call in `internal/play/api/` over raw HTTP; the interface stays `google.golang.org/api/androidpublisher`-free (ADR-0007). Auth uses `golang.org/x/oauth2/google`.
- `--output json` mirrors the API response verbatim (ADR-0003); stdout carries data, stderr carries logs. Keep it that way in every command.
- release-please bumps the CLI version from the commit **type** alone, blind to paths: reserve `feat`/`fix` for changes to the shipped binary, and type `website/`, `docs/`, `.github/` work as `docs`/`chore`/`ci` (the site deploys on path triggers regardless).
- Solo maintainer, so no approving review can exist: code PRs merge through `scripts/merge-pr.sh <n>` (refuses a head behind `origin/main` or a required check not green, then `gh pr merge --admin --squash`); docs-only PRs (only `*.md` and doc assets, the inverse of the `code` filter in `.github/workflows/ci.yml`, `docs/discovery/**` counts as code) may skip it once every check is green.
- `internal/` and `commands/` count as code whatever the extension: the binary embeds JSON and CSV via `go:embed`.
## Goût
New surfaces earn their place through an issue first (`type:prd`, or `type:parking` when deferred): surface the scope decision there, then apply the matching `docs/DESIGN.md` section, write the RoundTripper-mocked test, and keep `--help` and docs in `CONTEXT.md` vocabulary.