@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.
Files changed (41) hide show
  1. package/README.md +6 -1
  2. package/SKILLS.md +6 -1
  3. package/bin/c9n-skills.js +28 -3
  4. package/install.sh +25 -2
  5. package/package.json +1 -1
  6. package/skills/c9n/SKILL.md +344 -0
  7. package/skills/c9n-deliverables/REFERENCE.md +97 -0
  8. package/skills/c9n-deliverables/SKILL.md +63 -0
  9. package/skills/c9n-deliverables/scripts/data-dictionary.cjs +49 -0
  10. package/skills/c9n-deliverables/scripts/export-openapi.cjs +35 -0
  11. package/skills/c9n-deliverables/scripts/md-to-pdf.mjs +73 -0
  12. package/skills/c9n-deliverables/scripts/openapi-to-pdf.mjs +78 -0
  13. package/skills/c9n-deliverables/scripts/snapshot-source.sh +23 -0
  14. package/skills/c9n-pipeline/SKILL.md +128 -0
  15. package/skills/c9n-pipeline/templates/Dockerfile.api +49 -0
  16. package/skills/c9n-pipeline/templates/Dockerfile.service +45 -0
  17. package/skills/c9n-pipeline/templates/Dockerfile.web +50 -0
  18. package/skills/c9n-pipeline/templates/dockerignore +18 -0
  19. package/skills/c9n-pipeline/templates/workflows/_build-job.partial.yml +13 -0
  20. package/skills/c9n-pipeline/templates/workflows/_deploy-job.partial.yml +17 -0
  21. package/skills/c9n-pipeline/templates/workflows/_migration-check.partial.yml +16 -0
  22. package/skills/c9n-pipeline/templates/workflows/ci.yml +38 -0
  23. package/skills/c9n-pipeline/templates/workflows/deployment.yml +21 -0
  24. package/skills/c9n-sentry/REFERENCE.md +172 -0
  25. package/skills/c9n-sentry/SKILL.md +53 -0
  26. package/skills/c9n-spec/SKILL.md +92 -0
  27. package/skills/c9n-spec/templates/.github/pull_request_template.md +29 -0
  28. package/skills/c9n-spec/templates/AGENTS.md +179 -0
  29. package/skills/c9n-spec/templates/CLAUDE.md +6 -0
  30. package/skills/c9n-spec/templates/CONTEXT.md +53 -0
  31. package/skills/c9n-spec/templates/DESIGN.md +73 -0
  32. package/skills/c9n-spec/templates/docs/SRS.md +37 -0
  33. package/skills/c9n-spec/templates/docs/adr/0001-spec-driven-iso29110-docs.md +44 -0
  34. package/skills/c9n-spec/templates/docs/adr/_TEMPLATE.md +26 -0
  35. package/skills/c9n-spec/templates/docs/agents/domain.md +43 -0
  36. package/skills/c9n-spec/templates/docs/agents/issue-tracker.md +22 -0
  37. package/skills/c9n-spec/templates/docs/agents/triage-labels.md +27 -0
  38. package/skills/c9n-spec/templates/docs/architecture.md +50 -0
  39. package/skills/c9n-spec/templates/docs/features/_TEMPLATE.md +34 -0
  40. package/skills/c9n-spec/templates/docs/test-plan.md +30 -0
  41. package/skills/c9n-spec/templates/docs/traceability.md +27 -0
package/README.md CHANGED
@@ -8,8 +8,13 @@ Agent skills (SKILL.md) based on the CodePassion (C9N) conventions.
8
8
  npx @codepassion/skills install codex # ~/.codex/skills
9
9
  npx @codepassion/skills install project # ./.agents/skills
10
10
  npx @codepassion/skills install combined # one combined skill
11
+ npx @codepassion/skills install cowork # zip skills for claude.ai/Cowork upload (UI, no API)
11
12
 
12
- Or: ./install.sh {claude|codex|project|combined}
13
+ Or: ./install.sh {claude|codex|project|combined|cowork}
14
+
15
+ claude.ai and Claude Cowork share a personal skill library with no upload API, so `cowork`
16
+ packages upload-ready zips into dist/cowork/ — upload them at
17
+ claude.ai → Settings → Capabilities → Upload skill.
13
18
 
14
19
  ## Edit
15
20
 
package/SKILLS.md CHANGED
@@ -8,8 +8,13 @@ Agent skills (SKILL.md) based on the CodePassion (C9N) conventions.
8
8
  npx @codepassion/skills install codex # ~/.codex/skills
9
9
  npx @codepassion/skills install project # ./.agents/skills
10
10
  npx @codepassion/skills install combined # one combined skill
11
+ npx @codepassion/skills install cowork # zip skills for claude.ai/Cowork upload (UI, no API)
11
12
 
12
- Or: ./install.sh {claude|codex|project|combined}
13
+ Or: ./install.sh {claude|codex|project|combined|cowork}
14
+
15
+ claude.ai and Claude Cowork share a personal skill library with no upload API, so `cowork`
16
+ packages upload-ready zips into dist/cowork/ — upload them at
17
+ claude.ai → Settings → Capabilities → Upload skill.
13
18
 
14
19
  ## Edit
15
20
 
package/bin/c9n-skills.js CHANGED
@@ -1,9 +1,10 @@
1
1
  #!/usr/bin/env node
2
- import { cp, mkdir, readdir, stat } from 'node:fs/promises'
2
+ import { cp, mkdir, readdir, rm, stat } from 'node:fs/promises'
3
3
  import { existsSync } from 'node:fs'
4
4
  import { homedir } from 'node:os'
5
5
  import { dirname, join, resolve } from 'node:path'
6
6
  import { fileURLToPath } from 'node:url'
7
+ import { execFile } from 'node:child_process'
7
8
  const SRC = resolve(dirname(fileURLToPath(import.meta.url)), '..', 'skills')
8
9
  const [,, cmd='install', target='claude', ...rest] = process.argv
9
10
  if (cmd==='help'||cmd==='--help'||cmd==='-h'){ help(); process.exit(0) }
@@ -12,7 +13,12 @@ const flags={dest:null,force:false,dryRun:false}
12
13
  for (let i=0;i<rest.length;i++){ const a=rest[i]
13
14
  if (a==='--force') flags.force=true
14
15
  else if (a==='--dry-run') flags.dryRun=true
15
- else if (a==='--dest') flags.dest=resolve(rest[++i]??'') }
16
+ else if (a==='--dest'){ const v=rest[++i]
17
+ if (!v){ console.error('--dest requires a value'); process.exit(1) }
18
+ flags.dest=resolve(v) } }
19
+ // cowork: claude.ai / Cowork share a personal skill library with NO upload API —
20
+ // this packages upload-ready zips for manual drag-drop in Settings → Capabilities.
21
+ if (target==='cowork'){ await packageForCowork(flags); process.exit(0) }
16
22
  const dest = flags.dest ?? defaultDest(target)
17
23
  if (!dest){ help(); process.exit(1) }
18
24
  const sources = await resolveSources(target)
@@ -33,4 +39,23 @@ function defaultDest(t){ const h=homedir()
33
39
  if (t==='codex') return join(h,'.codex','skills')
34
40
  if (t==='project') return join(process.cwd(),'.agents','skills')
35
41
  return null }
36
- function help(){ console.log('c9n-skills install [claude|codex|project|combined] [--dest <dir>] [--force] [--dry-run]') }
42
+ async function packageForCowork(flags){
43
+ const ROOT=resolve(SRC,'..')
44
+ // only auto-clean the default output dir — never delete a user-supplied --dest
45
+ const isDefaultOut=!flags.dest
46
+ const out=flags.dest ?? join(ROOT,'dist','cowork')
47
+ const sources=[...await resolveSources('combined'), ...await resolveSources('cowork')]
48
+ if (!sources.length){ console.error('No skills found'); process.exit(1) }
49
+ console.log(`Packaging ${sources.length} skill zip(s) into ${out}${flags.dryRun?' (dry-run)':''}`)
50
+ if (!flags.dryRun){ if (isDefaultOut) await rm(out,{recursive:true,force:true}); await mkdir(out,{recursive:true}) }
51
+ for (const src of sources){ const n=src.split(/[\\/]/).pop()
52
+ console.log(` zip ${n}.zip`)
53
+ if (!flags.dryRun) await zipDir(SRC,n,join(out,`${n}.zip`)) }
54
+ console.log('Done. Upload at claude.ai → Settings → Capabilities → Upload skill (shared with Cowork).')
55
+ console.log('Action skills (c9n-spec, c9n-deliverables) bundle their templates/scripts in the zip.')
56
+ }
57
+ function zipDir(cwd,name,outFile){
58
+ return new Promise((res,rej)=>{ execFile('zip',['-qr',outFile,name],{cwd},(e)=>{
59
+ if (e && e.code==='ENOENT') rej(new Error("'zip' command not found — install zip and retry"))
60
+ else if (e) rej(e); else res() }) }) }
61
+ function help(){ console.log('c9n-skills install [claude|codex|project|combined|cowork] [--dest <dir>] [--force] [--dry-run]') }
package/install.sh CHANGED
@@ -1,13 +1,36 @@
1
1
  #!/usr/bin/env bash
2
2
  set -euo pipefail
3
- SRC="$(cd "$(dirname "$0")" && pwd)/skills"
3
+ ROOT="$(cd "$(dirname "$0")" && pwd)"
4
+ SRC="$ROOT/skills"
4
5
  MODE="${1:-claude}"
6
+
7
+ # cowork: claude.ai / Cowork share a personal skill library with NO upload API —
8
+ # package upload-ready zips for manual drag-drop in Settings → Capabilities.
9
+ if [ "$MODE" = "cowork" ]; then
10
+ command -v zip >/dev/null || { echo "error: 'zip' not found — install zip and retry"; exit 1; }
11
+ DEST="${TARGET_DIR:-$ROOT/dist/cowork}"
12
+ # only auto-clean the default output dir — never delete a user-supplied TARGET_DIR
13
+ if [ -z "${TARGET_DIR:-}" ]; then rm -rf "$DEST"; fi
14
+ mkdir -p "$DEST"
15
+ count=0
16
+ for d in "$SRC"/c9n "$SRC"/c9n-*; do
17
+ [ -d "$d" ] || continue
18
+ name="$(basename "$d")"
19
+ (cd "$SRC" && zip -qr "$DEST/$name.zip" "$name")
20
+ count=$((count + 1))
21
+ done
22
+ echo "Packaged $count skill zip(s) into $DEST"
23
+ echo "Upload at claude.ai → Settings → Capabilities → Upload skill (shared with Cowork)."
24
+ command -v open >/dev/null && open "$DEST" 2>/dev/null || true
25
+ exit 0
26
+ fi
27
+
5
28
  case "$MODE" in
6
29
  claude) DEST="${TARGET_DIR:-$HOME/.claude/skills}" ;;
7
30
  codex) DEST="${TARGET_DIR:-$HOME/.codex/skills}" ;;
8
31
  project) DEST="${TARGET_DIR:-$PWD/.agents/skills}" ;;
9
32
  combined) DEST="${TARGET_DIR:-$HOME/.claude/skills}" ;;
10
- *) echo "Use: claude | codex | project | combined"; exit 1 ;;
33
+ *) echo "Use: claude | codex | project | combined | cowork"; exit 1 ;;
11
34
  esac
12
35
  mkdir -p "$DEST"
13
36
  if [ "$MODE" = "combined" ]; then cp -R "$SRC/c9n" "$DEST/"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@codepassion/skills",
3
- "version": "1.1.1",
3
+ "version": "1.4.0",
4
4
  "description": "Agent skills (SKILL.md) for CodePassion (C9N) engineering conventions.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -172,3 +172,347 @@ Alpha: tag from develop, `git tag -a vX.Y.Z -m "Release vX.Y.Z" && git push orig
172
172
  Production: confirm Go → pull release branch → create release → CI deploys → monitor.
173
173
  Reference: https://semver.org/spec/v2.0.0.html
174
174
 
175
+
176
+
177
+ ---
178
+
179
+ ## Deliverables
180
+
181
+ Repeatable customer project delivery for the Code Passion team. Turns a codebase into a
182
+ clean, customer-ready documentation package. Fully generic — adapt to whatever stack the
183
+ project uses. Bundled `scripts/` are proven references; read and adapt them per project.
184
+
185
+ ## Four mandatory gates
186
+
187
+ These ALWAYS run, in order — never skip them:
188
+
189
+ 1. **Clarify-first** — interview before generating anything (see Workflow step 1).
190
+ 2. **Security/sanitize** — never ship secrets. Before packaging: scan for and exclude
191
+ `.env`, credentials, service-account JSON, `*.pem`/`*.key`; sanitize real env files to
192
+ `.env.example` (names + descriptions, no values); strip `.DS_Store`. If you copied any
193
+ credential into a build dir to make tooling work, delete it before finishing.
194
+ 3. **Verify rendered output** — after creating PDFs, screenshot each (headless browser
195
+ `--screenshot`) and visually confirm. Catches illegible/empty diagrams and truncation.
196
+ Do not trust `file`'s page count — use `mdls -name kMDItemNumberOfPages` on macOS.
197
+ 4. **Delivery email** — always draft one. Thai for Thai customer teams, Code Passion
198
+ framing (from Code Passion → client). Leave recipient/contact as fill-in blanks.
199
+
200
+ ## Workflow
201
+
202
+ 1. **Clarify** (ask, don't assume): audience (customer vs internal); which documents are
203
+ wanted; document language (default: English docs + Thai email); output format (PDF?);
204
+ package structure — **plain docs package (default)** or **ISO/IEC 29110 work-product
205
+ layout** (offer it, see [REFERENCE.md](../c9n-deliverables/REFERENCE.md)); any contractual scope.
206
+ 2. **Inventory** the codebase — detect stack, framework, DB, API doc tooling; decide which
207
+ generators apply. Skip what doesn't fit the stack.
208
+ 3. **Generate** the doc set (only what was requested). Common artifacts and recipes are in
209
+ [REFERENCE.md](../c9n-deliverables/REFERENCE.md): system/architecture overview (+ Mermaid diagrams),
210
+ database design (ER diagram + data dictionary), API reference (export spec → PDF),
211
+ deployment runbook, configuration reference, source snapshot.
212
+ 4. **Render PDFs** with `scripts/md-to-pdf.mjs` (Markdown+Mermaid) and
213
+ `scripts/openapi-to-pdf.mjs` (OpenAPI). Then run gate 3 (verify).
214
+ 5. **Organize** per the chosen structure. Master `README.md` index; for 29110 include a
215
+ supporting-artifact → work-product traceability map.
216
+ 6. **Security gate** (gate 2), then **package**: zip the organized folder directly (or, if a
217
+ dedicated packaging skill such as `deliverables-packager` is installed, hand off to it for
218
+ final folder polish + zip).
219
+ 7. **Delivery email** (gate 4).
220
+
221
+ ## Scripts
222
+
223
+ | Script | Purpose |
224
+ |--------|---------|
225
+ | `scripts/md-to-pdf.mjs <in.md> <out.pdf>` | Markdown → PDF, renders Mermaid. Needs a Chromium-family browser. |
226
+ | `scripts/openapi-to-pdf.mjs <spec.json> <out.pdf> [guide.md]` | OpenAPI → print-friendly PDF (no lazy-load truncation). |
227
+ | `scripts/export-openapi.cjs <out.json>` | TEMPLATE: boot a NestJS app, dump Swagger spec. Adapt to project. |
228
+ | `scripts/data-dictionary.cjs <out.md>` | Data dictionary from live MySQL `INFORMATION_SCHEMA`. |
229
+ | `scripts/snapshot-source.sh <repo> <out.zip>` | Clean `git archive` source snapshot. |
230
+
231
+ ## Gotchas
232
+
233
+ - **Wide Mermaid diagrams** render as an illegible strip at page width. Use `flowchart TB`
234
+ and split large ER diagrams into per-domain groups (portrait aspect ratio).
235
+ - **OpenAPI export**: build first (`nest build`); ts-node mis-emits decorator metadata.
236
+ Booting connects to the DB — use a dev DB, never production.
237
+ - **Redoc/Swagger UI → PDF**: they lazy-render; printing truncates. Use `openapi-to-pdf.mjs`.
238
+ - See [REFERENCE.md](../c9n-deliverables/REFERENCE.md) for the ISO/IEC 29110 layout and per-artifact recipes.
239
+
240
+
241
+
242
+ ---
243
+
244
+ ## Pipeline
245
+
246
+ Bootstraps the Code Passion (C9N) CI/CD pipeline into a target repo so a new project deploys the
247
+ same way as the reference implementation (Smiley): **one image per app, built once at the Alpha
248
+ tag, redeployed to Beta/Production by base tag**, env injected at runtime by Coolify. The heavy
249
+ lifting lives in the org reusable workflows `codepassion-team/cicd/.github/workflows/{build,deploy}.yml`
250
+ — the per-repo files this skill generates just call them. The skill's real value is **Phase 3**:
251
+ the interactive ops checklist that encodes every footgun the Smiley setup hit.
252
+
253
+ Bundled `templates/` are the source skeleton. **Copy them, then substitute tokens** — never edit
254
+ the templates in place for a specific project. The Next.js wiring is an **edit** of files the dev
255
+ already owns, not a file drop (see Phase 2).
256
+
257
+ ## What gets generated
258
+
259
+ | Path | Template | When |
260
+ |------|----------|------|
261
+ | `<app>/Dockerfile` | `Dockerfile.api` | app has `elysia` |
262
+ | `<app>/Dockerfile` | `Dockerfile.web` | app has `next` |
263
+ | `<app>/Dockerfile` | `Dockerfile.service` | any other deployable app (worker, plain Bun) |
264
+ | `.dockerignore` | `dockerignore` | always (repo root) |
265
+ | `.github/workflows/ci.yml` | `workflows/ci.yml` (+ `_migration-check.partial` if DB) | always |
266
+ | `.github/workflows/deployment.yml` | `workflows/deployment.yml` (+ `_build-job`/`_deploy-job` partials) | always |
267
+ | `<web>/next.config.js` | **edit, not copy** | per web app |
268
+ | `<web>/app/layout.tsx` | **edit, not copy** | per web app |
269
+
270
+ ## Workflow
271
+
272
+ Run in order; this is a table of contents — rules are below.
273
+
274
+ 1. **Detect (Phase 1).** Scan `apps/*/package.json`. Classify each: `next`→web, `elysia`→api, else
275
+ →service. Detect DB by **real artifacts** — a migration-generate script in some `package.json`
276
+ AND a migrations dir on disk — capture their actual names; never assume `drizzle:generate` /
277
+ `packages/supabase/migrations`. Read root `package.json` for the Bun version / lockfile name.
278
+ Ask which environments exist (Alpha / Beta / Production). **Print the detected plan and confirm
279
+ before writing anything.**
280
+ 2. **Generate (Phase 2).** Copy templates with tokens substituted. **Diff/confirm per file** — if a
281
+ target exists, show the diff and ask overwrite/skip/merge; never blind-clobber; leave unrelated
282
+ files (a hand-kept `staging.yaml`) alone. Then do the **web edits** (below). Run the web build
283
+ once to prove nothing is baked.
284
+ 3. **Checklist (Phase 3).** Walk the dev interactively through the out-of-repo ops (below). This is
285
+ the deliverable.
286
+ 4. **Verify (Phase 4).** After the dev confirms the ops are done, push a tag (or reuse one), watch
287
+ the Actions run, then `curl` each deployed URL per environment and report pass/fail per app.
288
+
289
+ ## Token substitution
290
+
291
+ | Token | Source |
292
+ |-------|--------|
293
+ | `{{PACKAGE_NAME}}` | `<project>-<appkey>`, e.g. `smiley-web`. Lowercase. This is the ghcr image name and the `package_name` workflow input. |
294
+ | `{{APP_DIR}}` | The app's path, e.g. `apps/web`. |
295
+ | `{{APP_KEY}}` | Short lowercase id unique per app: `api`, `web`, `worker`. Used in job names. |
296
+ | `{{APP_PORT}}` | `3001` api · `3000` web · service's listen port (drop `EXPOSE` for a portless worker). |
297
+ | `{{BUN_VERSION}}` | Pin from root toolchain, e.g. `1.3.10`. Same across all Dockerfiles. |
298
+ | `{{WORKSPACE_MANIFEST_COPIES}}` | **web template only:** one `COPY <app>/package.json ./<app>/package.json` line **per app** — the `deps` stage runs `bun install` before `COPY . .`, so it needs every workspace manifest to resolve the graph. The api/service compile templates copy only the built app's manifest (matches Smiley's api Dockerfile; avoids pulling a sibling app's postinstall without its src). |
299
+ | `{{MIGRATION_CHECK}}` | `_migration-check.partial.yml` with `{{MIGRATION_SCRIPT}}`/`{{MIGRATIONS_DIR}}` filled, **or empty string** if no DB. |
300
+ | `{{ORG_REF}}` | The org reusable-workflow ref — currently `turborepo`. One place; bump here if the org repo retags. |
301
+ | `{{BUILD_JOBS}}` / `{{DEPLOY_JOBS}}` | Stamp `_build-job.partial` once per app (Alpha only) and `_deploy-job.partial` once per app per environment, pruning unused envs. |
302
+ | `{{DEPLOY_NAME}}` | The org `deploy.yml` `name` input → uppercased to `<NAME>_UUID`. **Only `API` and `WEB` are wired** in the org deploy.yml (see Gotchas). |
303
+
304
+ ## Web edits (surgical — not a file drop)
305
+
306
+ For each **web** app, edit the files the dev owns; fail loudly if they can't be parsed rather than
307
+ overwrite:
308
+
309
+ - `next.config.js` — add `output: "standalone"`, `outputFileTracingRoot` (monorepo root), and
310
+ `transpilePackages` for the workspace packages the app imports.
311
+ - `app/layout.tsx` — add `<head><PublicEnvScript /></head>` (`import { PublicEnvScript } from
312
+ "next-runtime-env"`). Client code reads public config with `env("NEXT_PUBLIC_X")`, **not**
313
+ `process.env` (which bakes at build → undefined at runtime).
314
+ - Flag `next-runtime-env` as a dependency to add — **do not run `bun add` yourself**; tell the dev.
315
+ - **Caveat:** runtime values only reach the browser on non-statically-prerendered pages. A page that
316
+ reads runtime public env must opt out of static caching (`export const dynamic = "force-dynamic"`)
317
+ or rely on `<PublicEnvScript>` keeping the document dynamic. Note this so future feature work
318
+ doesn't silently bake a static page.
319
+
320
+ ## Phase 3 — interactive ops checklist (the deliverable)
321
+
322
+ Derived from the actual `codepassion-team/cicd` reusable workflows. Walk these one at a time:
323
+
324
+ **Repo prerequisites**
325
+ - A **`develop` branch must exist** — `build.yml` commits the version bump and does
326
+ `git pull --rebase origin develop` / `push HEAD:develop`. No develop branch → build fails.
327
+ - Tags drive deploys; the exact tag→env mapping is **c9n-semver-deployment** (don't restate it).
328
+
329
+ **Per environment** — create a GitHub **Environment** named exactly `Alpha` / `Beta` / `Production`:
330
+ - Variables: `COOLIFY_RESOURCE_API_UUID`, `COOLIFY_RESOURCE_WEB_UUID` (the Coolify app UUIDs;
331
+ `deploy.yml` resolves `${NAME}_UUID`), and `TURBO_TEAM`.
332
+ - Secrets: `COOLIFY_TOKEN` (Coolify API bearer) and `TURBO_TOKEN`. `GITHUB_TOKEN` is automatic
333
+ (ghcr push uses it; the build job already declares `packages: write`).
334
+
335
+ **Coolify** (one resource per app per env): source = Docker image
336
+ `ghcr.io/codepassion-team/{{PACKAGE_NAME}}:<base_tag>`; copy each resource's UUID into the matching
337
+ env variable above. Caddy `reverse_proxy <app>:<port>` (api `:3001`, web `:3000`).
338
+
339
+ **ghcr** — packages are **private**: give Coolify a registry pull credential (or set package
340
+ visibility), or the image pull silently fails.
341
+
342
+ **Web runtime env in Coolify** (the scars):
343
+ - `PORT=3000` — Next standalone obeys `PORT`; Coolify defaults it to `80`, which 502s behind a
344
+ Caddy `:3000` proxy. This is the single most common web-deploy failure.
345
+ - `HOSTNAME=0.0.0.0`.
346
+ - The app's `NEXT_PUBLIC_*` values — injected here at runtime, not baked into the image.
347
+
348
+ ## Phase 4 — verify
349
+
350
+ Push a `v*.*.*` tag (or reuse one), watch the run (`gh run watch`), then for each app per env
351
+ `curl -so /dev/null -w "%{http_code}"` the deployed URL (e.g. `https://api.<proj>.alpha.c9n.co`,
352
+ `https://<proj>.alpha.c9n.co`) and confirm `200`. Report a clean pass/fail table. Don't call it done
353
+ on a green Actions run alone — the 502 class only shows at the live URL.
354
+
355
+ ## Gotchas
356
+
357
+ - **Combined install mode does not carry `templates/`.** `install.sh combined` copies only the
358
+ generated `skills/c9n` SKILL.md body. Install via `install.sh claude` (or `project`/`codex`) so the
359
+ templates come along — same limitation as `c9n-spec`/`c9n-deliverables`.
360
+ - **Org deploy.yml wires only `API_UUID` + `WEB_UUID`.** A third app type (worker) needs a PR to
361
+ `codepassion-team/cicd` adding `COOLIFY_RESOURCE_<NAME>_UUID` to deploy.yml's `env:` block. Flag
362
+ this; don't generate a deploy job that silently can't resolve its UUID.
363
+ - **Build once, deploy by base tag.** build.yml strips `-alpha`/`-rc.*`; deploy.yml also strips
364
+ `-beta.*`. So `v1.2.3` (Alpha) and a later `v1.2.3-beta.1` release both resolve base tag `v1.2.3`
365
+ and redeploy the same image. Beta/Prod must have an Alpha build of that base version in ghcr first.
366
+ - **`.dockerignore` matters.** Without it, the host's `node_modules` (wrong platform) leaks into the
367
+ build context and clobbers the linux deps → "failed to load next.config". The template ships it.
368
+ - **Don't touch `.env*`.** Generate `.dockerignore` to exclude them; never read or write env files.
369
+
370
+
371
+
372
+ ---
373
+
374
+ ## Sentry
375
+
376
+ ## Sentry — Bun + Elysia + Next.js
377
+
378
+ ## Three landmines (check first)
379
+
380
+ 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.
381
+ 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.
382
+ 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).
383
+
384
+ ## Quick start
385
+
386
+ ```
387
+ packages/sentry/ ← @repo/sentry (shared)
388
+ src/pdpa.ts ← beforeSend scrubber (shared by all inits)
389
+ src/bun.ts ← initBun() for apps/api
390
+ src/client.ts ← initClient() for browser (uses env() not process.env)
391
+ src/server.ts ← initServer() for Next.js server runtime
392
+ src/edge.ts ← initEdge() for Next.js edge runtime
393
+ package.json ← exports map: ./bun ./client ./server ./edge ./pdpa
394
+ apps/api/src/lib/sentry.ts ← import { initBun } from "@repo/sentry/bun"; initBun()
395
+ apps/api/src/index.ts ← first import: "./lib/sentry.js", then withElysia(new Elysia())
396
+ apps/web/instrumentation.ts ← register() → dynamic import server/edge config
397
+ apps/web/instrumentation-client.ts ← initClient()
398
+ apps/web/sentry.server.config.ts / sentry.edge.config.ts
399
+ apps/web/next.config.js ← withSentryConfig + transpilePackages: ["@repo/sentry"]
400
+ ```
401
+
402
+ ## Env vars
403
+
404
+ | Service | Key | Read by |
405
+ |---------|-----|---------|
406
+ | API (Coolify) | `SENTRY_DSN`, `ENVIRONMENT` | `process.env` |
407
+ | Web (Coolify) | `NEXT_PUBLIC_SENTRY_DSN`, `NEXT_PUBLIC_ENVIRONMENT` | `env()` from next-runtime-env (client) / `process.env` (server/edge) |
408
+
409
+ 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.
410
+
411
+ ## Verification checklist
412
+
413
+ - [ ] `bun install --frozen-lockfile` clean
414
+ - [ ] `bun run check-types` (api + web) clean
415
+ - [ ] `bun run build --compile` on API — confirms `@sentry/node` never loaded (the landmine test)
416
+ - [ ] Web Sentry bundle builds green
417
+ - [ ] After deploy: `window.__ENV.NEXT_PUBLIC_SENTRY_DSN` populated in devtools (runtime env proof)
418
+ - [ ] Trigger a test error → event appears in Sentry tagged correct environment
419
+ - [ ] Open event payload — no phone/otp/lat/lng/member_id (PDPA proof)
420
+
421
+ ## Reference
422
+
423
+ See [REFERENCE.md](REFERENCE.md) for full file contents, PDPA scrubber code, and `turbo.json` config.
424
+
425
+
426
+
427
+ ---
428
+
429
+ ## Spec
430
+
431
+ Bootstraps the Code Passion (C9N) spec-driven development doc system into a target repo. Drops
432
+ a self-contained, agent-readable documentation skeleton so a fresh project starts with the same
433
+ approval gates, traceability, and glossary discipline as the reference implementation
434
+ (ddg-jewelry). Fully generic — adapt the placeholders to whatever stack the project uses.
435
+
436
+ Bundled `templates/` are the source skeleton. **Copy them, then substitute tokens** — never edit
437
+ the templates in place for a specific project.
438
+
439
+ ## What gets scaffolded
440
+
441
+ | File | Role |
442
+ |------|------|
443
+ | `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. |
444
+ | `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). |
445
+ | `CONTEXT.md` | Ubiquitous-language glossary skeleton (no implementation detail). |
446
+ | `DESIGN.md` | Visual design-system rules — **only if the repo has a frontend.** |
447
+ | `docs/SRS.md` | Requirements master registry (feature short-codes + system NFRs). |
448
+ | `docs/architecture.md` | Software-design as-is map. |
449
+ | `docs/traceability.md` | Requirement → design → test master index. |
450
+ | `docs/test-plan.md` | Master test strategy. |
451
+ | `docs/adr/0001-spec-driven-iso29110-docs.md` | Seed ADR: why this doc system exists. |
452
+ | `docs/adr/_TEMPLATE.md` | ADR format for future decisions. |
453
+ | `docs/features/_TEMPLATE.md` | Per-feature deep-doc stub (Requirements · Design · Test Plan · Test Cases · Traceability). |
454
+ | `docs/agents/{issue-tracker,triage-labels,domain}.md` | Agent-process docs (GitHub `gh`, triage vocab, domain-doc consumption). |
455
+ | `.github/pull_request_template.md` | The Definition-of-Done merge gate. |
456
+
457
+ ## Workflow
458
+
459
+ Run each step in order; this is a table of contents — the rules are below.
460
+
461
+ 1. **Detect repo shape.** Read the target's root `package.json`/workspaces. Decide:
462
+ monorepo vs single app; **frontend present?** (`apps/web`, or `next`/`astro`/`vite`/`react`
463
+ in any `package.json`) → include `DESIGN.md`. **Backend/API present?** → keep the API
464
+ module-patterns section in AGENTS.md; otherwise tell the user it's deletable.
465
+ 2. **No-clobber.** For every target path, **skip if it already exists** — never overwrite. Collect
466
+ skipped paths for the final report. (Re-running the skill must be safe and idempotent.)
467
+ 3. **Copy templates** into the target repo, substituting tokens (below). Skip `DESIGN.md` if no
468
+ frontend. Skip the API section guidance if no backend.
469
+ 4. **Optional scan — OFF by default.** Only if the user **explicitly** asks to seed from code
470
+ ("scan the codebase", "seed the glossary", "reverse-document"): read the codebase and fill
471
+ - `CONTEXT.md` — first real glossary terms (actors, core entities) from the domain;
472
+ - `docs/architecture.md` — the actual module map + data-model relationships;
473
+ - `docs/features/` — one as-built stub per shipped module (low-confidence, no test cases),
474
+ and register each in `docs/SRS.md` with a fresh short-code.
475
+ Without this request, leave the placeholders untouched.
476
+ 5. **Report.** Print created vs skipped files, then next steps: pick the first feature, write its
477
+ SRS section (Gate 1), get sign-off, then Design + Test Plan (Gate 2) — no production code
478
+ before Gate 2.
479
+
480
+ ## Token substitution
481
+
482
+ When copying, replace these placeholders:
483
+
484
+ | Token | Source |
485
+ |-------|--------|
486
+ | `{{PROJECT_NAME}}` | Target root dir name, or `package.json` `name` (humanized). |
487
+ | `{{YEAR}}` / `{{DATE}}` | Current year / ISO date (for the seed ADR). |
488
+ | `{{DECIDER}}` | Ask, or default to the repo owner. |
489
+ | Stack rows in AGENTS.md | Keep C9N defaults; trim rows the detected stack doesn't use. |
490
+
491
+ ## Conventions (referenced, not copied)
492
+
493
+ The scaffolded `AGENTS.md` points at the sibling C9N skills for engineering conventions — it does
494
+ **not** inline them, so they have a single source of truth:
495
+
496
+ - Commits → `c9n-commit-messages` · Branching → `c9n-git-branching` · PRs → `c9n-pull-requests`
497
+ - Clean code → `c9n-clean-code-typescript` · Lint/types → `c9n-typescript-eslint`
498
+ - Formatting → `c9n-code-formatting` · Review → `c9n-code-review`
499
+
500
+ For C9N-internal repos every dev has these installed, so the references always resolve. If you
501
+ scaffold into a repo where they may not be installed, tell the user to
502
+ `npx @codepassion/skills install claude`.
503
+
504
+ ## Gotchas
505
+
506
+ - **Combined install mode does not carry `templates/`.** `install.sh combined` copies only the
507
+ generated `skills/c9n` SKILL.md body; the bundled templates are absent. Install `c9n-spec` via
508
+ `install.sh claude` (or `project`/`codex`) so the templates come along. Same limitation as
509
+ `c9n-deliverables`' scripts.
510
+ - **AGENTS.md vs CLAUDE.md.** AGENTS.md is the real file. CLAUDE.md exists only so Claude Code's
511
+ memory auto-load reaches the protocol — it does so via the **`@AGENTS.md` import** (Claude Code's
512
+ memory-import syntax), not a markdown link (a link is inert and pulls nothing into context). Don't
513
+ duplicate content into CLAUDE.md. If a target tool doesn't support `@`-imports, it reads AGENTS.md
514
+ directly anyway, so nothing is lost.
515
+ - **Don't grade the stubs.** If you run the optional scan, as-built stubs describe *current*
516
+ behavior at low confidence with **no** test cases — deepen on touch, per the protocol. Don't
517
+ invent acceptance criteria for code you only read.
518
+
@@ -0,0 +1,97 @@
1
+ # C9N Deliverables — Reference
2
+
3
+ ## Document set (artifacts & recipes)
4
+
5
+ Generate only what the clarify step asked for. Each is a Markdown source rendered to PDF.
6
+
7
+ ### System / Architecture Overview
8
+ - Content: tech stack table, module map, auth model, API versioning, **architecture
9
+ diagrams** (Mermaid `flowchart`): System Context, Layered Request Flow, Deployment.
10
+ - Source from README + code structure. Render with `md-to-pdf.mjs`.
11
+ - Keep flow diagrams `flowchart TB` so they stay legible at page width.
12
+
13
+ ### Database Design
14
+ - ER diagram(s) as Mermaid `erDiagram`. **Split into per-domain groups** — one giant ER is
15
+ unreadable. Plus a domain-grouped entity catalog.
16
+ - **Data dictionary**: every table & column. Generate from the live DB with
17
+ `data-dictionary.cjs` (most accurate) — adjust the env var names to the project.
18
+
19
+ ### API Reference
20
+ - Export the spec from the running/built app (`export-openapi.cjs` for NestJS/Swagger, or
21
+ `curl <host>/api-json`). Render with `openapi-to-pdf.mjs` (optionally pass a guide.md
22
+ intro covering auth, versioning, how to import the spec).
23
+ - Also ship `openapi.json` (Postman/codegen) and optionally a Redoc HTML for browsing.
24
+
25
+ ### Deployment Runbook
26
+ - Prerequisites, env vars (point to `.env.example`), local dev, build, Docker, CI/CD
27
+ (e.g. Cloud Build → Cloud Run), production checklist, troubleshooting.
28
+
29
+ ### Configuration Reference
30
+ - Sanitized `.env.example` — variable names + descriptions, **no values**. Plus notes on
31
+ Docker/compose/CI config files.
32
+
33
+ ### Source Code Snapshot
34
+ - `snapshot-source.sh <repo> <out.zip>`. Run at final delivery so it isn't stale.
35
+
36
+ ## Plain docs package layout (default)
37
+
38
+ ```
39
+ deliverables/
40
+ ├── README.md # index
41
+ ├── 01-documentation/
42
+ │ ├── markdown/ # editable sources
43
+ │ └── pdf/ # rendered PDFs
44
+ ├── 02-database/ # data dictionary, ER
45
+ ├── 03-configuration/ # .env.example, notes
46
+ ├── 04-utilities/ # helper scripts
47
+ └── 05-source-code/ # snapshot (or placeholder)
48
+ ```
49
+
50
+ ## ISO/IEC 29110 layout (Basic Profile, offer when engagement needs it)
51
+
52
+ Two process groups. Formal work products at their slots; supporting engineering artifacts
53
+ filed under the SI work product they evidence, with a traceability map in the README.
54
+
55
+ ```
56
+ deliverables/
57
+ ├── README.md # master index + traceability
58
+ ├── 00-project-management/ # PM work products
59
+ │ ├── PM-01_Statement-of-Work.pdf
60
+ │ ├── PM-02_Project-Plan.pdf
61
+ │ ├── PM-03_Progress-Status-Record.pdf
62
+ │ ├── PM-04_Change-Request.pdf
63
+ │ ├── PM-05_Acceptance-Record.pdf
64
+ │ └── PM-06_Verification-Validation-Record.pdf
65
+ └── 01-software-implementation/ # SI work products
66
+ ├── SI-01_Requirements-Specification.pdf
67
+ ├── SI-02_Software-Design.pdf
68
+ ├── SI-03_Traceability-Record.pdf
69
+ ├── SI-04_Test-Cases-and-Procedures.pdf
70
+ ├── SI-05_Test-Report.pdf
71
+ ├── SI-06_Product-Operation-Guide.pdf
72
+ ├── SI-07_Maintenance-Documentation.pdf
73
+ └── supporting/
74
+ ├── architecture/ → SI.2
75
+ ├── database/ → SI.2
76
+ ├── api/ → SI.2 (interfaces)
77
+ ├── operations/ → SI.6 / SI.7
78
+ └── source-code/ → SI Software Components
79
+ ```
80
+
81
+ Traceability: architecture/database/api → **SI.2 Software Design**; operations →
82
+ **SI.6 Product Operation Guide** + **SI.7 Maintenance**; source-code → **SI Software
83
+ Components**. PM acceptance/sign-off rows stay open for the customer.
84
+
85
+ ## Delivery email shape (Thai default)
86
+
87
+ - Subject: `ส่งมอบชุด Deliverables โครงการ [PROJECT]`
88
+ - From Code Passion → customer team. One paragraph: package attached. One: contents
89
+ overview. One: PDFs for reading + Markdown sources retained. Note where the source
90
+ snapshot lives. Close with support availability. Leave `[ชื่อผู้รับ]` / `[ช่องทางติดต่อ]` blanks.
91
+
92
+ ## Dependency notes
93
+
94
+ - PDF rendering needs a Chromium-family browser (Brave/Chrome/Edge/Chromium). Never auto-
95
+ install heavy deps (puppeteer, pandoc, LaTeX) without asking the user first.
96
+ - `data-dictionary.cjs` needs `mysql2` resolvable from a project that has it.
97
+ - Mermaid + marked load from CDN → diagram rendering needs internet.
@@ -0,0 +1,63 @@
1
+ ---
2
+ name: c9n-deliverables
3
+ description: Generate a customer-facing delivery/handover package FROM a codebase — architecture docs, ER/data-dictionary, API reference, all rendered to PDF, organized, security-scanned, zipped, with a delivery email. Use when handing a project off to a customer or another team, preparing deliverables, "delivery package", "handover", "ส่งมอบงาน", or when asked to document a codebase for an external recipient. Complements deliverables-packager (this generates docs from code + organizes; that packages existing docs).
4
+ ---
5
+
6
+ Repeatable customer project delivery for the Code Passion team. Turns a codebase into a
7
+ clean, customer-ready documentation package. Fully generic — adapt to whatever stack the
8
+ project uses. Bundled `scripts/` are proven references; read and adapt them per project.
9
+
10
+ ## Four mandatory gates
11
+
12
+ These ALWAYS run, in order — never skip them:
13
+
14
+ 1. **Clarify-first** — interview before generating anything (see Workflow step 1).
15
+ 2. **Security/sanitize** — never ship secrets. Before packaging: scan for and exclude
16
+ `.env`, credentials, service-account JSON, `*.pem`/`*.key`; sanitize real env files to
17
+ `.env.example` (names + descriptions, no values); strip `.DS_Store`. If you copied any
18
+ credential into a build dir to make tooling work, delete it before finishing.
19
+ 3. **Verify rendered output** — after creating PDFs, screenshot each (headless browser
20
+ `--screenshot`) and visually confirm. Catches illegible/empty diagrams and truncation.
21
+ Do not trust `file`'s page count — use `mdls -name kMDItemNumberOfPages` on macOS.
22
+ 4. **Delivery email** — always draft one. Thai for Thai customer teams, Code Passion
23
+ framing (from Code Passion → client). Leave recipient/contact as fill-in blanks.
24
+
25
+ ## Workflow
26
+
27
+ 1. **Clarify** (ask, don't assume): audience (customer vs internal); which documents are
28
+ wanted; document language (default: English docs + Thai email); output format (PDF?);
29
+ package structure — **plain docs package (default)** or **ISO/IEC 29110 work-product
30
+ layout** (offer it, see [REFERENCE.md](../c9n-deliverables/REFERENCE.md)); any contractual scope.
31
+ 2. **Inventory** the codebase — detect stack, framework, DB, API doc tooling; decide which
32
+ generators apply. Skip what doesn't fit the stack.
33
+ 3. **Generate** the doc set (only what was requested). Common artifacts and recipes are in
34
+ [REFERENCE.md](../c9n-deliverables/REFERENCE.md): system/architecture overview (+ Mermaid diagrams),
35
+ database design (ER diagram + data dictionary), API reference (export spec → PDF),
36
+ deployment runbook, configuration reference, source snapshot.
37
+ 4. **Render PDFs** with `scripts/md-to-pdf.mjs` (Markdown+Mermaid) and
38
+ `scripts/openapi-to-pdf.mjs` (OpenAPI). Then run gate 3 (verify).
39
+ 5. **Organize** per the chosen structure. Master `README.md` index; for 29110 include a
40
+ supporting-artifact → work-product traceability map.
41
+ 6. **Security gate** (gate 2), then **package**: zip the organized folder directly (or, if a
42
+ dedicated packaging skill such as `deliverables-packager` is installed, hand off to it for
43
+ final folder polish + zip).
44
+ 7. **Delivery email** (gate 4).
45
+
46
+ ## Scripts
47
+
48
+ | Script | Purpose |
49
+ |--------|---------|
50
+ | `scripts/md-to-pdf.mjs <in.md> <out.pdf>` | Markdown → PDF, renders Mermaid. Needs a Chromium-family browser. |
51
+ | `scripts/openapi-to-pdf.mjs <spec.json> <out.pdf> [guide.md]` | OpenAPI → print-friendly PDF (no lazy-load truncation). |
52
+ | `scripts/export-openapi.cjs <out.json>` | TEMPLATE: boot a NestJS app, dump Swagger spec. Adapt to project. |
53
+ | `scripts/data-dictionary.cjs <out.md>` | Data dictionary from live MySQL `INFORMATION_SCHEMA`. |
54
+ | `scripts/snapshot-source.sh <repo> <out.zip>` | Clean `git archive` source snapshot. |
55
+
56
+ ## Gotchas
57
+
58
+ - **Wide Mermaid diagrams** render as an illegible strip at page width. Use `flowchart TB`
59
+ and split large ER diagrams into per-domain groups (portrait aspect ratio).
60
+ - **OpenAPI export**: build first (`nest build`); ts-node mis-emits decorator metadata.
61
+ Booting connects to the DB — use a dev DB, never production.
62
+ - **Redoc/Swagger UI → PDF**: they lazy-render; printing truncates. Use `openapi-to-pdf.mjs`.
63
+ - See [REFERENCE.md](../c9n-deliverables/REFERENCE.md) for the ISO/IEC 29110 layout and per-artifact recipes.