codymaster 4.1.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 (193) hide show
  1. package/CHANGELOG.md +50 -0
  2. package/README.md +285 -0
  3. package/adapters/antigravity.js +15 -0
  4. package/adapters/claude-code.js +17 -0
  5. package/adapters/cursor.js +16 -0
  6. package/commands/bootstrap.md +49 -0
  7. package/commands/build.md +48 -0
  8. package/commands/content.md +48 -0
  9. package/commands/continuity.md +60 -0
  10. package/commands/debug.md +51 -0
  11. package/commands/demo.md +96 -0
  12. package/commands/deploy.md +51 -0
  13. package/commands/plan.md +42 -0
  14. package/commands/review.md +55 -0
  15. package/commands/track.md +46 -0
  16. package/commands/ux.md +46 -0
  17. package/dist/agent-dispatch.js +161 -0
  18. package/dist/chains/builtin.js +85 -0
  19. package/dist/continuity.js +385 -0
  20. package/dist/dashboard.js +926 -0
  21. package/dist/data.js +122 -0
  22. package/dist/index.js +2434 -0
  23. package/dist/judge.js +252 -0
  24. package/dist/parallel-dispatch.js +359 -0
  25. package/dist/parallel-quality.js +172 -0
  26. package/dist/skill-chain.js +258 -0
  27. package/install.sh +513 -0
  28. package/package.json +79 -0
  29. package/skills/.content-factory-state.json +132 -0
  30. package/skills/.git 2/logs/refs/heads/main +1 -0
  31. package/skills/.git 2/logs/refs/remotes/origin/main +1 -0
  32. package/skills/.git 2/objects/02/fb0956734b5f8ba3f918b7defd04a89cfe0076 +0 -0
  33. package/skills/.git 2/objects/08/1e129d75dc6feac6c02037272e6bd1a04e3324 +0 -0
  34. package/skills/.git 2/objects/0c/5393416f3c5e01c9a655a802bff0dd52f76f0a +0 -0
  35. package/skills/.git 2/objects/10/0b9be46978a946a77188f68be725098a122001 +0 -0
  36. package/skills/.git 2/objects/10/cf041167fc9843610eb3d90259ef3396315fdc +0 -0
  37. package/skills/.git 2/objects/12/5e19538dd6e1338ffe74f6c4c165b00435bf48 +0 -0
  38. package/skills/.git 2/objects/16/a9b9d0088d5c1347628b45a2620b479d8ad57c +0 -0
  39. package/skills/.git 2/objects/17/8c2a9ef93c33ae4eec9d58e82321f9229843a1 +0 -0
  40. package/skills/.git 2/objects/25/397ae41d09104d763bdcac2695209d85cdea89 +0 -0
  41. package/skills/.git 2/objects/2f/a836b7947f2d458e1f639788bf4bb0983a3305 +0 -0
  42. package/skills/.git 2/objects/3a/baaaf0a1c0909c0828335791557125fba911e0 +0 -0
  43. package/skills/.git 2/objects/42/2924221b81f5ce3c4e4daac9a64a24f9b01f9a +0 -0
  44. package/skills/.git 2/objects/42/ec0ce707447dc11446a34c9995fb8533801731 +0 -0
  45. package/skills/.git 2/objects/46/e43ce92866d56ce74b1d750db307cfe6154a15 +0 -0
  46. package/skills/.git 2/objects/48/5e41b633c63f55b8277bcc59f44f67681f671a +0 -0
  47. package/skills/.git 2/objects/49/49c596a3a89fa240642acd95dd3258e261eb09 +0 -0
  48. package/skills/.git 2/objects/50/9d42d8412ef8eaf7f7e138476bac2e4d10ce60 +0 -0
  49. package/skills/.git 2/objects/55/0c8c389d981b463ef849aeb792d8be3ccb6ec8 +0 -0
  50. package/skills/.git 2/objects/5d/82d3b18410cdda3ace3677436f0cb599dbe2d2 +0 -0
  51. package/skills/.git 2/objects/60/0617c58e871a38b33bf29e282d132bb3c381ad +0 -0
  52. package/skills/.git 2/objects/6a/8369a99c687b7245c92ffaf0e0f0dab9014504 +0 -0
  53. package/skills/.git 2/objects/79/bea435d40ab531c1aaf6be0432c6a5b7aaed21 +0 -0
  54. package/skills/.git 2/objects/7e/5ebd79251c2f14e4aceb86c74b6b6daae6b500 +0 -0
  55. package/skills/.git 2/objects/81/98a822a60178d6d5023ddb3e222cddf048742e +0 -0
  56. package/skills/.git 2/objects/86/0a0e1943dfe53411d2e499a1f16f46a96ef758 +0 -0
  57. package/skills/.git 2/objects/86/971fb55fdc081fdbae52376f0f13e57a4e9b04 +0 -0
  58. package/skills/.git 2/objects/88/b89dd609a0a03f8d4fe8bfde20d5b8fc1d326d +0 -0
  59. package/skills/.git 2/objects/90/8737edb6b7809e32cc01590b4e08ba42a9d40d +0 -0
  60. package/skills/.git 2/objects/93/d5a8a9a7d4fb7f11491cb596a6880528725118 +0 -0
  61. package/skills/.git 2/objects/98/46a2ab81d0c3b3eb00ef88fc56989aa7e9f316 +0 -0
  62. package/skills/.git 2/objects/9b/d8dd1e49cf274eaf9c555f3ab39dce7af5715e +0 -0
  63. package/skills/.git 2/objects/a1/13329fb0cec96ae78b222d33a24c3b5bc7fa1f +0 -0
  64. package/skills/.git 2/objects/a9/e6effe626e8a3aea3a8fc3364b492191c6e7d0 +0 -0
  65. package/skills/.git 2/objects/ad/6de7e48d9782cca9353d1ff0aa1aab7fe1df85 +0 -0
  66. package/skills/.git 2/objects/af/54ae316f771ff692e299ffcd8bf2f06b413b59 +0 -0
  67. package/skills/.git 2/objects/b0/4cb8b0b00dad633e731c1472161419e738d674 +0 -0
  68. package/skills/.git 2/objects/b3/094abb0b9ed46419b269e4a4e36a459690e3b0 +0 -0
  69. package/skills/.git 2/objects/b9/435c5d4baac2cfc5c83009ddd27b46b60db5f1 +0 -0
  70. package/skills/.git 2/objects/ba/5da17dbaec5ec2dcfdfd126aead518d1171d5c +0 -0
  71. package/skills/.git 2/objects/c0/bf58703aa258ba5dd63083bebaec8f223d844c +0 -0
  72. package/skills/.git 2/objects/c4/701a34edf1fc1bad58ccc57bd03f9426acb59a +0 -0
  73. package/skills/.git 2/objects/c7/5ccce9a4e5cc74d9b3174550cf6d993ca43638 +0 -0
  74. package/skills/.git 2/objects/c7/710d59b5a35b0f1f0a0399386643a0bd94c929 +0 -0
  75. package/skills/.git 2/objects/d1/fe58237112e953e5fec52da22cf38e08be3df9 +5 -0
  76. package/skills/.git 2/objects/d2/2bbe9fd2f74c95bc5583e803f5e435f1e2cd86 +0 -0
  77. package/skills/.git 2/objects/d7/e72852ea2bff74581dbf247d400120086229f4 +0 -0
  78. package/skills/.git 2/objects/d8/d4c3b5553e4fd72807e1d4b49ef07d9ef3ac35 +0 -0
  79. package/skills/.git 2/objects/dc/75050c2876f6a02ae2a53a3c886f395b622977 +0 -0
  80. package/skills/.git 2/objects/ee/e8546f95acec500187c08a28a8b9ee02db0dec +0 -0
  81. package/skills/.git 2/objects/ef/263c059208b416c2146434f10cb2b9fabcba16 +0 -0
  82. package/skills/.git 2/objects/f3/ae597e84d9a59b88acd21c99bde2eaf686d785 +0 -0
  83. package/skills/.git 2/objects/f3/f6f5673c821d3d8e76fa267a9e882e7a5387ea +0 -0
  84. package/skills/.git 2/objects/f9/6e6d0ad02624dd11d5848594d056caef7a5e8b +0 -0
  85. package/skills/.git 2/objects/ff/278988fc1edf0db3abcf18de795f4cc0b4f3e1 +0 -0
  86. package/skills/.git 2/refs/heads/main +1 -0
  87. package/skills/.git 2/refs/remotes/origin/main +1 -0
  88. package/skills/.pytest_cache 2/v/cache/nodeids +76 -0
  89. package/skills/.pytest_cache 2/v/cache/stepwise +1 -0
  90. package/skills/_shared/helpers.md +123 -0
  91. package/skills/_shared/outputs-convention.md +24 -0
  92. package/skills/cm-ads-tracker/SKILL.md +109 -0
  93. package/skills/cm-ads-tracker/evals/evals.json +55 -0
  94. package/skills/cm-ads-tracker/references/gtm-architecture.md +321 -0
  95. package/skills/cm-ads-tracker/references/industry-events.md +294 -0
  96. package/skills/cm-ads-tracker/references/platforms-api.md +238 -0
  97. package/skills/cm-ads-tracker/templates/capi-payload.md +79 -0
  98. package/skills/cm-ads-tracker/templates/datalayer-push.js +104 -0
  99. package/skills/cm-ads-tracker/templates/gtm-variables.js +56 -0
  100. package/skills/cm-brainstorm-idea/SKILL.md +423 -0
  101. package/skills/cm-code-review/SKILL.md +151 -0
  102. package/skills/cm-content-factory/SKILL.md +416 -0
  103. package/skills/cm-continuity/SKILL.md +399 -0
  104. package/skills/cm-dashboard/SKILL.md +533 -0
  105. package/skills/cm-dashboard/ui/app.js +1270 -0
  106. package/skills/cm-dashboard/ui/index.html +206 -0
  107. package/skills/cm-dashboard/ui/style.css +440 -0
  108. package/skills/cm-debugging/SKILL.md +412 -0
  109. package/skills/cm-deep-search/SKILL.md +242 -0
  110. package/skills/cm-design-system/SKILL.md +97 -0
  111. package/skills/cm-design-system/resources/halo-modern.md +40 -0
  112. package/skills/cm-design-system/resources/lunaris-advanced.md +40 -0
  113. package/skills/cm-design-system/resources/nitro-enterprise.md +39 -0
  114. package/skills/cm-design-system/resources/shadcn-default.md +37 -0
  115. package/skills/cm-dockit/README.md +100 -0
  116. package/skills/cm-dockit/SKILL.md +302 -0
  117. package/skills/cm-dockit/index.html +443 -0
  118. package/skills/cm-dockit/package-lock.json +1850 -0
  119. package/skills/cm-dockit/package.json +14 -0
  120. package/skills/cm-dockit/prompts/analysis.md +34 -0
  121. package/skills/cm-dockit/prompts/api-reference.md +24 -0
  122. package/skills/cm-dockit/prompts/architecture.md +21 -0
  123. package/skills/cm-dockit/prompts/data-flow.md +20 -0
  124. package/skills/cm-dockit/prompts/database.md +21 -0
  125. package/skills/cm-dockit/prompts/deployment.md +22 -0
  126. package/skills/cm-dockit/prompts/flows.md +21 -0
  127. package/skills/cm-dockit/prompts/jtbd.md +20 -0
  128. package/skills/cm-dockit/prompts/personas.md +24 -0
  129. package/skills/cm-dockit/prompts/sop-modules.md +40 -0
  130. package/skills/cm-dockit/scripts/doc-gen.sh +121 -0
  131. package/skills/cm-dockit/scripts/dockit-dashboard.sh +142 -0
  132. package/skills/cm-dockit/scripts/dockit-runner.sh +607 -0
  133. package/skills/cm-dockit/scripts/dockit-task.sh +166 -0
  134. package/skills/cm-dockit/skills/analyze-codebase.md +174 -0
  135. package/skills/cm-dockit/skills/api-reference.md +237 -0
  136. package/skills/cm-dockit/skills/changelog-guide.md +195 -0
  137. package/skills/cm-dockit/skills/content-guidelines.md +190 -0
  138. package/skills/cm-dockit/skills/sop-guide.md +184 -0
  139. package/skills/cm-dockit/skills/tech-docs.md +287 -0
  140. package/skills/cm-dockit/templates/markdown/structure.md +60 -0
  141. package/skills/cm-dockit/templates/vitepress-premium/.vitepress/config.mts +110 -0
  142. package/skills/cm-dockit/templates/vitepress-premium/.vitepress/theme/custom.css +189 -0
  143. package/skills/cm-dockit/templates/vitepress-premium/.vitepress/theme/index.ts +4 -0
  144. package/skills/cm-dockit/templates/vitepress-premium/package.json +19 -0
  145. package/skills/cm-dockit/templates/vitepress-premium/tests/frontend.test.ts +45 -0
  146. package/skills/cm-dockit/tests/runner.test.ts +66 -0
  147. package/skills/cm-dockit/workflows/export-markdown.md +82 -0
  148. package/skills/cm-dockit/workflows/generate-docs.md +68 -0
  149. package/skills/cm-dockit/workflows/setup-vitepress.md +181 -0
  150. package/skills/cm-example/SKILL.md +26 -0
  151. package/skills/cm-execution/SKILL.md +268 -0
  152. package/skills/cm-git-worktrees/SKILL.md +164 -0
  153. package/skills/cm-how-it-work/SKILL.md +189 -0
  154. package/skills/cm-identity-guard/SKILL.md +412 -0
  155. package/skills/cm-jtbd/SKILL.md +98 -0
  156. package/skills/cm-planning/SKILL.md +130 -0
  157. package/skills/cm-project-bootstrap/SKILL.md +161 -0
  158. package/skills/cm-project-bootstrap/templates/AGENTS.md +42 -0
  159. package/skills/cm-project-bootstrap/templates/frontend-safety.test.js +51 -0
  160. package/skills/cm-project-bootstrap/templates/i18n-sync.test.js +38 -0
  161. package/skills/cm-project-bootstrap/templates/pr-template.md +12 -0
  162. package/skills/cm-project-bootstrap/templates/project-identity.json +29 -0
  163. package/skills/cm-project-bootstrap/templates/vitest.config.js +10 -0
  164. package/skills/cm-quality-gate/SKILL.md +218 -0
  165. package/skills/cm-readit/SKILL.md +289 -0
  166. package/skills/cm-readit/audio-player.md +206 -0
  167. package/skills/cm-readit/examples/blog-reader.js +352 -0
  168. package/skills/cm-readit/examples/voice-cro.js +390 -0
  169. package/skills/cm-readit/tts-engine.md +262 -0
  170. package/skills/cm-readit/ui-patterns.md +362 -0
  171. package/skills/cm-readit/voice-cro.md +223 -0
  172. package/skills/cm-safe-deploy/SKILL.md +120 -0
  173. package/skills/cm-safe-deploy/templates/deploy.sh +89 -0
  174. package/skills/cm-safe-i18n/SKILL.md +473 -0
  175. package/skills/cm-secret-shield/SKILL.md +580 -0
  176. package/skills/cm-skill-chain/SKILL.md +78 -0
  177. package/skills/cm-skill-index/SKILL.md +318 -0
  178. package/skills/cm-skill-mastery/SKILL.md +169 -0
  179. package/skills/cm-start/SKILL.md +65 -0
  180. package/skills/cm-status/SKILL.md +12 -0
  181. package/skills/cm-tdd/SKILL.md +370 -0
  182. package/skills/cm-terminal/SKILL.md +177 -0
  183. package/skills/cm-test-gate/SKILL.md +242 -0
  184. package/skills/cm-ui-preview/SKILL.md +291 -0
  185. package/skills/cm-ux-master/DESIGN_STANDARD_TEMPLATE.md +54 -0
  186. package/skills/cm-ux-master/SKILL.md +114 -0
  187. package/skills/cro-methodology/SKILL.md +98 -0
  188. package/skills/cro-methodology/references/COPYWRITING.md +178 -0
  189. package/skills/cro-methodology/references/OBJECTIONS.md +135 -0
  190. package/skills/cro-methodology/references/PERSUASION.md +158 -0
  191. package/skills/cro-methodology/references/RESEARCH.md +220 -0
  192. package/skills/cro-methodology/references/funnel-analysis.md +365 -0
  193. package/skills/cro-methodology/references/testing-methodology.md +330 -0
@@ -0,0 +1,89 @@
1
+ #!/bin/bash
2
+ # deploy.sh — 9-Gate Deploy Pipeline
3
+ # Usage: ./deploy.sh [staging|production]
4
+
5
+ set -e
6
+ TARGET="${1:-staging}"
7
+ echo "🚀 Deploying to $TARGET..."
8
+
9
+ # Gate 0: Secret Hygiene
10
+ echo "🔒 Gate 0: Secret Hygiene..."
11
+ if grep -rq 'SERVICE_KEY\|ANON_KEY\|DB_PASSWORD' wrangler.jsonc 2>/dev/null; then
12
+ echo "❌ Secrets found in wrangler.jsonc! Use 'wrangler secret put' instead."
13
+ exit 1
14
+ fi
15
+ if ! grep -q '.dev.vars' .gitignore; then
16
+ echo "❌ .dev.vars not in .gitignore!"
17
+ exit 1
18
+ fi
19
+ echo "✅ Gate 0 passed"
20
+
21
+ # Gate 1: Syntax Validation
22
+ echo "📝 Gate 1: Syntax Validation..."
23
+ if [ -f "tsconfig.json" ]; then
24
+ npx tsc --noEmit
25
+ else
26
+ find src/ public/ -name "*.js" -exec node -c {} \; 2>&1
27
+ fi
28
+ echo "✅ Gate 1 passed"
29
+
30
+ # Gate 2: Test Suite
31
+ echo "🧪 Gate 2: Test Suite..."
32
+ npm run test:gate
33
+ echo "✅ Gate 2 passed"
34
+
35
+ # Gate 3: i18n Parity
36
+ echo "🌍 Gate 3: i18n Parity..."
37
+ if [ -d "public/static/i18n" ]; then
38
+ PRIMARY=$(wc -l < public/static/i18n/vi.json)
39
+ for f in public/static/i18n/*.json; do
40
+ COUNT=$(wc -l < "$f")
41
+ if [ "$COUNT" != "$PRIMARY" ]; then
42
+ echo "❌ $(basename $f) has $COUNT lines vs primary $PRIMARY"
43
+ exit 1
44
+ fi
45
+ done
46
+ echo "✅ Gate 3 passed"
47
+ else
48
+ echo "⏭️ Gate 3 skipped (no i18n)"
49
+ fi
50
+
51
+ # Gate 4: Build
52
+ echo "🏗️ Gate 4: Build..."
53
+ if grep -q '"build"' package.json; then
54
+ npm run build
55
+ echo "✅ Gate 4 passed"
56
+ else
57
+ echo "⏭️ Gate 4 skipped (no build script)"
58
+ fi
59
+
60
+ # Gate 5: Dist Verification
61
+ echo "📦 Gate 5: Dist Verification..."
62
+ # Customize this for your project
63
+ echo "✅ Gate 5 passed"
64
+
65
+ # Gate 6: Deploy + Smoke Test
66
+ echo "🚀 Gate 6: Deploy..."
67
+ if [ "$TARGET" = "production" ]; then
68
+ BRANCH=$(git branch --show-current)
69
+ if [ "$BRANCH" != "production" ]; then
70
+ echo "❌ Must be on 'production' branch for production deploy"
71
+ exit 1
72
+ fi
73
+ fi
74
+ # Replace with your deploy command:
75
+ # npx wrangler pages deploy dist/ --project-name=YOUR_PROJECT
76
+ echo "✅ Gate 6 passed"
77
+
78
+ # Gate 7: Version Bump (post-deploy)
79
+ echo "🏷️ Gate 7: Version Bump..."
80
+ # npm run release:version
81
+ echo "✅ Gate 7 passed"
82
+
83
+ # Gate 8: Changelog (post-deploy)
84
+ echo "📋 Gate 8: Changelog..."
85
+ # npm run release:changelog
86
+ echo "✅ Gate 8 passed"
87
+
88
+ echo ""
89
+ echo "🎉 All 9 gates passed! Deployed to $TARGET."
@@ -0,0 +1,473 @@
1
+ ---
2
+ name: cm-safe-i18n
3
+ description: Use when translating, extracting, or mass-converting hardcoded strings to i18n t() calls. Enforces multi-pass batching, parallel-per-language dispatch, 8 audit gates, and HTML integrity checks. Battle-tested through 21+ batches and 12 bug categories from the March 2026 incidents.
4
+ ---
5
+
6
+ # Safe i18n Translation v2.0
7
+
8
+ ## Overview
9
+
10
+ Mass i18n conversion is the most dangerous code transformation in a frontend monolith. A single-pass conversion of 600+ strings corrupted `app.js` beyond repair while 572 backend tests passed green. Additional incidents include HTML tag corruption, variable shadowing, and placeholder translation errors.
11
+
12
+ **Core principle:** Every batch of i18n changes MUST pass ALL 8 audit gates before proceeding. No exceptions.
13
+
14
+ **Violating the letter of this rule is violating the spirit of this rule.**
15
+
16
+ ## The Iron Law
17
+
18
+ ```
19
+ NO BATCH WITHOUT PASSING ALL 8 AUDIT GATES.
20
+ NO LANGUAGE FILE WITHOUT KEY PARITY.
21
+ NO DEPLOY WITHOUT FULL SYNTAX VALIDATION.
22
+ NO HTML TAG MODIFICATION — TEXT CONTENT ONLY.
23
+ NO REGEX TO FIX REGEX ERRORS — USE LEXICAL SCANNER.
24
+ ```
25
+
26
+ ## When to Use
27
+
28
+ **ALWAYS** when any of these happen:
29
+ - Extracting hardcoded strings to `t()` calls
30
+ - Adding new language file (e.g., `ph.json`)
31
+ - Mass-converting strings across >10 lines
32
+ - Updating translation keys or namespaces
33
+ - Migrating i18n library or pattern
34
+
35
+ **Don't use for:**
36
+ - Adding 1-3 translation keys (just add manually + test)
37
+ - Fixing a single typo in a JSON file
38
+
39
+ ## The Protocol
40
+
41
+ ```dot
42
+ digraph i18n_flow {
43
+ rankdir=TB;
44
+ "0. Pre-flight" [shape=box];
45
+ "1. Scan ALL files" [shape=box];
46
+ ">10 strings?" [shape=diamond];
47
+ "Manual add + test" [shape=box];
48
+ "2. Plan passes" [shape=box];
49
+ "3. Extract batch (max 30)" [shape=box];
50
+ "4. 8-Gate Audit" [shape=box, style=filled, fillcolor="#ffffcc"];
51
+ "All 8 pass?" [shape=diamond];
52
+ "FIX or ROLLBACK" [shape=box, style=filled, fillcolor="#ffcccc"];
53
+ "More batches?" [shape=diamond];
54
+ "5. Parallel language sync" [shape=box];
55
+ "6. Final validation" [shape=box];
56
+
57
+ "0. Pre-flight" -> "1. Scan ALL files";
58
+ "1. Scan ALL files" -> ">10 strings?";
59
+ ">10 strings?" -> "Manual add + test" [label="no"];
60
+ ">10 strings?" -> "2. Plan passes" [label="yes"];
61
+ "2. Plan passes" -> "3. Extract batch (max 30)";
62
+ "3. Extract batch (max 30)" -> "4. 8-Gate Audit";
63
+ "4. 8-Gate Audit" -> "All 8 pass?";
64
+ "All 8 pass?" -> "FIX or ROLLBACK" [label="no"];
65
+ "FIX or ROLLBACK" -> "4. 8-Gate Audit";
66
+ "All 8 pass?" -> "More batches?" [label="yes"];
67
+ "More batches?" -> "3. Extract batch (max 30)" [label="yes"];
68
+ "More batches?" -> "5. Parallel language sync" [label="no"];
69
+ "5. Parallel language sync" -> "6. Final validation";
70
+ }
71
+ ```
72
+
73
+ ---
74
+
75
+ ### Phase 0: Pre-Flight Checks (NEW)
76
+
77
+ #### 0a. Load i18n Learnings (cm-continuity)
78
+
79
+ Before ANY i18n work, read `.cm/memory/learnings.json` filtered by `scope: "module:i18n"`.
80
+ Apply all active prevention patterns. Known high-value learnings:
81
+ - **L001**: Always run i18n-sync test after each batch extraction
82
+ - **L004**: Use namespace-split architecture (not monolithic JSON)
83
+ - **L005**: Add exclusion list to extraction scripts to prevent junk keys
84
+
85
+ > If learnings.json has relevant entries, reference them before starting. If no `.cm/` directory exists, proceed but create learnings after this workflow.
86
+
87
+ Before ANY i18n work:
88
+
89
+ ```bash
90
+ # NEVER work on main
91
+ git checkout -b i18n/$(date +%Y%m%d)-target-description
92
+
93
+ # Verify baseline is clean
94
+ node -c public/static/app.js
95
+ npm run test:gate
96
+ ```
97
+
98
+ If either fails, DO NOT PROCEED. Fix the baseline first.
99
+
100
+ ---
101
+
102
+ ### Phase 1: Scan ALL Frontend Files (IMPROVED)
103
+
104
+ > [!CAUTION]
105
+ > **Lesson #11:** `import-adapters.js` and `import-engine.js` had 60+ hardcoded strings that were initially missed because only `app.js` was scanned.
106
+
107
+ Scan EVERY file that produces user-visible UI text:
108
+ ```bash
109
+ # Scan ALL .js files for Vietnamese strings
110
+ node scripts/i18n-lint.js
111
+
112
+ # Also check non-app.js files
113
+ grep -rnP '[àáạảãâầấậẩẫăằắặẳẵ]' public/static/*.js --include="*.js" | grep -v "\.backup" | grep -v "i18n"
114
+ ```
115
+
116
+ Group strings by **functional domain** — never by file position:
117
+
118
+ | Pass | Domain | Example Keys |
119
+ |------|--------|-------------|
120
+ | 1 | Core UI | `sidebar.*`, `common.*`, `login.*` |
121
+ | 2 | Primary Feature | `vio.*`, `emp.*`, `scores.*` |
122
+ | 3 | Config & Settings | `config.*`, `benconf.*` |
123
+ | 4 | Reports & Export | `report.*`, `export.*` |
124
+ | 5 | Secondary Files | `import-adapters.js`, `import-engine.js` |
125
+ | 6 | Edge cases | Tooltips, error messages, dynamic labels |
126
+
127
+ **Output:** A numbered list of passes with estimated string count per pass per FILE.
128
+
129
+ ---
130
+
131
+ ### Phase 2: Extract Batch (MAX 30 strings per batch)
132
+
133
+ > [!CAUTION]
134
+ > **MAX 30 strings per batch. Not 31. Not "about 30". Exactly 30 or fewer.**
135
+ > The i18n crash happened because 600+ strings were done in one pass.
136
+
137
+ For each batch:
138
+
139
+ 1. **Identify** up to 30 hardcoded strings in the current pass domain
140
+ 2. **Generate** namespace-compliant keys: `domain.descriptive_key`
141
+ 3. **Replace** strings with `t('domain.key')` calls
142
+ 4. **Add** keys to the **primary** language JSON (usually `vi.json`)
143
+
144
+ #### String Replacement Rules (12 Bug Categories Encoded)
145
+
146
+ ```javascript
147
+ // ✅ CORRECT — backtick template with t() inside
148
+ `<div>${t('login.welcome')}</div>`
149
+
150
+ // ✅ CORRECT — concatenation
151
+ '<div>' + t('login.welcome') + '</div>'
152
+
153
+ // ❌ BUG #1 (FATAL) — single-quote wrapping template expression
154
+ '${t("login.welcome")}' // ← THIS DESTROYED APP.JS
155
+
156
+ // ❌ BUG #4 — mismatched delimiters
157
+ t('login.welcome`) // ← quote/backtick mismatch
158
+ t(`login.welcome') // ← backtick/quote mismatch
159
+ ```
160
+
161
+ #### Ternary Inside Template Literals (Bug #5)
162
+ ```javascript
163
+ // ❌ BROKEN — single-quote ternary result with template expression
164
+ ${ canDo ? '...${t('key')}...' : '' }
165
+
166
+ // ✅ CORRECT — backtick ternary result
167
+ ${ canDo ? `...${t('key')}...` : '' }
168
+ ```
169
+
170
+ #### Variable Shadowing (Bug #3)
171
+ ```javascript
172
+ // ❌ BROKEN — shadows global t() translation function
173
+ items.map((t, i) => `<div>${t('key')}</div>`)
174
+
175
+ // ✅ CORRECT — use different variable name
176
+ items.map((item, i) => `<div>${t('key')}</div>`)
177
+ ```
178
+
179
+ #### HTML Tag Protection (Bug #2)
180
+ ```javascript
181
+ // ❌ NEVER modify content inside HTML tags
182
+ `< div class="card" >` // spaces inside tags = broken rendering
183
+ `style = "color: red"` // space around = breaks attributes
184
+ `<!-- text-- >` // broken comment closers
185
+
186
+ // ✅ ONLY replace text content between tags
187
+ `<div class="card">${t('card.title')}</div>`
188
+ ```
189
+
190
+ #### Static Keys Only (Bug #8)
191
+ ```javascript
192
+ // ❌ FORBIDDEN — dynamic keys can't be statically validated
193
+ t('nav.' + pageName)
194
+ t(`messages.${type}`)
195
+
196
+ // ✅ REQUIRED — static keys only
197
+ t('nav.dashboard')
198
+ t('nav.employees')
199
+ ```
200
+
201
+ ---
202
+
203
+ ### Phase 3: 8-Gate Audit (MANDATORY after every batch)
204
+
205
+ > [!IMPORTANT]
206
+ > All 8 gates must pass. **Any failure = STOP and FIX before continuing.**
207
+
208
+ ```bash
209
+ # Gate 1: JavaScript syntax (fast, <1s)
210
+ node -c public/static/app.js
211
+ # Must output: "public/static/app.js: No syntax errors"
212
+
213
+ # Gate 2: Syntax check on ALL modified .js files
214
+ node -c public/static/import-adapters.js 2>/dev/null
215
+ node -c public/static/import-engine.js 2>/dev/null
216
+
217
+ # Gate 3: Corruption pattern check (catches what node -c misses)
218
+ grep -nP "=\s*'[^']*\$\{t\(" public/static/app.js
219
+ # Must return 0 matches
220
+
221
+ # Gate 4: Mismatched delimiter check
222
+ grep -nP "t\('[^']*\`\)" public/static/app.js
223
+ grep -nP "t\(\`[^']*'\)" public/static/app.js
224
+ # Must return 0 matches each
225
+
226
+ # Gate 5: HTML tag integrity (NEW — Bug #2)
227
+ grep -nP "<\s+\w" public/static/app.js | head -5
228
+ grep -nP "</\s+\w" public/static/app.js | head -5
229
+ grep -nP "--\s+>" public/static/app.js | head -5
230
+ grep -nP '\w+\s+=\s+"' public/static/app.js | grep -v "==\|!=\|<=\|>=" | head -5
231
+ # Must return 0 matches (excluding legitimate JS operators)
232
+
233
+ # Gate 6: Variable shadowing check
234
+ grep -nP "\.\s*(map|filter|forEach|reduce)\s*\(\s*\(\s*t\s*[,)]" public/static/app.js
235
+ # Must return 0 matches
236
+
237
+ # Gate 7: JSON validity
238
+ node -e "JSON.parse(require('fs').readFileSync('public/static/i18n/vi.json'))"
239
+
240
+ # Gate 8: Full test suite
241
+ npm run test:gate
242
+ # Must output: 0 failures
243
+ ```
244
+
245
+ **Audit Summary Table:**
246
+
247
+ | Gate | Check | Command | Pass Criteria | Bug # Prevented |
248
+ |------|-------|---------|---------------|-----------------|
249
+ | 1 | JS syntax (main) | `node -c app.js` | No syntax errors | #1, #4 |
250
+ | 2 | JS syntax (all files) | `node -c *.js` | No syntax errors | #11 |
251
+ | 3 | Corruption pattern | grep `= '..${t(` | 0 matches | #1 |
252
+ | 4 | Delimiter mismatch | grep mixed delims | 0 matches | #4 |
253
+ | 5 | HTML tag integrity | grep `< div`, `</ div` | 0 matches | #2 |
254
+ | 6 | Variable shadowing | grep `.map((t,` | 0 matches | #3 |
255
+ | 7 | JSON valid | `JSON.parse()` | No parse errors | #6 |
256
+ | 8 | Full test suite | `npm run test:gate` | 0 failures | #9 |
257
+
258
+ **If ALL 8 gates pass → commit:**
259
+ ```bash
260
+ git add -A && git commit -m "i18n pass N batch M/T: domain description (X strings)"
261
+ ```
262
+
263
+ **If ANY gate fails → FIX immediately.** Do NOT proceed to next batch.
264
+
265
+ **If fix attempt uses regex → STOP.** Use the lexical scanner instead (Bug #10).
266
+
267
+ ---
268
+
269
+ ### Phase 4: Parallel Language Sync
270
+
271
+ **REQUIRED SUB-SKILL:** Use `cm-execution` (Parallel mode).
272
+
273
+ After ALL strings are extracted to the primary language, sync remaining languages **in parallel**:
274
+
275
+ ```
276
+ Agent 1 → Translate all keys to en.json (English)
277
+ Agent 2 → Translate all keys to th.json (Thai)
278
+ Agent 3 → Translate all keys to ph.json (Filipino)
279
+ ```
280
+
281
+ **Each agent prompt MUST include:**
282
+ ```markdown
283
+ Translate the following i18n keys from vi.json to [LANGUAGE]:
284
+
285
+ Source file: public/static/lang/vi.json
286
+ Target file: public/static/lang/[LANG].json
287
+
288
+ Rules:
289
+ 1. Translate ALL keys — missing keys will break the app
290
+ 2. Keep key names EXACTLY the same (only values change)
291
+ 3. Keep {{param}} interpolation placeholders intact — NEVER translate them
292
+ 4. Do NOT translate technical terms (e.g., PPH, KPI, CSV)
293
+ 5. Preserve HTML entities if present in values
294
+ 6. Do NOT produce empty string "" values — every key must have content
295
+ 7. Preserve the exact same JSON structure/nesting
296
+
297
+ After translation:
298
+ 1. Validate JSON: node -e "JSON.parse(require('fs').readFileSync('[LANG].json'))"
299
+ 2. Count keys must EQUAL vi.json key count
300
+ 3. No null or empty string values
301
+ 4. All {{param}} placeholders preserved identically
302
+
303
+ Return: Key count + any untranslatable terms flagged.
304
+ ```
305
+
306
+ **After agents return — 3-Point Parity Check:**
307
+ ```bash
308
+ # Check 1: Key count parity
309
+ node -e "
310
+ const fs = require('fs');
311
+ const langs = ['vi','en','th','ph'];
312
+ const counts = langs.map(l => {
313
+ const keys = Object.keys(JSON.parse(fs.readFileSync('public/static/i18n/'+l+'.json')));
314
+ console.log(l + ': ' + keys.length + ' keys');
315
+ return keys.length;
316
+ });
317
+ if (new Set(counts).size !== 1) {
318
+ console.error('❌ KEY PARITY FAILURE! Counts differ across languages.');
319
+ process.exit(1);
320
+ } else {
321
+ console.log('✅ Key parity: all languages have ' + counts[0] + ' keys');
322
+ }
323
+ "
324
+
325
+ # Check 2: Empty value detection (NEW — prevents blank UI)
326
+ node -e "
327
+ const fs = require('fs');
328
+ const langs = ['vi','en','th','ph'];
329
+ let hasEmpty = false;
330
+ for (const lang of langs) {
331
+ const data = JSON.parse(fs.readFileSync('public/static/i18n/' + lang + '.json'));
332
+ const check = (obj, prefix) => {
333
+ for (const [k, v] of Object.entries(obj)) {
334
+ const key = prefix ? prefix + '.' + k : k;
335
+ if (v === '' || v === null) { console.error('❌ Empty value: ' + lang + ':' + key); hasEmpty = true; }
336
+ if (typeof v === 'object' && v !== null) check(v, key);
337
+ }
338
+ };
339
+ check(data, '');
340
+ }
341
+ if (hasEmpty) process.exit(1);
342
+ console.log('✅ No empty values');
343
+ "
344
+
345
+ # Check 3: Placeholder preservation (NEW — Bug #7)
346
+ node -e "
347
+ const fs = require('fs');
348
+ const vi = JSON.parse(fs.readFileSync('public/static/i18n/vi.json'));
349
+ const flatten = (obj, pre='') => Object.entries(obj).reduce((a, [k,v]) => {
350
+ const key = pre ? pre+'.'+k : k;
351
+ if (typeof v === 'object' && v !== null && !Array.isArray(v)) return [...a, ...flatten(v, key)];
352
+ return [...a, [key, v]];
353
+ }, []);
354
+ const viFlat = Object.fromEntries(flatten(vi));
355
+ let errors = 0;
356
+ for (const lang of ['en','th','ph']) {
357
+ const other = Object.fromEntries(flatten(JSON.parse(fs.readFileSync('public/static/i18n/'+lang+'.json'))));
358
+ for (const [key, viVal] of Object.entries(viFlat)) {
359
+ if (typeof viVal !== 'string') continue;
360
+ const viParams = (viVal.match(/\{\{[^}]+\}\}/g) || []).sort().join(',');
361
+ const otherVal = other[key] || '';
362
+ const otherParams = (otherVal.match(/\{\{[^}]+\}\}/g) || []).sort().join(',');
363
+ if (viParams && viParams !== otherParams) {
364
+ console.error('❌ ' + lang + ':' + key + ' placeholder mismatch: vi=' + viParams + ' ' + lang + '=' + otherParams);
365
+ errors++;
366
+ }
367
+ }
368
+ }
369
+ if (errors) process.exit(1);
370
+ console.log('✅ All placeholders preserved');
371
+ "
372
+ ```
373
+
374
+ ---
375
+
376
+ ### Phase 5: Final Validation
377
+
378
+ ```bash
379
+ # 1. Full syntax check on ALL frontend files
380
+ for f in public/static/app.js public/static/import-adapters.js public/static/import-engine.js; do
381
+ [ -f "$f" ] && node -c "$f"
382
+ done
383
+
384
+ # 2. Full test gate (includes frontend-safety + i18n-sync tests)
385
+ npm run test:gate
386
+
387
+ # 3. Build
388
+ npm run build
389
+
390
+ # 4. Remaining hardcoded scan (should be ~0)
391
+ node scripts/i18n-lint.js
392
+
393
+ # 5. Manual smoke test — switch languages in browser
394
+ ```
395
+
396
+ **Commit and merge:**
397
+ ```bash
398
+ git add -A && git commit -m "i18n: complete [scope] - N strings across M languages"
399
+ git checkout main
400
+ git merge i18n/...
401
+ ```
402
+
403
+ #### Post-completion: Update Memory (cm-continuity)
404
+
405
+ After final validation passes:
406
+ 1. Update `.cm/CONTINUITY.md` → Just Completed: "i18n: [N] strings across [M] languages"
407
+ 2. Record any NEW bug patterns to `.cm/memory/learnings.json` with `scope: "module:i18n"`
408
+ 3. **Anti-duplicate**: If same pattern as existing learning → reinforce (count++), don't create new entry
409
+
410
+ ---
411
+
412
+ ## Quick Reference: Key Naming Convention
413
+
414
+ | Namespace | Usage | Example |
415
+ |-----------|-------|---------|
416
+ | `common` | Shared UI (buttons, statuses) | `common.save`, `common.cancel` |
417
+ | `login` | Authentication flows | `login.welcome`, `login.forgot_pw` |
418
+ | `sidebar` | Navigation menu | `sidebar.dashboard`, `sidebar.logout` |
419
+ | `vio` | Violations module | `vio.confirm_title`, `vio.level_high` |
420
+
421
+ ---
422
+
423
+ ## The 13 Bug Categories — Quick Reference
424
+
425
+ | # | Bug | Pattern | Detection Gate |
426
+ |---|-----|---------|---------------|
427
+ | 1 | Single-quote wrapping `${t()}` | `= '..${t(..'` | Gate 3 |
428
+ | 2 | HTML tag corruption | `< div`, `</ div`, `-- >` | Gate 5 |
429
+ | 3 | Variable shadowing | `.map((t,` | Gate 6 |
430
+ | 4 | Mismatched delimiters | `t('key\`)`, `t(\`key')` | Gate 4 |
431
+ | 5 | Ternary nesting trap | Single-quote branch with `${t()}` | Gate 1 + 3 |
432
+ | 6 | Key parity failures | Missing keys in some languages | Phase 4 parity |
433
+ | 7 | Placeholder translation | `{{count}}` → `{{จำนวน}}` | Phase 4 placeholder check |
434
+ | 8 | Dynamic key concatenation | `t('nav.' + var)` | Static analysis |
435
+ | 9 | Backend pass, frontend broken | 572 tests green, white screen | Gate 1 + 8 |
436
+ | 10 | Regex fixing regex | Infinite fix-break loop | Use lexical scanner |
437
+ | 11 | Missed files | Only scanned app.js | Phase 1 scan ALL |
438
+ | 12 | Line number drift | Stale line refs across batches | Target by function name |
439
+ | 13 | **Flat vs nested key count mismatch** | Test vs Gate metrics | i18n-sync test design |
440
+
441
+ ---
442
+
443
+ ## Red Flags — STOP Immediately
444
+
445
+ - ❌ Converting >30 strings without running ALL 8 audit gates
446
+ - ❌ Using find-replace without verifying backtick vs single-quote context
447
+ - ❌ Committing all translations in a single commit
448
+ - ❌ Skipping key parity check across language files
449
+ - ❌ "It's just a string replacement, it'll be fine"
450
+
451
+ ## Rationalization Table
452
+
453
+ | Excuse | Reality |
454
+ |--------|---------|
455
+ | "It's just find-replace" | Find-replace destroyed app.js. MAX 30 strings per batch. |
456
+ | "The regex handles everything" | Regex false-positives crashed the app. 8 audit gates after each batch. |
457
+ | "I'll test at the end" | You won't find which of 600 changes broke it. Test after each 30. |
458
+ | "One commit is cleaner" | One commit = one rollback point for 600 changes. Granular commits. |
459
+
460
+ ## Integration with Other Skills
461
+
462
+ | Skill | When |
463
+ |-------|------|
464
+ | `cm-quality-gate` | Final test gate before deploy |
465
+ | `cm-execution` | Phase 4: Parallel language translation |
466
+ | `cm-terminal` | While running audit commands |
467
+ | `cm-continuity` | Phase 0: load i18n learnings; Post-completion: record new patterns |
468
+
469
+ ## The Bottom Line
470
+
471
+ **30 strings per batch. 8 audit gates after each. No exceptions.**
472
+
473
+ The i18n incidents of March 2026 produced 12 distinct bug categories. This skill encodes protections against every single one. Follow the protocol exactly.