codymaster 4.4.4 → 4.5.1

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 (190) 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 +7 -1
  16. package/skills/_shared/helpers.md +50 -14
  17. package/skills/cm-autopilot/SKILL.md +29 -0
  18. package/skills/cm-autopilot/scripts/autopilot.py +190 -0
  19. package/skills/cm-continuity/SKILL.md +90 -28
  20. package/skills/cm-quality-gate/SKILL.md +11 -1
  21. package/skills/cm-safe-deploy/SKILL.md +38 -2
  22. package/skills/cm-security-gate/SKILL.md +158 -34
  23. package/skills/cm-skill-chain/SKILL.md +47 -1
  24. package/skills/cm-start/SKILL.md +11 -2
  25. package/skills/cm-test-gate/SKILL.md +3 -0
  26. package/skills/boxme-git-config/SKILL.md +0 -56
  27. package/skills/boxme-local-dev/SKILL.md +0 -66
  28. package/skills/jobs-to-be-done/SKILL.md +0 -266
  29. package/skills/jobs-to-be-done/references/case-studies.md +0 -154
  30. package/skills/jobs-to-be-done/references/competitive-strategy.md +0 -280
  31. package/skills/jobs-to-be-done/references/diagnostics.md +0 -158
  32. package/skills/jobs-to-be-done/references/innovation-process.md +0 -392
  33. package/skills/jobs-to-be-done/references/organizational-change.md +0 -328
  34. package/skills/marketplace-report-crawler/SKILL.md +0 -176
  35. package/skills/marketplace-report-crawler/config/accounts.json +0 -41
  36. package/skills/marketplace-report-crawler/config/report-types.json +0 -422
  37. package/skills/marketplace-report-crawler/config/sessions.json +0 -3
  38. package/skills/marketplace-report-crawler/scripts/ab-wrapper.sh +0 -102
  39. package/skills/marketplace-report-crawler/scripts/browser-actions/lazada/lazada-actions.js +0 -114
  40. package/skills/marketplace-report-crawler/scripts/browser-actions/shopee/shopee-actions.js +0 -94
  41. package/skills/marketplace-report-crawler/scripts/browser-actions/tiktok/tiktok-actions.js +0 -272
  42. package/skills/marketplace-report-crawler/scripts/crawl-runner.js +0 -281
  43. package/skills/marketplace-report-crawler/scripts/session-check.sh +0 -72
  44. package/skills/marketplace-report-crawler/scripts/session-manager.sh +0 -349
  45. package/skills/marketplace-report-crawler/scripts/setup-folders.sh +0 -83
  46. package/skills/medical-research/SKILL.md +0 -194
  47. package/skills/medical-research/scripts/evidence_checker.py +0 -288
  48. package/skills/mom-test/SKILL.md +0 -267
  49. package/skills/mom-test/references/avoiding-bad-data.md +0 -221
  50. package/skills/mom-test/references/case-studies.md +0 -306
  51. package/skills/mom-test/references/commitment-advancement.md +0 -219
  52. package/skills/mom-test/references/finding-conversations.md +0 -251
  53. package/skills/mom-test/references/processing-learning.md +0 -256
  54. package/skills/mom-test/references/question-patterns.md +0 -198
  55. package/skills/pandasai-analytics/SKILL.md +0 -251
  56. package/skills/release-it/SKILL.md +0 -235
  57. package/skills/release-it/references/anti-patterns.md +0 -279
  58. package/skills/release-it/references/capacity-planning.md +0 -285
  59. package/skills/release-it/references/chaos-engineering.md +0 -325
  60. package/skills/release-it/references/deployment-strategies.md +0 -331
  61. package/skills/release-it/references/observability.md +0 -301
  62. package/skills/release-it/references/stability-patterns.md +0 -355
  63. package/skills/skill-creator-ultra/.agents/workflows/skill-audit.md +0 -37
  64. package/skills/skill-creator-ultra/.agents/workflows/skill-compare.md +0 -34
  65. package/skills/skill-creator-ultra/.agents/workflows/skill-export.md +0 -51
  66. package/skills/skill-creator-ultra/.agents/workflows/skill-generate.md +0 -39
  67. package/skills/skill-creator-ultra/.agents/workflows/skill-scaffold.md +0 -52
  68. package/skills/skill-creator-ultra/.agents/workflows/skill-simulate.md +0 -25
  69. package/skills/skill-creator-ultra/.agents/workflows/skill-stats.md +0 -31
  70. package/skills/skill-creator-ultra/.agents/workflows/skill-validate.md +0 -25
  71. package/skills/skill-creator-ultra/README.md +0 -1242
  72. package/skills/skill-creator-ultra/SKILL.md +0 -388
  73. package/skills/skill-creator-ultra/agents/analyzer.md +0 -274
  74. package/skills/skill-creator-ultra/agents/comparator.md +0 -202
  75. package/skills/skill-creator-ultra/agents/grader.md +0 -223
  76. package/skills/skill-creator-ultra/assets/eval_review.html +0 -146
  77. package/skills/skill-creator-ultra/eval-viewer/generate_review.py +0 -471
  78. package/skills/skill-creator-ultra/eval-viewer/viewer.html +0 -1325
  79. package/skills/skill-creator-ultra/examples/example_anthropic_frontend.md +0 -109
  80. package/skills/skill-creator-ultra/examples/example_anthropic_pdf.md +0 -116
  81. package/skills/skill-creator-ultra/examples/example_api_docs.md +0 -189
  82. package/skills/skill-creator-ultra/examples/example_db_migration.md +0 -253
  83. package/skills/skill-creator-ultra/examples/example_git_commit.md +0 -111
  84. package/skills/skill-creator-ultra/install.ps1 +0 -289
  85. package/skills/skill-creator-ultra/install.sh +0 -313
  86. package/skills/skill-creator-ultra/phases/phase1_interview.md +0 -202
  87. package/skills/skill-creator-ultra/phases/phase2_extract.md +0 -55
  88. package/skills/skill-creator-ultra/phases/phase3_detect.md +0 -57
  89. package/skills/skill-creator-ultra/phases/phase4_generate.md +0 -543
  90. package/skills/skill-creator-ultra/phases/phase5_test.md +0 -319
  91. package/skills/skill-creator-ultra/phases/phase6_eval.md +0 -301
  92. package/skills/skill-creator-ultra/phases/phase7_iterate.md +0 -103
  93. package/skills/skill-creator-ultra/phases/phase8_optimize.md +0 -113
  94. package/skills/skill-creator-ultra/resources/advanced_patterns.md +0 -499
  95. package/skills/skill-creator-ultra/resources/anti_patterns.md +0 -376
  96. package/skills/skill-creator-ultra/resources/blueprints.md +0 -498
  97. package/skills/skill-creator-ultra/resources/checklist.md +0 -243
  98. package/skills/skill-creator-ultra/resources/composition_cookbook.md +0 -291
  99. package/skills/skill-creator-ultra/resources/description_optimization.md +0 -90
  100. package/skills/skill-creator-ultra/resources/eval_guide.md +0 -133
  101. package/skills/skill-creator-ultra/resources/industry_questions.md +0 -189
  102. package/skills/skill-creator-ultra/resources/interview_questions.md +0 -200
  103. package/skills/skill-creator-ultra/resources/pattern_detection.md +0 -200
  104. package/skills/skill-creator-ultra/resources/prompt_engineering.md +0 -531
  105. package/skills/skill-creator-ultra/resources/schemas.md +0 -430
  106. package/skills/skill-creator-ultra/resources/script_integration.md +0 -593
  107. package/skills/skill-creator-ultra/resources/scripts_guide.md +0 -339
  108. package/skills/skill-creator-ultra/resources/skill_template.md +0 -124
  109. package/skills/skill-creator-ultra/resources/skill_writing_guide.md +0 -634
  110. package/skills/skill-creator-ultra/resources/versioning_guide.md +0 -193
  111. package/skills/skill-creator-ultra/scripts/ci_eval.py +0 -200
  112. package/skills/skill-creator-ultra/scripts/package_skill.py +0 -165
  113. package/skills/skill-creator-ultra/scripts/simulate_skill.py +0 -398
  114. package/skills/skill-creator-ultra/scripts/skill_audit.py +0 -611
  115. package/skills/skill-creator-ultra/scripts/skill_compare.py +0 -265
  116. package/skills/skill-creator-ultra/scripts/skill_export.py +0 -334
  117. package/skills/skill-creator-ultra/scripts/skill_scaffold.py +0 -403
  118. package/skills/skill-creator-ultra/scripts/skill_stats.py +0 -339
  119. package/skills/skill-creator-ultra/scripts/validate_skill.py +0 -411
  120. package/skills/tailwind-mastery/SKILL.md +0 -229
  121. package/skills/vercel-react-best-practices/AGENTS.md +0 -3373
  122. package/skills/vercel-react-best-practices/README.md +0 -123
  123. package/skills/vercel-react-best-practices/SKILL.md +0 -143
  124. package/skills/vercel-react-best-practices/rules/_sections.md +0 -46
  125. package/skills/vercel-react-best-practices/rules/_template.md +0 -28
  126. package/skills/vercel-react-best-practices/rules/advanced-event-handler-refs.md +0 -55
  127. package/skills/vercel-react-best-practices/rules/advanced-init-once.md +0 -42
  128. package/skills/vercel-react-best-practices/rules/advanced-use-latest.md +0 -39
  129. package/skills/vercel-react-best-practices/rules/async-api-routes.md +0 -38
  130. package/skills/vercel-react-best-practices/rules/async-defer-await.md +0 -80
  131. package/skills/vercel-react-best-practices/rules/async-dependencies.md +0 -51
  132. package/skills/vercel-react-best-practices/rules/async-parallel.md +0 -28
  133. package/skills/vercel-react-best-practices/rules/async-suspense-boundaries.md +0 -99
  134. package/skills/vercel-react-best-practices/rules/bundle-barrel-imports.md +0 -59
  135. package/skills/vercel-react-best-practices/rules/bundle-conditional.md +0 -31
  136. package/skills/vercel-react-best-practices/rules/bundle-defer-third-party.md +0 -49
  137. package/skills/vercel-react-best-practices/rules/bundle-dynamic-imports.md +0 -35
  138. package/skills/vercel-react-best-practices/rules/bundle-preload.md +0 -50
  139. package/skills/vercel-react-best-practices/rules/client-event-listeners.md +0 -74
  140. package/skills/vercel-react-best-practices/rules/client-localstorage-schema.md +0 -71
  141. package/skills/vercel-react-best-practices/rules/client-passive-event-listeners.md +0 -48
  142. package/skills/vercel-react-best-practices/rules/client-swr-dedup.md +0 -56
  143. package/skills/vercel-react-best-practices/rules/js-batch-dom-css.md +0 -107
  144. package/skills/vercel-react-best-practices/rules/js-cache-function-results.md +0 -80
  145. package/skills/vercel-react-best-practices/rules/js-cache-property-access.md +0 -28
  146. package/skills/vercel-react-best-practices/rules/js-cache-storage.md +0 -70
  147. package/skills/vercel-react-best-practices/rules/js-combine-iterations.md +0 -32
  148. package/skills/vercel-react-best-practices/rules/js-early-exit.md +0 -50
  149. package/skills/vercel-react-best-practices/rules/js-flatmap-filter.md +0 -60
  150. package/skills/vercel-react-best-practices/rules/js-hoist-regexp.md +0 -45
  151. package/skills/vercel-react-best-practices/rules/js-index-maps.md +0 -37
  152. package/skills/vercel-react-best-practices/rules/js-length-check-first.md +0 -49
  153. package/skills/vercel-react-best-practices/rules/js-min-max-loop.md +0 -82
  154. package/skills/vercel-react-best-practices/rules/js-set-map-lookups.md +0 -24
  155. package/skills/vercel-react-best-practices/rules/js-tosorted-immutable.md +0 -57
  156. package/skills/vercel-react-best-practices/rules/rendering-activity.md +0 -26
  157. package/skills/vercel-react-best-practices/rules/rendering-animate-svg-wrapper.md +0 -47
  158. package/skills/vercel-react-best-practices/rules/rendering-conditional-render.md +0 -40
  159. package/skills/vercel-react-best-practices/rules/rendering-content-visibility.md +0 -38
  160. package/skills/vercel-react-best-practices/rules/rendering-hoist-jsx.md +0 -46
  161. package/skills/vercel-react-best-practices/rules/rendering-hydration-no-flicker.md +0 -82
  162. package/skills/vercel-react-best-practices/rules/rendering-hydration-suppress-warning.md +0 -30
  163. package/skills/vercel-react-best-practices/rules/rendering-resource-hints.md +0 -85
  164. package/skills/vercel-react-best-practices/rules/rendering-script-defer-async.md +0 -68
  165. package/skills/vercel-react-best-practices/rules/rendering-svg-precision.md +0 -28
  166. package/skills/vercel-react-best-practices/rules/rendering-usetransition-loading.md +0 -75
  167. package/skills/vercel-react-best-practices/rules/rerender-defer-reads.md +0 -39
  168. package/skills/vercel-react-best-practices/rules/rerender-dependencies.md +0 -45
  169. package/skills/vercel-react-best-practices/rules/rerender-derived-state-no-effect.md +0 -40
  170. package/skills/vercel-react-best-practices/rules/rerender-derived-state.md +0 -29
  171. package/skills/vercel-react-best-practices/rules/rerender-functional-setstate.md +0 -74
  172. package/skills/vercel-react-best-practices/rules/rerender-lazy-state-init.md +0 -58
  173. package/skills/vercel-react-best-practices/rules/rerender-memo-with-default-value.md +0 -38
  174. package/skills/vercel-react-best-practices/rules/rerender-memo.md +0 -44
  175. package/skills/vercel-react-best-practices/rules/rerender-move-effect-to-event.md +0 -45
  176. package/skills/vercel-react-best-practices/rules/rerender-no-inline-components.md +0 -82
  177. package/skills/vercel-react-best-practices/rules/rerender-simple-expression-in-memo.md +0 -35
  178. package/skills/vercel-react-best-practices/rules/rerender-split-combined-hooks.md +0 -64
  179. package/skills/vercel-react-best-practices/rules/rerender-transitions.md +0 -40
  180. package/skills/vercel-react-best-practices/rules/rerender-use-deferred-value.md +0 -59
  181. package/skills/vercel-react-best-practices/rules/rerender-use-ref-transient-values.md +0 -73
  182. package/skills/vercel-react-best-practices/rules/server-after-nonblocking.md +0 -73
  183. package/skills/vercel-react-best-practices/rules/server-auth-actions.md +0 -96
  184. package/skills/vercel-react-best-practices/rules/server-cache-lru.md +0 -41
  185. package/skills/vercel-react-best-practices/rules/server-cache-react.md +0 -76
  186. package/skills/vercel-react-best-practices/rules/server-dedup-props.md +0 -65
  187. package/skills/vercel-react-best-practices/rules/server-hoist-static-io.md +0 -142
  188. package/skills/vercel-react-best-practices/rules/server-parallel-fetching.md +0 -83
  189. package/skills/vercel-react-best-practices/rules/server-serialization.md +0 -38
  190. 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.4",
3
+ "version": "4.5.1",
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": {
@@ -59,12 +59,15 @@
59
59
  },
60
60
  "dependencies": {
61
61
  "@clack/prompts": "^1.1.0",
62
+ "better-sqlite3": "^12.8.0",
62
63
  "chalk": "^5.6.2",
64
+ "chokidar": "^5.0.0",
63
65
  "commander": "^14.0.3",
64
66
  "express": "^5.2.1",
65
67
  "prompts": "^2.4.2"
66
68
  },
67
69
  "devDependencies": {
70
+ "@types/better-sqlite3": "^7.6.13",
68
71
  "@types/express": "^5.0.6",
69
72
  "@types/node": "^25.5.0",
70
73
  "@types/prompts": "^2.4.9",
@@ -73,5 +76,8 @@
73
76
  "ts-node": "^10.9.2",
74
77
  "typescript": "^5.9.3",
75
78
  "vitest": "^4.1.0"
79
+ },
80
+ "overrides": {
81
+ "path-to-regexp": "^8.4.0"
76
82
  }
77
83
  }
@@ -7,20 +7,56 @@
7
7
 
8
8
  ## #Load-Working-Memory
9
9
 
10
- Before executing any significant action, ALWAYS:
11
-
12
- 1. **Read** `.cm/CONTINUITY.md` understand current state, Active Goal, Next Actions
13
- 2. **Run Memory Audit** — decay check + conflict detection + integrity scan (see `cm-continuity`)
14
- 3. **Scope-filter learnings** if working on module X:
15
- - Load from `.cm/learnings.json` ONLY where `scope == "global"` or `scope == "module:X"`
16
- - **NEVER** load `status = "invalidated"` (proven wrong — skip entirely)
17
- - **CAUTION** with `status = "corrected"` (was wrong, verify before applying)
18
- - **TRUST** high `reinforceCount` + recent `lastRelevant`
19
- - **VERIFY** `reinforceCount = 0` + old `lastRelevant` (low confidence)
20
- - SKIP learnings for other modules (reduces noise + saves tokens)
21
- 4. **Check** "Next Actions" — pick up where you left off
22
-
23
- > **Token savings:** Scope-filtered reading loads ~250 tokens instead of ~2,500.
10
+ Before executing any significant action, ALWAYS load context in this order (cheapest → richest):
11
+
12
+ ### Step 1 Check context bus (free, ~50 tokens)
13
+ ```
14
+ Read .cm/context-bus.json (or: cm continuity bus)
15
+ If active pipeline found:
16
+ - Note current_step and pipeline name
17
+ - Read shared_context to see what upstream skills already produced
18
+ - SKIP re-doing any work already recorded in shared_context
19
+ If no bus: fresh session, proceed normally
20
+ ```
21
+
22
+ ### Step 2 — Load L0 indexes first (~600 tokens total)
23
+ ```
24
+ Read .cm/learnings-index.md (~100 tokens) — IDs + 1-line summaries
25
+ Read .cm/skeleton-index.md (~500 tokens) — modules, entry points, config files
26
+
27
+ → If a specific learning ID looks relevant → resolve cm://memory/learnings/{id} for full detail
28
+ → If a specific module looks relevant → resolve cm://resources/skeleton at L2 for full detail
29
+ → Otherwise: L0 is sufficient — DO NOT load full files
30
+ ```
31
+
32
+ ### Step 3 — Scope-filter learnings (only if L0 flags relevant entries)
33
+ ```
34
+ Query: cm_query(scope="learnings", query="{current module or error type}", limit=5)
35
+ OR read .cm/memory/learnings.json filtered to scope == "global" | "module:X"
36
+
37
+ Rules:
38
+ NEVER load status = "invalidated" (proven wrong)
39
+ CAUTION status = "corrected" (verify before applying)
40
+ TRUST high reinforceCount + recent lastRelevant
41
+ SKIP learnings for other modules (noise + wasted tokens)
42
+ ```
43
+
44
+ ### Step 4 — Check working memory
45
+ ```
46
+ Read .cm/CONTINUITY.md → Active Goal, Next Actions, current phase
47
+ Run Memory Audit (decay + conflict detection) — see cm-continuity
48
+ ```
49
+
50
+ ### Step 5 — Token budget check (before injecting large context)
51
+ ```
52
+ cm continuity budget (or: loadBudget + checkBudget in code)
53
+ → If category is over soft limit → use L0/L1 depth instead of L2
54
+ → Never inject full skeleton (20KB) when skeleton-index.md (~2KB) suffices
55
+ ```
56
+
57
+ > **Token savings v5:** Full cold load ~3,200 tokens → Smart Spine load ~700 tokens (78% reduction).
58
+ > L0 indexes + context bus + scope filter make this possible.
59
+ > Only escalate to L2 when L0/L1 explicitly flag the need.
24
60
 
25
61
  ---
26
62
 
@@ -0,0 +1,29 @@
1
+ ---
2
+ name: cm-autopilot
3
+ description: Easy-to-use conversational CLI (Claude Code style) for non-technical users to spawn parallel AI tasks supervised by a visual web dashboard.
4
+ ---
5
+
6
+ # CM AutoPilot CLI — Conversational Task Supervisor
7
+
8
+ > **Just talk to it. It plans, splits, and watches parallel tasks for you.**
9
+
10
+ ## What it does
11
+ - Provides a conversational CLI interface using `rich` and `prompt_toolkit`.
12
+ - Translates user intent into multiple parallel tasks.
13
+ - Integrates with `cm-content-factory`'s Dashboard (`localhost:5050`) for a visual way to track multi-threading.
14
+ - Allows non-technical users to utilize the Cody Master skill set effortlessly.
15
+
16
+ ## Requirements
17
+ - Python 3.9+
18
+ - `rich`
19
+ - `prompt_toolkit`
20
+
21
+ ## How to run
22
+
23
+ 1. Launch the conversational CLI:
24
+ ```bash
25
+ python3 skills/cm-autopilot/scripts/autopilot.py
26
+ ```
27
+ 2. The CLI will ask what you want to do. Explain your complex request (e.g., "Dịch 10 bài báo sang tiếng anh", "Research 5 competitors").
28
+ 3. The AutoPilot will generate tasks and push them into the Queue.
29
+ 4. AutoPilot will automatically start the visual Dashboard at `http://localhost:5050` so you can watch your jobs execute in parallel.
@@ -0,0 +1,190 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ AutoPilot CLI — Conversational Interface for Cody Master Skills
4
+
5
+ This is a Claude Code-style interactive CLI. It talks to the user,
6
+ understands their goals, creates a plan, and then parallelizes
7
+ tasks into the Agent Dispatcher (queue) while launching the Visual
8
+ Dashboard for easy tracking.
9
+ """
10
+
11
+ import sys
12
+ import time
13
+ import os
14
+ import subprocess
15
+ import threading
16
+ from pathlib import Path
17
+
18
+ # Add cm-content-factory to sys.path to reuse the dispatcher and state manager
19
+ SKILLS_DIR = Path(__file__).resolve().parent.parent.parent
20
+ CF_SCRIPTS = SKILLS_DIR / "cm-content-factory" / "scripts"
21
+ sys.path.append(str(CF_SCRIPTS))
22
+
23
+ try:
24
+ from agent_dispatcher import AgentDispatcher
25
+ from state_manager import StateManager
26
+ from rich.console import Console
27
+ from rich.markdown import Markdown
28
+ from rich.panel import Panel
29
+ from rich.prompt import Prompt
30
+ from rich.progress import Progress, SpinnerColumn, TextColumn
31
+ except ImportError:
32
+ print("Please install requirements: pip install rich prompt_toolkit")
33
+ sys.exit(1)
34
+
35
+ console = Console()
36
+ project_root = Path(os.getcwd()).resolve()
37
+
38
+ dispatcher = AgentDispatcher(str(project_root))
39
+ state_mgr = StateManager(str(project_root))
40
+
41
+ DASHBOARD_PROCESS = None
42
+
43
+ def start_dashboard():
44
+ """Starts the cm-content-factory dashboard server in the background."""
45
+ global DASHBOARD_PROCESS
46
+ dashboard_script = CF_SCRIPTS / "dashboard_server.py"
47
+ if dashboard_script.exists():
48
+ DASHBOARD_PROCESS = subprocess.Popen(
49
+ [sys.executable, str(dashboard_script), "--port", "5050", "--no-open"],
50
+ stdout=subprocess.DEVNULL,
51
+ stderr=subprocess.DEVNULL
52
+ )
53
+ return True
54
+ return False
55
+
56
+ def show_welcome():
57
+ console.print(Panel.fit(
58
+ "[bold cyan]🚀 Welcome to Cody Master AutoPilot[/bold cyan]\n"
59
+ "[dim]Your conversational AI orchestrator.[/dim]\n\n"
60
+ "Tell me what you want to achieve, and I will plan, split,\n"
61
+ "and execute parallel tasks for you. No technical skills required.",
62
+ title="AutoPilot v1.0", border_style="cyan"
63
+ ))
64
+
65
+ def mock_llm_task_parser(prompt: str) -> list:
66
+ """
67
+ Mock parser that simulates an LLM breaking down a user request
68
+ into parallel tasks based on keywords.
69
+ """
70
+ tasks = []
71
+ lower_prompt = prompt.lower()
72
+
73
+ if "dịch" in lower_prompt or "translate" in lower_prompt:
74
+ # Example: Dịch 5 bài báo
75
+ count = 5
76
+ for w in lower_prompt.split():
77
+ if w.isdigit():
78
+ count = int(w)
79
+ break
80
+ for i in range(1, count + 1):
81
+ tasks.append({
82
+ "id": f"translate-{int(time.time()*100)}-{i}",
83
+ "type": "translate",
84
+ "meta": {"file": f"article_{i}.txt", "target_lang": "en"}
85
+ })
86
+ elif "research" in lower_prompt or "tìm hiểu" in lower_prompt:
87
+ tasks.append({"id": f"res-1", "type": "research", "meta": {"topic": "Market Trends"}})
88
+ tasks.append({"id": f"res-2", "type": "research", "meta": {"topic": "Competitors"}})
89
+ tasks.append({"id": f"res-3", "type": "research", "meta": {"topic": "Keywords"}})
90
+ else:
91
+ # Generic fallback
92
+ tasks.append({"id": f"task-1", "type": "general", "meta": {"instruction": prompt}})
93
+ tasks.append({"id": f"task-2", "type": "general", "meta": {"instruction": "Review output"}})
94
+
95
+ return tasks
96
+
97
+ def background_worker(worker_id: str):
98
+ """A simple worker loop simulating parallel execution of tasks."""
99
+ state_mgr.register_agent(worker_id, "autopilot_worker")
100
+ while True:
101
+ task = dispatcher.claim_next(worker_id)
102
+ if not task:
103
+ time.sleep(2)
104
+ continue
105
+
106
+ # Log active phase
107
+ phase_map = {"translate": "write", "research": "extract", "general": "plan"}
108
+ phase = phase_map.get(task["type"], "write")
109
+ state_mgr.update_phase(phase, "running", progress=0.1)
110
+ state_mgr.add_task(task["id"], "running", task["meta"])
111
+
112
+ # Simulate work
113
+ dispatcher.heartbeat(worker_id, task["id"])
114
+ time.sleep(3) # Heavy work
115
+
116
+ state_mgr.add_task(task["id"], "done", task["meta"])
117
+ dispatcher.complete(task["id"], worker_id, {"result": "success"})
118
+ state_mgr.log_event("info", f"[{worker_id}] Completed task: {task['id']}")
119
+
120
+ # Check if phase done
121
+ q = dispatcher.get_queue()
122
+ if q["queued"] == 0 and q["claimed"] == 0:
123
+ state_mgr.update_phase(phase, "done", progress=1.0)
124
+
125
+ def main_loop():
126
+ # Reset queue and state for fresh start
127
+ dispatcher.reset()
128
+ state_mgr.reset()
129
+
130
+ # Start dashboard
131
+ if start_dashboard():
132
+ state_mgr.log_event("info", "Dashboard Server started on port 5050")
133
+
134
+ # Start background workers (simulating multiple parallel agents)
135
+ for i in range(3):
136
+ t = threading.Thread(target=background_worker, args=(f"worker-{i+1}",), daemon=True)
137
+ t.start()
138
+
139
+ try:
140
+ while True:
141
+ user_input = Prompt.ask("\n[bold green]You[/bold green]")
142
+ if user_input.lower() in ("exit", "quit", "q"):
143
+ break
144
+
145
+ if not user_input.strip():
146
+ continue
147
+
148
+ with Progress(
149
+ SpinnerColumn(),
150
+ TextColumn("[progress.description]{task.description}"),
151
+ transient=True
152
+ ) as progress:
153
+ progress.add_task("Thinking and Planning...", total=None)
154
+ time.sleep(1.5) # Simulate LLM thinking
155
+ tasks = mock_llm_task_parser(user_input)
156
+
157
+ console.print(f"[bold blue]AutoPilot:[/bold blue] I've analyzed your request and created [bold]{len(tasks)}[/bold] parallel tasks.")
158
+
159
+ # Queue them
160
+ dispatcher.enqueue_batch(tasks)
161
+ for t in tasks:
162
+ state_mgr.add_task(t["id"], "queued", t["meta"])
163
+
164
+ console.print("[dim]Tasks have been dispatched to the worker queue.[/dim]")
165
+ console.print(f"👉 [bold magenta]Watch live progress at: http://localhost:5050[/bold magenta]")
166
+
167
+ # Simple live status wait
168
+ with Progress() as pb:
169
+ task_pb = pb.add_task("Executing Pipeline...", total=len(tasks))
170
+ while True:
171
+ q = dispatcher.get_queue()
172
+ completed = q["done"] + q["failed"]
173
+ pb.update(task_pb, completed=completed)
174
+
175
+ if completed >= len(tasks):
176
+ break
177
+ time.sleep(1)
178
+
179
+ console.print("\n[bold green]✅ All tasks completed successfully![/bold green]")
180
+
181
+ except KeyboardInterrupt:
182
+ console.print("\n[dim]Shutting down...[/dim]")
183
+
184
+ finally:
185
+ if DASHBOARD_PROCESS:
186
+ DASHBOARD_PROCESS.terminate()
187
+
188
+ if __name__ == "__main__":
189
+ show_welcome()
190
+ main_loop()