diff --git a/.agents/skills/browser-automation/SKILL.md b/.agents/skills/browser-automation/SKILL.md new file mode 100644 index 000000000..5c040fe1d --- /dev/null +++ b/.agents/skills/browser-automation/SKILL.md @@ -0,0 +1,31 @@ +--- +name: browser-automation +description: + Use when opening, inspecting, clicking, filling, snapshotting, or otherwise + automating web pages for this repo, including local dev servers and + browser-based verification. +--- + +# Browser Automation + +Use `agent-browser` for web automation in this repo. Run: + +```bash +agent-browser --help +``` + +Core workflow: + +```bash +agent-browser open +agent-browser snapshot -i +agent-browser click @e1 +agent-browser fill @e2 "text" +``` + +Re-run `agent-browser snapshot -i` after page changes so element refs stay +current. + +Use browser automation for behavior that needs a rendered page, real DOM state, +or interactive verification. Prefer focused Bun tests for pure logic and +non-browser integration behavior. diff --git a/.agents/skills/git-commits/SKILL.md b/.agents/skills/git-commits/SKILL.md new file mode 100644 index 000000000..4c31fd46a --- /dev/null +++ b/.agents/skills/git-commits/SKILL.md @@ -0,0 +1,74 @@ +--- +name: git-commits +description: + Use when preparing, splitting, reviewing, or creating git commits in this + repo, especially after larger implementations that should be broken into + independently verified commits. +--- + +# Git Commits + +## Message Style + +Use the following commit message template: + +``` +(): + + +``` + +- The can be: agents, chore, ci, docs, feat, fix, perf, refactor, test, + tool. +- The can be a project, package, or app name; omit the scope and its + wrapped parens if none is clear. +- The and should explain the motivations and changes. +- All line lengths must be 72 characters or fewer; hard-wrap to 72 columns +- Use imperative mood; be concise +- Include user-provided context when it improves the message +- Do not include AI attribution in or after the description + +## Commit Boundaries + +Each commit should be independently understandable and shippable. + +- Split unrelated behavior, package areas, generated artifacts, and dependency + bumps into separate commits. +- For larger implementations, commit in vertical slices: tests or fixtures, + implementation, docs/examples, and follow-up polish can be separate only when + each commit still makes sense on its own. +- Do not mix mechanical formatting with behavioral changes unless the formatter + only touched the files required for that change. +- Do not include local artifacts from `.agents/ignore/`, `.context/`, logs, + build outputs, or editor files. +- Before committing, inspect staged changes with `git diff --cached` and make + sure every staged file belongs to the commit's stated purpose. + +If two changes would need different test commands or different reviewers, they +usually deserve different commits. + +## Verification Before Each Commit + +Every commit should be verified before it is created. + +If the full baseline fails for unrelated pre-existing issues, say that in the +commit handoff and include the first relevant failure. Do not describe the +commit as fully verified unless the required commands actually passed. + +## Creating Commits + +Use non-interactive commands where possible: + +```bash +git status --short +git diff -- +git add +git diff --cached +git commit -m "" +``` + +Use a commit body for non-obvious changes: + +```bash +git commit -m "fix(diffs): Fix virtualized scroll focus" -m "Keep focus anchored when rows are recycled during scroll so keyboard navigation does not lose the active item." +``` diff --git a/.agents/skills/performance/SKILL.md b/.agents/skills/performance/SKILL.md new file mode 100644 index 000000000..360bf379f --- /dev/null +++ b/.agents/skills/performance/SKILL.md @@ -0,0 +1,39 @@ +--- +name: performance +description: + Use when changing loops, collection processing, invalidation logic, tree/diff + traversal, path scanning, virtualized rendering calculations, or any code + where repeated scans or boolean control flow affect performance or + correctness. +--- + +# Performance + +Avoid nested loops and O(n^2) operations unless there is a clear reason. + +- Calculate expensive values once before a loop, not inside it. +- Prefer precomputed maps, sets, indexes, or a single backward scan over nested + repeated scans. +- If you need to know whether meaningful elements remain, compute that boundary + once before the main loop. + +Example of the preferred pattern: + +```typescript +let lastMeaningfulIndex = items.length - 1; +for (let i = items.length - 1; i >= 0; i--) { + if (items[i].someCondition) { + lastMeaningfulIndex = i; + break; + } +} + +for (let i = 0; i <= lastMeaningfulIndex; i++) { + const isLast = i === lastMeaningfulIndex; + // ... +} +``` + +After changing boolean logic or invalidation paths, simplify the final control +flow before calling the work done. If code is already inside `if (foo)`, do not +keep `|| foo` in assignments inside that block. diff --git a/.agents/skills/testing-and-verification/SKILL.md b/.agents/skills/testing-and-verification/SKILL.md new file mode 100644 index 000000000..cb9b958fc --- /dev/null +++ b/.agents/skills/testing-and-verification/SKILL.md @@ -0,0 +1,81 @@ +--- +name: testing-and-verification +description: + Use when adding or running tests, checking snapshots, choosing between Bun + tests and Playwright, running lint/format/typecheck, or deciding the + verification scope for a change. +--- + +# Testing and Verification + +## Baseline Commands + +After code changes, run the required baseline from the monorepo root: + +```bash +bun run format +bun run lint +``` + +Useful check/fix pairs also run from the monorepo root: + +```bash +bun run format:check +bun run format +bun run lint +bun run lint:fix +bun run lint:css +bun run lint:css:fix +``` + +For code changes, also run the relevant package-level typecheck: + +```bash +cd +bun run tsc +``` + +## Unit and Integration Tests + +Use Bun's built-in test runner. Tests usually live in a `test/` folder inside +each package and use `describe`, `test`, and `expect` from `bun:test`. + +Prefer unit or integration tests by default: + +```bash +cd packages/diffs && bun test +cd packages/trees && bun test +cd packages/truncate && bun test +``` + +Other packages and apps also expose local test scripts when relevant, for +example `packages/path-store`, `packages/tree-test-data`, and `apps/docs`. + +## Snapshots + +Bun supports `toMatchSnapshot()`. Avoid new snapshot coverage unless it is +shallow and narrowly scoped to the exact behavior under test. + +Update snapshots from the package directory: + +```bash +bun test -u +``` + +## Browser and E2E Tests + +Add Playwright/browser E2E tests only when behavior cannot be validated without +a real browser engine. Good candidates include computed style checks, shadow DOM +boundaries, and browser-only rendering behavior. + +Keep E2E coverage small and high-value: + +```bash +cd packages/trees && bun run coverage +cd packages/trees && bun run test:e2e +cd packages/path-store && bun run test:demo +cd apps/docs && bun run test:e2e +``` + +If E2E fixtures or dev servers are started in a worktree, follow the cleanup +contract from the `worktrees-and-dev-servers` skill. diff --git a/.agents/skills/tooling-and-dependencies/SKILL.md b/.agents/skills/tooling-and-dependencies/SKILL.md new file mode 100644 index 000000000..e399ef70e --- /dev/null +++ b/.agents/skills/tooling-and-dependencies/SKILL.md @@ -0,0 +1,49 @@ +--- +name: tooling-and-dependencies +description: + Use when running repo scripts, adding or changing dependencies, editing + package.json files, installing packages, or deciding how Bun workspace + commands should be invoked in this monorepo. +--- + +# Tooling and Dependencies + +## Bun + +- Use `bun` exclusively for commands and package operations. +- Do not use `npm`, `pnpm`, `npx`, or other package runners unless there is a + specific reason and you explain it. +- Bun can run TypeScript directly, so local scripts may be `.ts` files without a + separate compile step. + +## Dependency Catalog + +This monorepo uses Bun's `workspaces.catalog` in the root `package.json`. + +- Never add a version directly to an individual package's `package.json` by + default. +- To add a dependency: + 1. Add the exact version to the root `package.json` under + `workspaces.catalog`, for example `"new-package": "1.2.3"`. + 2. Reference it from the package with `"new-package": "catalog:"`. +- Do not run `bun add ` inside a package directory; it writes direct + versions and breaks the catalog pattern. +- Published packages may intentionally use ranges for end-user compatibility. + `apps/docs` should use catalog versions; published packages such as + `packages/diffs` may use ranges only when that is intentional. + +## Scripts + +- Package scripts should work from the package directory. +- Common scripts may be mirrored at the root as shortcuts. A root mirror should + not behave differently from the package script it wraps. +- Use the workspace runner when convenient: + +```bash +bun ws +bun ws --some --flag +``` + +`bun ws` forwards arguments to the target script and does not require a +standalone `--` separator. The only special handling is that `-v` and +`--verbose` are consumed by `scripts/ws.ts`. diff --git a/.agents/skills/typescript-monorepo/SKILL.md b/.agents/skills/typescript-monorepo/SKILL.md new file mode 100644 index 000000000..8625279af --- /dev/null +++ b/.agents/skills/typescript-monorepo/SKILL.md @@ -0,0 +1,41 @@ +--- +name: typescript-monorepo +description: + Use when adding or changing packages/apps, TypeScript configs, workspace + dependencies, package references, exports, or monorepo project-reference + relationships. +--- + +# TypeScript Monorepo + +## TypeScript + +Use TypeScript everywhere practical. Compiler settings are intentionally fairly +strict. + +- Shared compiler options live in `tsconfig.options.json`. +- Root `tsconfig.json` manages project references across the monorepo. +- Most package `tsc` scripts use `tsgo`, but agents should run them through the + package script: `bun run tsc`. + +## Project References + +When adding a new package or app: + +- Add it to the root `tsconfig.json` references. +- Ensure its local `tsconfig.json` follows existing package/app patterns. + +When one workspace package depends on another: + +- Add the dependency as `workspace:*` in the consuming package. +- Add the dependency to the consuming package's TypeScript `references` block + when needed for accurate and fast typechecking. + +## Workspace Dependencies + +Use the dependency catalog rules from `tooling-and-dependencies` for external +packages. Use `workspace:*` for internal package dependencies. + +If a package is published, review its `exports`, `typesVersions`, `files`, peer +dependencies, and publish scripts before changing public entrypoints or +dependency ranges. diff --git a/.agents/skills/worktrees-and-dev-servers/SKILL.md b/.agents/skills/worktrees-and-dev-servers/SKILL.md new file mode 100644 index 000000000..4705dfd94 --- /dev/null +++ b/.agents/skills/worktrees-and-dev-servers/SKILL.md @@ -0,0 +1,58 @@ +--- +name: worktrees-and-dev-servers +description: + Use when working with the repo's bun run wt helper, Pierre-managed worktrees, + dev-server port offsets, stale server cleanup, Playwright fixtures, or Chrome + debug instances. Do not use this as a substitute for host-provided workspace + isolation. +--- + +# Worktrees and Dev Servers + +Pierre includes a repo-specific `git worktree` helper for local/manual +parallelization outside host-managed agent workspaces. Managed Pierre worktrees +live at: + +```text +~/pierre/pierre-worktrees// +``` + +Each managed Pierre worktree owns a port offset so dev servers, E2E fixtures, +and the Chrome remote-debug instance do not collide. The main clone keeps +historical default ports; linked Pierre worktrees shift ports. + +If you are already inside a Conductor, Codex, Claude, or other host-provided +workspace, do not create another worktree unless the user explicitly asks for a +Pierre-managed worktree. Still use this skill when you start repo dev servers or +E2E fixtures, because the cleanup and port-offset rules apply to those scripts. + +## Worktree Commands + +The `bun run wt` suite is defined in `scripts/wt.ts` and manages only +Pierre-managed worktrees: + +```bash +bun run wt new # create a worktree, allocate offset, bun install +bun run wt rm # kill its processes, remove the worktree +bun run wt clean # kill zombie servers on all managed worktree ports +bun run wt clean # clean one managed worktree +bun run wt ps # show per-worktree port status (LISTEN / -) +bun run wt list # summary of managed + external worktrees +``` + +Dev scripts pick up the offset through `scripts/ws.ts`, which reads +`/.env.worktree`. Before starting, they run `scripts/run-dev.sh` to +kill any stale process bound to the target port. + +## Cleanup Contract + +If you start dev servers, Playwright fixtures, or Chrome debug instances inside +a worktree, run cleanup before completing your turn: + +```bash +bun run wt clean +``` + +Use `bun run wt clean` when you do not know the slug or need to clean every +managed worktree. Use `bun run wt rm ` only when intentionally tearing +down the worktree itself. diff --git a/.gitignore b/.gitignore index 67b9db1f7..b2fe93bfc 100644 --- a/.gitignore +++ b/.gitignore @@ -30,6 +30,7 @@ tsconfig.tsbuildinfo .claude/* .codemogger/* .omx/ +.agents/ignore/ .env.worktree #tmp diff --git a/AGENTS.md b/AGENTS.md index b29d2d7ff..acb4378f3 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -2,272 +2,67 @@ ## Agent Environment -You must set `AGENT=1` at the start of any terminal session to enable -AI-friendly output from Bun's test runner: +Set `AGENT=1` at the start of every terminal session so Bun's test runner emits +AI-friendly output: ```bash export AGENT=1 ``` -## Tooling +## Core Rules -- We exclusively use `bun` to run commands and install packages. Don't use `npm` - or `pnpm` or `npx` or other variants unless there's a specific reason to break - from the norm. -- Since we use `bun` we can natively run TypeScript without compilation. So even - local scripts we run can be `.ts` files. -- We use Bun's `catalog` feature for dependencies in order to reduce differences - in dependencies across monorepo packages. - - **CRITICAL: NEVER add a version number directly to a package's** - `package.json`. Always follow this two-step process: - 1. First, add the dependency with its exact version to the root - `package.json` file inside `workspaces.catalog` (e.g., - `"new-package": "1.2.3"`) - 2. Then, in the individual package's `package.json`, reference it using - `"catalog:"` (e.g., `"new-package": "catalog:"`) - - **NEVER run `bun add ` inside a package directory** - this will add - a version number directly which breaks our catalog pattern. - - This rule is sometimes broken in packages that are published, in order to - make sure that end-users aren't forced to our specific version. `apps/docs` - would use the catalog version and `diffs` _may_ choose to use a range. -- npm "scripts" should work from inside the folder of the given package, but - common scripts are often "mirrored" into the root `package.json`. In general - the root scripts should not do something different than the package-level - script, it's simply a shortcut to calling it from the root. +- Use `bun` for commands and dependency work. Do not use `npm`, `pnpm`, `npx`, + or similar tools unless there is a specific reason. +- Dependencies use Bun's root `workspaces.catalog`. Never add dependency + versions directly to package-level `package.json` files unless a published + package intentionally needs its own range. +- Run commands from the monorepo root when they operate across the repo. Use + package directories for package-local scripts, or use + `bun ws ` as the root shortcut when that fits the task. +- Preserve trailing newlines at the end of files. -## Worktrees +## Skills -We use `git worktree` to parallelize work. Each worktree lives at -`~/pierre/pierre-worktrees//` and owns a **port offset** so dev servers, -E2E fixtures, and the Chrome remote-debug instance don't collide across -worktrees. The main clone keeps the historical default ports; only worktrees -shift. +Domain-specific context and conventions live in `.agents/skills/`. Before +starting any task: -The `bun run wt` command suite (defined in `scripts/wt.ts`) manages worktrees: +1. List `.agents/skills/*/SKILL.md` +2. Read only each skill's frontmatter description to identify relevant skills +3. Read only the full `SKILL.md` files relevant to your task -```bash -bun run wt new # create a worktree, allocate offset, bun install -bun run wt rm # kill its processes, remove the worktree -bun run wt clean # kill zombie servers on all worktrees' ports -bun run wt ps # show per-worktree port status (LISTEN / —) -bun run wt list # summary of all worktrees (managed + external) -``` - -Dev scripts inside a worktree automatically pick up the offset through -`scripts/ws.ts`, which reads `/.env.worktree` when invoked. Before -starting, they run `scripts/run-dev.sh` to kill any stale process bound to the -target port (zombies survive uncleanly-closed terminals, which is common under -AI agents). - -**Cleanup contract for agents.** If you spin up dev servers, Playwright -fixtures, or Chrome debug instances inside a worktree, **you must run -`bun run wt clean` (or `bun run wt rm ` if the worktree itself is being -torn down) before completing your turn.** This releases ports and kills spawned -processes so they don't accumulate across runs. Running `wt clean` with no -arguments cleans every managed worktree; prefer the targeted `wt clean ` -when you know which worktree you were working in. - -## Linting - -We use `oxlint` at the root of the monorepo rather than per-package lint setups. - -Run linting from the monorepo root: - -```bash -bun run lint -bun run lint:fix -``` - -For CSS, we use `stylelint`: +Do not load skills that are not relevant to the task. -```bash -bun run lint:css -bun run lint:css:fix -``` +## Agent Artifacts -## Code formatting +Write agent-only planning and scratch artifacts under `.agents/ignore/` by +default: -We use `oxfmt` at the root of the monorepo. +- Plans: `.agents/ignore/plans/YYYY-MM-DD-.md` +- Specs: `.agents/ignore/specs/YYYY-MM-DD-.md` -Check formatting from the monorepo root: +`.agents/ignore/` is gitignored. Do not put source files, tests, or committed +documentation there. -```bash -bun run format:check -``` +## Verification Baseline -Apply formatting from the monorepo root: +After code changes, verification is not complete until you have run these from +the monorepo root: ```bash bun run format +bun run lint ``` -**Important:** Always run `bun run format` from the monorepo root after making -changes to ensure consistent formatting. For code changes, verification is not -complete until you have also run `bun run lint` from the monorepo root and the -relevant `bun run tsc` typecheck. - -- Always preserve trailing newlines at the end of files. - -## TypeScript - -We use TypeScript everywhere possible and prefer fairly strict compiler -settings. - -All projects should individually respond to `bun run tsc` for typechecking, but -many of those scripts are implemented with `tsgo` rather than plain `tsc`. - -Shared compiler options live in the root `tsconfig.options.json` file. - -The root `tsconfig.json` file is used to manage project references across the -monorepo. - -We use project references between packages and apps. - -- When adding a new package or app, update the root `tsconfig.json` references. -- When a package depends on another `workspace:` package, add the dependency to - the consuming package's `references` block when needed for accurate and fast - typechecking. - -## Code readability - -- When adding non-trivial helper functions, prefer a short comment directly - above the function declaration that explains, in plain language, what the - helper does and why it exists. -- Write these comments as if the reader is new to the codepath. Avoid vague - shorthand like "snapshot" unless you immediately explain what data is being - captured or derived. -- Prefer function-level comments over a lot of inline comments. Use inline - comments only when a specific step inside the function is still non-obvious. -- Keep comments concrete and behavior-focused. Good comments usually explain - what data is being transformed, what invariant is being checked, or what the - helper is protecting against. -- After changing boolean logic or invalidation paths, simplify the final control - flow before calling the work done. If code is already inside `if (foo)`, don't - keep `|| foo` in assignments inside that block. Prefer direct values that make - the invariant obvious. - -## Performance - -**CRITICAL: Avoid nested loops and O(n²) operations.** - -- When iterating over collections, calculate expensive values ONCE before the - loop, not inside it -- Never nest loops unless absolutely necessary - it's expensive and usually - there's a better way -- If you need to check conditions on remaining elements, scan backwards once - upfront instead of checking inside the main loop - -Example of BAD code: - -```typescript -for (let i = 0; i < items.length; i++) { - // DON'T DO THIS - nested loop on every iteration - let hasMoreItems = false; - for (let j = i + 1; j < items.length; j++) { - if (items[j].someCondition) { - hasMoreItems = true; - break; - } - } -} -``` - -Example of GOOD code: - -```typescript -// Calculate once upfront -let lastMeaningfulIndex = items.length - 1; -for (let i = items.length - 1; i >= 0; i--) { - if (items[i].someCondition) { - lastMeaningfulIndex = i; - break; - } -} - -// Now iterate efficiently -for (let i = 0; i <= lastMeaningfulIndex; i++) { - const isLast = i === lastMeaningfulIndex; - // ... -} -``` - -## Running scripts - -We use a custom workspace script runner to make typing things out a little -easier. - -`bun ws ` `bun ws --some --flag` - -`bun ws` forwards arguments through to the target script and does **not -require** a standalone `--` to separate its own options from task arguments. You -may still use `--` when a downstream tool expects it (for example, when using -`bun run` with glob filters). The only special handling is that `-v` / -`--verbose` is consumed by `ws.ts` itself and not forwarded on. - -Note that a few scripts exist at the root and usually operate against all -packages. e.g. `bun run lint` - -## Testing - -We use Bun's built-in test runner for unit and integration tests. Tests usually -live in a `test/` folder within each package, separate from the source code. - -Some packages also include browser-level tests. In particular, `packages/trees` -has Playwright E2E coverage for browser-specific behavior. - -### Test Strategy - -- Prefer unit/integration tests (`bun test`) by default. -- Add Playwright/browser E2E tests only when behavior cannot be validated - without a real browser engine. -- Good Playwright candidates include computed style checks, shadow DOM - encapsulation boundaries, and browser-only rendering behavior. -- Keep E2E coverage intentionally small and high-value. -- Prefer explicit assertions over broad snapshots. -- Avoid snapshot tests unless they are shallow and narrowly scoped to the exact - behavior under test. - -### Running Tests - -Examples (run these from the package directory): - -```bash -# diffs -cd packages/diffs && bun test - -# trees -cd packages/trees && bun test -cd packages/trees && bun run coverage -cd packages/trees && bun run test:e2e - -# truncate -cd packages/truncate && bun test -``` - -### Updating Snapshots - -Update snapshots from the package directory: - -```bash -bun test -u -``` - -### Test Structure - -- Tests use Bun's native `describe`, `test`, and `expect` from `bun:test` -- Snapshot testing is supported natively via `toMatchSnapshot()` -- Test helpers and fixtures usually live alongside each package's tests -- For example, `packages/diffs/test/mocks.ts` contains shared mocks for diffs - tests - -## Browser Automation - -Use `agent-browser` for web automation. Run `agent-browser --help` for all -commands. +Also run the relevant package-level `bun run tsc` and focused tests for the +changed area. For docs-only or AGENTS/skill-only changes, formatting and linting +are sufficient unless the edit touches executable code or package config. -Core workflow: +## Code Readability -1. `agent-browser open ` - Navigate to page -2. `agent-browser snapshot -i` - Get interactive elements with refs (@e1, @e2) -3. `agent-browser click @e1` / `fill @e2 "text"` - Interact using refs -4. Re-snapshot after page changes +- When adding non-trivial helpers, prefer a short comment directly above the + function explaining what the helper does and why it exists. +- Write comments for readers new to the codepath. Avoid vague shorthand like + "snapshot" unless you immediately explain what data is captured or derived. +- Prefer function-level comments over many inline comments. Use inline comments + only when a specific step is still non-obvious. +- Keep comments concrete and behavior-focused.