Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 17 additions & 17 deletions AGENTS.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -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
Expand DownExpand Up@@ -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
Expand DownExpand Up@@ -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-<task> -b <branch>
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
Expand DownExpand Up@@ -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 <your-branch> -- <path>`, out of a commit
that really exists. Against an **uncommitted** edit there is no restore point at all: the
Expand DownExpand Up@@ -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<major>.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/<tree>/` — 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/<tree>/` — 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

Expand DownExpand Up@@ -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.

---

Expand Down
Loading