@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
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')
|
|
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
|
|
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
|
-
|
|
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
package/skills/c9n/SKILL.md
CHANGED
|
@@ -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.
|