AGENTS.md · git:20261001.e1b3636 · 2026-10-01 · sha256 c088677a669d4fb0
AGENTS.md git:20261001.e1b3636A
Immutable. This exact content never changes and is served at /api/v1/blob/c088677a669d4fb0.
<!-- browser-automation:start -->
- Ordinary owned automated browser runs use versioned Chrome for Testing or the browser provisioned for the pinned Playwright version. Reject the installed auto-updating Chrome application, including explicit executable overrides and symlinks; never fall back to it when provisioning is missing. Report the resolved executable and browser version, and close owned contexts and browsers gracefully in cleanup. Attaching to an explicitly authorized user-owned browser is a separate operation: preserve its profile and lifetime. Keep regression checks for browser selection in the existing required checks; see [browser automation](https://github.com/hraness/.github/blob/main/BROWSER_AUTOMATION.md).
- Never start the system Chrome app directly from an agent shell; use the repository's browser tooling and respect its scheduler and browser custody controls. For owned launches, pass `--mute-audio` and merge `PaintHolding,MacAppCodeSignClone` into any existing `--disable-features` value instead of adding a second switch. Finish owned process, context, and profile cleanup before releasing the browser lane. Never signal another holder or manipulate its lease to obtain a slot.
- The sole native-runtime exception is Slopcamera’s documented signature-verified, version-bound, immutable task-owned Chrome snapshot, never a direct launch of the installed application. Its current integrity-bound launch contract must disable `MacAppCodeSignClone`; retain vendor identity verification, browser custody, graceful cleanup, and regression checks. Qualify the native fix with live clone-growth and cleanup evidence before activating this exception. It is not an executable override or fallback for ordinary automation; see [the native-runtime exception](https://github.com/hraness/.github/blob/main/BROWSER_AUTOMATION.md#slopcamera-native-runtime-exception).
<!-- browser-automation:end -->
# Contents
- `src/` – canonical, ontology, schema, graph, operation, sync, SQLite, search, SDK, CLI, and optional semantic runtime code with colocated tests. The local semantic lifecycle and sync orchestration use bundled Effect runtimes.
- `dist/` – committed Bun-targeted ESM, executable CLI, and TypeScript declarations built from `src/`.
- `spec/` – versioned human and machine-readable ontology, wire, storage, sync, embedding, and migration contracts.
- `skills/oh/` – installable Agent Skill for operating Oh from a coding-agent workflow.
- `site/` – the public Next.js website for `https://oh.computer`, deployed from the existing Hraness Vercel project.
- `.agents/skills/` – portable plan authoring, phased execution, implementation, and independent review workflows.
- `scripts/benchmarks/` and `scripts/benchmark-memory.ts` – isolated memory-state, retrieval, projection-performance, and explicitly budgeted reader experiments.
- `benchmarks/` – source/protocol audit and compact reproducibility evidence; datasets and full run artifacts stay in ignored `.cache/benchmarks/`.
- `.github/` – public contribution templates, branch validation, dependency updates, and exact-artifact release automation.
- `README.md`, `CONTRIBUTING.md`, `SECURITY.md`, `LICENSE`, and `THIRD_PARTY_NOTICES.md` – public usage, project policy, threat model, terms, and bundled third-party notices.
- `CHANGELOG.md` – one section per release; the release workflow copies the version's section onto its GitHub Release page.
- `STYLE.md` and `WRITING.md` – public and internal writing guides synced from hraness/.github; rules for this repository sit under “Repository additions”.
- `package.json`, `tsconfig.json`, and `bun.lock` – package identity, exported surfaces, and frozen Bun toolchain.
# Guidelines
- Use Bun 1.3.14 for installs, scripts, tests, builds, and package checks. Keep the base package free of required runtime dependencies.
- Follow `STYLE.md` for the public website, specifications, documentation, README, and Agent Skill prose, including its benchmark-results rule, and `WRITING.md` for commits, pull requests, plans, and agent notes.
- Keep `site/` deployable as an ordinary Vercel Next.js root. Do not add OpenAI Sites, Vinext, Cloudflare Worker, Wrangler, or alternate hosting configuration.
- Build the site on the pinned Hraness design-kit release and its `product-marketing` grammar: use the shared editorial preset for homepage marketing display headings, and Nebula Sans for body text and specification display roles. Use the Wordcell family Gruvbox default with system-resolved light/dark appearance and preserve saved palette choices, sentence-case labels, and one accent. Keep true monospace for code, commands, and data surfaces only.
- Keep shared controls, mark rows, and showcase fitting in Design Kit; product code owns its copy and composition. Preserve complete, readable text across surface switches, phone layouts, and enlarged text settings.
- Keep readable content at full opacity, including its ancestors. Show selection and focus through borders, surfaces, or accents rather than dimming text with opacity.
- Share images come only from the shared `@hraness/web-discovery` social-image template, rendered from the site's single `defineSocialImageSite` declaration in `site/app/social.ts`. Pages pass copy only (headline, description, eyebrow); keep no per-site drawing code.
- The homepage alone opts into the immutable Lantern material snapshot in `site/vendor/hraness-lantern`. Keep citation reading on an opaque pane, glazing on the hero and scrolling header, and the specification and code transcripts unchanged. The exact-byte PostCSS bridge moves only the admitted Lantern component layer after the editorial layer; its base tokens and all package layers stay intact. `check:theme` runs the canonical snapshot checker before site tests/builds.
- Treat this repository as the complete public project. Use only its public identities, paths, commands, examples, and contributor workflow.
- Follow the shared [Hraness README guidelines](https://github.com/hraness/.github/blob/main/README_GUIDELINES.md). Keep the durable definition, mechanism-backed rationale, shortest verified first task, observable behavior, boundaries, verification, and task-oriented documentation path current.
- Preserve canonical JSON, digest preimages, V1 identifier grammars, record kinds, limits, operation ordering, protocol literals, and applied SQLite migration bytes. Version a wire change instead of mutating an existing contract.
- Oh is embedded downstream in two distinct roles: Wordcell consumes the store, SQLite, and positive-Datalog projection behind its engine-neutral `src/graph-authority.ts` port as a disposable, rebuildable derivation of an authoritative Markdown vault; Sponge consumes the store, libSQL, projection, and memory-host surfaces as server-side agent working memory whose store is itself authoritative. Both pin immutable releases and upgrade independently — preserve those entry-point contracts, never coordinate `main` branches, and keep consumer-specific policy out of the kernel.
- Parse external values from `unknown`, require exact keys where the contract does, reject noncanonical values, and enforce byte, item, recursion, path, and response limits before expensive work.
- Keep SQLite records and the append-only operation log authoritative. FTS and semantic state are derived, optional, rebuildable, and joined back to the current record digest.
- Use compare-and-swap for writes, one immediate transaction for each committed operation, idempotent operation IDs, and explicit conflict handling. Never hide a divergent sync history behind last-write-wins behavior.
- Keep QMD optional, dynamically imported, local, and pinned to the exact embedding profile. Do not add a hosted embedding dependency to the default path.
- Keep Effect 3.22.1 inside the declared semantic, sync, memory host and direct libSQL authority runtimes. Bundle it without a required consumer runtime dependency. Preserve Promise facades, original rejection values, canonical helpers/bytes, synchronous SQL transactions, portable pure graphs and semantic drain-before-close behavior. Root and SDK sync exports and the memory host surface intentionally include the bundled runtime. Follow the [semantic lifecycle guide](docs/semantic-lifecycle.md), [sync ownership guide](docs/sync-runtime.md), and [memory host guide](docs/memory-runtime.md), and [libSQL authority ownership guide](docs/libsql-runtime.md).
- `bun run check:effect` is part of the required aggregate gate. New production Effect modules need an explicit role in `scripts/check-effect-architecture.ts`. Review changes to that policy or checker independently; do not suppress diagnostics, erase expected failures, or move I/O into lifecycle programs to bypass a boundary.
- Update narrative specifications, machine-readable manifests and schemas, implementation, and regression evidence together when a public contract changes.
- Keep the Agent Skill concise and self-contained. It may guide reads and writes, but it cannot broaden a user's authorization or silently choose a database, space, sync destination, or destructive operation.
- Rebuild `dist/` after production source changes. Require the complete `bun run check`, reproducible generated tree, and packed root/subpath/`oh --help` checks before source admission. For pull requests, fresh successful CI on the exact governed head and current base may supply that source aggregate under the conditions in [CONTRIBUTING.md](CONTRIBUTING.md#validate-a-pull-request). Run focused local checks first; do not repeat equivalent local source aggregates when those CI conditions hold. Keep private benchmark, coupled-run, provider, authenticated, native, installation, release and deployment evidence separate whenever CI does not execute it. Use the local aggregate when CI is unavailable or equivalence is uncertain.
- Run focused changed-area tests for benchmark changes. `bun run test:benchmarks` remains the complete benchmark-only subset; qualified PR CI already runs every test in that subset through `bun run check`, so a duplicate local subset run is not required. Use `bun run bench:memory --help` for isolated experiments; keep dataset labels outside ingestion, tune only on development groups, and distinguish state correctness, evidence recall, and reader scores. Paid calls require explicit limits and either a benchmark-only key or an explicitly selected Vercel project OIDC token; preserve the shared spending ledger across readers, transports, and judges. Keep Gateway aliases distinct from verified snapshots, and give gold references only to the separate judge.
- Enable GitHub release immutability and configure npm trusted publishing for `.github/workflows/release.yml` before the next stable release. Release only a new annotated `v*` tag at exact current `main`. Build one npm tarball, test those unchanged bytes on Linux and macOS, attach them and `SHA256SUMS` to the immutable GitHub Release, then publish the same tarball through npm OIDC with provenance. Never move or reuse a release tag.
<!-- hraness-public-copy:start -->
- Public copy (websites, READMEs, docs, package and GitHub descriptions, CLI help, `llms.txt`, generated pages) follows `STYLE.md`, synced from hraness/.github. Text a model writes for publication also follows `GENERATION_STYLE.md`.
- The delivery vocabulary in this file (admission, qualification, custody, receipt, bounded, lane, gate, surface, projection) is internal. Translate it into what the reader gets.
- Take one-line product and sibling descriptions from the portfolio registry and versions from the release record. Tests pin facts, not prose.
- Run `bun run check:copy` before handoff when the repository has it.
<!-- hraness-public-copy:end -->
<!-- hraness-releases:start -->
- GitHub Release pages follow `RELEASES.md` in hraness/.github: the title is the registry product name and the tag, and the body is a summary, `## Changes`, `## Install`, `## Verify`, then the repository's identity record as a trailing HTML comment.
- The summary and changes come from the version's section of `CHANGELOG.md` in the tagged commit. Write that section in the version bump pull request. The release workflow copies it, generates Install and Verify from the release record, fails when the section is missing or empty, and never uses GitHub's generated notes.
<!-- hraness-releases:end -->
<!-- hraness-articles:start -->
- Essays and blog posts follow the essay addendum in `GENERATION_STYLE.md` and `ARTICLE_COPY.md` in `@hraness/design-kit`. The byline is “Hraness”, every post shows the provenance note naming its recorded reviewer, and no AI-drafted post is credited to a person unless that person rewrites and adopts it.
- Take product names, one-line descriptions, addresses, status labels, and relations from the portfolio facts in `@hraness/design-kit`. Render versions from the release record (`package.json`, a published-release file), never typed by hand.
- Write a “How X uses Y” post only for a registered relation that has a description. Change the relation and its post in the same change. Link between products only along registered relations, and between a technique post and product posts about the same technique.
- Every post has a review record: reader job, non-obvious answer, sources with the date checked, owner, reviewer identity, reviewer type (`ai` or `human`), a score out of 12, and a `reassessOn` date 28 to 56 days after review. The reviewer is independent of the run or person that drafted the post. An AI reviewer is recorded and shown as AI; `humanReview` stays null unless a person reviewed the post.
- A new post starts out of search indexes, sitemaps, and feeds. It becomes indexable only when its review record is complete, scores at least 9 of 12 with no zero score, and the page shows the provenance note.
- When a product is renamed or a relation changes, update the post bodies that mention it in the same change.
<!-- hraness-articles:end -->
<!-- hraness-launch:start -->
- Launch posts, their social posts, product mockups, and launch films follow the launch beats and social posts addendum in `GENERATION_STYLE.md` and the beats shape under “Introducing a product” in `ARTICLE_COPY.md` in `@hraness/design-kit`. Channel limits are in the launch posts section of `MESSAGING.md`.
- Build them with the `product-launch` agent skill, the `./mockups` and `./launch` exports of `@hraness/design-kit`, and `slopcamera html init --template launch-film`.
- Take every number in a beat, social post, film caption, or store listing from the product's launch facts module, and the status from the release record. Keep mockups faithful to product behavior. Use readable fine print for qualifications tied to a specific claim; omit generic illustration and development labels.
- The social kit emits posts for X, Bluesky, Threads, and LinkedIn, and a fact sheet for the Show HN post and the Product Hunt first comment. A person writes those two.
<!-- hraness-launch:end -->
<!-- hraness-delivery:start -->
- Treat the user's request to change this repository as standing authorization for routine task-owned commits, pushes, pull requests, merges, releases, deployments, and production verification after the gates applicable to that action pass. Do not ask for duplicate confirmation. Build confidence through relevant automated checks, bounded diagnostics, and independent review, not another human approval. Passing checks does not expand task scope or authority.
- Prefer agentic service provisioning for new infrastructure. Check Vercel Marketplace for a native product that can provision the required resource first; use Stripe Projects as a supported alternative when it better covers the service or the Marketplace route only connects an existing account. Verify the current catalog, account, region, plan, recurring cost and resource capabilities before selecting a route. Prefer supported provider CLIs or APIs over browser-only setup when neither catalog fits, and explain the concrete exception. Reuse existing owner-controlled resources where appropriate; this preference alone does not authorize migrations, duplicate accounts, paid upgrades or wider access. Continue setup already authorized by the task and budget without duplicate confirmation. Keep provider credentials and generated environment files private, complete required interactive authentication, and verify deployment, persistence and recovery separately from successful provisioning.
- Separate artifact admission from live qualification and operational activation. Use applicable automated source, security, package/install, and provenance evidence for artifact admission; live provider qualification is not a universal publication prerequisite. Preserve explicit live acceptance criteria and require relevant live evidence for claims that depend on it. If publication or an artifact's install, upgrade, or default-use path activates risky unqualified behavior, keep that behavior guarded or disabled, or obtain bounded relevant evidence before shipping or activation.
- Use the repository's documented delivery workflow and preserve the identity, target, capacity, migration, and recovery guards applicable to operational activation. Replace an obsolete gate through a reviewed source and policy change with corresponding tests, never an ad hoc skip. Preserve every runtime-enforced approval, access control, branch protection, environment rule, safety policy, and required final gate. Ask for user input only when delivery needs a material product decision, missing credentials or authority, unavoidable interactive authentication, an irreversibly destructive action outside task scope, or resolution of a failure that cannot be handled safely and autonomously.
- Preserve production and user data throughout delivery. Inspect the exact account, environment, deployment, and data target before writes. For data changes, inspect a dry run or equivalent migration plan and validate the recovery path before any effect that could lose or corrupt data. Prefer additive, backward-compatible migrations and bounded batches. Record mutation intent, use idempotency or conditional writes, and reconcile uncertain results before retrying. Verify deployed identity, health, and relevant data invariants after delivery. Routine delivery never authorizes resetting, truncating, dropping, or overwriting user data; stop the unsafe operation if preservation or recovery cannot be established.
- Prefer short-lived repository workload identities such as OIDC trusted publishing, GitHub Apps, and narrowly scoped machine identities. Use unattended stable publication and production promotion when supported by the provider and repository. Establish supported machine authority once and verify it with a non-publishing preflight where available; routine releases should not require recurring interactive authentication or conversational approval. Releases and deployments run without a human in the loop: do not add required reviewers, manual approval environments, or wait timers to release or deployment paths, and remove any you find through a reviewed change. Keep account two-factor authentication, and do not add long-lived personal tokens.
- Main delivery is unattended. Open the pull request and enable auto-merge in the same breath (`gh pr merge --auto --squash <number>`), then move on; the required `Required` check is the reviewer. Until a repository's ruleset requires a check, `--auto` merges immediately, so wait for green checks there before merging. Never request a human reviewer or add required approvals, code owners, required conversation resolution, merge queues, manual-approval environments, or wait timers, and remove any you find with `scripts/apply-delivery-policy.py` from hraness/.github rather than by hand. Required checks run on the pull request head and are not re-required after main moves, so auto-merge never stalls behind another merge; main reruns the same gate after integration, and a red main is fixed forward by the next change. Repositories without CI use direct pushes to main.
- Preserve useful reasoning fan-out, but avoid unnecessary checkout fan-out. Prefer subagents in the current task for bounded research, review, diagnosis, and focused checks when they can safely share one working tree; create a separate task or worktree only for independently deliverable divergent edits, an isolated verification tree, or a different execution environment.
- Give each expensive focused validation command and external wait one owner. The integration owner reviews that evidence and runs the repository-required aggregate or final gate once after convergence. Reuse evidence only for the exact Git tree, command, lockfiles, toolchain, relevant environment, and validity period, and never to skip a required final integration, merge, release, deployment, or production-verification gate.
- On Hraness development machines, use the installed host scheduler for heavyweight top-level commands when available. Ordinary work and loopback dev/preview servers use the compute lane; owned headless checks use `browser`, the sole explicitly authorized signed-in browser owner uses `browser-auth`, and Mac-only validation uses `mac-native`.
- When a CI or policy gate scans complete Git history, check out the exact governed SHA and fetch only the fully qualified governed refs before scanning. Preserve the complete-history gate and reject unexpected refs instead of importing unrelated concurrent heads.
- At closeout, record applicable branch, PR, check, merge, release, deployment, and production evidence. Archive only conclusively finished tasks, never from silence alone, and reclaim only freshly revalidated clean merged worktrees through the guarded exact-path flow.
<!-- hraness-delivery:end -->
<!-- hraness-ci:start -->
- CI exists to admit a change in minutes, not to perform a ceremony. Every workflow declares `concurrency: { group: <name>-${{ github.ref }}, cancel-in-progress: true }` (release and deploy workflows set `cancel-in-progress: false`), a `timeout-minutes` on every job, and `permissions: contents: read` at the top with job-level widening only where needed.
- One job named `Required` closes every check workflow: `if: always()`, `needs:` every blocking job, and a single step that fails unless each `needs.<job>.result == 'success'`, or `skipped` because the change filter below reported its inputs unchanged. Branch policy requires only `Required` (plus a provider's own automated admission status when the product depends on it). Never make CodeQL, scheduled, or advisory jobs required.
- Cache by lockfile hash and restore before install: `Swatinem/rust-cache@v2` (with `save-if: ${{ github.ref == 'refs/heads/main' }}`) for Cargo, `oven-sh/setup-bun@v2` plus `actions/cache` on `~/.bun/install/cache` for Bun, `actions/setup-node` cache or `actions/cache` for npm/pnpm, `actions/setup-python` with `cache: pip` or `astral-sh/setup-uv` with cache for Python. Playwright browsers are cached under `~/.cache/ms-playwright` keyed by the Playwright version.
- Rust: install the pinned toolchain with `dtolnay/rust-toolchain` (`rustup toolchain install` at most once per job, `--profile minimal`), set `CARGO_INCREMENTAL: 0`, `CARGO_TERM_COLOR: always`, `CARGO_NET_RETRY: 10`, `RUSTFLAGS: -D warnings` and `RUST_BACKTRACE: short` at workflow level, use `cargo nextest` or one `cargo test --workspace --locked` after a shared `cargo build --all-targets --locked`, run `clippy` and `fmt` once on Linux only, install tools with `taiki-e/install-action` or `cargo-binstall` instead of `cargo install`, and build release binaries in one job whose artifact every later job reuses. Never build the same crate twice in one workflow.
- Run the matrix Linux-first. A macOS or Windows job exists only when the product ships a native surface for that OS, runs the OS-specific tests only, and is never the only place a generic check runs. Split long serial script lists into parallel jobs that share one build artifact instead of one job that runs for twenty minutes.
- Skip work that cannot change the result inside the workflow: a change-detection job runs `dorny/paths-filter@v4` (it needs job permission `pull-requests: read`, and `predicate-quantifier: some-with-excludes` needs v4), and jobs whose inputs did not change skip through job-level `if:`. Never put `paths`, `paths-ignore`, or `branches-ignore` on the `pull_request` trigger of the workflow that produces `Required`: a skipped workflow never reports `Required`, and the pull request can never merge. Every `uses:` pins a major tag or a SHA with a version comment, and Dependabot keeps `github-actions` current weekly with auto-merge.
- Measure before and after: a CI change records the previous and new median wall time of the slowest workflow in its pull request body. Regressions that add more than a minute to `Required` are reverted forward the same day.
<!-- hraness-ci:end -->
- `costs.json` at the repository root is the checked registry of every product data surface: store, kind (`authoritative` | `derived` | `telemetry` | `served`), retention class (`ephemeral` | `ttl:<ISO-8601>` | `account` | `tombstone` | `persistent`), owner module, and budget. A new table, bucket, stream, dynamic route, blob, or provider meter fails `check:cost-surfaces` until it registers.
- Bound every input before storage or provider I/O: request bytes, row counts, page sizes, batch sizes, retry counts, and event payloads. Unbounded input is a contract violation.
- No writes on read paths. Reads may cache; they never mutate.
- Derived state is rebuildable and lives in the cheapest tier that can serve it. Only authoritative state pays for transactional storage.
- Every mutation carries an idempotency key; a retried write never double-charges storage, quota, or provider spend.
- Analytics and metering events come from a checked allowlist with a byte ceiling per event.
- Content bytes live in the content store; the control plane keeps references and metadata only.
- Run `bun run check:cost-surfaces` before handoff whenever a data surface changes.
<!-- algal-skills:start -->
## ALGAL skills
- Prefer the globally installed `algal-*` skills for bounded git state, diffs, repository survey/search, test and release gates, CI polling, and web fetches instead of repeated raw tool output.
- At session start, if the `algal` skill is unavailable, install the current skill pack for Claude Code, Codex, and Devin for Terminal with `bunx skills add 0thernet/algal-skills --global --agent claude-code codex devin --skill '*' --copy --yes`.
- Confirm installation with `bunx skills list --global`. If Bun or network access is unavailable, continue with repository-native tools instead of blocking delivery.
- Treat ALGAL receipts as execution evidence, not provider attestation, and preserve the repository's normal verification and release gates.
<!-- algal-skills:end -->