diff --git a/.claude/agents/autopilot-builder.md b/.claude/agents/autopilot-builder.md new file mode 100644 index 0000000..eea9439 --- /dev/null +++ b/.claude/agents/autopilot-builder.md @@ -0,0 +1,19 @@ +--- +name: AutopilotBuilder +description: Implements one planned backlog item on an autopilot/ branch, with tests. +tools: + - Read + - Write + - Edit + - Grep + - Glob + - Bash +--- + +You are the builder for Project Atlas autopilot runs. Read `docs/16_autopilot.md` first and follow it, including the Never list. + +- Work only on the plan you were given, on a branch named `autopilot/-`. +- Prefer typed interfaces, explicit validation, and tests, as `CLAUDE.md` requires. +- Run `pnpm typecheck`, `pnpm lint`, and `pnpm test` before you hand back. Run `node scripts/bundle-backend.mjs` and commit `api/` if backend code changed. +- Commit in small steps. Never push to `main`, never merge, never touch secrets. +- Hand back a short list: what changed, which commands you ran, what you could not verify. Do not describe anything as working that you did not run. diff --git a/.claude/agents/autopilot-planner.md b/.claude/agents/autopilot-planner.md new file mode 100644 index 0000000..9d57d1d --- /dev/null +++ b/.claude/agents/autopilot-planner.md @@ -0,0 +1,18 @@ +--- +name: AutopilotPlanner +description: Turns one backlog item into a short, checkable plan for an autopilot run. Read-only. +tools: + - Read + - Grep + - Glob + - Bash +--- + +You are the planner for Project Atlas autopilot runs. Read `docs/16_autopilot.md` first and follow it. + +Given one backlog item from `docs/17_backlog.md`: + +- Read only the code the item touches. Do not edit anything. +- Check whether the item's premise is still true in the current code. If it is not, say so and propose marking it done or rewriting it. +- Return a plan of at most 15 lines: files to change, tests to add, the exact commands that prove it works, and anything the item forbids. +- If the item needs a decision that belongs to the owner, return "BLOCKED: owner decision needed" with the question, and nothing else. diff --git a/.claude/agents/autopilot-reviewer.md b/.claude/agents/autopilot-reviewer.md new file mode 100644 index 0000000..38d96ae --- /dev/null +++ b/.claude/agents/autopilot-reviewer.md @@ -0,0 +1,18 @@ +--- +name: AutopilotReviewer +description: Independently reviews an autopilot branch and re-runs the checks. Cannot edit files. +tools: + - Read + - Grep + - Glob + - Bash +--- + +You are the reviewer for Project Atlas autopilot runs. You did not write this change. Read `docs/16_autopilot.md` first. + +- Read the full diff against `main`. Do not trust the builder's summary. +- Re-run `pnpm typecheck`, `pnpm lint`, and `pnpm test` yourself. Compare passed and skipped counts with the baseline in the plan. +- If backend code changed, run `node scripts/bundle-backend.mjs` and confirm `git status` shows no uncommitted change under `api/`. +- Check the diff against the Never list, the item's "Done when" text, and `CLAUDE.md`. +- Look for tests that cannot fail, skipped tests added to dodge a failure, invented facts in copy, and anything touching a Tier C item. +- Answer `PASS` or `FAIL`. On FAIL, list each problem with a file and line. You may not edit files. diff --git a/docs/16_autopilot.md b/docs/16_autopilot.md new file mode 100644 index 0000000..2ad2a40 --- /dev/null +++ b/docs/16_autopilot.md @@ -0,0 +1,62 @@ +# 16 — Autopilot + +Rules for unattended Claude runs on this repository. A scheduled run starts with no memory of earlier runs, so everything it needs to know is in the repo: this file, `docs/17_backlog.md`, `docs/18_autopilot_log.md`, and `docs/15_progress_report.md`. + +`CLAUDE.md` still applies. If this file and `CLAUDE.md` disagree, `CLAUDE.md` wins. + +## Principle + +Ship the smallest safe, verified change per run, as a pull request the owner can review in a few minutes. A run that ends with "blocked, here is why" is a good run. A run that ends with an unverified claim is a bad one. + +## One run, in order + +1. **Orient.** Read `CLAUDE.md`, this file, `docs/17_backlog.md`, `docs/18_autopilot_log.md`, and the "Known gaps" and "Next steps" sections of `docs/15_progress_report.md`. Run `pnpm install --frozen-lockfile`. +2. **Baseline.** On a clean `main`, run `pnpm typecheck`, `pnpm lint`, `pnpm test`. Record the passed and skipped counts. If anything is red, do no feature work: fix it only if the cause is clear and small, otherwise log it and stop. +3. **Open-PR gate.** List open pull requests with the REST API (`gh api repos/NiksheyYadav/autoapply/pulls`; GraphQL is blocked in these sessions). Count those whose head branch starts with `autopilot/`. + - Two or more open: start no new item. Check each one's CI status and review comments, push fixes to that branch if needed, log it, and stop. + - Fewer than two: continue. +4. **Pick one item.** Take the first backlog item in Tier A, then Tier B, whose status is `todo` and which no open `autopilot/` branch is already working on. One item per run. If it cannot finish in one run, finish the first coherent slice, set it to `in-progress`, and write what remains under it. +5. **Plan, build, review.** Use three separate subagents so the work never grades itself: + - `AutopilotPlanner` returns a short plan: files, tests, acceptance check. + - `AutopilotBuilder` implements it on branch `autopilot/-`. + - `AutopilotReviewer` has no write tools. It reads the diff, re-runs the checks itself, and answers PASS or FAIL with reasons. On FAIL the builder gets at most two fix rounds. After that, abandon the item, mark it `blocked` with the reason, and stop. +6. **Verify (all must hold).** + - `pnpm typecheck` and `pnpm lint` are clean. + - `pnpm test`: passed count is not lower than the baseline and skipped count is not higher, unless the item is explicitly about removing or unskipping tests. + - If anything under `services/` or `packages/` changed, run `node scripts/bundle-backend.mjs` and commit the regenerated `api/`. Vercel reads functions from the git checkout, so a stale `api/` ships old code. + - If `apps/web` or `apps/admin` changed, run that app's `typecheck` and `build` using the environment variables in `.github/workflows/ci.yml`. +7. **Ship.** Push the branch and open a pull request through the REST API. Update the item's status in `docs/17_backlog.md` and add an entry to `docs/18_autopilot_log.md` in the same pull request, so merging records the state. Never merge your own pull request. +8. **Report.** Send the owner a summary of at most five lines, in simple language (English or Hinglish, casual, no jargon): what shipped, the pull request link, what is blocked, and anything that needs an owner decision. The later run of each day (after 05:00 IST) starts the message with "Daily report:" and covers every run since midnight IST, using `docs/18_autopilot_log.md` and the list of open `autopilot/` pull requests. + +## Pull request body + +- What changed and why, tied to a backlog id. +- Evidence: the commands run and their results. +- What is **not** verified. Use the labels from `docs/15_progress_report.md`: Verified (with date), Last verified, Unverified. + +## Never + +- Push to `main`, force-push, rewrite history, merge a pull request, or delete a branch that does not start with `autopilot/`. +- Run a migration or any command against live Supabase, Vercel, or any production system. Do not deploy. +- Read, print, or commit secrets. Only `.env.example` may change, and only with placeholder values. +- Change an API contract (`packages/types`) unless the backlog item says to. +- Touch a Tier C item. +- Add a dependency unless the pull request explains why existing code or the standard library will not do. Keep the lockfile consistent. +- Write public-facing copy that states facts not found in `docs/`: no metrics, customers, certifications, or pricing. +- Claim something works without having run it. + +## Budget + +These runs draw on the owner's Claude usage limits, so they are deliberately small. + +- **A run uses at most about half of one five-hour usage window.** A run cannot read the usage meter, so this is enforced by size: one item, targeted file reads only, and roughly 50 tool calls in total including the subagents' calls. If you reach that and are not done, stop at a clean point: commit only what is verified, mark the item `in-progress` with notes, and log it. +- The schedule is two runs a day, at 01:12 and 06:12 IST, five hours apart so each gets its own window. The owner should check Settings > Usage after the first few runs and tell Claude to tighten or loosen the size cap. +- One item per run. Stop early rather than expanding scope. +- If a usage limit interrupts a run, nothing is lost: progress lives on the branch and in the log. The next run resumes from there. +- The owner sets the cadence by editing the scheduled task. The agent never changes its own schedule. + +## Tiers + +- **Tier A** — safe to implement and verify inside the sandbox. +- **Tier B** — may be prepared as a pull request, but cannot be fully verified here. It must be labelled Unverified and is not "done" until CI is green and the owner reviews it. +- **Tier C** — owner only. Never done by autopilot. Autopilot may write a docs-only options paper to support the decision, if a Tier A item asks for one. diff --git a/docs/17_backlog.md b/docs/17_backlog.md new file mode 100644 index 0000000..aac4533 --- /dev/null +++ b/docs/17_backlog.md @@ -0,0 +1,93 @@ +# 17 — Backlog + +Ordered by priority. Autopilot takes the first `todo` item in Tier A, then Tier B. The owner can reorder, add, or cross out items at any time; edit this file directly. + +Status values: `todo`, `in-progress`, `blocked`, `done`. + +Evidence below comes from `docs/15_progress_report.md` and a baseline run on 2026-10-31 (typecheck clean, lint clean, 114 tests passed and 51 skipped, committed `api/` bundle current). + +## Tier A — autopilot may implement + +### A1 — Explain the test-count drop + +Status: `todo` +`docs/15` records 125 passed / 55 skipped before the Supabase migration and 114 / 51 now, and says the drop "was not investigated separately". +Done when: the PR explains the difference with evidence from history. Any lost test that guarded real behavior is restored. Intentional removals are noted in `docs/15`. +History tip: the clone is shallow. Deepen with a bounded `git fetch --depth=1000 origin main`, not `--unshallow`. + +### A2 — Retry and failure tests for `packages/messaging` + +Status: `todo` +`packages/messaging` has no test files. `docs/13` says every queue consumer gets retry and failure tests. +Done when: tests cover publish and consume with the in-memory driver, a handler that throws, the retry behavior that exists, and what happens when retries run out. No network needed. If the code lacks behavior the principle expects, record the gap in the PR rather than inventing the behavior. + +### A3 — SEO and AI-discoverability pass for `apps/web` + +Status: `todo` +Goal: the public site leads with "Project Atlas" and is easy for search engines and LLMs to read. +Done when: page metadata and Open Graph tags, `robots.txt`, `sitemap.xml`, `llms.txt`, and JSON-LD (`SoftwareApplication`) are in place, and `pnpm --filter @atlas/web run build` passes with the CI env vars. Copy uses only facts from `docs/01_product_architecture.md`. + +### A4 — Tests for `services/auth` + +Status: `todo` +`services/auth` has no test files. It now only serves `GET /v1/auth/me` and `/health`, and `/me` does a fresh permissions lookup. +Done when: tests cover missing and invalid token, a valid token with a mocked permissions lookup, and `/health`. DB-backed variants may self-skip like the existing suites. + +### A5 — Mocked-OAuth coverage for `services/connectors` + +Status: `todo` +`docs/13`: every connector gets mocked OAuth tests. +Done when: the PR lists each connector, whether it has a mocked OAuth test, and adds the missing ones. Token isolation between connectors is asserted. + +### A6 — API schema-validation tests, one service per run + +Status: `todo` +`docs/13`: every public API gets schema validation tests. +Order: matching, applications, referrals, outreach, learning, analytics, jobs, profile. Each run takes the next service that has no validation tests for its public routes and marks it here. +Done so far: none. + +### A7 — Options paper: where do the workers run? + +Status: `todo` +Gap 1 in `docs/15`: event-driven workers need a persistent process and a real broker, and Vercel provides neither. +Done when: `docs/` has a short options paper comparing RabbitMQ plus a persistent worker host against cron-triggered polling endpoints, grounded in how the worker code is actually written, with costs, risks, and a clear "owner decision needed" ending. Docs only. It does not decide. + +### A8 — Options paper: transactional outbox + +Status: `todo` +Gap 2 in `docs/15`: a broker failure after the database commit loses the event permanently. +Done when: a docs-only options paper lists the routes affected, a schema sketch, the relay design, and migration impact, and ends with "owner decision needed". + +### A9 — Bring `docs/09_security_model.md` in line with today's auth + +Status: `todo` +The document still describes the pre-Supabase design. +Done when: it describes what exists now (Supabase Auth, JWKS verification through `@atlas/auth-kit`, `/me` permission lookup). Things not implemented, such as MFA, lockout, and platform-level admin, are marked as not implemented. It does not claim migration phase 6 is done. + +## Tier B — prepare a PR, label it Unverified + +### B1 — Run the DB-backed tests in CI + +Status: `todo` +51 tests are skipped because no Postgres is wired into the CI job. +Done when: `.github/workflows/ci.yml` has a Postgres service and sets `ATLAS_TEST_DATABASE_URL`, and the PR reports what the skipped suites did on the PR's own CI run. The sandbox has no database, so the CI run is the only evidence. If suites need Supabase-specific SQL, say so and stop short of guessing. + +### B2 — Platform-level admin role + +Status: `todo` +Gap 3 in `docs/15`. Touches the permissions model, so the first PR is a short design note only. Implementation waits for the owner's go-ahead written under this item. + +### B3 — Production drivers: storage `s3`, outreach `smtp` + +Status: `todo` +Both throw "not implemented" today. Implement against mocked clients with unit tests, and label the PR Unverified because nothing here can reach real S3 or an SMTP server. Connectors `kms` is excluded because it needs a secrets-backend decision (Tier C). + +## Tier C — owner only, never autopilot + +- Supabase migration phase 6: dropping `password_hash`, `mfa_enabled`, `mfa_secret`, `failed_login_count`, `locked_until`. It is destructive on the live project, and `mfa_enabled` is part of the public API contract. +- Configuring Microsoft (`azure`) sign-in in Supabase. +- Exercising PDF upload on the deployed backend with a real resume. +- Deciding the worker-hosting question and whether to build the outbox (A7 and A8 only prepare the decision). +- Rotating the Supabase database credential; deleting the nine superseded Vercel projects; providing RabbitMQ, SMTP credentials, and a secrets backend. +- Kubernetes manifests, Dockerfiles, OpenTelemetry tracing, MFA, anomaly detection. These were deliberately not attempted because they cannot be verified in the sandbox. +- Billing (out of scope). diff --git a/docs/18_autopilot_log.md b/docs/18_autopilot_log.md new file mode 100644 index 0000000..30684bf --- /dev/null +++ b/docs/18_autopilot_log.md @@ -0,0 +1,20 @@ +# 18 — Autopilot log + +One entry per run, newest first. Each run adds its own entry in the same pull request as its work. + +Entry format: + +``` +## — +- Baseline: typecheck , lint , tests / +- Did: +- Result: +- Needs owner: +``` + +## 2026-10-31 — setup + +- Baseline: typecheck clean, lint clean, tests 114 passed / 51 skipped; `node scripts/bundle-backend.mjs` produced no diff, so the committed `api/` is current. +- Did: added `docs/16_autopilot.md`, `docs/17_backlog.md`, this log, and three role agents under `.claude/agents/`. +- Result: this pull request. +- Needs owner: review the backlog order and the Tier C list, then merge.