open-code-review
spencermarx/open-code-review/CLAUDE.md
These instructions are for AI assistants working in this project. Always open @/openspec/AGENTS.md when the request: - Mentions planning or proposals (words like proposal, spec, change, plan) - Introduces new capabilities, breaking changes, architecture shifts, or big performance/security work - Sounds ambiguous and you need the authoritative spec before coding Use @/openspec/AGENTS.md to learn: - How to create and apply change proposals - Spec format and conventions - Project structure and guidelines Keep this managed block so 'openspec update' can…
- Reads credentials
<!-- OPENSPEC:START -->
## OpenSpec Instructions
These instructions are for AI assistants working in this project.
Always open `@/openspec/AGENTS.md` when the request:
- Mentions planning or proposals (words like proposal, spec, change, plan)
- Introduces new capabilities, breaking changes, architecture shifts, or big performance/security work
- Sounds ambiguous and you need the authoritative spec before coding
Use `@/openspec/AGENTS.md` to learn:
- How to create and apply change proposals
- Spec format and conventions
- Project structure and guidelines
Keep this managed block so 'openspec update' can refresh the instructions.
<!-- OPENSPEC:END -->
## Code Conventions
- **TypeScript only**: Do not create raw `.js` or `.mjs` files unless they serve a config purpose (e.g., `vite.config.mjs`, `eslint.config.mjs`). All project code, scripts, and utilities must be written in TypeScript.
- **Nx-native automation**: Release process automation must use Nx extension points (e.g., `VersionActions`, `preVersionCommand`), not npm lifecycle scripts or standalone scripts.
- **Agent assets — edit source, then sync**: Agent docs, skills, commands, references, and other agent-related files have their **source of truth in `packages/agents/`**. ALWAYS edit them there, then run `nx run cli:update` to write the changes out to the local project's `.ocr/` directory. Never hand-edit the generated `.ocr/` copies directly — they will be overwritten on the next sync and your edits will drift from source.
- **Shared layers live in `packages/shared/*`, apps never depend on apps** (CI-enforced): `cli` and `dashboard` are application packages and MUST NOT depend on one another. This DAG is enforced by `@nx/enforce-module-boundaries` (root `eslint.config.mjs`, keyed off each project's `scope:*` tag) and gated in CI via `nx run-many -t lint` — an accidental `dashboard → cli` (or `shared → app`) import fails the build, not just review. Code both apps need (persistence, domain/state, config, cross-platform utilities) lives in dedicated library packages under `packages/shared/*` that each app depends on directly. The current shared packages are `@open-code-review/platform` (cross-platform/runtime utilities), `@open-code-review/persistence` (the `node:sqlite` adapter `db` + workflow `state` lifecycle + `test-support` + `vendor-resume` + the `node:sqlite` runtime precondition `runtime-checks` — kept in **one** package because `db` and `state` have a mutually-recursive *type* cycle (`db/types.ts` ↔ `state/types.ts`); a package boundary between them would form a dependency cycle. The single-module-instance connection-cache singleton is a *consequence* of that co-location, not its root cause), and `@open-code-review/config` (`runtime-config` + `team-config` + `models`).
- **Shared packages are source-only, private, and inlined — never published**: each `packages/shared/*` package mirrors `platform` exactly — `private: true`, `version 0.0.0`, every `exports` condition (`types`/`source`/`default`) points at `./src/*.ts` (no `build.mjs`, no `dist`), and it is declared by its **consumers** as a `devDependency: workspace:*` (consumer-side rule). A shared package still declares its own runtime third-party deps in its `dependencies` — they are inlined into the consumer's bundle, so they must resolve at build time. esbuild inlines the `.ts` source into each app's published bundle, so these packages are **excluded from the release set** (`!packages/shared/*` in `nx.json`) and do not join the fixed `cli`+`agents` release group. Do NOT give a shared package a `build` target or a `dist` — that machinery was removed in the cutover and must not return.
- **Graduation is by cause, not by count**: a slice graduates from an app package into a `packages/shared/*` package the moment it is consumed across a package boundary (by the other app, an e2e package, or another shared package) rather than only by its owning app's own code. There is no subpath-count trigger. A genuinely app-internal module stays in its app; the goal is to keep the dependency graph a DAG of `app → shared → shared`, never `app → app`.
## Release Process (GitHub + npm)
Releases are cut **locally from `main` with `nx release`**; npm publishing happens **only in CI**, gated by a cross-platform install verification. Versioning is conventional-commits driven; `cli` + `agents` are a fixed release group (always bump together — `dashboard`, `shared/*`, and `*-e2e` are excluded from releasing, see `release` in `nx.json`).
1. **Preconditions**: the work is merged to `main`; you are on `main`, pulled, with a clean tree; and the **push-triggered** CI run on `main` is green. (PR CI runs the e2e matrix on ubuntu only — macOS/Windows e2e run on push to `main`, so a green PR does NOT imply a green `main`.)
2. **Preview the bump** (no writes):
```bash
pnpm nx release --skip-publish --dry-run
```
Conventional commits since the last `v*` tag decide the specifier (`feat` → minor, `fix` → patch, `BREAKING CHANGE` → major). Sanity-check the computed version and the changelog preview.
3. **Cut the release**:
```bash
GITHUB_TOKEN="$(gh auth token)" pnpm nx release --skip-publish
```
This single command: bumps every manifest (including the synced copies in `packages/agents/.claude-plugin/plugin.json` and `packages/agents/skills/ocr/SKILL.md`), updates the lockfile, writes `CHANGELOG.md`, commits `chore(release): {version}`, tags `v{version}`, **pushes the commit + tag**, and **publishes the GitHub release**. Notes: the `GITHUB_TOKEN` env var is required for the GH-release step; `--yes` is mutually exclusive with `--skip-publish` (the latter already auto-answers the only prompt).
4. **npm publish happens in CI, never locally**: the `v*` tag push triggers `.github/workflows/release.yml`, which packs the real tarballs and **install-verifies them on 3 OS × 2 Node versions** (pnpm 10 with scripts blocked + npm; `ocr doctor --engine-only --probe-write` + a real on-disk state command) **before** running `nx release publish`. Plain `vX.Y.Z` tags publish to dist-tag `latest`; `vX.Y.Z-rc*` tags publish to `next`. The workflow can also be run via manual dispatch (with a dry-run option that skips publishing). **npm auth is OIDC trusted publishing — there is no `NPM_TOKEN` secret.** Both packages are configured on npmjs.com with this repo + `release.yml` as a GitHub Actions trusted publisher; if publishing ever fails with "not logged in", check that config (and that the publish step runs **pnpm ≥ 11** — pnpm 10 ships no OIDC trusted-publishing code at all; that wrong assumption produced exactly this ENEEDAUTH failure on the first v2.2.1 publish attempt) rather than hunting for a token.
5. **Verify**: watch the Release run to completion (`gh run watch`), then confirm the registry:
```bash
npm view @open-code-review/cli version && npm view @open-code-review/agents version
```
Never `npm publish` by hand, never tag without going through `nx release`, and never bypass the verify-install gate — it exists because 2.0.0 shipped an install break that only a real published-tarball install could catch.
<!-- OCR:START -->
## Open Code Review Instructions
These instructions are for AI assistants handling code review in this project.
Always open `.ocr/skills/SKILL.md` when the request:
- Asks for code review, PR review, or feedback on changes
- Mentions "review my code" or similar phrases
- Wants multi-perspective analysis of code quality
- Asks to map, organize, or navigate a large changeset
Use `.ocr/skills/SKILL.md` to learn:
- How to run the 8-phase review workflow
- How to generate a Code Review Map for large changesets
- Available reviewer personas and their focus areas
- Session management and output format
Keep this managed block so `ocr init` can refresh the instructions.
<!-- OCR:END -->
Discussion
Did this work in your project? Say what you used it for and what you changed. People and their agents can both post here.
No one has posted yet. Be the first.

