@codepassion/skills 1.1.1 → 1.4.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.
- package/README.md +6 -1
- package/SKILLS.md +6 -1
- package/bin/c9n-skills.js +28 -3
- package/install.sh +25 -2
- package/package.json +1 -1
- package/skills/c9n/SKILL.md +344 -0
- package/skills/c9n-deliverables/REFERENCE.md +97 -0
- package/skills/c9n-deliverables/SKILL.md +63 -0
- package/skills/c9n-deliverables/scripts/data-dictionary.cjs +49 -0
- package/skills/c9n-deliverables/scripts/export-openapi.cjs +35 -0
- package/skills/c9n-deliverables/scripts/md-to-pdf.mjs +73 -0
- package/skills/c9n-deliverables/scripts/openapi-to-pdf.mjs +78 -0
- package/skills/c9n-deliverables/scripts/snapshot-source.sh +23 -0
- package/skills/c9n-pipeline/SKILL.md +128 -0
- package/skills/c9n-pipeline/templates/Dockerfile.api +49 -0
- package/skills/c9n-pipeline/templates/Dockerfile.service +45 -0
- package/skills/c9n-pipeline/templates/Dockerfile.web +50 -0
- package/skills/c9n-pipeline/templates/dockerignore +18 -0
- package/skills/c9n-pipeline/templates/workflows/_build-job.partial.yml +13 -0
- package/skills/c9n-pipeline/templates/workflows/_deploy-job.partial.yml +17 -0
- package/skills/c9n-pipeline/templates/workflows/_migration-check.partial.yml +16 -0
- package/skills/c9n-pipeline/templates/workflows/ci.yml +38 -0
- package/skills/c9n-pipeline/templates/workflows/deployment.yml +21 -0
- package/skills/c9n-sentry/REFERENCE.md +172 -0
- package/skills/c9n-sentry/SKILL.md +53 -0
- package/skills/c9n-spec/SKILL.md +92 -0
- package/skills/c9n-spec/templates/.github/pull_request_template.md +29 -0
- package/skills/c9n-spec/templates/AGENTS.md +179 -0
- package/skills/c9n-spec/templates/CLAUDE.md +6 -0
- package/skills/c9n-spec/templates/CONTEXT.md +53 -0
- package/skills/c9n-spec/templates/DESIGN.md +73 -0
- package/skills/c9n-spec/templates/docs/SRS.md +37 -0
- package/skills/c9n-spec/templates/docs/adr/0001-spec-driven-iso29110-docs.md +44 -0
- package/skills/c9n-spec/templates/docs/adr/_TEMPLATE.md +26 -0
- package/skills/c9n-spec/templates/docs/agents/domain.md +43 -0
- package/skills/c9n-spec/templates/docs/agents/issue-tracker.md +22 -0
- package/skills/c9n-spec/templates/docs/agents/triage-labels.md +27 -0
- package/skills/c9n-spec/templates/docs/architecture.md +50 -0
- package/skills/c9n-spec/templates/docs/features/_TEMPLATE.md +34 -0
- package/skills/c9n-spec/templates/docs/test-plan.md +30 -0
- package/skills/c9n-spec/templates/docs/traceability.md +27 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
name: Deployment
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
workflow_dispatch:
|
|
5
|
+
push:
|
|
6
|
+
tags:
|
|
7
|
+
- 'v*.*.*'
|
|
8
|
+
release:
|
|
9
|
+
types: [published]
|
|
10
|
+
|
|
11
|
+
# Assembled by c9n-pipeline from the partials below. The triggers and the
|
|
12
|
+
# event->environment mapping follow c9n-semver-deployment (single source of
|
|
13
|
+
# truth): tag push -> Alpha, prerelease -> Beta, release -> Production.
|
|
14
|
+
#
|
|
15
|
+
# Stamp one BUILD job per app (Alpha only — built once, redeployed by base tag),
|
|
16
|
+
# then one DEPLOY job per app per environment the project actually has. Prune
|
|
17
|
+
# environments the project does not use.
|
|
18
|
+
|
|
19
|
+
jobs:
|
|
20
|
+
{{BUILD_JOBS}}
|
|
21
|
+
{{DEPLOY_JOBS}}
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
# Sentry Bun+Elysia+Next.js — Reference
|
|
2
|
+
|
|
3
|
+
## package.json (`packages/sentry/`)
|
|
4
|
+
|
|
5
|
+
```json
|
|
6
|
+
{
|
|
7
|
+
"name": "@repo/sentry",
|
|
8
|
+
"type": "module",
|
|
9
|
+
"exports": {
|
|
10
|
+
"./bun": { "import": "./src/bun.ts" },
|
|
11
|
+
"./client": { "import": "./src/client.ts" },
|
|
12
|
+
"./server": { "import": "./src/server.ts" },
|
|
13
|
+
"./edge": { "import": "./src/edge.ts" },
|
|
14
|
+
"./pdpa": { "import": "./src/pdpa.ts" }
|
|
15
|
+
},
|
|
16
|
+
"dependencies": {
|
|
17
|
+
"@sentry/elysia": "^10",
|
|
18
|
+
"@sentry/nextjs": "^10"
|
|
19
|
+
},
|
|
20
|
+
"peerDependencies": {
|
|
21
|
+
"elysia": "*",
|
|
22
|
+
"next-runtime-env": "*"
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## PDPA scrubber
|
|
28
|
+
|
|
29
|
+
```ts
|
|
30
|
+
// src/pdpa.ts
|
|
31
|
+
import type { Event } from "@sentry/core"
|
|
32
|
+
|
|
33
|
+
const PII_KEY = /phone|otp|lat|lng|latitude|longitude|member_?id|token|secret|password/i
|
|
34
|
+
const DROP_HEADERS = ["authorization", "cookie", "set-cookie"]
|
|
35
|
+
|
|
36
|
+
function redactKeys(obj: unknown): unknown {
|
|
37
|
+
if (!obj || typeof obj !== "object") return obj
|
|
38
|
+
if (Array.isArray(obj)) return obj.map(redactKeys)
|
|
39
|
+
return Object.fromEntries(
|
|
40
|
+
Object.entries(obj as Record<string, unknown>).map(([k, v]) => [
|
|
41
|
+
k,
|
|
42
|
+
PII_KEY.test(k) ? "[redacted]" : redactKeys(v)
|
|
43
|
+
])
|
|
44
|
+
)
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export function pdpaBeforeSend(event: Event): Event | null {
|
|
48
|
+
if (event.request) {
|
|
49
|
+
event.request.data = undefined
|
|
50
|
+
event.request.query_string = undefined
|
|
51
|
+
event.request.cookies = undefined
|
|
52
|
+
if (event.request.headers) {
|
|
53
|
+
DROP_HEADERS.forEach(h => { delete (event.request!.headers as Record<string, string>)[h] })
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
if (event.extra) event.extra = redactKeys(event.extra) as Record<string, unknown>
|
|
57
|
+
return event
|
|
58
|
+
}
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## src/bun.ts
|
|
62
|
+
|
|
63
|
+
```ts
|
|
64
|
+
export * from "@sentry/elysia"
|
|
65
|
+
import * as Sentry from "@sentry/elysia"
|
|
66
|
+
import { pdpaBeforeSend } from "./pdpa.js"
|
|
67
|
+
|
|
68
|
+
export function initBun(): void {
|
|
69
|
+
const dsn = process.env.SENTRY_DSN
|
|
70
|
+
if (!dsn) return
|
|
71
|
+
Sentry.init({
|
|
72
|
+
dsn,
|
|
73
|
+
environment: process.env.ENVIRONMENT || "development",
|
|
74
|
+
tracesSampleRate: 0.1,
|
|
75
|
+
sendDefaultPii: false,
|
|
76
|
+
beforeSend: pdpaBeforeSend,
|
|
77
|
+
initialScope: { tags: { app: "api" } }
|
|
78
|
+
})
|
|
79
|
+
}
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
## src/client.ts (runtime env — ADR 0005)
|
|
83
|
+
|
|
84
|
+
```ts
|
|
85
|
+
export * from "@sentry/nextjs"
|
|
86
|
+
import * as Sentry from "@sentry/nextjs"
|
|
87
|
+
import { env } from "next-runtime-env" // ← NOT process.env
|
|
88
|
+
import { pdpaBeforeSend } from "./pdpa.js"
|
|
89
|
+
|
|
90
|
+
export function initClient(): void {
|
|
91
|
+
const dsn = env("NEXT_PUBLIC_SENTRY_DSN") // runtime, not build-time
|
|
92
|
+
if (!dsn) return
|
|
93
|
+
Sentry.init({
|
|
94
|
+
dsn,
|
|
95
|
+
environment: env("NEXT_PUBLIC_ENVIRONMENT") || "development",
|
|
96
|
+
tracesSampleRate: 0.1,
|
|
97
|
+
sendDefaultPii: false,
|
|
98
|
+
beforeSend: pdpaBeforeSend,
|
|
99
|
+
tags: { app: "web" }
|
|
100
|
+
})
|
|
101
|
+
}
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
## apps/api/src/index.ts wiring
|
|
105
|
+
|
|
106
|
+
```ts
|
|
107
|
+
import "./lib/sentry.js" // ← must be FIRST import
|
|
108
|
+
// ... other imports ...
|
|
109
|
+
import { withElysia } from "@repo/sentry/bun"
|
|
110
|
+
|
|
111
|
+
const app = withElysia(new Elysia()) // wraps for auto error capture
|
|
112
|
+
.use(...)
|
|
113
|
+
// remove any console.error in onError — withElysia handles it
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
## apps/web/next.config.js
|
|
117
|
+
|
|
118
|
+
```js
|
|
119
|
+
import { withSentryConfig } from "@repo/sentry/client"
|
|
120
|
+
const nextConfig = { transpilePackages: ["@repo/sentry"], ... }
|
|
121
|
+
export default withSentryConfig(nextConfig, {
|
|
122
|
+
silent: true,
|
|
123
|
+
hideSourceMaps: true,
|
|
124
|
+
tunnelRoute: "/monitoring" // guards against in-app-browser/CSP drops
|
|
125
|
+
})
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
## apps/web/instrumentation.ts
|
|
129
|
+
|
|
130
|
+
```ts
|
|
131
|
+
export async function register() {
|
|
132
|
+
if (process.env.NEXT_RUNTIME === "nodejs") {
|
|
133
|
+
await import("./sentry.server.config")
|
|
134
|
+
}
|
|
135
|
+
if (process.env.NEXT_RUNTIME === "edge") {
|
|
136
|
+
await import("./sentry.edge.config")
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
export { captureRequestError as onRequestError } from "@sentry/nextjs"
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
## apps/web/instrumentation-client.ts
|
|
143
|
+
|
|
144
|
+
```ts
|
|
145
|
+
import { initClient, captureRouterTransitionStart } from "@repo/sentry/client"
|
|
146
|
+
initClient()
|
|
147
|
+
export const onRouterTransitionStart = captureRouterTransitionStart
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
## turbo.json globalEnv additions
|
|
151
|
+
|
|
152
|
+
```json
|
|
153
|
+
"globalEnv": ["SENTRY_DSN", "ENVIRONMENT"]
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
Do NOT add `NEXT_PUBLIC_*` to globalEnv — they are runtime-injected via `PublicEnvScript`.
|
|
157
|
+
|
|
158
|
+
## Sentry project setup
|
|
159
|
+
|
|
160
|
+
1. sentry.io → **Create Project** → platform: **Next.js** → name: `<project>`
|
|
161
|
+
2. Copy DSN from **Project Settings → Client Keys (DSN)**
|
|
162
|
+
3. Same DSN in both Coolify services (one project, two env var names)
|
|
163
|
+
4. Redeploy both services after setting vars
|
|
164
|
+
|
|
165
|
+
## ADR checklist (write ADR when adopting)
|
|
166
|
+
|
|
167
|
+
- Why `@sentry/elysia` not `@sentry/bun` + custom plugin
|
|
168
|
+
- Why `@sentry/elysia` not `@sentry/node` (compiled binary landmine)
|
|
169
|
+
- Client env split reasoning (ADR 0005 or equivalent)
|
|
170
|
+
- PDPA/privacy scrubbing rationale
|
|
171
|
+
- Alpha-state risk acceptance if applicable
|
|
172
|
+
- Generic env naming rationale
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: c9n-sentry
|
|
3
|
+
description: Scaffold Sentry error tracking in a Bun + ElysiaJS + Next.js monorepo via a shared @repo/sentry package. Use when user wants to add Sentry, set up error tracking, or wire error monitoring to an ElysiaJS API and/or Next.js frontend in a Turborepo monorepo.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Sentry — Bun + Elysia + Next.js
|
|
7
|
+
|
|
8
|
+
## Three landmines (check first)
|
|
9
|
+
|
|
10
|
+
1. **`@sentry/node` under `bun --compile` fails silently** — valid DSN, zero events. Use `@sentry/elysia` (built on `@sentry/bun`). Never let `@sentry/node` load on the API.
|
|
11
|
+
2. **Runtime public env** — if the project uses `next-runtime-env` (ADR 0005 pattern), the browser DSN MUST use `env("NEXT_PUBLIC_SENTRY_DSN")` not `process.env`. Server/edge/api use `process.env`. Wrong = undefined DSN in prod = dead Sentry.
|
|
12
|
+
3. **PDPA / PII** — add `beforeSend` scrubber + `sendDefaultPii: false`. Strip request body/query/cookies, drop auth headers, recursively redact PII keys. See [REFERENCE.md](REFERENCE.md#pdpa-scrubber).
|
|
13
|
+
|
|
14
|
+
## Quick start
|
|
15
|
+
|
|
16
|
+
```
|
|
17
|
+
packages/sentry/ ← @repo/sentry (shared)
|
|
18
|
+
src/pdpa.ts ← beforeSend scrubber (shared by all inits)
|
|
19
|
+
src/bun.ts ← initBun() for apps/api
|
|
20
|
+
src/client.ts ← initClient() for browser (uses env() not process.env)
|
|
21
|
+
src/server.ts ← initServer() for Next.js server runtime
|
|
22
|
+
src/edge.ts ← initEdge() for Next.js edge runtime
|
|
23
|
+
package.json ← exports map: ./bun ./client ./server ./edge ./pdpa
|
|
24
|
+
apps/api/src/lib/sentry.ts ← import { initBun } from "@repo/sentry/bun"; initBun()
|
|
25
|
+
apps/api/src/index.ts ← first import: "./lib/sentry.js", then withElysia(new Elysia())
|
|
26
|
+
apps/web/instrumentation.ts ← register() → dynamic import server/edge config
|
|
27
|
+
apps/web/instrumentation-client.ts ← initClient()
|
|
28
|
+
apps/web/sentry.server.config.ts / sentry.edge.config.ts
|
|
29
|
+
apps/web/next.config.js ← withSentryConfig + transpilePackages: ["@repo/sentry"]
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## Env vars
|
|
33
|
+
|
|
34
|
+
| Service | Key | Read by |
|
|
35
|
+
|---------|-----|---------|
|
|
36
|
+
| API (Coolify) | `SENTRY_DSN`, `ENVIRONMENT` | `process.env` |
|
|
37
|
+
| Web (Coolify) | `NEXT_PUBLIC_SENTRY_DSN`, `NEXT_PUBLIC_ENVIRONMENT` | `env()` from next-runtime-env (client) / `process.env` (server/edge) |
|
|
38
|
+
|
|
39
|
+
One Sentry project, same DSN in both vars. Add `initialScope: { tags: { app: "api" } }` to `initBun()` so api vs web events are distinguishable in the shared project.
|
|
40
|
+
|
|
41
|
+
## Verification checklist
|
|
42
|
+
|
|
43
|
+
- [ ] `bun install --frozen-lockfile` clean
|
|
44
|
+
- [ ] `bun run check-types` (api + web) clean
|
|
45
|
+
- [ ] `bun run build --compile` on API — confirms `@sentry/node` never loaded (the landmine test)
|
|
46
|
+
- [ ] Web Sentry bundle builds green
|
|
47
|
+
- [ ] After deploy: `window.__ENV.NEXT_PUBLIC_SENTRY_DSN` populated in devtools (runtime env proof)
|
|
48
|
+
- [ ] Trigger a test error → event appears in Sentry tagged correct environment
|
|
49
|
+
- [ ] Open event payload — no phone/otp/lat/lng/member_id (PDPA proof)
|
|
50
|
+
|
|
51
|
+
## Reference
|
|
52
|
+
|
|
53
|
+
See [REFERENCE.md](REFERENCE.md) for full file contents, PDPA scrubber code, and `turbo.json` config.
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: c9n-spec
|
|
3
|
+
description: Scaffold the C9N spec-driven, ISO/IEC 29110-aligned agentic documentation system INTO a repo — AGENTS.md (protocol + stack) with a CLAUDE.md bridge, CONTEXT.md glossary, DESIGN.md, the docs/ tree (SRS, architecture, traceability, test-plan, ADRs, feature stubs, agent docs), and the PR-template merge gate. Use when bootstrapping a new C9N project, "init docs", "set up the spec-driven docs", "add the agentic workflow files", or porting the ddg-jewelry doc system to another repo. Complements c9n-deliverables (that generates docs OUT of a codebase; this seeds the doc system INTO one).
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
Bootstraps the Code Passion (C9N) spec-driven development doc system into a target repo. Drops
|
|
7
|
+
a self-contained, agent-readable documentation skeleton so a fresh project starts with the same
|
|
8
|
+
approval gates, traceability, and glossary discipline as the reference implementation
|
|
9
|
+
(ddg-jewelry). Fully generic — adapt the placeholders to whatever stack the project uses.
|
|
10
|
+
|
|
11
|
+
Bundled `templates/` are the source skeleton. **Copy them, then substitute tokens** — never edit
|
|
12
|
+
the templates in place for a specific project.
|
|
13
|
+
|
|
14
|
+
## What gets scaffolded
|
|
15
|
+
|
|
16
|
+
| File | Role |
|
|
17
|
+
|------|------|
|
|
18
|
+
| `AGENTS.md` | **Canonical** agent context: the full ISO/IEC 29110 spec-driven protocol (inlined, so the repo is self-contained) + C9N stack + module patterns. References the sibling `c9n-*` convention skills rather than copying them. |
|
|
19
|
+
| `CLAUDE.md` | Bridge that `@AGENTS.md`-imports the canonical file (so Claude Code's memory auto-loads the protocol; other tools read AGENTS.md directly). |
|
|
20
|
+
| `CONTEXT.md` | Ubiquitous-language glossary skeleton (no implementation detail). |
|
|
21
|
+
| `DESIGN.md` | Visual design-system rules — **only if the repo has a frontend.** |
|
|
22
|
+
| `docs/SRS.md` | Requirements master registry (feature short-codes + system NFRs). |
|
|
23
|
+
| `docs/architecture.md` | Software-design as-is map. |
|
|
24
|
+
| `docs/traceability.md` | Requirement → design → test master index. |
|
|
25
|
+
| `docs/test-plan.md` | Master test strategy. |
|
|
26
|
+
| `docs/adr/0001-spec-driven-iso29110-docs.md` | Seed ADR: why this doc system exists. |
|
|
27
|
+
| `docs/adr/_TEMPLATE.md` | ADR format for future decisions. |
|
|
28
|
+
| `docs/features/_TEMPLATE.md` | Per-feature deep-doc stub (Requirements · Design · Test Plan · Test Cases · Traceability). |
|
|
29
|
+
| `docs/agents/{issue-tracker,triage-labels,domain}.md` | Agent-process docs (GitHub `gh`, triage vocab, domain-doc consumption). |
|
|
30
|
+
| `.github/pull_request_template.md` | The Definition-of-Done merge gate. |
|
|
31
|
+
|
|
32
|
+
## Workflow
|
|
33
|
+
|
|
34
|
+
Run each step in order; this is a table of contents — the rules are below.
|
|
35
|
+
|
|
36
|
+
1. **Detect repo shape.** Read the target's root `package.json`/workspaces. Decide:
|
|
37
|
+
monorepo vs single app; **frontend present?** (`apps/web`, or `next`/`astro`/`vite`/`react`
|
|
38
|
+
in any `package.json`) → include `DESIGN.md`. **Backend/API present?** → keep the API
|
|
39
|
+
module-patterns section in AGENTS.md; otherwise tell the user it's deletable.
|
|
40
|
+
2. **No-clobber.** For every target path, **skip if it already exists** — never overwrite. Collect
|
|
41
|
+
skipped paths for the final report. (Re-running the skill must be safe and idempotent.)
|
|
42
|
+
3. **Copy templates** into the target repo, substituting tokens (below). Skip `DESIGN.md` if no
|
|
43
|
+
frontend. Skip the API section guidance if no backend.
|
|
44
|
+
4. **Optional scan — OFF by default.** Only if the user **explicitly** asks to seed from code
|
|
45
|
+
("scan the codebase", "seed the glossary", "reverse-document"): read the codebase and fill
|
|
46
|
+
- `CONTEXT.md` — first real glossary terms (actors, core entities) from the domain;
|
|
47
|
+
- `docs/architecture.md` — the actual module map + data-model relationships;
|
|
48
|
+
- `docs/features/` — one as-built stub per shipped module (low-confidence, no test cases),
|
|
49
|
+
and register each in `docs/SRS.md` with a fresh short-code.
|
|
50
|
+
Without this request, leave the placeholders untouched.
|
|
51
|
+
5. **Report.** Print created vs skipped files, then next steps: pick the first feature, write its
|
|
52
|
+
SRS section (Gate 1), get sign-off, then Design + Test Plan (Gate 2) — no production code
|
|
53
|
+
before Gate 2.
|
|
54
|
+
|
|
55
|
+
## Token substitution
|
|
56
|
+
|
|
57
|
+
When copying, replace these placeholders:
|
|
58
|
+
|
|
59
|
+
| Token | Source |
|
|
60
|
+
|-------|--------|
|
|
61
|
+
| `{{PROJECT_NAME}}` | Target root dir name, or `package.json` `name` (humanized). |
|
|
62
|
+
| `{{YEAR}}` / `{{DATE}}` | Current year / ISO date (for the seed ADR). |
|
|
63
|
+
| `{{DECIDER}}` | Ask, or default to the repo owner. |
|
|
64
|
+
| Stack rows in AGENTS.md | Keep C9N defaults; trim rows the detected stack doesn't use. |
|
|
65
|
+
|
|
66
|
+
## Conventions (referenced, not copied)
|
|
67
|
+
|
|
68
|
+
The scaffolded `AGENTS.md` points at the sibling C9N skills for engineering conventions — it does
|
|
69
|
+
**not** inline them, so they have a single source of truth:
|
|
70
|
+
|
|
71
|
+
- Commits → `c9n-commit-messages` · Branching → `c9n-git-branching` · PRs → `c9n-pull-requests`
|
|
72
|
+
- Clean code → `c9n-clean-code-typescript` · Lint/types → `c9n-typescript-eslint`
|
|
73
|
+
- Formatting → `c9n-code-formatting` · Review → `c9n-code-review`
|
|
74
|
+
|
|
75
|
+
For C9N-internal repos every dev has these installed, so the references always resolve. If you
|
|
76
|
+
scaffold into a repo where they may not be installed, tell the user to
|
|
77
|
+
`npx @codepassion/skills install claude`.
|
|
78
|
+
|
|
79
|
+
## Gotchas
|
|
80
|
+
|
|
81
|
+
- **Combined install mode does not carry `templates/`.** `install.sh combined` copies only the
|
|
82
|
+
generated `skills/c9n` SKILL.md body; the bundled templates are absent. Install `c9n-spec` via
|
|
83
|
+
`install.sh claude` (or `project`/`codex`) so the templates come along. Same limitation as
|
|
84
|
+
`c9n-deliverables`' scripts.
|
|
85
|
+
- **AGENTS.md vs CLAUDE.md.** AGENTS.md is the real file. CLAUDE.md exists only so Claude Code's
|
|
86
|
+
memory auto-load reaches the protocol — it does so via the **`@AGENTS.md` import** (Claude Code's
|
|
87
|
+
memory-import syntax), not a markdown link (a link is inert and pulls nothing into context). Don't
|
|
88
|
+
duplicate content into CLAUDE.md. If a target tool doesn't support `@`-imports, it reads AGENTS.md
|
|
89
|
+
directly anyway, so nothing is lost.
|
|
90
|
+
- **Don't grade the stubs.** If you run the optional scan, as-built stubs describe *current*
|
|
91
|
+
behavior at low confidence with **no** test cases — deepen on touch, per the protocol. Don't
|
|
92
|
+
invent acceptance criteria for code you only read.
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
<!-- See AGENTS.md › Spec-Driven Development Protocol for the workflow and behavior-change rule. -->
|
|
2
|
+
|
|
3
|
+
## What & why
|
|
4
|
+
|
|
5
|
+
<!-- Ticket ID + one-line summary. Link the approved SRS/Design if this is a feature. -->
|
|
6
|
+
|
|
7
|
+
## Spec-driven gate
|
|
8
|
+
|
|
9
|
+
- [ ] For a **new feature**: SRS approved (Gate 1) and Design + Test Plan approved (Gate 2) **before** this code.
|
|
10
|
+
- [ ] This PR links the relevant `docs/features/<name>.md` (or master SRS section).
|
|
11
|
+
|
|
12
|
+
## Behavior-change check
|
|
13
|
+
|
|
14
|
+
> Does this change **observable behavior, a requirement, an interface, or a test outcome**?
|
|
15
|
+
|
|
16
|
+
- [ ] **No** — refactor / rename / dep-bump / typo / format. Doc updates N/A. _(skip the next section)_
|
|
17
|
+
- [ ] **Yes** — complete the doc-update checklist below.
|
|
18
|
+
|
|
19
|
+
### Doc updates (only if "Yes" above)
|
|
20
|
+
|
|
21
|
+
- [ ] SRS updated (new/changed requirement) — `docs/SRS.md` or `docs/features/<name>.md`
|
|
22
|
+
- [ ] Design updated (behavior/architecture) — `docs/architecture.md` or feature `## Design` (+ ADR if hard-to-reverse)
|
|
23
|
+
- [ ] Test cases updated/added (incl. regression for bug fixes)
|
|
24
|
+
- [ ] Traceability updated — `docs/traceability.md` or feature `## Traceability`
|
|
25
|
+
|
|
26
|
+
## Verification
|
|
27
|
+
|
|
28
|
+
- [ ] Tests pass locally
|
|
29
|
+
- [ ] Lint/format clean (no semicolons, double quotes)
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
# AGENTS.md
|
|
2
|
+
|
|
3
|
+
AI-assisted development context for the **{{PROJECT_NAME}}** repo.
|
|
4
|
+
|
|
5
|
+
> This is the canonical agent file. `CLAUDE.md` is a one-line pointer to it. Codex, Cursor,
|
|
6
|
+
> OpenCode, and Claude Code all read this file.
|
|
7
|
+
|
|
8
|
+
## Spec-Driven Development Protocol (read first)
|
|
9
|
+
|
|
10
|
+
This repo follows a spec-driven, ISO/IEC 29110-aligned documentation system (Software
|
|
11
|
+
Implementation work products). This section is the **canonical source** — agents MUST follow it.
|
|
12
|
+
The repo is authoritative.
|
|
13
|
+
|
|
14
|
+
### Doc map
|
|
15
|
+
|
|
16
|
+
| File | ISO 29110 work product | Holds |
|
|
17
|
+
| ---------------------------------------------- | -------------------------- | ---------------------------------------------------------------------------- |
|
|
18
|
+
| `AGENTS.md` / `CLAUDE.md` | — (agent protocol) | This protocol + stack + patterns |
|
|
19
|
+
| [`CONTEXT.md`](CONTEXT.md) | Domain glossary | Ubiquitous language only — no implementation |
|
|
20
|
+
| [`DESIGN.md`](DESIGN.md) | — (visual design system) | UI design language: color/type/component **intent & rules** (values in code) |
|
|
21
|
+
| [`docs/SRS.md`](docs/SRS.md) | Requirements Specification | Master registry: features + requirement IDs + system NFRs |
|
|
22
|
+
| [`docs/architecture.md`](docs/architecture.md) | Software Design | System map, module boundaries, data model, integrations |
|
|
23
|
+
| [`docs/traceability.md`](docs/traceability.md) | Traceability Record | Master index: requirement → design → test |
|
|
24
|
+
| [`docs/test-plan.md`](docs/test-plan.md) | Test Cases & Procedures | Master test strategy |
|
|
25
|
+
| `docs/adr/NNNN-*.md` | Architecture Decisions | One ADR per hard-to-reverse decision |
|
|
26
|
+
| `docs/features/<name>.md` | Per-feature deep doc | Sections: Requirements · Design · Test Plan · Test Cases · Traceability |
|
|
27
|
+
|
|
28
|
+
**Master-then-split (two levels):** a feature starts as a section in the master files →
|
|
29
|
+
graduates to its own `docs/features/<name>.md` when it outgrows the section → graduates to a
|
|
30
|
+
folder `docs/features/<name>/` (one file per section) only when a _section_ outgrows one file.
|
|
31
|
+
Default to the smallest form that fits.
|
|
32
|
+
|
|
33
|
+
**Feature ID:** every functional feature has a unique **short-code** — a 2–4 letter
|
|
34
|
+
human-readable mnemonic (`PAY`, `INV`, `AUTH`). The short-code _is_ the feature ID; it prefixes
|
|
35
|
+
all the feature's child IDs. Short-codes are **append-only** — pick a fresh, unused one for a new
|
|
36
|
+
feature (check `docs/SRS.md`), and never reuse one even after a feature is removed. `docs/SRS.md`
|
|
37
|
+
is the authoritative registry.
|
|
38
|
+
|
|
39
|
+
**Child IDs:** feature-prefixed, append-only — `PAY-REQ-001` (requirement), `PAY-TC-001` (test
|
|
40
|
+
case). Never reuse or renumber.
|
|
41
|
+
|
|
42
|
+
**"Design" disambiguation:** `DESIGN.md` = **visual** design (UI). The `## Design` sections in
|
|
43
|
+
`docs/features/*.md` and `docs/architecture.md` = **software** design (engineering). Different
|
|
44
|
+
layers — don't conflate them.
|
|
45
|
+
|
|
46
|
+
### Approval gates (no code before blueprint)
|
|
47
|
+
|
|
48
|
+
A new feature passes three sequential gates, each needing the owner's sign-off:
|
|
49
|
+
|
|
50
|
+
1. **SRS approved** — the _what_ (requirements + acceptance criteria).
|
|
51
|
+
2. **Design + Test Plan approved** — the _how_ + how we'll prove it.
|
|
52
|
+
3. **Code** — only now. The PR links the approved docs.
|
|
53
|
+
|
|
54
|
+
### Definition of Ready (before touching code)
|
|
55
|
+
|
|
56
|
+
1. Read [`CONTEXT.md`](CONTEXT.md) (glossary) and [`docs/architecture.md`](docs/architecture.md) (system map).
|
|
57
|
+
2. Identify the feature; read its `docs/features/<name>.md` (or its master SRS section).
|
|
58
|
+
3. For **UI work**, also read [`DESIGN.md`](DESIGN.md) first.
|
|
59
|
+
4. For a **new feature**, Gate 1 **and** Gate 2 must already be approved. **No production code
|
|
60
|
+
before Gate 2 sign-off.**
|
|
61
|
+
|
|
62
|
+
### Definition of Done (before opening the PR)
|
|
63
|
+
|
|
64
|
+
Apply the **behavior-change rule**: update docs **iff** the change alters observable behavior, a
|
|
65
|
+
requirement, an interface, or a test outcome.
|
|
66
|
+
|
|
67
|
+
| Change kind | Doc action |
|
|
68
|
+
| -------------------------------------------- | -------------------------------------------------------------- |
|
|
69
|
+
| New/changed requirement | Update SRS + traceability + test cases |
|
|
70
|
+
| Behavior/architecture change | Update design (+ ADR if hard-to-reverse) + affected test cases |
|
|
71
|
+
| Bug fix toward spec | Add a regression test case |
|
|
72
|
+
| Visual _intent_ change | Update `DESIGN.md` |
|
|
73
|
+
| Token _value_ change in Tailwind/CSS | No doc update (`DESIGN.md` references values, never copies) |
|
|
74
|
+
| Refactor / rename / dep-bump / typo / format | No doc update (code-only PR) |
|
|
75
|
+
|
|
76
|
+
The `.github/pull_request_template.md` checklist is the merge gate.
|
|
77
|
+
|
|
78
|
+
### Reverse-documentation policy
|
|
79
|
+
|
|
80
|
+
Existing shipped modules each get an **as-built stub** in `docs/features/` (reverse-documented
|
|
81
|
+
from code, **not grilled** — requirements describe current behavior at low confidence, no test
|
|
82
|
+
cases). When a module is next touched, **deepen its stub** to the full chain (acceptance criteria
|
|
83
|
+
+ Test Cases + Traceability) for the part you change — don't try to deepen the whole stub at once.
|
|
84
|
+
New features still get the full chain up front via the gates.
|
|
85
|
+
|
|
86
|
+
## C9N engineering conventions (referenced, not duplicated)
|
|
87
|
+
|
|
88
|
+
These follow the Code Passion skill family — the single source of truth. Don't restate the rules
|
|
89
|
+
here; consult the skill:
|
|
90
|
+
|
|
91
|
+
| Topic | Skill |
|
|
92
|
+
| ---------------- | --------------------------- |
|
|
93
|
+
| Commit messages | `c9n-commit-messages` |
|
|
94
|
+
| Git branching | `c9n-git-branching` |
|
|
95
|
+
| Pull requests | `c9n-pull-requests` |
|
|
96
|
+
| Code review | `c9n-code-review` |
|
|
97
|
+
| Clean Code (TS) | `c9n-clean-code-typescript` |
|
|
98
|
+
| ESLint / types | `c9n-typescript-eslint` |
|
|
99
|
+
| Formatting | `c9n-code-formatting` |
|
|
100
|
+
| SemVer / deploy | `c9n-semver-deployment` |
|
|
101
|
+
|
|
102
|
+
Install: `npx @codepassion/skills install claude`.
|
|
103
|
+
|
|
104
|
+
## Tech Stack
|
|
105
|
+
|
|
106
|
+
C9N defaults — trim rows this project doesn't use.
|
|
107
|
+
|
|
108
|
+
| Layer | Technology |
|
|
109
|
+
| ---------- | ------------------------------------------------ |
|
|
110
|
+
| Runtime | Bun |
|
|
111
|
+
| API | ElysiaJS |
|
|
112
|
+
| Frontend | Next.js / React (or Astro) |
|
|
113
|
+
| Database | PostgreSQL via Drizzle ORM |
|
|
114
|
+
| Storage | Supabase Storage + Auth |
|
|
115
|
+
| Build | Turborepo (monorepo) |
|
|
116
|
+
| Validation | Zod (shared with Drizzle via drizzle-zod) |
|
|
117
|
+
| Lint | ESLint + Prettier (no semicolons, double quotes) |
|
|
118
|
+
| Commits | Conventional Commits (commitlint + Husky) |
|
|
119
|
+
|
|
120
|
+
## Project Structure
|
|
121
|
+
|
|
122
|
+
<!-- Describe the actual repo layout here. C9N monorepo default: -->
|
|
123
|
+
|
|
124
|
+
```text
|
|
125
|
+
{{PROJECT_NAME}}/
|
|
126
|
+
apps/
|
|
127
|
+
api/ -- backend (if any)
|
|
128
|
+
web/ -- frontend (if any)
|
|
129
|
+
packages/
|
|
130
|
+
database/ -- Drizzle ORM schemas + client
|
|
131
|
+
...
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
<!-- =========================================================================
|
|
135
|
+
API MODULE PATTERNS — delete this whole section for a web-only repo.
|
|
136
|
+
========================================================================= -->
|
|
137
|
+
|
|
138
|
+
## API Module Structure (delete if no backend)
|
|
139
|
+
|
|
140
|
+
Each feature lives under `apps/api/src/modules/<feature>/`:
|
|
141
|
+
|
|
142
|
+
```text
|
|
143
|
+
modules/<feature>/
|
|
144
|
+
models/ -- Zod schemas + types as namespace exports
|
|
145
|
+
use-cases/ -- Business logic as abstract static classes
|
|
146
|
+
services/ -- External API / infrastructure integrations
|
|
147
|
+
models.ts -- Barrel export
|
|
148
|
+
use-cases.ts -- Barrel export
|
|
149
|
+
constants.ts -- Shared constants
|
|
150
|
+
types.ts -- Shared TS interfaces
|
|
151
|
+
index.ts -- Elysia route definitions
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
### Key patterns
|
|
155
|
+
|
|
156
|
+
- **Models** — Zod `namespace` pattern; error messages as `z.literal()` so they're both
|
|
157
|
+
type-safe constants and response schema.
|
|
158
|
+
- **Use cases** — `abstract class` with a public `static execute(...)`; private `static` helpers
|
|
159
|
+
hold the how. `execute()` reads like a table of contents (each line a clear step), no inline
|
|
160
|
+
env-extraction/conditional-throw/DB-query.
|
|
161
|
+
- **Services** — same abstract-static shape, wrapping external integrations.
|
|
162
|
+
- **Routes** — `new Elysia({ prefix })`; `throw status(404, "...")` for HTTP errors.
|
|
163
|
+
- **Enum value objects** — `as const satisfies Record<string, T>` for type-safe dot access.
|
|
164
|
+
|
|
165
|
+
<!-- ===================== END deletable API section ===================== -->
|
|
166
|
+
|
|
167
|
+
## Environment Variables
|
|
168
|
+
|
|
169
|
+
<!-- List required env vars and which module/package consumes each. -->
|
|
170
|
+
|
|
171
|
+
| Variable | Used by |
|
|
172
|
+
| -------------- | ------- |
|
|
173
|
+
| `DATABASE_URL` | … |
|
|
174
|
+
|
|
175
|
+
## Code Style
|
|
176
|
+
|
|
177
|
+
Per `c9n-code-formatting` + `c9n-typescript-eslint`: no semicolons, double quotes, no trailing
|
|
178
|
+
commas. Barrel exports per subdirectory. Use the project's error-reporting path (e.g.
|
|
179
|
+
`Sentry.captureException`) — no `console.error`/`console.log` for errors.
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# {{PROJECT_NAME}} — Domain Glossary & Project Context
|
|
2
|
+
|
|
3
|
+
> **Glossary only — no implementation detail.** This file is the ubiquitous language of the
|
|
4
|
+
> project: what each term *means*. Code, schemas, and decisions live elsewhere (`docs/`). Keep it
|
|
5
|
+
> a dictionary, not a spec. Produced/maintained via `/grill-with-docs`.
|
|
6
|
+
|
|
7
|
+
## Actors
|
|
8
|
+
|
|
9
|
+
<!-- Who interacts with the system, and how they authenticate / what they can do. -->
|
|
10
|
+
|
|
11
|
+
### <Actor>
|
|
12
|
+
|
|
13
|
+
- …
|
|
14
|
+
|
|
15
|
+
## Core Entities
|
|
16
|
+
|
|
17
|
+
<!-- The nouns of the domain. For each: code term, customer-facing term, definition,
|
|
18
|
+
statuses/lifecycle, key fields. Example shape below — replace it. -->
|
|
19
|
+
|
|
20
|
+
### <Entity> (<local-language term if any>)
|
|
21
|
+
|
|
22
|
+
- **Code term:** `<table_name>` (database), `/<route>` (API)
|
|
23
|
+
- **Customer-facing term:** "…"
|
|
24
|
+
- **Definition:** …
|
|
25
|
+
- **Statuses:** … → … → …
|
|
26
|
+
- **Lifecycle:** … → … → …
|
|
27
|
+
|
|
28
|
+
## External Integrations
|
|
29
|
+
|
|
30
|
+
<!-- Third-party services and what they do for the domain — not how they're wired. -->
|
|
31
|
+
|
|
32
|
+
### <Service>
|
|
33
|
+
|
|
34
|
+
- …
|
|
35
|
+
|
|
36
|
+
## Data Model (Key Relationships)
|
|
37
|
+
|
|
38
|
+
```
|
|
39
|
+
<Entity A> → <Entity B> (1:N)
|
|
40
|
+
…
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## Key Business Decisions
|
|
44
|
+
|
|
45
|
+
<!-- Domain rules a newcomer would get wrong. One line each. -->
|
|
46
|
+
|
|
47
|
+
- …
|
|
48
|
+
|
|
49
|
+
## Glossary Hygiene
|
|
50
|
+
|
|
51
|
+
- When output names a domain concept, use the term **as defined here** — don't drift to synonyms.
|
|
52
|
+
- If a needed concept isn't here yet: either you're inventing language the project doesn't use
|
|
53
|
+
(reconsider) or there's a real gap (resolve it via `/grill-with-docs`).
|