AGENTS.md · git:20261021.196cf4c · 2026-10-21 · sha256 753099a794e3e374

AGENTS.md git:20261021.196cf4cA

Immutable. This exact content never changes and is served at /api/v1/blob/753099a794e3e374.

# Agent guide for the source repository

Tedix runs persistent, organization-owned AI workers on Cloudflare. Start with
`README.md` and `docs/public/index.md`; `docs/public/release-status.md` says
what is available today.

## Start locally

Run `bun run-local` from the repository root. It needs no login and makes no
model calls by default; `docs/public/getting-started.md` lists its options.

For UI-only work, use `bun run --cwd apps/os dev` (fixture data). Never treat
passing local tests as a check of Cloud behavior or a deployment.

## Choose a source path

| Change           | Read first                                                                                                      |
| ---------------- | --------------------------------------------------------------------------------------------------------------- |
| UI               | `apps/os/README.md`, `apps/os/AGENTS.md`, then `apps/os/src/routes/`                                            |
| API              | `apps/api/AGENTS.md`, contract in `packages/api-contract/src/contracts/`, router in `apps/api/src/rpc/routers/` |
| Persistence      | `packages/db/AGENTS.md`, owning `src/schema/` and `src/queries/` modules                                        |
| Worker execution | `apps/tedi-runtime/AGENTS.md`, `src/do.ts` and the relevant adjacent module                                     |
| MCP tools        | `apps/mcp/AGENTS.md`, `src/mcp/handler.ts` and `packages/db/src/schema/tools.ts`                                |
| CLI              | `packages/cli/README.md` and the command's implementation                                                       |

Read the nearest scoped `AGENTS.md`, exact callers, and tests before changing
behavior. Keep unrelated work intact. Contracts and current code take priority
over prose; fix stale instructions when you encounter them.

Before each patch, re-read the exact lines it replaces. Never copy context
lines from memory or from your own earlier edit, because a formatter may have
rewritten them. Keep Markdown line breaks exactly as the file has them.

## Validate the change

- `bun run --cwd <workspace> type-check`: TypeScript source.
- `bun run --cwd <workspace> test:run`: that workspace's tests; follow scoped
  guidance for narrower tests. Never use bare `bun test` on Worker apps.
- `bun run types:check`: generated Worker bindings; regenerate with
  `bun run types:generate`, never by hand.
- `bun run lint:repo`: architecture boundaries.
- `bun run docs:public:check`: public documentation and agent references.
- `bun run scan:secrets`: public source safety.

The pre-push hook selects relevant checks. Do not weaken a failing check to
make it pass. Report exactly what ran, and keep passing tests, a recorded
outcome, and a deployment distinct.

Before committing, run `bun run format <changed files>`; unformatted files are
the most common pre-push failure. Push with `bun run push`, not `git push`: it
queues behind other sessions on this machine, rebases onto `origin/main`, runs
the normal pre-push gates, and retries if main moved elsewhere.

## Worktrees and closeout

Agents must create worktrees under `.worktrees/` (or harness-managed locations), never sibling clones.
Work in a worktree, never in a checkout another session is using.
Run `git worktree list` before creating one and reuse your own.
Once your change is pushed or abandoned, remove your worktree and scratch
files; never remove one a live session is in. `bun run worktree:gc` lists every
worktree of this repo and `--apply` removes only merged, clean, idle ones. The
`worktree-closeout` skill in `.agents/skills/` is the full procedure.

## Hard Invariants

Breaking these is expensive and usually invisible locally. Do not:

- **Use `db.transaction()`.** D1 rejects `BEGIN` (error 7500). `db.batch()`
  is the transaction primitive.
- **Select two columns with the same output name in one query.** D1 batch
  results are object rows and silently collapse duplicates before Drizzle
  maps them. Every query must stay safe when composed into a batch; tests use
  a D1 facade that rejects both idioms.
- **Define oRPC contracts inline in routers.** Contracts live in
  `packages/api-contract/src/contracts/`, schemas in
  `packages/api-contract/src/schemas/`; apps import direct
  `@tedix/api-contract/...` paths.
- **Add barrel files or re-export facades.** Direct imports everywhere. DB
  access goes through `@tedix/db/queries/<domain>` modules — never inline
  Drizzle queries in routers, jobs, services, or workflows
  (`scripts/lint-db-access.ts` enforces this).
- **Hardcode per-tenant behavior in TypeScript.** Config-driven behavior
  (tools, widgets, scopes, policies, schedules) belongs in D1 rows and
  versioned assets; TypeScript provides the engines, validators, renderers,
  and adapters.
- **Name MCP tools anything but verb-first snake_case.** `list_skills`,
  `get_skill`, `run_skill_workflow`. A noun prefix is allowed only for
  multi-product disambiguation (`gmail_send`). Internal oRPC contract keys
  keep their TypeScript `{noun}.{verb}` shape and are exempt.
- **Edit `worker-configuration.d.ts` by hand** — regenerate with
  `bun run types:generate`. Worker config is
  `cloudflare.config.ts` or `wrangler.jsonc`, never `.toml`.

## Local work and live access

A local checkout gives no access to any live organization. For permitted live
work, read `docs/public/agent-guide.md`, check `tedix auth status`, and discover
the exact tool and schema before calling it. Consent, MFA, and user presence
stay with the human; other approvals go to the designated approver.

Maintainers commit directly to `main` after validation. Agents never create
GitHub issues or pull requests (pull requests are disabled). File proposals,
bugs and follow-ups as Tedix Work items; GitHub issues are for outside
contributors (`CONTRIBUTING.md`). Never invent a Work Item or agent identity.

A user-visible CLI change adds a changeset (`bun changeset`) in the same
commit. Never bump the CLI version, edit its `CHANGELOG.md`, or tag a release
as part of a change; releases are batched, at most daily (`CONTRIBUTING.md`, Releases).

## Deployment boundary

A commit changing a deployable `wrangler.jsonc` or `cloudflare.config.ts`
requires one `Ops-Overlay: <full ops commit SHA> <config path>` trailer per
changed config before pushing to this repository. Validate the corresponding
private overlay against the exact product config and land it in ops first.
The pre-push gate checks the reference offline; Ship checks compatibility.

This repository owns product source and example configuration, not the live
Tedix Cloud installation. Managed releases run from `tedix-hq/tedix-cloud-ops`,
which owns the guarded deployment workflow, live configuration and credentials.
Do not hand-deploy Tedix Cloud from this checkout or add its account, database,
organization or resource IDs, secret references, or private runbooks here.
Keep checked-in Worker configuration usable as examples, with placeholders
instead of live installation coordinates. Never commit real `.env` files,
`.dev.vars`, credentials or customer data; `.env.example` contains key names
and placeholders only. Use fictional tenant identities in tests and examples.

Deploying into your own Cloudflare account is experimental operator work. Follow
`docs/public/installation-manifests.md` and
`docs/public/self-hosted-boundary.md` only when deployment is the task. A source
checkout is not authorization to operate Tedix Cloud.