pluribus-context 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,145 @@
1
+ # OpenClaw Integration
2
+
3
+ OpenClaw is an AI agent runner that uses **`AGENTS.md`** as its primary context file. Pluribus can generate and keep `AGENTS.md` in sync from a single `pluribus.md` source.
4
+
5
+ ---
6
+
7
+ ## How It Works
8
+
9
+ OpenClaw reads `AGENTS.md` on startup to understand:
10
+
11
+ - The agent's **identity** — name, role, persona
12
+ - **Sub-agent system** — what agents exist and when to spawn them
13
+ - **Tools and integrations** — external services the agent can use
14
+ - **Operating rules** — constraints, protocols, and guardrails
15
+ - **Soul/tone** — how the agent communicates
16
+
17
+ Pluribus maps your `pluribus.md` sections to a well-structured `AGENTS.md`:
18
+
19
+ | `pluribus.md` section | `AGENTS.md` output |
20
+ |---|---|
21
+ | `# Identity` | Identity block (name, role, emoji) |
22
+ | `# Agents` | Sub-agent system table |
23
+ | `# Stack` | Tools and integrations |
24
+ | `# Conventions` | Operating protocols |
25
+ | `# Constraints` | Hard rules and guardrails |
26
+ | `# Soul` | Tone and behavior guidance |
27
+
28
+ ---
29
+
30
+ ## Workflow
31
+
32
+ ### 1. Initialize
33
+
34
+ ```bash
35
+ cd your-openclaw-workspace/
36
+ pluribus init --tools openclaw
37
+ ```
38
+
39
+ This scaffolds `pluribus.md` with OpenClaw-specific sections pre-filled.
40
+
41
+ ### 2. Edit `pluribus.md`
42
+
43
+ Write your agent context once:
44
+
45
+ ```markdown
46
+ # Identity
47
+
48
+ I am Friday, the primary AI agent for Lucio.
49
+
50
+ # Agents
51
+
52
+ | Agent | Role | When to spawn |
53
+ |---|---|---|
54
+ | FORGE | Engineering | All coding tasks |
55
+ | ARGUS | Research | Feed collection, market signals |
56
+
57
+ # Constraints
58
+
59
+ - Never write code directly — delegate to FORGE
60
+ - Never send external messages without confirmation
61
+ ```
62
+
63
+ ### 3. Sync
64
+
65
+ ```bash
66
+ pluribus sync --tools openclaw
67
+ ```
68
+
69
+ Output:
70
+
71
+ ```
72
+ 🔄 Syncing pluribus.md → openclaw
73
+
74
+ ✅ [openclaw] → AGENTS.md
75
+
76
+ ✅ Sync complete — 1 file(s) written.
77
+ ```
78
+
79
+ ### 4. OpenClaw picks it up
80
+
81
+ On next gateway startup (or `openclaw gateway restart`), OpenClaw reads the updated `AGENTS.md` and your agent reflects the new context.
82
+
83
+ ---
84
+
85
+ ## File Placement
86
+
87
+ By default, `AGENTS.md` is written to the current directory (your OpenClaw workspace root). This is typically:
88
+
89
+ ```
90
+ workspace/
91
+ ├── pluribus.md ← your source of truth
92
+ ├── AGENTS.md ← generated by pluribus sync
93
+ ├── SOUL.md ← tone file (optional, not generated)
94
+ └── TOOLS.md ← tool notes (optional, not generated)
95
+ ```
96
+
97
+ ---
98
+
99
+ ## Dry Run
100
+
101
+ Preview what will be generated without writing:
102
+
103
+ ```bash
104
+ pluribus sync --tools openclaw --dry-run
105
+ ```
106
+
107
+ ---
108
+
109
+ ## Example
110
+
111
+ See [`examples/openclaw/`](../examples/openclaw/) for a full working example:
112
+
113
+ - [`pluribus.md`](../examples/openclaw/pluribus.md) — source context file
114
+ - [`AGENTS.md`](../examples/openclaw/AGENTS.md) — generated output
115
+
116
+ ---
117
+
118
+ ## OpenClaw-Specific Sections
119
+
120
+ When targeting OpenClaw, two sections unlock additional output:
121
+
122
+ ### `# Agents` (sub-agent table)
123
+
124
+ Generates the sub-agent routing table in `AGENTS.md`:
125
+
126
+ ```markdown
127
+ # Agents
128
+
129
+ | Agent | Role | When to spawn |
130
+ |---|---|---|
131
+ | FORGE ⚙️ | Engineering | All coding and system-building |
132
+ | ARGUS 🔍 | Research | Market signals, feed collection |
133
+ ```
134
+
135
+ ### `# Soul`
136
+
137
+ Maps to a behavioral guidance block in `AGENTS.md`. This is the tone section — how the agent communicates, what it avoids, how it handles uncertainty.
138
+
139
+ ---
140
+
141
+ ## Notes
142
+
143
+ - `AGENTS.md` is generated — do not edit it manually. Edit `pluribus.md` and re-sync.
144
+ - If you also use Claude Code, run `pluribus sync --tools openclaw,claude` to update both `AGENTS.md` and `CLAUDE.md` from the same source.
145
+ - The OpenClaw skill is built-in — no configuration needed.
@@ -0,0 +1,91 @@
1
+ # Release checklist
2
+
3
+ This checklist keeps Pluribus releases reproducible and avoids accidentally publishing stale context, missing docs, or a package name that collides with an unrelated project.
4
+
5
+ ## 0. Preconditions
6
+
7
+ - Work from a clean `main` branch tracking `origin/main`.
8
+ - Confirm the package name is available or intentionally chosen:
9
+ - `npm view pluribus-context name version description`
10
+ - `npm view pluribus name version description` — expected to return an unrelated package, so do not publish as `pluribus`.
11
+ - Confirm npm auth only through the npm CLI/session, never by writing tokens into the repo:
12
+ - `npm whoami`
13
+
14
+ ## 1. Version and release notes
15
+
16
+ - Update `package.json` version.
17
+ - Update `CHANGELOG.md` with user-facing changes, migration notes, and verification commands.
18
+ - Confirm README install commands use the package name `pluribus-context` and that the binary remains `pluribus`.
19
+
20
+ ## 2. Local checks
21
+
22
+ Run from the repo root:
23
+
24
+ ```bash
25
+ npm test
26
+ git diff --check
27
+ npm pack --dry-run
28
+ npm publish --dry-run
29
+ ```
30
+
31
+ The dry-run package should include at least:
32
+
33
+ - `README.md`
34
+ - `LICENSE`
35
+ - `CHANGELOG.md`
36
+ - `bin/pluribus.js`
37
+ - `src/`
38
+ - `docs/`
39
+ - `spec/`
40
+ - `examples/`
41
+
42
+ ## 3. Tarball install smoke
43
+
44
+ Before publishing, install the exact tarball that `npm pack` creates into a temporary project and run the CLI as a user would. This catches version drift or missing packaged files that unit tests and dry-runs can miss.
45
+
46
+ ```bash
47
+ npm run release:smoke
48
+ ```
49
+
50
+ The script packs the current checkout, installs that tarball into a temporary project, runs `pluribus --version`, `--help`, `init`, `validate`, `sync --dry-run`, and a real `sync`, then checks that generated output includes the package version from `package.json`. It also removes the temporary project and generated tarball on exit.
51
+
52
+ Expected results:
53
+
54
+ - `pluribus --version` matches `package.json`.
55
+ - `pluribus --help` shows the same version.
56
+ - generated files mention the same Pluribus version.
57
+ - `validate` and `sync --dry-run` work from the installed package, not the repo checkout.
58
+
59
+ ## 4. Publish
60
+
61
+ Only publish after npm auth is active and the dry run is clean:
62
+
63
+ ```bash
64
+ npm publish --access public
65
+ ```
66
+
67
+ Then verify:
68
+
69
+ ```bash
70
+ npm view pluribus-context version dist.tarball
71
+ npx pluribus-context --help
72
+ ```
73
+
74
+ ## 5. GitHub release
75
+
76
+ After npm publish succeeds:
77
+
78
+ - Tag the exact published commit: `vX.Y.Z`.
79
+ - Create a GitHub release using the matching `CHANGELOG.md` section.
80
+ - Link the npm package and the GitHub release from any launch post or reply.
81
+
82
+ ## 6. Post-release monitoring
83
+
84
+ Within the next work block, check:
85
+
86
+ - GitHub Actions for the release commit/tag.
87
+ - GitHub issues/notifications.
88
+ - npm package page metadata.
89
+ - Any X/Reddit/Discord replies mentioning install problems.
90
+
91
+ If install fails or package contents are wrong, do not keep posting. Patch, test, publish a fix version, and document what changed.
@@ -0,0 +1,233 @@
1
+ # Remote Composable Context Imports
2
+
3
+ Status: remote MVP implemented for explicit `github:`/`https://` fetches, lock/cache offline reuse, and optional GitHub auth for private imports. Remaining design work: CI/cache policy ergonomics and deeper structured error context.
4
+
5
+ ## Goals
6
+
7
+ Remote imports should let teams inherit shared context from GitHub or HTTPS without making Pluribus non-deterministic, credential-leaky, or unsafe in CI.
8
+
9
+ The design principle is the same as local imports: explicit context inheritance, expanded before project-local context, with local sections still winning.
10
+
11
+ ## Syntax
12
+
13
+ Keep the existing directive form:
14
+
15
+ ```markdown
16
+ # @import <spec>
17
+ ```
18
+
19
+ Add remote specs:
20
+
21
+ ```markdown
22
+ # @import github:owner/repo/path/to/context.md
23
+ # @import github:owner/repo/path/to/context.md@ref
24
+ # @import https://example.com/context.md
25
+ ```
26
+
27
+ For GitHub imports, `@ref` should support a branch, tag, or commit SHA. Pinned refs are recommended; floating default-branch imports should warn in local/dev use and fail in CI unless explicitly refreshed.
28
+
29
+ If a GitHub path includes `@`, parse the ref from the rightmost `@`.
30
+
31
+ ## Resolution semantics
32
+
33
+ - Preserve the current expansion order: imported content expands before the importing file's local content.
34
+ - Preserve current duplicate-section behavior: later local sections override earlier imported sections.
35
+ - Remote files may contain nested imports, but they must obey the same max depth and safety rules.
36
+ - Relative imports inside a GitHub file resolve relative to that file path in the same repo/ref.
37
+ - Relative imports inside arbitrary HTTPS files are a non-goal for the first remote MVP.
38
+ - Keep the existing max import depth of `5` unless there is strong evidence to change it.
39
+
40
+ ## Auth
41
+
42
+ - Public GitHub and HTTPS imports work without auth.
43
+ - Private GitHub imports may use existing credentials only during `pluribus sync --update-imports`.
44
+ - Credential lookup order: `GH_TOKEN`, then `GITHUB_TOKEN`, then an existing GitHub CLI login via `gh auth token`.
45
+ - Do not support inline tokens, token CLI flags, lockfile/cache auth metadata, or arbitrary custom headers in the MVP.
46
+ - Do not store tokens in `pluribus.lock.json` or `.pluribus/cache/remote/`; the lockfile is safe to commit and the cache is local/regenerable.
47
+ - Error messages must redact credentials, credential-bearing URLs, and known token values.
48
+
49
+ ## Lockfile and cache
50
+
51
+ Add a project lockfile:
52
+
53
+ ```text
54
+ pluribus.lock.json
55
+ ```
56
+
57
+ Each locked remote import should include:
58
+
59
+ - normalized import spec
60
+ - resolved source URL or GitHub API target
61
+ - resolved immutable commit SHA when available
62
+ - SHA-256 content digest
63
+ - byte size
64
+ - fetched timestamp
65
+ - content type
66
+
67
+ Cache downloaded content by digest, for example:
68
+
69
+ ```text
70
+ .pluribus/cache/remote/<sha256>.md
71
+ ```
72
+
73
+ Default `pluribus sync` should prefer the lockfile/cache for deterministic runs. Network refresh should require an explicit flag such as:
74
+
75
+ ```bash
76
+ pluribus sync --update-imports
77
+ ```
78
+
79
+ ## Deterministic CI
80
+
81
+ CI/non-interactive runs should be deterministic by default:
82
+
83
+ - fail if a remote import is unlocked
84
+ - fail if required cached content is missing
85
+ - fail if an import uses a floating GitHub ref without an explicit update mode
86
+ - fail on digest mismatch
87
+ - avoid network unless explicitly enabled
88
+
89
+ Recommended workflow:
90
+
91
+ 1. Developer runs `pluribus sync --update-imports`.
92
+ 2. Pluribus writes or updates `pluribus.lock.json` and cache entries.
93
+ 3. Developer commits the lockfile.
94
+ 4. CI runs `pluribus sync --dry-run` without fetching remote content.
95
+
96
+ ## Network and content limits
97
+
98
+ Defaults for the MVP:
99
+
100
+ - HTTPS only; continue rejecting `http://`
101
+ - 5s per-request timeout
102
+ - 15s total remote resolution budget
103
+ - 256 KiB max per remote file
104
+ - 1 MiB max merged remote content
105
+ - max 3 redirects
106
+ - redirects must stay on `https://`
107
+ - UTF-8 Markdown text only
108
+ - reject binary or non-UTF-8 content
109
+ - strip UTF-8 BOM before parsing, matching local import behavior
110
+
111
+ ## Supply-chain safety
112
+
113
+ - Never execute imported content.
114
+ - Never shell out based on imported content or import specs; the only subprocess is the fixed optional `gh auth token` credential lookup when env tokens are absent.
115
+ - Never support post-processing hooks.
116
+ - Require digest pinning for deterministic use.
117
+ - Fail hard on lockfile digest mismatch.
118
+ - Do not allow remote imports to resolve into local filesystem paths.
119
+ - Treat remote imports as data, not configuration authority.
120
+
121
+ ## Error model
122
+
123
+ Keep the current clear failure style from `resolveImports`, but add structured internal error codes for tests and callers:
124
+
125
+ - `REMOTE_IMPORT_TIMEOUT`
126
+ - `REMOTE_IMPORT_TOO_LARGE`
127
+ - `REMOTE_IMPORT_AUTH_REQUIRED`
128
+ - `REMOTE_IMPORT_LOCK_MISSING`
129
+ - `REMOTE_IMPORT_DIGEST_MISMATCH`
130
+ - `REMOTE_IMPORT_UNSAFE_REDIRECT`
131
+ - `REMOTE_IMPORT_UNSUPPORTED_CONTENT`
132
+
133
+ User-facing errors should include:
134
+
135
+ - import spec
136
+ - importing file
137
+ - import chain
138
+ - concise cause
139
+
140
+ They should never include auth headers, tokens, credential-bearing URLs, or remote body content.
141
+
142
+ ## MVP scope
143
+
144
+ Shipped in the first remote MVP:
145
+
146
+ - `github:owner/repo/path.md[@ref]`
147
+ - direct `https://...` Markdown/text files
148
+ - unauthenticated public imports
149
+ - optional private GitHub imports via `GH_TOKEN`/`GITHUB_TOKEN` or logged-in `gh`
150
+ - explicit `pluribus sync --update-imports` network access
151
+ - lockfile generation/update and cache by SHA-256 digest
152
+ - deterministic offline lock/cache reuse with digest verification
153
+ - timeout, redirect, content-type, UTF-8, per-file size, and merged-size guards
154
+ - credential-bearing URL rejection/redaction
155
+ - nested GitHub imports within the same repo/ref
156
+
157
+ Still pending for the hardening phase:
158
+
159
+ - CI/cache policy ergonomics
160
+ - immutable GitHub commit resolution metadata
161
+ - richer import-chain context in structured errors
162
+
163
+ Non-goals:
164
+
165
+ - `http://`
166
+ - GitLab/Bitbucket shorthand
167
+ - arbitrary request headers
168
+ - remote directory imports or globs
169
+ - executable imports or hooks
170
+ - automatic dependency updates
171
+ - relative imports from arbitrary HTTPS documents
172
+ - silent network access in deterministic CI mode
173
+
174
+ ## Implementation shape
175
+
176
+ Current implementation keeps `resolveImports(sourcePath, options)` as the synchronous local-only entry point and adds `resolveImportsAsync(sourcePath, { allowRemote })` for explicit remote resolution:
177
+
178
+ - local resolver: existing filesystem behavior
179
+ - GitHub resolver: normalize `github:` specs and fetch raw content, optionally with existing GitHub auth
180
+ - HTTPS resolver: fetch Markdown/text with timeout and size guards
181
+ - lock/cache module: read/write `pluribus.lock.json`, verify digest, read/write cached blobs
182
+
183
+ Potential options:
184
+
185
+ ```js
186
+ resolveImports(sourcePath, {
187
+ allowRemote: false,
188
+ updateImports: false,
189
+ offline: false,
190
+ lockfilePath: 'pluribus.lock.json',
191
+ cacheDir: '.pluribus/cache/remote',
192
+ timeoutMs: 5000,
193
+ maxRemoteBytes: 256 * 1024,
194
+ maxMergedRemoteBytes: 1024 * 1024,
195
+ })
196
+ ```
197
+
198
+ CLI flag shipped: `pluribus sync --update-imports` enables remote network fetches. Without that flag, remote directives fail clearly instead of doing silent network access.
199
+
200
+ ## Test checklist
201
+
202
+ - [x] parses `github:` imports with `@ref`
203
+ - [x] rejects `http://`
204
+ - [x] redacts auth in errors
205
+ - [x] enforces timeout
206
+ - [x] enforces per-file and merged-size limits
207
+ - [x] rejects unsafe redirects
208
+ - [x] writes deterministic lockfile entries
209
+ - [x] reads from lock/cache without network in CI/offline mode
210
+ - [x] fails on missing lock entry in CI/offline mode
211
+ - [x] fails on digest mismatch
212
+ - [x] supports nested GitHub imports within the same repo/ref
213
+ - [x] rejects unsupported HTTPS-relative nested imports
214
+ - [x] preserves local override behavior after remote expansion
215
+
216
+ ## Suggested issue #9 checklist
217
+
218
+ ```markdown
219
+ Next phase for #9: harden remote composable context imports.
220
+
221
+ - [x] Specify remote syntax: `github:owner/repo/path.md[@ref]` and `https://...`.
222
+ - [x] Preserve local MVP merge behavior: imports expand before local content; local duplicate sections win.
223
+ - [x] Add `pluribus.lock.json` design with SHA-256 digest, size, fetched timestamp, and content type. Resolved commit metadata remains pending.
224
+ - [x] Add cache design around the explicit `--update-imports` refresh flow.
225
+ - [x] Define CI/offline behavior: fail on unlocked/cache-missing imports unless explicitly updating. Floating ref policy remains pending.
226
+ - [x] Define auth: public unauthenticated fetches plus optional existing `GH_TOKEN`/`GITHUB_TOKEN` or logged-in `gh`; never persist or log secrets.
227
+ - [x] Enforce safety limits: HTTPS only, request timeout, max bytes, redirect limit, UTF-8 Markdown only.
228
+ - [x] Define supply-chain protections: digest verification, hard fail on mismatch, no execution/hooks.
229
+ - [ ] Add structured remote import errors with import-chain context and broader secret redaction.
230
+ - [x] MVP: GitHub + direct HTTPS files only.
231
+ - [x] Non-goals: `http://`, arbitrary headers, GitLab/Bitbucket shorthand, directory/glob imports, HTTPS-relative nested imports.
232
+ - [ ] Add tests for lockfile determinism, digest mismatch, and CI/offline mode.
233
+ ```
@@ -0,0 +1,82 @@
1
+ # Generated by Pluribus 0.1.0 on 2026-03-08 — do not edit manually
2
+ # Source: pluribus.md | Skill: cursor
3
+ # Project: Orbital — Multi-tenant logistics SaaS
4
+
5
+ ## Project Overview
6
+
7
+ You are assisting the **Orbital** engineering team — 5 backend engineers building a multi-tenant SaaS for logistics operations. TypeScript monorepo using NestJS, PostgreSQL (drizzle-orm), and BullMQ. All engineers use shared conventions.
8
+
9
+ ## Tech Stack
10
+
11
+ - TypeScript 5.4 (strict mode) + Node.js 22 LTS
12
+ - NestJS 10 with Fastify adapter
13
+ - PostgreSQL 16 via drizzle-orm (NO raw SQL in application code)
14
+ - BullMQ + Redis 7 for job queues
15
+ - Jest 29 + Supertest for testing
16
+ - pnpm workspaces monorepo
17
+ - ESLint flat config + Prettier (2-space, single quotes, trailing commas)
18
+
19
+ ## Code Conventions
20
+
21
+ - `async/await` only — never `.then()/.catch()`
22
+ - No `any` — use `unknown` with explicit narrowing
23
+ - Named exports only — no default exports, no barrel files
24
+ - File naming: `kebab-case.ts`
25
+ - NestJS pattern: `<feature>.module.ts`, `<feature>.service.ts`, `<feature>.controller.ts`
26
+ - Error handling: always use `AppError` from `packages/core/errors` — never throw plain strings or generic `Error`
27
+ - No circular dependencies (enforced by ESLint)
28
+ - No `@ts-ignore` or `@ts-expect-error`
29
+
30
+ ## Testing
31
+
32
+ - Unit tests for all service methods with side effects
33
+ - Integration tests for all controller endpoints via Supertest
34
+ - Use test factories from `test/factories/` — never construct objects manually in tests
35
+ - Inject mocks via DI — no module-level `jest.mock()`
36
+ - Test naming: `describe('<Unit>', () => { it('should <behavior> when <condition>', ...) })`
37
+
38
+ ## Pull Requests
39
+
40
+ - PRs must be < 400 lines (excluding generated files and migrations)
41
+ - Every PR needs at least one test covering the new behavior
42
+ - Migrations must be reviewed by Ana (`@ana/tech-lead`) before merge
43
+ - No self-merging — minimum 1 approval required
44
+ - Fill the PR description template: What, Why, How, Risk, Test plan
45
+
46
+ ## AI Review Rules
47
+
48
+ When reviewing code:
49
+ - Check for correctness, type safety, and convention violations (not style — Prettier handles that)
50
+ - Flag missing error handling in async paths
51
+ - Flag raw SQL outside drizzle-orm
52
+ - Flag new endpoints without integration tests
53
+ - Flag new endpoints without declared RBAC role
54
+ - Never suggest approving a PR with failing CI
55
+
56
+ ## Constraints (Non-negotiable)
57
+
58
+ - NO raw SQL — all queries through drizzle-orm schema types
59
+ - NO `any` type — use `unknown` and narrow
60
+ - NO secrets in the repository — ever
61
+ - NO new direct dependencies without an ADR in `docs/adr/`
62
+ - NO bypassing RBAC — every endpoint declares its required role
63
+ - NO modifying migration files after they've been applied to staging or production
64
+ - NO `console.log` in production code — use `packages/core/logger`
65
+ - NO singleton mutable state outside of NestJS module providers
66
+
67
+ ## Goals
68
+
69
+ - Correctness over speed — a broken feature costs more than a slow one
70
+ - Consistent codebase across all 5 engineers
71
+ - PR cycle time under 24 hours
72
+ - Zero production incidents from merged code
73
+ - Junior team members learn through Claude's explanations, not just receive generated code
74
+
75
+ ## Anti-patterns to Avoid
76
+
77
+ - Fat controllers: business logic belongs in services
78
+ - Barrel files that re-export everything
79
+ - Data transforms inside schema migration files
80
+ - Returning HTTP 200 for business errors — use proper status codes + `AppError.httpStatus`
81
+ - `console.log` in production paths
82
+ - Optimistic locking without retry loop
@@ -0,0 +1,137 @@
1
+ # Identity
2
+
3
+ We are the **Orbital** engineering team — 5 backend engineers building a multi-tenant SaaS platform for logistics operations.
4
+
5
+ We use Claude Code heavily for code review, pair programming, and greenfield feature work. Claude is treated as a senior team member, not a code autocomplete tool. It attends PR reviews, writes tests, and proposes architectural changes.
6
+
7
+ **Team:**
8
+ - **Ana (tech lead):** owns architecture decisions, API design, and final approval on schema changes
9
+ - **Bruno:** payment integrations, billing engine
10
+ - **Clara:** logistics domain, route optimization
11
+ - **Diego:** infrastructure, observability, CI/CD
12
+ - **Elena:** frontend (React + TypeScript), design system
13
+
14
+ All engineers use Claude Code. Shared conventions apply to all AI-assisted work.
15
+
16
+ # Stack
17
+
18
+ - **Language:** TypeScript 5.4 (strict mode)
19
+ - **Runtime:** Node.js 22 LTS
20
+ - **Framework:** NestJS 10 (REST API) + Fastify adapter
21
+ - **Database:** PostgreSQL 16 via `drizzle-orm`
22
+ - **Message queue:** BullMQ + Redis 7
23
+ - **Testing:** Jest 29 + Supertest; coverage threshold: 80% on all PRs
24
+ - **Linting:** ESLint flat config (team-shared config in `packages/eslint-config`)
25
+ - **Formatting:** Prettier (2-space indent, single quotes, trailing commas)
26
+ - **Package manager:** pnpm + workspaces monorepo
27
+ - **CI/CD:** GitHub Actions — lint, test, type-check on every PR; deploy to staging on merge to `main`
28
+ - **Auth:** JWT (access) + refresh tokens; role-based access control (RBAC)
29
+ - **Monitoring:** OpenTelemetry → Grafana Cloud
30
+ - **No raw SQL in application code** — all queries through drizzle-orm schema types
31
+
32
+ # Conventions
33
+
34
+ ## Code
35
+
36
+ - `async/await` only — no `.then()/.catch()`
37
+ - No class decorators for business logic — NestJS decorators only for DI wiring
38
+ - No `any` — `unknown` with explicit narrowing
39
+ - Error handling: use the shared `AppError` class from `packages/core/errors`; never throw plain strings or generic `Error`
40
+ - Named exports — no default exports, no barrel files unless explicitly discussed
41
+ - File naming: `kebab-case.ts`; NestJS modules follow `<feature>.module.ts`, `<feature>.service.ts` etc.
42
+ - No circular dependencies — enforce with `eslint-plugin-import`
43
+
44
+ ## Testing
45
+
46
+ - Unit tests for all service methods with side effects
47
+ - Integration tests for all controller endpoints using Supertest
48
+ - Test factories in `test/factories/` — never construct objects manually in tests
49
+ - No `jest.mock()` at module level — use dependency injection and pass mocks through constructor
50
+ - Test descriptions: `describe('<Unit>', () => { it('<should do X when Y>', ...) })`
51
+
52
+ ## Pull Requests
53
+
54
+ - PRs must be < 400 lines changed (excluding generated files and migrations)
55
+ - Every PR needs at least one test covering the new behavior
56
+ - PR description: fill the template (What, Why, How, Risk, Test plan)
57
+ - Migrations must be reviewed by Ana before merge — tag `@ana/tech-lead` in the PR
58
+ - No self-merging — at least one approval required
59
+ - Draft PRs are welcome for early feedback; mark ready when CI passes
60
+
61
+ ## AI-Assisted Code Review
62
+
63
+ When Claude is used for PR review:
64
+ - Focus on correctness, type safety, and convention violations — not style (Prettier handles that)
65
+ - Always check for missing error handling in async paths
66
+ - Flag any SQL written outside drizzle-orm types
67
+ - Check that new endpoints have corresponding integration tests
68
+ - Do not approve PRs with failing tests, regardless of context
69
+
70
+ ## Branching
71
+
72
+ - `main` → production
73
+ - `staging` → staging environment (auto-deploy)
74
+ - Feature branches: `feat/<ticket-id>-<short-description>`
75
+ - Hotfix branches: `hotfix/<ticket-id>-<short-description>`
76
+ - Never commit directly to `main` or `staging`
77
+
78
+ # Goals
79
+
80
+ 1. Ship reliable features — correctness over speed; a broken feature costs more than a slow one
81
+ 2. Maintain a consistent codebase across 5 engineers — conventions enforce shared quality, not personal preference
82
+ 3. PR cycle time < 24h — fast reviews unblock the team; slow reviews kill momentum
83
+ 4. Zero production incidents from merged code — staging catches what tests miss
84
+ 5. Knowledge sharing — Claude should help junior team members learn through its explanations, not just generate code
85
+
86
+ # Constraints
87
+
88
+ - Never approve or suggest merging a PR with failing CI
89
+ - Never write raw SQL — always use drizzle-orm schema types and query builder
90
+ - Never commit secrets or environment variables to the repository
91
+ - Do not add direct dependencies without an ADR (Architecture Decision Record) in `docs/adr/`
92
+ - Never bypass RBAC — new endpoints must declare their required role
93
+ - Never modify migration files after they've been applied to staging or production
94
+ - Do not suggest patterns that require `@ts-ignore` or `@ts-expect-error`
95
+ - No singleton state outside of NestJS module providers — no module-level mutable variables
96
+
97
+ # Workflow
98
+
99
+ ## Feature Development
100
+
101
+ 1. Pick ticket from the sprint board
102
+ 2. Create feature branch: `feat/<ticket-id>-<description>`
103
+ 3. Write tests first for complex domain logic (TDD preferred in logistics domain)
104
+ 4. Open PR as Draft early — tag relevant reviewers
105
+ 5. When CI passes → mark PR as Ready for Review
106
+ 6. One approval + all checks green → merge to `main`
107
+ 7. Monitor staging deploy; check observability dashboard
108
+
109
+ ## Code Review Checklist
110
+
111
+ When reviewing (human or AI-assisted):
112
+
113
+ - [ ] Does it have tests covering the new behavior?
114
+ - [ ] Are errors handled correctly (using `AppError`)?
115
+ - [ ] Is the TypeScript type coverage complete (no `any`)?
116
+ - [ ] Are there any raw SQL queries?
117
+ - [ ] Does it respect RBAC for new endpoints?
118
+ - [ ] Is the PR < 400 lines?
119
+ - [ ] Is the PR description filled out?
120
+ - [ ] Are new dependencies justified?
121
+
122
+ ## ADR Process
123
+
124
+ Any new library, architectural pattern, or significant deviation from convention requires an ADR:
125
+ - File: `docs/adr/YYYY-MM-DD-<slug>.md`
126
+ - Sections: Context, Decision, Alternatives considered, Consequences
127
+ - Reviewed asynchronously; Ana signs off on architectural ADRs
128
+
129
+ # Anti-patterns
130
+
131
+ - **Fat controllers:** Business logic belongs in services, not in NestJS controllers
132
+ - **Barrel files that re-export everything:** They make refactoring hard and break tree-shaking
133
+ - **Test isolation via `jest.clearAllMocks()` in `afterEach`:** Use proper DI and scoped mocks instead
134
+ - **Migrations with data transforms:** Schema changes and data migrations are separate PRs
135
+ - **Optimistic locking without retries:** If you use `version` columns for optimistic concurrency, you must handle the retry loop
136
+ - **`console.log` in production code:** Use the shared `logger` from `packages/core/logger`
137
+ - **Returning 200 for business errors:** Use proper HTTP status codes + `AppError` with `httpStatus` field