AGENTS.md@web · git:20260902.dac7a0d · 2026-09-02 · sha256 c2ffb1dcced02134
AGENTS.md@web git:20260902.dac7a0dA
Immutable. This exact content is served forever at /api/v1/blob/c2ffb1dcced02134.
# Working in `web/`
The web app is a **view over the user's own files**, not a second engine. Read this
before changing anything under `web/`.
## The three rules that are not style preferences
1. **Orchestrate the core; never reimplement it.** The CLI already resolves tracker
paths, matches tailored CVs and canonicalises statuses: call it, or mirror it
behind a parity test. A second implementation of the same rule is how the two
halves start disagreeing, and the disagreement is always silent.
`web/src/lib/core/` holds the access layer for exactly this.
2. **Markdown is the source of truth.** `data/applications.md`, `cv.md`, `reports/`
are canonical; anything else is a derived index. Status changes go through
`/api/status`, which delegates to the root `set-status.mjs`. That is the single
write path, and it is single on purpose. Never write a user's file from a route
that bypasses it.
3. **Nothing is ever submitted automatically.** The apply flow fills in and previews;
a human presses send. There is no exception, no flag, and no "just for testing".
## A missing file is not a malformed file
Treating a parse error as "not there yet" is how a user's config gets overwritten
with the shipped example. Distinguish `ENOENT` from every other failure, and let a
broken user-layer file surface as an error the user can act on rather than as an
empty default. (`web/src/lib/portals-config.mjs` is the worked example.)
## Testing
Logic that deserves a test lives in a plain `.mjs` module so `node --test` can import
it with no build step and no `@/` alias loader. See `tracker-table.mjs`,
`cv-selection.mjs`, `report-sections.mjs`. A component is not a place to put a rule
you want to assert.
```
npm test # node --test "tests/**/*.test.mjs"
npm run typecheck # tsc --noEmit
npm run dev # the app, reading the sibling career-ops files
```
Point `CAREER_OPS_ROOT` at a scratch directory when you need data to test against;
it is how the app finds the user's files, and it keeps your real pipeline out of it.
## Reviews and scope
`web/` is maintained as first-party: functional and correctness fixes are very
welcome, design and feature proposals are routed to Discussion #156 so the surface
stays coherent. That is a routing decision, not a judgement on the work.
<!-- The block below is written and re-added by `next dev`. It is committed
deliberately: keeping it in the file means Next updates only the marked
region and never scaffolds a separate CLAUDE.md, so an agent's instructions
here stay reviewable in a diff instead of appearing untracked. -->
<!-- BEGIN:nextjs-agent-rules -->
# This is NOT the Next.js you know
This version has breaking changes — APIs, conventions, and file structure may all differ from your training data. Read the relevant guide in `node_modules/next/dist/docs/` (resolved from this file's directory; in monorepos the `next` package may not be visible from the repo root) before writing any code. Heed deprecation notices.
This block is written and re-added by `next dev` — verify at `node_modules/next/dist/server/lib/generate-agent-files.js`. Removing it from a diff only re-creates the uncommitted change; committing it with your work keeps the tree clean.
<!-- END:nextjs-agent-rules -->