AGENTS.md · diff

git:20260927.20a4e3c to git:20260927.c7bfa2e

2 added, 2 removed. Audit A to A.

# Project agent memory
This file is the project's committed home for project-intrinsic agent knowledge: build, test, release, architecture, and sharp-edge notes that should travel with the code.
- Build/test: `yarn install --immutable`, then `yarn build` (topological — run it BEFORE `yarn test`; workspace tests resolve sibling packages from `dist/`, so unbuilt `@ask-llm/shared` fails every suite). Lint via `yarn lint` (biome format is enforced; `biome check --write` fixes). Harness-facing changes use the canonical local-only `yarn prepr:harness` gate; opt-in live authorization and evidence rules are in `docs/HARNESS-SMOKE.md`. Supported platforms are Linux and macOS (CI: Ubuntu Node 24 five-batch plus `pi-lifecycle-macos`); every package requires Node 24, the current LTS (ADR-171); do not add Windows jobs or claim Windows support (ADR-159). Claude GitHub Action is `@claude` on demand only (ADR-160); do not restore automatic PR review via `claude-code-review.yml`.
- Every `packages/claude-plugin/scripts/**/*.mjs` is generated from a TypeScript 7 `.mts` sibling and committed (marketplace git-subdir installs cannot build): after editing an `.mts`, run `yarn workspace @ask-llm/plugin build:hooks` and commit both; never add or hand-edit a `.mjs` there (`generated-hooks.test.ts` enforces this, ADR-170/171).
- Repo-root `scripts/*.ts` (and test fixtures) are plain TypeScript run directly by Node 24 type stripping, with no build step: import siblings as `./x.ts`, use erasable syntax only; `yarn lint` typechecks them. No other `.js`/`.mjs`/`.cjs` may be committed (ADR-172, `scripts/typescript-contract.test.ts`).
- Architecture decisions live in `docs/DECISIONS.md` (numbered ADRs, newest prepended at the top); provider behavior differences are deliberate and cataloged in `docs/PROVIDER-PARITY.md` — read both before "aligning" providers.
- Docs-model drift is CI-enforced: `scripts/check-docs-drift.ts` requires `apps/docs/.vitepress/theme/providers.ts` `defaultModel` (and gemini/antigravity `fallbackModel`) values to match each package's `constants.ts` literally, matched inside each provider's own object block. Change both together.
- MCP Registry rejects duplicate versions. Keep normal and recovery publication routed through `scripts/publish-mcp-registry.ts`; it verifies exact existing records and publishes only missing ones (ADR-139), after waiting up to 10 min for npm to show each selected version (ADR-174). Manual Release dispatch has no inputs: on `main` it always repairs Registry, the unified GitHub Release, and per-package tags, and must not re-enter npm publication (ADR-158).
- Public package source tags are remote `<name>@<version>` refs managed only by `scripts/create-or-verify-package-tags.ts` on normal and recovery release paths (ADR-151/152); `changesets/action` v2 must keep both `create-github-releases: false` and `push-git-tags: false`, while the helper excludes private shared, never retags/forces, and coexists with the single unified `v*` GitHub Release. Changesets 3 publishes via `yarn npm publish`, so `release.yml` must pass `YARN_NPM_AUTH_TOKEN` from `secrets.NODE_AUTH_TOKEN` (ADR-156); `NODE_AUTH_TOKEN` alone authenticates npm CLI steps only. After publish, `npm access set status=public` is verify-first and must not fail the job on 401/403 when packages are already public or the token cannot change access (ADR-157).
- - Gemini quota fallback is `gemini-3.8-flash` (ADR-155); the antigravity fallback stays `gemini-3.5-flash` deliberately — agy slugs are evidence-pinned to its live catalog (ADR-137), so never bump both in sympathy.
+ - Gemini quota fallback is `gemini-3.8-flash` (ADR-155); the antigravity fallback is also `gemini-3.8-flash` but on independent evidence (ADR-178: agy's base slug + `--effort`; `agy models` lists only tiered ids like `gemini-3.8-flash-high`, which conflict with `--effort`) — agy slugs are evidence-pinned to its live catalog (ADR-137), so never bump both in sympathy.
- Provider default-model constants leak further than the provider package: `packages/llm-mcp/src/constants.ts` (`PROVIDERS.*.defaultModel`) is threaded into executors as `options.model` by `machine.ts`, so executors cannot use "was a model passed?" to detect user pins (see ADR-137).
- Antigravity MCP tool and read-only machine execution refuse before any agy spawn unless `ASK_ANTIGRAVITY_ALLOW_UNISOLATED=1`; opt-in has no read-only guarantee (ADR-177, shared `executeAntigravityCLI` boundary).
- - agy (Antigravity) CLI ground truth for this repo's executor is recorded in ADR-137 (minimum 1.1.5, base slug + separate `--effort`, per-slug effort tiers, the live-captured `invalid model selection` error grammar), ADR-141 (answers come from `--output-format json` stdout — key `response`, usage object — on every supported version; `--disable-slash-commands` is 1.1.9+ only), and ADR-162 (agy ≥1.1.28 `--print-timeout` expiry is exit 0 with a truncated answer; fail closed, do not serve it as complete).
+ - agy (Antigravity) CLI ground truth for this repo's executor is recorded in ADR-137 (minimum 1.1.5, base slug + separate `--effort`, per-slug effort tiers, the live-captured `invalid model selection` error grammar), ADR-141 (answers come from `--output-format json` stdout — key `response`, usage object — on every supported version; `--disable-slash-commands` is 1.1.9+ only), ADR-162 (agy ≥1.1.28 `--print-timeout` expiry is exit 0 with a truncated answer; fail closed, do not serve it as complete), and ADR-178 (agy ≥1.2.6 exit-3 `AGY_ERROR:` stderr line: classify only its compacted fields, never the opaque `error_id`).
- Grok transport and model identity are separate (ADR-146/147; `/brainstorm` exact Grok + Sol routing and partial-consensus rules are in ADR-148): unified startup probes both `xai-api` and `grok-cli` readiness because request-level harness selection happens later (an explicit `ASK_GROK_HARNESS` narrows readiness to that default), but execution selects exactly one explicit/default harness with no failover; Cursor Agent is a model-neutral harness (`ask-cursor-agent`) requiring separate provider + exact Cursor catalog ID, never a provider itself.
- `@ask-llm/plugin` is the one publishable Claude Code + Cursor Agent + Pi host package (ADR-142/147/161); host contracts live in the skill adapters, `apps/docs/plugin/cursor.md`, and `docs/PI-COMPATIBILITY.md`. Cursor uses Agent Skills + a unified-only `mcp.json` (one `ask-llm` entry; split Codex/Grok servers are optional user installs whose leaves are preferred when exposed) exposing exactly `codex-pair`/`grok-pair` (explicit empty `agents`/`commands`/`hooks` so Claude agents and `hooks/hooks.json` are not auto-discovered; other skills deferred), never Claude hooks/namespaces; the Claude plugin `.mcp.json` bundles only Codex while `@ask-llm/mcp`/`@ask-llm/grok-mcp` stay user-scoped. Codex-facing plugin workflows prefer any `ask-codex` leaf, then fully pinned unified `ask-llm` (`provider`, model, `reasoningEffort`, `includeDirs`, `preferred`, `sandbox`; older schemas fail closed), then disclosed `codex exec`; pair skills call unified `ask-llm` only fully pinned. Pi excludes `fable-review`/`grok-pair`, uses native provider tools, and codex-pair requires marker + project trust + a user-owned canonical-project allowlist. The published Pi host floor must equal the oldest exact `pi-package-smoke` matrix pin (currently 0.83.0).
## Maintaining this file
Keep this file for knowledge useful to almost every future agent session in this project.
Do not repeat what the codebase already shows; point to the authoritative file or command instead.
Prefer rewriting or pruning existing entries over appending new ones.
When updating this file, preserve this bar for all agents and keep entries concise.