diff --git a/AGENTS.md b/AGENTS.md index 57bb733aa9..77193ad844 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -48,6 +48,11 @@ pnpm typecheck # turbo typecheck — per-package `tsc --noEmit`; tsup/vit pnpm docs:dev # docs site ``` +**⛔ Push a WIP commit before every step that takes minutes** — a build, a full test run, a +gate sweep, an ablation. Not because you are about to wait: because you are about to stop +being the only copy. The cost rises with how well you are working — a hard card defers +committing *because it is not done yet*, and the one killed mid-measurement lost 2,081 lines. + Type-check coverage and its debt counts are ratcheted in CI (`pnpm check:type-check-coverage`, `pnpm check:type-check-debt`; the script headers are the authority on detail): every package declares a `typecheck` script or carries a @@ -235,9 +240,8 @@ localStorage / auth gotchas. repo**, so sibling repos (`objectui`/`cloud`) you touch are covered too (deliberate non-task override: `OS_ALLOW_MAIN_EDITS=1`, one switch for both). The Bash guard is precision-first: it never blocks reads, and any shape it cannot resolve with confidence (`bash -c …`, `xargs`, `node -e`, a `$VAR`/glob target) is allowed through - — the rule still outranks the hook. **The one thing a worktree does *not* isolate is the stash** — `refs/stash` - lives in the **common** `.git`, shared by every worktree; a third hook (`guard-shared-stash.sh`, `OS_ALLOW_STASH=1`) - blocks the mutating forms, and the collision-free replacements are in Multi-agent discipline below. + — the rule still outranks the hook. **A worktree isolates neither the stash nor the build cache** — the + third hook (`guard-shared-stash.sh`, `OS_ALLOW_STASH=1`) and the replacements live in Multi-agent discipline below. 12. **Contract-first — fix the metadata, not the runtime.** This is a metadata-driven framework: `packages/spec` is the one contract between metadata *producers* and the runtime/renderers that *consume* it. When a piece of metadata "doesn't work," ask **first**: *is it spec-compliant? is this the long-term-correct direction?* If the metadata is @@ -362,12 +366,8 @@ localStorage / auth gotchas. ## Multi-agent working discipline -This repo is worked on by **multiple agents in parallel**. **Use one git worktree per -agent/task** (`git fetch origin main && git worktree add ../objectstack- -b -origin/main`; run `pnpm install` in the new tree) so file systems are physically isolated — -mandatory, not a preference (Prime Directive #11), and hook-enforced. Working in the shared `main` checkout is *not* a -supported fallback: branches get switched and shared files — including ones you just wrote -— get reset *under you* mid-task (full sessions were silently reverted before enforcement). +This repo is worked on by **multiple agents in parallel**, one worktree per task — +mandatory, hook-enforced, and specified in **Prime Directive #11**. What it does not cover: **⛔ `git stash` is the sharpest thing the worktree does NOT isolate — never run a bare `git stash push`/`pop`.** `refs/stash` lives in the **common** `.git` directory, so every @@ -409,6 +409,11 @@ ref's content by occurrence counts on disk; fetch into a ref you own (`git fetch staging. ⛔ **No hook backs this one** — safe and unsafe spellings are both ordinary `git checkout` / `git fetch`, so a mechanical block would fire on correct usage. +**⛔ Nor the build cache** — turbo resolves the repo root through the **common** dir, so every +worktree replays ONE `.turbo/cache`. Symptom: a typecheck failing on a package your diff never +touched, unrepaired by a plain rebuild because that rebuild is a cache **HIT** — force-rebuild +that package. Ablating a build tool is a sanctioned producer; `--force` writes the whole closure. + **Doing reverse verification ("revert the fix, watch the diagnostics")? Commit the fix FIRST.** Committed, restoring is `git checkout -- `, out of a commit that really exists. Against an **uncommitted** edit there is no restore point at all: the @@ -709,10 +714,7 @@ Root also exports: `defineStack`, `composeStacks`, `defineView`, `defineApp`, `d | `content/docs/references/` | **AUTO-GEN** | ❌ Never hand-edit. Regenerated by `packages/spec/scripts/build-docs.ts`. | | `content/docs/releases/` | **RELEASE-OWNED** | ❌ Never edit in a code PR. Release notes are written **centrally at release time**, compiled from changesets + the ADR-0087 registries — not accreted a row per PR. Per-PR appends made `releases/v.mdx` the repo's hottest conflict magnet (three PRs raced the same table inside one afternoon), and every manual resolution risks dropping someone else's row. Your PR's input is its **changeset**; for spec removals also the D2/D3 registry entries. Factual error on a releases page → dedicated docs-only PR or an issue, never a rider on code changes. | | `**/translations/*.generated.ts` (nine packages — `platform-objects`, five plugins, three services) | **AUTO-GEN** | ❌ Never hand-edit the file *structure*. Run `node scripts/check-i18n-bundles.mjs --write` to regenerate all nine (merge mode preserves every existing **translated-locale** value; the default locale `en` is rewritten from the source on every run — it is a copy of the source, not a translation: when the extractor merged `en` too, a stale bundle entry always beat an edited source string, so the served text drifted from the source silently under a green gate. Hand-edits to `en.*.generated.ts` therefore do not survive and belong in the source metadata instead); `pnpm i18n:extract` still covers `platform-objects` alone. Translated-locale *values* (`zh-CN` / `ja-JP` / `es-ES`) are hand-written and expected to be: the gate compares against a merge-mode extract, so editing one of those strings is fine, while adding or dropping keys is drift. `pnpm check:i18n` gates all nine in CI, and `pnpm check:i18n-coverage` ratchets untranslated declared labels. | -| `content/docs//` — every tree except `references/` and `releases/` above | hand-written | ✅ Update that tree's own `meta.json` when adding a page: each is an explicit ordered `pages` array with no rest-spread, so a page you add but never list is absent from the nav. The rows below are named examples, not the whole set. | -| `content/docs/concepts/` | hand-written | ✅ | -| `content/docs/getting-started/` | hand-written | ✅ | -| `content/docs/protocol/` | hand-written | ✅ | +| `content/docs//` — every tree except `references/` and `releases/` above | hand-written | ✅ Update that tree's own `meta.json` when adding a page: each is an explicit ordered `pages` array with no rest-spread, so a page you add but never list is absent from the nav. | ### Touched `packages/spec`? Regenerate its artifacts BEFORE pushing @@ -830,10 +832,8 @@ such lists drifted stale as skills landed): - `.claude/skills/` — repo-internal agent playbooks; every entry must carry `metadata.internal: true`. -⛔ **Both roots are governed surfaces**: a PR touching either is human-merge only and may -never be queued, armed or flipped out of draft — **Prime Directive #14**. No per-PR check -holds this any more; the discipline is the whole barrier, and a post-merge audit lists -what landed. +⛔ **Both roots are governed surfaces** — human-merge only, never queued, armed or flipped +out of draft, and no per-PR check holds it: **Prime Directive #14** is the whole barrier. ---