codymaster 4.4.5 → 4.5.2

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 (197) hide show
  1. package/CHANGELOG.md +33 -0
  2. package/README.md +29 -14
  3. package/commands/demo.md +1 -1
  4. package/dist/context-bus.js +70 -0
  5. package/dist/context-db.js +265 -0
  6. package/dist/continuity.js +12 -0
  7. package/dist/file-watcher.js +79 -0
  8. package/dist/index.js +152 -1
  9. package/dist/l0-indexer.js +158 -0
  10. package/dist/mcp-context-server.js +400 -0
  11. package/dist/migrate-json-to-sqlite.js +126 -0
  12. package/dist/skill-chain.js +19 -3
  13. package/dist/token-budget.js +108 -0
  14. package/dist/uri-resolver.js +203 -0
  15. package/package.json +5 -1
  16. package/scripts/gate-0-secrets.js +63 -0
  17. package/scripts/gate-1-syntax.js +53 -0
  18. package/scripts/gate-5-dist-verify.js +55 -0
  19. package/scripts/gate-6-smoke-test.js +30 -0
  20. package/scripts/index-codebase.sh +552 -0
  21. package/scripts/mcp-bridge.js +284 -0
  22. package/scripts/postinstall.js +301 -0
  23. package/scripts/security-fixer.js +143 -0
  24. package/scripts/security-scan.js +55 -0
  25. package/scripts/test-gemini.js +13 -0
  26. package/scripts/todo-bridge.js +112 -0
  27. package/skills/_shared/helpers.md +50 -14
  28. package/skills/cm-autopilot/SKILL.md +29 -0
  29. package/skills/cm-autopilot/scripts/autopilot.py +190 -0
  30. package/skills/cm-continuity/SKILL.md +90 -28
  31. package/skills/cm-skill-chain/SKILL.md +47 -1
  32. package/skills/cm-start/SKILL.md +11 -2
  33. package/skills/boxme-git-config/SKILL.md +0 -56
  34. package/skills/boxme-local-dev/SKILL.md +0 -66
  35. package/skills/jobs-to-be-done/SKILL.md +0 -266
  36. package/skills/jobs-to-be-done/references/case-studies.md +0 -154
  37. package/skills/jobs-to-be-done/references/competitive-strategy.md +0 -280
  38. package/skills/jobs-to-be-done/references/diagnostics.md +0 -158
  39. package/skills/jobs-to-be-done/references/innovation-process.md +0 -392
  40. package/skills/jobs-to-be-done/references/organizational-change.md +0 -328
  41. package/skills/marketplace-report-crawler/SKILL.md +0 -176
  42. package/skills/marketplace-report-crawler/config/accounts.json +0 -41
  43. package/skills/marketplace-report-crawler/config/report-types.json +0 -422
  44. package/skills/marketplace-report-crawler/config/sessions.json +0 -3
  45. package/skills/marketplace-report-crawler/scripts/ab-wrapper.sh +0 -102
  46. package/skills/marketplace-report-crawler/scripts/browser-actions/lazada/lazada-actions.js +0 -114
  47. package/skills/marketplace-report-crawler/scripts/browser-actions/shopee/shopee-actions.js +0 -94
  48. package/skills/marketplace-report-crawler/scripts/browser-actions/tiktok/tiktok-actions.js +0 -272
  49. package/skills/marketplace-report-crawler/scripts/crawl-runner.js +0 -281
  50. package/skills/marketplace-report-crawler/scripts/session-check.sh +0 -72
  51. package/skills/marketplace-report-crawler/scripts/session-manager.sh +0 -349
  52. package/skills/marketplace-report-crawler/scripts/setup-folders.sh +0 -83
  53. package/skills/medical-research/SKILL.md +0 -194
  54. package/skills/medical-research/scripts/evidence_checker.py +0 -288
  55. package/skills/mom-test/SKILL.md +0 -267
  56. package/skills/mom-test/references/avoiding-bad-data.md +0 -221
  57. package/skills/mom-test/references/case-studies.md +0 -306
  58. package/skills/mom-test/references/commitment-advancement.md +0 -219
  59. package/skills/mom-test/references/finding-conversations.md +0 -251
  60. package/skills/mom-test/references/processing-learning.md +0 -256
  61. package/skills/mom-test/references/question-patterns.md +0 -198
  62. package/skills/pandasai-analytics/SKILL.md +0 -251
  63. package/skills/release-it/SKILL.md +0 -235
  64. package/skills/release-it/references/anti-patterns.md +0 -279
  65. package/skills/release-it/references/capacity-planning.md +0 -285
  66. package/skills/release-it/references/chaos-engineering.md +0 -325
  67. package/skills/release-it/references/deployment-strategies.md +0 -331
  68. package/skills/release-it/references/observability.md +0 -301
  69. package/skills/release-it/references/stability-patterns.md +0 -355
  70. package/skills/skill-creator-ultra/.agents/workflows/skill-audit.md +0 -37
  71. package/skills/skill-creator-ultra/.agents/workflows/skill-compare.md +0 -34
  72. package/skills/skill-creator-ultra/.agents/workflows/skill-export.md +0 -51
  73. package/skills/skill-creator-ultra/.agents/workflows/skill-generate.md +0 -39
  74. package/skills/skill-creator-ultra/.agents/workflows/skill-scaffold.md +0 -52
  75. package/skills/skill-creator-ultra/.agents/workflows/skill-simulate.md +0 -25
  76. package/skills/skill-creator-ultra/.agents/workflows/skill-stats.md +0 -31
  77. package/skills/skill-creator-ultra/.agents/workflows/skill-validate.md +0 -25
  78. package/skills/skill-creator-ultra/README.md +0 -1242
  79. package/skills/skill-creator-ultra/SKILL.md +0 -388
  80. package/skills/skill-creator-ultra/agents/analyzer.md +0 -274
  81. package/skills/skill-creator-ultra/agents/comparator.md +0 -202
  82. package/skills/skill-creator-ultra/agents/grader.md +0 -223
  83. package/skills/skill-creator-ultra/assets/eval_review.html +0 -146
  84. package/skills/skill-creator-ultra/eval-viewer/generate_review.py +0 -471
  85. package/skills/skill-creator-ultra/eval-viewer/viewer.html +0 -1325
  86. package/skills/skill-creator-ultra/examples/example_anthropic_frontend.md +0 -109
  87. package/skills/skill-creator-ultra/examples/example_anthropic_pdf.md +0 -116
  88. package/skills/skill-creator-ultra/examples/example_api_docs.md +0 -189
  89. package/skills/skill-creator-ultra/examples/example_db_migration.md +0 -253
  90. package/skills/skill-creator-ultra/examples/example_git_commit.md +0 -111
  91. package/skills/skill-creator-ultra/install.ps1 +0 -289
  92. package/skills/skill-creator-ultra/install.sh +0 -313
  93. package/skills/skill-creator-ultra/phases/phase1_interview.md +0 -202
  94. package/skills/skill-creator-ultra/phases/phase2_extract.md +0 -55
  95. package/skills/skill-creator-ultra/phases/phase3_detect.md +0 -57
  96. package/skills/skill-creator-ultra/phases/phase4_generate.md +0 -543
  97. package/skills/skill-creator-ultra/phases/phase5_test.md +0 -319
  98. package/skills/skill-creator-ultra/phases/phase6_eval.md +0 -301
  99. package/skills/skill-creator-ultra/phases/phase7_iterate.md +0 -103
  100. package/skills/skill-creator-ultra/phases/phase8_optimize.md +0 -113
  101. package/skills/skill-creator-ultra/resources/advanced_patterns.md +0 -499
  102. package/skills/skill-creator-ultra/resources/anti_patterns.md +0 -376
  103. package/skills/skill-creator-ultra/resources/blueprints.md +0 -498
  104. package/skills/skill-creator-ultra/resources/checklist.md +0 -243
  105. package/skills/skill-creator-ultra/resources/composition_cookbook.md +0 -291
  106. package/skills/skill-creator-ultra/resources/description_optimization.md +0 -90
  107. package/skills/skill-creator-ultra/resources/eval_guide.md +0 -133
  108. package/skills/skill-creator-ultra/resources/industry_questions.md +0 -189
  109. package/skills/skill-creator-ultra/resources/interview_questions.md +0 -200
  110. package/skills/skill-creator-ultra/resources/pattern_detection.md +0 -200
  111. package/skills/skill-creator-ultra/resources/prompt_engineering.md +0 -531
  112. package/skills/skill-creator-ultra/resources/schemas.md +0 -430
  113. package/skills/skill-creator-ultra/resources/script_integration.md +0 -593
  114. package/skills/skill-creator-ultra/resources/scripts_guide.md +0 -339
  115. package/skills/skill-creator-ultra/resources/skill_template.md +0 -124
  116. package/skills/skill-creator-ultra/resources/skill_writing_guide.md +0 -634
  117. package/skills/skill-creator-ultra/resources/versioning_guide.md +0 -193
  118. package/skills/skill-creator-ultra/scripts/ci_eval.py +0 -200
  119. package/skills/skill-creator-ultra/scripts/package_skill.py +0 -165
  120. package/skills/skill-creator-ultra/scripts/simulate_skill.py +0 -398
  121. package/skills/skill-creator-ultra/scripts/skill_audit.py +0 -611
  122. package/skills/skill-creator-ultra/scripts/skill_compare.py +0 -265
  123. package/skills/skill-creator-ultra/scripts/skill_export.py +0 -334
  124. package/skills/skill-creator-ultra/scripts/skill_scaffold.py +0 -403
  125. package/skills/skill-creator-ultra/scripts/skill_stats.py +0 -339
  126. package/skills/skill-creator-ultra/scripts/validate_skill.py +0 -411
  127. package/skills/tailwind-mastery/SKILL.md +0 -229
  128. package/skills/vercel-react-best-practices/AGENTS.md +0 -3373
  129. package/skills/vercel-react-best-practices/README.md +0 -123
  130. package/skills/vercel-react-best-practices/SKILL.md +0 -143
  131. package/skills/vercel-react-best-practices/rules/_sections.md +0 -46
  132. package/skills/vercel-react-best-practices/rules/_template.md +0 -28
  133. package/skills/vercel-react-best-practices/rules/advanced-event-handler-refs.md +0 -55
  134. package/skills/vercel-react-best-practices/rules/advanced-init-once.md +0 -42
  135. package/skills/vercel-react-best-practices/rules/advanced-use-latest.md +0 -39
  136. package/skills/vercel-react-best-practices/rules/async-api-routes.md +0 -38
  137. package/skills/vercel-react-best-practices/rules/async-defer-await.md +0 -80
  138. package/skills/vercel-react-best-practices/rules/async-dependencies.md +0 -51
  139. package/skills/vercel-react-best-practices/rules/async-parallel.md +0 -28
  140. package/skills/vercel-react-best-practices/rules/async-suspense-boundaries.md +0 -99
  141. package/skills/vercel-react-best-practices/rules/bundle-barrel-imports.md +0 -59
  142. package/skills/vercel-react-best-practices/rules/bundle-conditional.md +0 -31
  143. package/skills/vercel-react-best-practices/rules/bundle-defer-third-party.md +0 -49
  144. package/skills/vercel-react-best-practices/rules/bundle-dynamic-imports.md +0 -35
  145. package/skills/vercel-react-best-practices/rules/bundle-preload.md +0 -50
  146. package/skills/vercel-react-best-practices/rules/client-event-listeners.md +0 -74
  147. package/skills/vercel-react-best-practices/rules/client-localstorage-schema.md +0 -71
  148. package/skills/vercel-react-best-practices/rules/client-passive-event-listeners.md +0 -48
  149. package/skills/vercel-react-best-practices/rules/client-swr-dedup.md +0 -56
  150. package/skills/vercel-react-best-practices/rules/js-batch-dom-css.md +0 -107
  151. package/skills/vercel-react-best-practices/rules/js-cache-function-results.md +0 -80
  152. package/skills/vercel-react-best-practices/rules/js-cache-property-access.md +0 -28
  153. package/skills/vercel-react-best-practices/rules/js-cache-storage.md +0 -70
  154. package/skills/vercel-react-best-practices/rules/js-combine-iterations.md +0 -32
  155. package/skills/vercel-react-best-practices/rules/js-early-exit.md +0 -50
  156. package/skills/vercel-react-best-practices/rules/js-flatmap-filter.md +0 -60
  157. package/skills/vercel-react-best-practices/rules/js-hoist-regexp.md +0 -45
  158. package/skills/vercel-react-best-practices/rules/js-index-maps.md +0 -37
  159. package/skills/vercel-react-best-practices/rules/js-length-check-first.md +0 -49
  160. package/skills/vercel-react-best-practices/rules/js-min-max-loop.md +0 -82
  161. package/skills/vercel-react-best-practices/rules/js-set-map-lookups.md +0 -24
  162. package/skills/vercel-react-best-practices/rules/js-tosorted-immutable.md +0 -57
  163. package/skills/vercel-react-best-practices/rules/rendering-activity.md +0 -26
  164. package/skills/vercel-react-best-practices/rules/rendering-animate-svg-wrapper.md +0 -47
  165. package/skills/vercel-react-best-practices/rules/rendering-conditional-render.md +0 -40
  166. package/skills/vercel-react-best-practices/rules/rendering-content-visibility.md +0 -38
  167. package/skills/vercel-react-best-practices/rules/rendering-hoist-jsx.md +0 -46
  168. package/skills/vercel-react-best-practices/rules/rendering-hydration-no-flicker.md +0 -82
  169. package/skills/vercel-react-best-practices/rules/rendering-hydration-suppress-warning.md +0 -30
  170. package/skills/vercel-react-best-practices/rules/rendering-resource-hints.md +0 -85
  171. package/skills/vercel-react-best-practices/rules/rendering-script-defer-async.md +0 -68
  172. package/skills/vercel-react-best-practices/rules/rendering-svg-precision.md +0 -28
  173. package/skills/vercel-react-best-practices/rules/rendering-usetransition-loading.md +0 -75
  174. package/skills/vercel-react-best-practices/rules/rerender-defer-reads.md +0 -39
  175. package/skills/vercel-react-best-practices/rules/rerender-dependencies.md +0 -45
  176. package/skills/vercel-react-best-practices/rules/rerender-derived-state-no-effect.md +0 -40
  177. package/skills/vercel-react-best-practices/rules/rerender-derived-state.md +0 -29
  178. package/skills/vercel-react-best-practices/rules/rerender-functional-setstate.md +0 -74
  179. package/skills/vercel-react-best-practices/rules/rerender-lazy-state-init.md +0 -58
  180. package/skills/vercel-react-best-practices/rules/rerender-memo-with-default-value.md +0 -38
  181. package/skills/vercel-react-best-practices/rules/rerender-memo.md +0 -44
  182. package/skills/vercel-react-best-practices/rules/rerender-move-effect-to-event.md +0 -45
  183. package/skills/vercel-react-best-practices/rules/rerender-no-inline-components.md +0 -82
  184. package/skills/vercel-react-best-practices/rules/rerender-simple-expression-in-memo.md +0 -35
  185. package/skills/vercel-react-best-practices/rules/rerender-split-combined-hooks.md +0 -64
  186. package/skills/vercel-react-best-practices/rules/rerender-transitions.md +0 -40
  187. package/skills/vercel-react-best-practices/rules/rerender-use-deferred-value.md +0 -59
  188. package/skills/vercel-react-best-practices/rules/rerender-use-ref-transient-values.md +0 -73
  189. package/skills/vercel-react-best-practices/rules/server-after-nonblocking.md +0 -73
  190. package/skills/vercel-react-best-practices/rules/server-auth-actions.md +0 -96
  191. package/skills/vercel-react-best-practices/rules/server-cache-lru.md +0 -41
  192. package/skills/vercel-react-best-practices/rules/server-cache-react.md +0 -76
  193. package/skills/vercel-react-best-practices/rules/server-dedup-props.md +0 -65
  194. package/skills/vercel-react-best-practices/rules/server-hoist-static-io.md +0 -142
  195. package/skills/vercel-react-best-practices/rules/server-parallel-fetching.md +0 -83
  196. package/skills/vercel-react-best-practices/rules/server-serialization.md +0 -38
  197. package/skills/web-design-guidelines/SKILL.md +0 -39
@@ -0,0 +1,108 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.getDefaultBudget = getDefaultBudget;
7
+ exports.loadBudget = loadBudget;
8
+ exports.checkBudget = checkBudget;
9
+ exports.estimateTokens = estimateTokens;
10
+ exports.generateBudgetReport = generateBudgetReport;
11
+ const fs_1 = __importDefault(require("fs"));
12
+ const path_1 = __importDefault(require("path"));
13
+ // ─── Constants ──────────────────────────────────────────────────────────────
14
+ const CM_DIR = '.cm';
15
+ const BUDGET_FILE = 'token-budget.json';
16
+ // ─── Default Budget ─────────────────────────────────────────────────────────
17
+ function getDefaultBudget() {
18
+ return {
19
+ model_context_window: 200000,
20
+ allocations: {
21
+ system_prompt: 5000, // 2.5%
22
+ skill_index_L0: 2500, // 1.25%
23
+ skill_active_full: 5000, // 2.5%
24
+ memory_working: 500, // 0.25%
25
+ memory_learnings: 650, // 0.325%
26
+ codebase_skeleton: 1500, // 0.75%
27
+ context_retrieval: 10000, // 5%
28
+ conversation_history: 30000, // 15%
29
+ generation_budget: 144850, // 72.425%
30
+ },
31
+ enforcement: 'soft',
32
+ };
33
+ }
34
+ // ─── Load Budget ────────────────────────────────────────────────────────────
35
+ function loadBudget(projectPath) {
36
+ const budgetPath = path_1.default.join(projectPath, CM_DIR, BUDGET_FILE);
37
+ if (!fs_1.default.existsSync(budgetPath)) {
38
+ return getDefaultBudget();
39
+ }
40
+ try {
41
+ const raw = fs_1.default.readFileSync(budgetPath, 'utf-8');
42
+ return JSON.parse(raw);
43
+ }
44
+ catch (_a) {
45
+ return getDefaultBudget();
46
+ }
47
+ }
48
+ // ─── Check Budget ────────────────────────────────────────────────────────────
49
+ function checkBudget(budget, category, tokenCount) {
50
+ const allocs = budget.allocations;
51
+ const allocated = allocs[category];
52
+ if (allocated === undefined) {
53
+ return {
54
+ allowed: false,
55
+ remaining: 0,
56
+ suggestion: `Unknown category "${category}". Valid: ${Object.keys(allocs).join(', ')}`,
57
+ };
58
+ }
59
+ const remaining = allocated - tokenCount;
60
+ const overBudget = remaining < 0;
61
+ if (!overBudget) {
62
+ return { allowed: true, remaining };
63
+ }
64
+ const suggestion = buildSuggestion(category, tokenCount, allocated);
65
+ if (budget.enforcement === 'hard') {
66
+ return { allowed: false, remaining, suggestion };
67
+ }
68
+ // Soft mode: allow but warn
69
+ return { allowed: true, remaining, suggestion };
70
+ }
71
+ function buildSuggestion(category, used, allocated) {
72
+ const over = used - allocated;
73
+ if (category === 'memory_learnings') {
74
+ return `memory_learnings over by ~${over} tokens. Switch to L0 index (cm://memory/learnings/L0) to reduce to ~100 tokens.`;
75
+ }
76
+ if (category === 'codebase_skeleton') {
77
+ return `codebase_skeleton over by ~${over} tokens. Use cm://resources/skeleton/L0 for module-level index (~500 tokens).`;
78
+ }
79
+ if (category === 'memory_working') {
80
+ return `memory_working over by ~${over} tokens. Read CONTINUITY abstract only (first 3 lines).`;
81
+ }
82
+ return `${category} over budget by ~${over} tokens. Consider using L0 index instead of full content.`;
83
+ }
84
+ // ─── Estimate Tokens ─────────────────────────────────────────────────────────
85
+ function estimateTokens(text) {
86
+ if (!text)
87
+ return 0;
88
+ return Math.ceil(text.length / 4);
89
+ }
90
+ // ─── Budget Report ────────────────────────────────────────────────────────────
91
+ function generateBudgetReport(budget) {
92
+ const total = budget.model_context_window;
93
+ const lines = [
94
+ `Token Budget Report (${total.toLocaleString()} context window, enforcement: ${budget.enforcement})`,
95
+ '─'.repeat(70),
96
+ `${'Category'.padEnd(25)} ${'Allocated'.padStart(10)} ${'% of CTX'.padStart(10)}`,
97
+ '─'.repeat(70),
98
+ ];
99
+ const allocs = budget.allocations;
100
+ for (const [cat, allocated] of Object.entries(allocs)) {
101
+ const pct = ((allocated / total) * 100).toFixed(2);
102
+ lines.push(`${cat.padEnd(25)} ${allocated.toLocaleString().padStart(10)} ${(pct + '%').padStart(10)}`);
103
+ }
104
+ const sum = Object.values(allocs).reduce((a, b) => a + b, 0);
105
+ lines.push('─'.repeat(70));
106
+ lines.push(`${'TOTAL'.padEnd(25)} ${sum.toLocaleString().padStart(10)} ${(((sum / total) * 100).toFixed(2) + '%').padStart(10)}`);
107
+ return lines.join('\n');
108
+ }
@@ -0,0 +1,203 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.resolve = resolve;
7
+ const fs_1 = __importDefault(require("fs"));
8
+ const path_1 = __importDefault(require("path"));
9
+ const context_db_1 = require("./context-db");
10
+ const context_bus_1 = require("./context-bus");
11
+ // ─── Main Resolver ───────────────────────────────────────────────────────────
12
+ /**
13
+ * Resolve a cm:// URI to content at the requested depth.
14
+ *
15
+ * URI patterns:
16
+ * cm://memory/working → CONTINUITY.md abstract (L0) or full (L2)
17
+ * cm://memory/learnings → learnings index (L0) or all learnings (L2)
18
+ * cm://memory/learnings/{id} → specific learning by ID
19
+ * cm://memory/decisions → decisions index (L0) or all (L2)
20
+ * cm://skills/{name} → SKILL.md at depth
21
+ * cm://skills/{name}/L0 → index entry only
22
+ * cm://resources/skeleton → skeleton-index.md (L0) or full (L2)
23
+ * cm://resources/architecture → architecture.mmd
24
+ * cm://pipeline/current → context bus state
25
+ */
26
+ function resolve(uri, projectPath, depth = 'L1') {
27
+ if (!uri.startsWith('cm://')) {
28
+ return notFound(uri, depth, `URI must start with cm://`);
29
+ }
30
+ const rest = uri.slice('cm://'.length); // e.g. "memory/learnings/L005"
31
+ const parts = rest.split('/').filter(Boolean);
32
+ if (parts.length === 0) {
33
+ return notFound(uri, depth, 'Empty URI path');
34
+ }
35
+ const [ns, ...tail] = parts;
36
+ switch (ns) {
37
+ case 'memory': return resolveMemory(uri, tail, projectPath, depth);
38
+ case 'skills': return resolveSkill(uri, tail, projectPath, depth);
39
+ case 'resources': return resolveResource(uri, tail, projectPath, depth);
40
+ case 'pipeline': return resolvePipeline(uri, tail, projectPath, depth);
41
+ default:
42
+ return notFound(uri, depth, `Unknown namespace "${ns}". Valid: memory, skills, resources, pipeline`);
43
+ }
44
+ }
45
+ // ─── memory/* ────────────────────────────────────────────────────────────────
46
+ function resolveMemory(uri, tail, projectPath, depth) {
47
+ const [resource, id] = tail;
48
+ switch (resource) {
49
+ case 'working': {
50
+ const contPath = path_1.default.join(projectPath, '.cm', 'CONTINUITY.md');
51
+ if (!fs_1.default.existsSync(contPath))
52
+ return notFound(uri, depth, 'CONTINUITY.md not found');
53
+ const full = fs_1.default.readFileSync(contPath, 'utf-8');
54
+ if (depth === 'L0' || depth === 'L1') {
55
+ // Return first 10 non-empty lines as abstract
56
+ const abstract = full.split('\n').filter(l => l.trim()).slice(0, 10).join('\n');
57
+ return found(uri, depth, abstract);
58
+ }
59
+ return found(uri, depth, full);
60
+ }
61
+ case 'learnings': {
62
+ if (id) {
63
+ // cm://memory/learnings/L005 — specific entry
64
+ const dbPath = (0, context_db_1.getDbPath)(projectPath);
65
+ const learning = (0, context_db_1.getLearningById)(dbPath, id);
66
+ if (!learning)
67
+ return notFound(uri, depth, `Learning "${id}" not found`);
68
+ return found(uri, depth, formatLearning(learning));
69
+ }
70
+ if (depth === 'L0') {
71
+ // Return cached L0 index
72
+ const indexPath = path_1.default.join(projectPath, '.cm', 'learnings-index.md');
73
+ if (fs_1.default.existsSync(indexPath)) {
74
+ return found(uri, depth, fs_1.default.readFileSync(indexPath, 'utf-8'));
75
+ }
76
+ }
77
+ // L1/L2: query all from SQLite
78
+ const dbPath = (0, context_db_1.getDbPath)(projectPath);
79
+ const learnings = (0, context_db_1.queryLearnings)(dbPath, '', undefined, 50);
80
+ if (learnings.length === 0) {
81
+ // Fallback to JSON file
82
+ const jsonPath = path_1.default.join(projectPath, '.cm', 'memory', 'learnings.json');
83
+ if (fs_1.default.existsSync(jsonPath)) {
84
+ return found(uri, depth, fs_1.default.readFileSync(jsonPath, 'utf-8'));
85
+ }
86
+ return found(uri, depth, '[]');
87
+ }
88
+ return found(uri, depth, JSON.stringify(learnings, null, 2));
89
+ }
90
+ case 'decisions': {
91
+ if (depth === 'L0') {
92
+ // Short list of decision IDs + 1-line summary
93
+ const dbPath = (0, context_db_1.getDbPath)(projectPath);
94
+ const decisions = (0, context_db_1.queryDecisions)(dbPath, '', 20);
95
+ const lines = ['# Decisions Index', ''];
96
+ for (const d of decisions) {
97
+ lines.push(`- ${d.id}: ${d.decision.slice(0, 80)}`);
98
+ }
99
+ return found(uri, depth, lines.join('\n'));
100
+ }
101
+ const dbPath = (0, context_db_1.getDbPath)(projectPath);
102
+ const decisions = (0, context_db_1.queryDecisions)(dbPath, '', 50);
103
+ if (decisions.length === 0) {
104
+ const jsonPath = path_1.default.join(projectPath, '.cm', 'memory', 'decisions.json');
105
+ if (fs_1.default.existsSync(jsonPath)) {
106
+ return found(uri, depth, fs_1.default.readFileSync(jsonPath, 'utf-8'));
107
+ }
108
+ return found(uri, depth, '[]');
109
+ }
110
+ return found(uri, depth, JSON.stringify(decisions, null, 2));
111
+ }
112
+ default:
113
+ return notFound(uri, depth, `Unknown memory resource "${resource}". Valid: working, learnings, decisions`);
114
+ }
115
+ }
116
+ // ─── skills/* ────────────────────────────────────────────────────────────────
117
+ function resolveSkill(uri, tail, projectPath, depth) {
118
+ const [skillName, depthOverride] = tail;
119
+ if (!skillName)
120
+ return notFound(uri, depth, 'Skill name required: cm://skills/{name}');
121
+ const effectiveDepth = depthOverride || depth;
122
+ // Look in project skills/ dir, then global ~/.claude/skills/
123
+ const candidates = [
124
+ path_1.default.join(projectPath, 'skills', skillName, 'SKILL.md'),
125
+ path_1.default.join(projectPath, '.claude', 'skills', skillName, 'SKILL.md'),
126
+ path_1.default.join(process.env.HOME || '', '.claude', 'skills', skillName, 'SKILL.md'),
127
+ ];
128
+ const skillPath = candidates.find(p => fs_1.default.existsSync(p));
129
+ if (!skillPath)
130
+ return notFound(uri, depth, `Skill "${skillName}" not found`);
131
+ const full = fs_1.default.readFileSync(skillPath, 'utf-8');
132
+ if (effectiveDepth === 'L0') {
133
+ // Front matter + description only (~50 tokens)
134
+ const lines = full.split('\n');
135
+ const summary = lines.slice(0, 10).join('\n');
136
+ return found(uri, effectiveDepth, summary);
137
+ }
138
+ if (effectiveDepth === 'L1') {
139
+ // First 40 lines (~600 tokens)
140
+ return found(uri, effectiveDepth, full.split('\n').slice(0, 40).join('\n'));
141
+ }
142
+ return found(uri, effectiveDepth, full);
143
+ }
144
+ // ─── resources/* ─────────────────────────────────────────────────────────────
145
+ function resolveResource(uri, tail, projectPath, depth) {
146
+ const [resource] = tail;
147
+ switch (resource) {
148
+ case 'skeleton': {
149
+ if (depth === 'L0' || depth === 'L1') {
150
+ const indexPath = path_1.default.join(projectPath, '.cm', 'skeleton-index.md');
151
+ if (fs_1.default.existsSync(indexPath)) {
152
+ return found(uri, depth, fs_1.default.readFileSync(indexPath, 'utf-8'));
153
+ }
154
+ }
155
+ const fullPath = path_1.default.join(projectPath, '.cm', 'skeleton.md');
156
+ if (!fs_1.default.existsSync(fullPath))
157
+ return notFound(uri, depth, 'skeleton.md not found — run: cm continuity index');
158
+ return found(uri, depth, fs_1.default.readFileSync(fullPath, 'utf-8'));
159
+ }
160
+ case 'architecture': {
161
+ const mmdPath = path_1.default.join(projectPath, '.cm', 'architecture.mmd');
162
+ if (!fs_1.default.existsSync(mmdPath))
163
+ return notFound(uri, depth, 'architecture.mmd not found');
164
+ return found(uri, depth, fs_1.default.readFileSync(mmdPath, 'utf-8'));
165
+ }
166
+ default:
167
+ return notFound(uri, depth, `Unknown resource "${resource}". Valid: skeleton, architecture`);
168
+ }
169
+ }
170
+ // ─── pipeline/* ──────────────────────────────────────────────────────────────
171
+ function resolvePipeline(uri, tail, projectPath, depth) {
172
+ const [sub] = tail;
173
+ if (!sub || sub === 'current') {
174
+ const bus = (0, context_bus_1.readBus)(projectPath);
175
+ if (!bus)
176
+ return notFound(uri, depth, 'No active context bus. Start a chain first.');
177
+ if (depth === 'L0') {
178
+ const summary = `Pipeline: ${bus.pipeline} | Step: ${bus.current_step} | Steps done: ${Object.keys(bus.shared_context).length}`;
179
+ return found(uri, depth, summary);
180
+ }
181
+ return found(uri, depth, JSON.stringify(bus, null, 2));
182
+ }
183
+ return notFound(uri, depth, `Unknown pipeline resource "${sub}"`);
184
+ }
185
+ // ─── Helpers ──────────────────────────────────────────────────────────────────
186
+ function found(uri, depth, content) {
187
+ return { uri, depth, content, tokenEstimate: Math.ceil(content.length / 4), found: true };
188
+ }
189
+ function notFound(uri, depth, reason) {
190
+ const content = `# Not Found\n\nURI: ${uri}\nReason: ${reason}`;
191
+ return { uri, depth, content, tokenEstimate: Math.ceil(content.length / 4), found: false };
192
+ }
193
+ function formatLearning(l) {
194
+ var _a, _b;
195
+ if (!l)
196
+ return '';
197
+ return [
198
+ `### ${l.id}: ${l.what_failed}`,
199
+ `- **Why:** ${l.why_failed}`,
200
+ `- **Fix:** ${l.how_to_prevent}`,
201
+ `- **Scope:** ${(_a = l.scope) !== null && _a !== void 0 ? _a : 'global'} | **TTL:** ${(_b = l.ttl) !== null && _b !== void 0 ? _b : 60}d`,
202
+ ].join('\n');
203
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "codymaster",
3
- "version": "4.4.5",
3
+ "version": "4.5.2",
4
4
  "description": "68+ Skills. Ship 10x faster. AI-powered coding skill kit for Claude, Cursor, Gemini & more.",
5
5
  "main": "dist/index.js",
6
6
  "repository": {
@@ -46,6 +46,7 @@
46
46
  "type": "commonjs",
47
47
  "files": [
48
48
  "dist/",
49
+ "scripts/",
49
50
  "skills/",
50
51
  "adapters/",
51
52
  "commands/",
@@ -59,12 +60,15 @@
59
60
  },
60
61
  "dependencies": {
61
62
  "@clack/prompts": "^1.1.0",
63
+ "better-sqlite3": "^12.8.0",
62
64
  "chalk": "^5.6.2",
65
+ "chokidar": "^5.0.0",
63
66
  "commander": "^14.0.3",
64
67
  "express": "^5.2.1",
65
68
  "prompts": "^2.4.2"
66
69
  },
67
70
  "devDependencies": {
71
+ "@types/better-sqlite3": "^7.6.13",
68
72
  "@types/express": "^5.0.6",
69
73
  "@types/node": "^25.5.0",
70
74
  "@types/prompts": "^2.4.9",
@@ -0,0 +1,63 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Gate 0: Secret Hygiene
4
+ * Fastest gate (< 0.5s). Checks for leaked secrets before anything else runs.
5
+ */
6
+ const fs = require('fs');
7
+ const { execSync } = require('child_process');
8
+
9
+ let failed = false;
10
+
11
+ // 1. Check wrangler config files for hardcoded secret values
12
+ const wranglerFiles = ['wrangler.toml', 'wrangler.jsonc', 'wrangler.json'];
13
+ const dangerous = [
14
+ 'SERVICE_KEY', 'ANON_KEY', 'DB_PASSWORD', 'SECRET_KEY', 'PRIVATE_KEY', 'API_SECRET',
15
+ 'GCP_SERVICE_ACCOUNT', 'AZURE_CONNECTION_STRING', 'HEROKU_API_KEY', 'POSTMAN_API_KEY'
16
+ ];
17
+
18
+ for (const wf of wranglerFiles) {
19
+ if (!fs.existsSync(wf)) continue;
20
+ const src = fs.readFileSync(wf, 'utf-8');
21
+ for (const key of dangerous) {
22
+ const valuePattern = new RegExp(key + '\\s*[=:]\\s*["\'][a-zA-Z0-9/+=]{20,}', 'g');
23
+ if (valuePattern.test(src)) {
24
+ console.error('āŒ DANGEROUS: ' + wf + ' contains a ' + key + ' VALUE');
25
+ console.error(' Fix: wrangler secret put ' + key + ' (then remove from ' + wf + ')');
26
+ failed = true;
27
+ }
28
+ }
29
+ }
30
+
31
+ // 2. Check .gitignore has required patterns
32
+ if (fs.existsSync('.gitignore')) {
33
+ const gi = fs.readFileSync('.gitignore', 'utf-8');
34
+ const required = ['.env', '.dev.vars'];
35
+ const missing = required.filter(r => !gi.includes(r));
36
+ if (missing.length > 0) {
37
+ console.error('āŒ .gitignore missing: ' + missing.join(', '));
38
+ failed = true;
39
+ }
40
+ } else {
41
+ console.error('āŒ No .gitignore found!');
42
+ failed = true;
43
+ }
44
+
45
+ // 3. Check .env / .dev.vars files aren't tracked by git
46
+ try {
47
+ const tracked = execSync('git ls-files', { encoding: 'utf-8' });
48
+ const badFiles = ['.env', '.dev.vars', '.env.local', '.env.production'];
49
+ const trackedBad = badFiles.filter(f => tracked.split('\n').includes(f));
50
+ if (trackedBad.length > 0) {
51
+ console.error('āŒ CRITICAL: Secret files tracked by git: ' + trackedBad.join(', '));
52
+ console.error(' Fix: git rm --cached ' + trackedBad.join(' '));
53
+ failed = true;
54
+ }
55
+ } catch (e) {
56
+ // Not a git repo — skip
57
+ }
58
+
59
+ if (failed) {
60
+ console.error('\nšŸ›”ļø Gate 0 FAILED. Fix issues above before deploying.');
61
+ process.exit(1);
62
+ }
63
+ console.log('āœ… Gate 0 passed: secret hygiene verified');
@@ -0,0 +1,53 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Gate 1: Syntax Validation
4
+ * Fast-fail (< 2s). Catches syntax errors before the slower test suite.
5
+ * - Parses all JS files in public/js/ with acorn
6
+ * - Runs tsc --noEmit for TypeScript in src/
7
+ */
8
+ const { parse } = require('acorn');
9
+ const fs = require('fs');
10
+ const path = require('path');
11
+ const { execSync } = require('child_process');
12
+
13
+ let failed = false;
14
+
15
+ // 1. Parse all JS files in public/js/
16
+ const jsDir = 'public/js';
17
+ if (fs.existsSync(jsDir)) {
18
+ const jsFiles = fs.readdirSync(jsDir).filter(f => f.endsWith('.js'));
19
+ for (const file of jsFiles) {
20
+ const filePath = path.join(jsDir, file);
21
+ const code = fs.readFileSync(filePath, 'utf-8');
22
+ try {
23
+ parse(code, { ecmaVersion: 2022, sourceType: 'script' });
24
+ } catch (err) {
25
+ console.error(`āŒ Syntax error in ${filePath}:`);
26
+ console.error(` Line ${err.loc?.line}, Column ${err.loc?.column}: ${err.message}`);
27
+ failed = true;
28
+ }
29
+ }
30
+ if (!failed) {
31
+ console.log(`āœ… ${jsFiles.length} JS files parsed successfully`);
32
+ }
33
+ } else {
34
+ console.log('⚠ No public/js/ directory found, skipping JS syntax check');
35
+ }
36
+
37
+ // 2. TypeScript compilation check
38
+ if (fs.existsSync('tsconfig.json')) {
39
+ try {
40
+ execSync('npx tsc --noEmit', { encoding: 'utf-8', stdio: 'pipe' });
41
+ console.log('āœ… TypeScript compilation check passed');
42
+ } catch (err) {
43
+ console.error('āŒ TypeScript compilation errors:');
44
+ console.error(err.stdout || err.stderr || err.message);
45
+ failed = true;
46
+ }
47
+ }
48
+
49
+ if (failed) {
50
+ console.error('\nšŸ”“ Gate 1 FAILED. Fix syntax errors before proceeding.');
51
+ process.exit(1);
52
+ }
53
+ console.log('āœ… Gate 1 passed: syntax validation complete');
@@ -0,0 +1,55 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Gate 5: Dist Asset Verification
4
+ * Verifies critical files exist in public/ after build:html + docs:build.
5
+ * Build can "succeed" but produce an incomplete output directory.
6
+ */
7
+ const fs = require('fs');
8
+ const path = require('path');
9
+
10
+ const publicDir = 'public';
11
+ // Critical HTML pages
12
+ const requiredHtml = [
13
+ 'dashboard/index.html',
14
+ ];
15
+
16
+ // Critical JS files
17
+ const requiredJs = [
18
+ 'dashboard/app.js',
19
+ ];
20
+
21
+ // Critical CSS files
22
+ const requiredCss = [
23
+ 'dashboard/style.css',
24
+ ];
25
+
26
+ // Build required file list
27
+ const required = [];
28
+
29
+ // HTML pages
30
+ for (const html of requiredHtml) {
31
+ required.push(path.join(publicDir, html));
32
+ }
33
+
34
+ // JS files
35
+ for (const js of requiredJs) {
36
+ required.push(path.join(publicDir, js));
37
+ }
38
+
39
+ // CSS files
40
+ for (const css of requiredCss) {
41
+ required.push(path.join(publicDir, css));
42
+ }
43
+
44
+
45
+ // Check all required files
46
+ const missing = required.filter(f => !fs.existsSync(f));
47
+
48
+ if (missing.length > 0) {
49
+ console.error('āŒ Missing critical files:');
50
+ missing.forEach(f => console.error(' ' + f));
51
+ console.error(`\nšŸ”“ Gate 5 FAILED. ${missing.length} file(s) missing from build output.`);
52
+ process.exit(1);
53
+ }
54
+
55
+ console.log(`āœ… Gate 5 passed: all ${required.length} critical files present`);
@@ -0,0 +1,30 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Gate 6: Post-Deploy Smoke Test
4
+ * Verifies the deployed site returns HTTP 200.
5
+ * Usage: node scripts/gate-6-smoke-test.js [optional-url]
6
+ */
7
+
8
+ const DEPLOY_URL = process.argv[2] || process.env.DEPLOY_URL || 'https://cody.todyle.com';
9
+
10
+ async function smokeTest() {
11
+ console.log(`šŸ” Smoke testing: ${DEPLOY_URL}`);
12
+
13
+ try {
14
+ const res = await fetch(DEPLOY_URL);
15
+ if (res.status === 200) {
16
+ console.log(`āœ… Gate 6 passed: HTTP ${res.status} from ${DEPLOY_URL}`);
17
+ } else {
18
+ console.error(`āŒ Gate 6 FAILED: HTTP ${res.status} from ${DEPLOY_URL}`);
19
+ console.error(' ⚠ Consider immediate rollback.');
20
+ process.exit(1);
21
+ }
22
+ } catch (err) {
23
+ console.error(`āŒ Gate 6 FAILED: Could not reach ${DEPLOY_URL}`);
24
+ console.error(` Error: ${err.message}`);
25
+ console.error(' ⚠ Consider immediate rollback.');
26
+ process.exit(1);
27
+ }
28
+ }
29
+
30
+ smokeTest();