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
package/dist/judge.js ADDED
@@ -0,0 +1,252 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.evaluateTaskState = evaluateTaskState;
4
+ exports.evaluateAllTasks = evaluateAllTasks;
5
+ exports.suggestAgentsForSkill = suggestAgentsForSkill;
6
+ exports.suggestAgentsForTask = suggestAgentsForTask;
7
+ exports.getSkillDomain = getSkillDomain;
8
+ exports.suggestTransitions = suggestTransitions;
9
+ exports.suggestChain = suggestChain;
10
+ const skill_chain_1 = require("./skill-chain");
11
+ // ─── Judge Configuration ────────────────────────────────────────────────────
12
+ const STUCK_THRESHOLD_MS = 10 * 60 * 1000; // 10 minutes
13
+ const MAX_FAIL_COUNT = 3;
14
+ // ─── Skill → Domain Mapping ────────────────────────────────────────────────
15
+ const SKILL_DOMAIN = {
16
+ 'cm-tdd': 'engineering',
17
+ 'cm-debugging': 'engineering',
18
+ 'cm-quality-gate': 'engineering',
19
+ 'cm-test-gate': 'engineering',
20
+ 'cm-code-review': 'engineering',
21
+ 'cm-safe-deploy': 'operations',
22
+ 'cm-identity-guard': 'operations',
23
+ 'cm-git-worktrees': 'operations',
24
+ 'cm-terminal': 'operations',
25
+ 'cm-planning': 'product',
26
+ 'cm-ux-master': 'product',
27
+ 'cm-dockit': 'product',
28
+ 'cm-project-bootstrap': 'product',
29
+ 'cm-content-factory': 'growth',
30
+ 'cm-ads-tracker': 'growth',
31
+ 'cro-methodology': 'growth',
32
+ 'booking-calendar': 'growth',
33
+ 'cm-execution': 'orchestration',
34
+ 'cm-continuity': 'orchestration',
35
+ 'cm-skill-mastery': 'orchestration',
36
+ 'cm-safe-i18n': 'orchestration',
37
+ };
38
+ // ─── Agent Affinity ─────────────────────────────────────────────────────────
39
+ const AGENT_AFFINITY = {
40
+ engineering: ['claude-code', 'cursor', 'antigravity'],
41
+ operations: ['claude-code', 'antigravity', 'cursor'],
42
+ product: ['antigravity', 'claude-code', 'cursor'],
43
+ growth: ['antigravity', 'claude-code', 'cursor'],
44
+ orchestration: ['antigravity', 'claude-code', 'cursor'],
45
+ specialized: ['antigravity', 'claude-code', 'cursor'],
46
+ debugging: ['claude-code', 'cursor', 'antigravity'],
47
+ review: ['antigravity', 'claude-code'],
48
+ documentation: ['antigravity', 'claude-code'],
49
+ design: ['cursor', 'antigravity'],
50
+ };
51
+ // ─── Agent Display ──────────────────────────────────────────────────────────
52
+ const AGENT_DISPLAY = {
53
+ 'antigravity': 'Google Antigravity',
54
+ 'claude-code': 'Claude Code',
55
+ 'cursor': 'Cursor',
56
+ 'gemini-cli': 'Gemini CLI',
57
+ 'windsurf': 'Windsurf',
58
+ 'cline': 'Cline / RooCode',
59
+ 'copilot': 'GitHub Copilot',
60
+ };
61
+ // ─── Judge Agent ────────────────────────────────────────────────────────────
62
+ /**
63
+ * Evaluate the current state of a task and decide what action to take.
64
+ * Returns a JudgeDecision with one of: CONTINUE, COMPLETE, ESCALATE, PIVOT.
65
+ *
66
+ * Inspired by Loki Mode's Judge Agent Protocol.
67
+ */
68
+ function evaluateTaskState(task, allTasks, learnings = []) {
69
+ // ─── COMPLETE: Task is already done ────────────────────────────────────
70
+ if (task.column === 'done') {
71
+ return {
72
+ action: 'COMPLETE',
73
+ reason: 'Task has been marked as done.',
74
+ confidence: 1.0,
75
+ badge: '🏁',
76
+ };
77
+ }
78
+ // ─── ESCALATE: Task stuck for too long ─────────────────────────────────
79
+ const updatedAt = new Date(task.updatedAt).getTime();
80
+ const elapsed = Date.now() - updatedAt;
81
+ if (task.column === 'in-progress' && elapsed > STUCK_THRESHOLD_MS) {
82
+ const minutesStuck = Math.round(elapsed / 60000);
83
+ return {
84
+ action: 'ESCALATE',
85
+ reason: `Task stuck in progress for ${minutesStuck} minutes without updates.`,
86
+ confidence: 0.85,
87
+ badge: '⚠️',
88
+ };
89
+ }
90
+ // ─── PIVOT: Too many failures → change approach ────────────────────────
91
+ const taskLearnings = learnings.filter(l => l.taskId === task.id);
92
+ if (taskLearnings.length >= MAX_FAIL_COUNT) {
93
+ const suggestedSkill = suggestAlternativeSkill(task.skill);
94
+ return {
95
+ action: 'PIVOT',
96
+ reason: `Task has failed ${taskLearnings.length} times. Consider changing approach.`,
97
+ confidence: 0.75,
98
+ suggestedNextSkill: suggestedSkill,
99
+ badge: '🔄',
100
+ };
101
+ }
102
+ // ─── ESCALATE: Dispatch failed previously ──────────────────────────────
103
+ if (task.dispatchStatus === 'failed' && task.dispatchError) {
104
+ return {
105
+ action: 'ESCALATE',
106
+ reason: `Dispatch failed: ${task.dispatchError}`,
107
+ confidence: 0.9,
108
+ badge: '⚠️',
109
+ };
110
+ }
111
+ // ─── COMPLETE: All related tasks in same project are done ──────────────
112
+ const projectTasks = allTasks.filter(t => t.projectId === task.projectId);
113
+ const allOthersDone = projectTasks
114
+ .filter(t => t.id !== task.id)
115
+ .every(t => t.column === 'done');
116
+ if (task.column === 'review' && allOthersDone) {
117
+ return {
118
+ action: 'COMPLETE',
119
+ reason: 'This is the last task in the project. Ready to finalize.',
120
+ confidence: 0.8,
121
+ badge: '🏁',
122
+ };
123
+ }
124
+ // ─── CONTINUE: Normal progress ─────────────────────────────────────────
125
+ // Check if task has a chain — suggest advancing
126
+ if (task.chainId && task.column === 'review') {
127
+ return {
128
+ action: 'CHAIN_NEXT',
129
+ reason: `Task is part of chain "${task.chainId}". Ready to advance to next step.`,
130
+ confidence: 0.8,
131
+ badge: '⛓️',
132
+ };
133
+ }
134
+ return {
135
+ action: 'CONTINUE',
136
+ reason: 'Task is progressing normally.',
137
+ confidence: 0.7,
138
+ badge: '🟢',
139
+ };
140
+ }
141
+ /**
142
+ * Evaluate all in-progress/review tasks and return decisions for each.
143
+ */
144
+ function evaluateAllTasks(tasks, learnings = []) {
145
+ const decisions = new Map();
146
+ const activeTasks = tasks.filter(t => t.column === 'in-progress' || t.column === 'review');
147
+ for (const task of activeTasks) {
148
+ decisions.set(task.id, evaluateTaskState(task, tasks, learnings));
149
+ }
150
+ return decisions;
151
+ }
152
+ // ─── Dynamic Agent Selection ────────────────────────────────────────────────
153
+ /**
154
+ * Suggest the best agents for a given skill, ordered by affinity.
155
+ */
156
+ function suggestAgentsForSkill(skill) {
157
+ const domain = SKILL_DOMAIN[skill] || 'specialized';
158
+ const agents = AGENT_AFFINITY[domain] || AGENT_AFFINITY.engineering;
159
+ return agents;
160
+ }
161
+ /**
162
+ * Suggest the best agents for a task based on its skill.
163
+ * Returns formatted display names.
164
+ */
165
+ function suggestAgentsForTask(task) {
166
+ const skill = task.skill || '';
167
+ const domain = SKILL_DOMAIN[skill] || guessdomainFromTitle(task.title);
168
+ const agents = AGENT_AFFINITY[domain] || AGENT_AFFINITY.engineering;
169
+ return agents.map((id, index) => ({
170
+ id,
171
+ name: AGENT_DISPLAY[id] || id,
172
+ affinity: index === 0 ? 'best' : index === 1 ? 'good' : 'acceptable',
173
+ }));
174
+ }
175
+ /**
176
+ * Get the domain of a skill.
177
+ */
178
+ function getSkillDomain(skill) {
179
+ return SKILL_DOMAIN[skill] || 'specialized';
180
+ }
181
+ // ─── Helpers ────────────────────────────────────────────────────────────────
182
+ function suggestAlternativeSkill(currentSkill) {
183
+ const alternatives = {
184
+ 'cm-tdd': 'cm-debugging',
185
+ 'cm-debugging': 'cm-tdd',
186
+ 'cm-execution': 'cm-planning',
187
+ 'cm-safe-deploy': 'cm-quality-gate',
188
+ 'cm-quality-gate': 'cm-debugging',
189
+ };
190
+ return alternatives[currentSkill];
191
+ }
192
+ function guessdomainFromTitle(title) {
193
+ const fTitle = title.toLowerCase();
194
+ if (/test|bug|fix|error|debug/.test(fTitle))
195
+ return 'engineering';
196
+ if (/deploy|ci|cd|release|docker/.test(fTitle))
197
+ return 'operations';
198
+ if (/design|ui|ux|plan|feature/.test(fTitle))
199
+ return 'product';
200
+ if (/content|marketing|seo|ads|tracking/.test(fTitle))
201
+ return 'growth';
202
+ if (/i18n|translate|review|docs/.test(fTitle))
203
+ return 'orchestration';
204
+ return 'engineering'; // default
205
+ }
206
+ /**
207
+ * Suggest transitions for stuck tasks based on heuristics:
208
+ * - in-progress > 60 min + dispatched → suggest "review"
209
+ * - in-progress > 120 min → suggest "review" even without dispatch
210
+ * - review > 30 min → suggest "done"
211
+ */
212
+ function suggestTransitions(tasks) {
213
+ const now = Date.now();
214
+ const suggestions = [];
215
+ for (const task of tasks) {
216
+ const elapsed = now - new Date(task.updatedAt).getTime();
217
+ const minutes = Math.round(elapsed / 60000);
218
+ if (task.column === 'in-progress') {
219
+ if (task.dispatchStatus === 'dispatched' && elapsed > 60 * 60 * 1000) {
220
+ suggestions.push({
221
+ taskId: task.id, from: 'in-progress', to: 'review',
222
+ reason: `Dispatched ${minutes}m ago, likely completed. Move to review?`,
223
+ confidence: 0.7, stuckMinutes: minutes,
224
+ });
225
+ }
226
+ else if (elapsed > 120 * 60 * 1000) {
227
+ suggestions.push({
228
+ taskId: task.id, from: 'in-progress', to: 'review',
229
+ reason: `Stuck for ${minutes}m. Consider moving to review or back to backlog.`,
230
+ confidence: 0.6, stuckMinutes: minutes,
231
+ });
232
+ }
233
+ }
234
+ if (task.column === 'review' && elapsed > 30 * 60 * 1000) {
235
+ suggestions.push({
236
+ taskId: task.id, from: 'review', to: 'done',
237
+ reason: `In review for ${minutes}m. Ready to mark as done?`,
238
+ confidence: 0.5, stuckMinutes: minutes,
239
+ });
240
+ }
241
+ }
242
+ return suggestions.sort((a, b) => b.stuckMinutes - a.stuckMinutes);
243
+ }
244
+ // ─── Chain Suggestions ───────────────────────────────────────────────────
245
+ // TRIZ #10: Preliminary Action — analyze task before dispatch
246
+ /**
247
+ * Suggest the best chain for a task based on its title.
248
+ * Returns the matching chain definition or undefined.
249
+ */
250
+ function suggestChain(taskTitle) {
251
+ return (0, skill_chain_1.matchChain)(taskTitle);
252
+ }
@@ -0,0 +1,359 @@
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.analyzeDependencies = analyzeDependencies;
7
+ exports.buildDependencyGraph = buildDependencyGraph;
8
+ exports.preFlightCheck = preFlightCheck;
9
+ exports.detectConflicts = detectConflicts;
10
+ exports.adaptBatchSize = adaptBatchSize;
11
+ exports.dispatchParallelBatch = dispatchParallelBatch;
12
+ exports.initConflictLedger = initConflictLedger;
13
+ exports.readConflictLedger = readConflictLedger;
14
+ exports.registerExpectedFiles = registerExpectedFiles;
15
+ exports.reportModifiedFiles = reportModifiedFiles;
16
+ exports.clearConflictLedger = clearConflictLedger;
17
+ exports.readParallelHistory = readParallelHistory;
18
+ exports.recordParallelSession = recordParallelSession;
19
+ const fs_1 = __importDefault(require("fs"));
20
+ const path_1 = __importDefault(require("path"));
21
+ const crypto_1 = __importDefault(require("crypto"));
22
+ const agent_dispatch_1 = require("./agent-dispatch");
23
+ const continuity_1 = require("./continuity");
24
+ // ─── Constants ──────────────────────────────────────────────────────────────
25
+ const PARALLEL_HISTORY_FILE = 'parallel-history.json';
26
+ const PARALLEL_LEDGER_FILE = 'parallel-ledger.json';
27
+ const DEFAULT_BATCH_SIZE = 2;
28
+ const MIN_BATCH_SIZE = 1;
29
+ const MAX_BATCH_SIZE = 5;
30
+ const CLEAN_RUNS_TO_SCALE_UP = 3;
31
+ const DEFAULT_QUALITY_CONTRACT = {
32
+ mustPassSyntax: true,
33
+ mustPassTests: true,
34
+ mustSelfReview: true,
35
+ maxModifiedFiles: 10,
36
+ timeoutMs: 300000, // 5 minutes
37
+ };
38
+ // ─── TRIZ #1: Segmentation — Dependency Analysis ───────────────────────────
39
+ /**
40
+ * Analyzes task descriptions to extract file paths that each task will modify.
41
+ * Uses pattern matching on common file path formats.
42
+ *
43
+ * TRIZ Principle #1 (Segmentation): Divide the system into independent parts.
44
+ */
45
+ function analyzeDependencies(tasks) {
46
+ var _a;
47
+ const depMap = new Map();
48
+ // Common file path patterns in task descriptions
49
+ const filePatterns = [
50
+ // Explicit file paths: src/foo/bar.ts, ./components/Button.tsx
51
+ /(?:^|\s|[`"'(])([a-zA-Z0-9_./-]+\.[a-zA-Z]{1,10})(?:\s|[`"')]|$)/g,
52
+ // Backtick-quoted paths: `src/index.ts`
53
+ /`([a-zA-Z0-9_./-]+\.[a-zA-Z]{1,10})`/g,
54
+ ];
55
+ // File extensions we care about
56
+ const codeExtensions = new Set([
57
+ 'ts', 'tsx', 'js', 'jsx', 'mjs', 'cjs',
58
+ 'json', 'yaml', 'yml', 'toml',
59
+ 'css', 'scss', 'less',
60
+ 'html', 'vue', 'svelte', 'astro',
61
+ 'md', 'mdx',
62
+ ]);
63
+ for (const task of tasks) {
64
+ const searchText = `${task.title}\n${task.description}`;
65
+ const files = new Set();
66
+ for (const pattern of filePatterns) {
67
+ // Reset lastIndex for global regex
68
+ pattern.lastIndex = 0;
69
+ let match;
70
+ while ((match = pattern.exec(searchText)) !== null) {
71
+ const filePath = match[1];
72
+ const ext = ((_a = filePath.split('.').pop()) === null || _a === void 0 ? void 0 : _a.toLowerCase()) || '';
73
+ if (codeExtensions.has(ext) && !filePath.startsWith('http')) {
74
+ // Normalize path separators
75
+ files.add(filePath.replace(/\\/g, '/'));
76
+ }
77
+ }
78
+ }
79
+ depMap.set(task.id, Array.from(files));
80
+ }
81
+ return depMap;
82
+ }
83
+ // ─── TRIZ #1: Segmentation — Build Dependency Graph ────────────────────────
84
+ /**
85
+ * Groups tasks into independent batches where no two tasks in the same batch
86
+ * modify the same file. Uses greedy graph coloring for optimal grouping.
87
+ *
88
+ * TRIZ Principle #1 (Segmentation): Only truly independent tasks in same batch.
89
+ */
90
+ function buildDependencyGraph(tasks, depMap, batchSize = DEFAULT_BATCH_SIZE) {
91
+ // Build adjacency: two tasks conflict if they share any affected file
92
+ const conflicts = new Map();
93
+ for (const task of tasks) {
94
+ conflicts.set(task.id, new Set());
95
+ }
96
+ for (let i = 0; i < tasks.length; i++) {
97
+ const filesA = new Set(depMap.get(tasks[i].id) || []);
98
+ for (let j = i + 1; j < tasks.length; j++) {
99
+ const filesB = depMap.get(tasks[j].id) || [];
100
+ const overlap = filesB.some(f => filesA.has(f));
101
+ if (overlap) {
102
+ conflicts.get(tasks[i].id).add(tasks[j].id);
103
+ conflicts.get(tasks[j].id).add(tasks[i].id);
104
+ }
105
+ }
106
+ }
107
+ // Greedy graph coloring → assign each task to a batch
108
+ const batchAssignment = new Map();
109
+ let maxBatch = 0;
110
+ // Sort tasks by number of conflicts (most constrained first)
111
+ const sortedTasks = [...tasks].sort((a, b) => {
112
+ var _a, _b;
113
+ const conflictsA = ((_a = conflicts.get(a.id)) === null || _a === void 0 ? void 0 : _a.size) || 0;
114
+ const conflictsB = ((_b = conflicts.get(b.id)) === null || _b === void 0 ? void 0 : _b.size) || 0;
115
+ return conflictsB - conflictsA;
116
+ });
117
+ for (const task of sortedTasks) {
118
+ const taskConflicts = conflicts.get(task.id);
119
+ // Find used batch numbers among conflicting tasks
120
+ const usedBatches = new Set();
121
+ for (const conflictId of taskConflicts) {
122
+ const batch = batchAssignment.get(conflictId);
123
+ if (batch !== undefined)
124
+ usedBatches.add(batch);
125
+ }
126
+ // Assign to first available batch
127
+ let assigned = 0;
128
+ while (usedBatches.has(assigned))
129
+ assigned++;
130
+ batchAssignment.set(task.id, assigned);
131
+ maxBatch = Math.max(maxBatch, assigned);
132
+ }
133
+ // Group into batches, respecting batchSize limit
134
+ const rawBatches = Array.from({ length: maxBatch + 1 }, () => []);
135
+ for (const task of tasks) {
136
+ const batchNum = batchAssignment.get(task.id) || 0;
137
+ rawBatches[batchNum].push(task);
138
+ }
139
+ // Split large batches by batchSize limit
140
+ const finalBatches = [];
141
+ let batchCounter = 0;
142
+ for (const rawBatch of rawBatches) {
143
+ for (let i = 0; i < rawBatch.length; i += batchSize) {
144
+ const slice = rawBatch.slice(i, i + batchSize);
145
+ const batchId = `batch-${batchCounter++}`;
146
+ const parallelTasks = slice.map(task => (Object.assign(Object.assign({}, task), { affectedFiles: depMap.get(task.id) || [], batchId, qualityContract: Object.assign({}, DEFAULT_QUALITY_CONTRACT) })));
147
+ finalBatches.push(parallelTasks);
148
+ }
149
+ }
150
+ return {
151
+ batches: finalBatches,
152
+ totalTasks: tasks.length,
153
+ batchSize,
154
+ independentGroups: maxBatch + 1,
155
+ };
156
+ }
157
+ // ─── TRIZ #10: Prior Action — Pre-flight Check ─────────────────────────────
158
+ /**
159
+ * Checks for potential conflicts BEFORE dispatching a batch.
160
+ * Reads the current conflict ledger and ensures no overlap with running agents.
161
+ *
162
+ * TRIZ Principle #10 (Prior Action): Place objects before they are needed.
163
+ */
164
+ function preFlightCheck(batch, projectPath) {
165
+ const ledger = readConflictLedger(projectPath);
166
+ const detectedConflicts = [];
167
+ // Check against already-running agents
168
+ for (const task of batch) {
169
+ for (const [existingTaskId, existingFiles] of Object.entries(ledger.entries)) {
170
+ const overlap = task.affectedFiles.filter(f => existingFiles.includes(f));
171
+ if (overlap.length > 0) {
172
+ detectedConflicts.push({
173
+ taskA: existingTaskId,
174
+ taskB: task.id,
175
+ overlappingFiles: overlap,
176
+ detectedAt: new Date().toISOString(),
177
+ });
178
+ }
179
+ }
180
+ }
181
+ return {
182
+ safe: detectedConflicts.length === 0,
183
+ conflicts: detectedConflicts,
184
+ };
185
+ }
186
+ // ─── TRIZ #18: Feedback — Conflict Detection ───────────────────────────────
187
+ /**
188
+ * Detects conflicts in the conflict ledger after agents report their modified files.
189
+ *
190
+ * TRIZ Principle #18 (Mechanical Vibration / Feedback):
191
+ * If an action is insufficient, use periodic/feedback-driven correction.
192
+ */
193
+ function detectConflicts(ledger) {
194
+ const conflicts = [];
195
+ const entries = Object.entries(ledger.entries);
196
+ for (let i = 0; i < entries.length; i++) {
197
+ const [taskIdA, filesA] = entries[i];
198
+ const setA = new Set(filesA);
199
+ for (let j = i + 1; j < entries.length; j++) {
200
+ const [taskIdB, filesB] = entries[j];
201
+ const overlap = filesB.filter(f => setA.has(f));
202
+ if (overlap.length > 0) {
203
+ conflicts.push({
204
+ taskA: taskIdA,
205
+ taskB: taskIdB,
206
+ overlappingFiles: overlap,
207
+ detectedAt: new Date().toISOString(),
208
+ });
209
+ }
210
+ }
211
+ }
212
+ return conflicts;
213
+ }
214
+ // ─── TRIZ #15: Dynamicity — Adaptive Batch Sizing ──────────────────────────
215
+ /**
216
+ * Adapts batch size based on conflict history.
217
+ * - 3 clean runs → increase batch size by 1 (max 5)
218
+ * - Any conflict → decrease by 1 (min 1)
219
+ *
220
+ * TRIZ Principle #15 (Dynamicity): Allow characteristics to change
221
+ * to be optimal at each stage.
222
+ */
223
+ function adaptBatchSize(history) {
224
+ const sessions = history.sessions;
225
+ if (sessions.length === 0)
226
+ return DEFAULT_BATCH_SIZE;
227
+ const lastSession = sessions[sessions.length - 1];
228
+ // If last session had conflicts → decrease
229
+ if (lastSession.conflictCount > 0) {
230
+ return Math.max(MIN_BATCH_SIZE, lastSession.batchSize - 1);
231
+ }
232
+ // Count consecutive clean sessions
233
+ let cleanCount = 0;
234
+ for (let i = sessions.length - 1; i >= 0; i--) {
235
+ if (sessions[i].conflictCount === 0) {
236
+ cleanCount++;
237
+ }
238
+ else {
239
+ break;
240
+ }
241
+ }
242
+ // 3+ clean → scale up
243
+ if (cleanCount >= CLEAN_RUNS_TO_SCALE_UP) {
244
+ return Math.min(MAX_BATCH_SIZE, lastSession.batchSize + 1);
245
+ }
246
+ return lastSession.batchSize;
247
+ }
248
+ // ─── Dispatch Parallel Batch ────────────────────────────────────────────────
249
+ /**
250
+ * Dispatches a batch of independent tasks in parallel.
251
+ * Each task gets its own .agent-tasks file with parallel context.
252
+ */
253
+ function dispatchParallelBatch(batch, project, force = false) {
254
+ var _a;
255
+ const batchId = ((_a = batch[0]) === null || _a === void 0 ? void 0 : _a.batchId) || `batch-${crypto_1.default.randomUUID().substring(0, 8)}`;
256
+ const dispatched = [];
257
+ const failed = [];
258
+ // TRIZ #10: Pre-flight check
259
+ const preflight = preFlightCheck(batch, project.path);
260
+ if (!preflight.safe) {
261
+ return {
262
+ success: false,
263
+ batchId,
264
+ dispatched: [],
265
+ failed: batch.map(t => t.id),
266
+ conflicts: preflight.conflicts,
267
+ error: `Pre-flight check failed: ${preflight.conflicts.length} potential conflict(s) detected`,
268
+ };
269
+ }
270
+ // Initialize conflict ledger for this batch
271
+ initConflictLedger(project.path, batchId);
272
+ // Dispatch each task
273
+ for (const task of batch) {
274
+ // Register expected files in the ledger BEFORE dispatch
275
+ registerExpectedFiles(project.path, task.id, task.affectedFiles);
276
+ const result = (0, agent_dispatch_1.dispatchTaskToAgent)(task, project, force);
277
+ if (result.success) {
278
+ dispatched.push(task.id);
279
+ }
280
+ else {
281
+ failed.push(task.id);
282
+ }
283
+ }
284
+ return {
285
+ success: failed.length === 0,
286
+ batchId,
287
+ dispatched,
288
+ failed,
289
+ conflicts: [],
290
+ };
291
+ }
292
+ // ─── Conflict Ledger Persistence ────────────────────────────────────────────
293
+ function getLedgerPath(projectPath) {
294
+ return path_1.default.join((0, continuity_1.getCmDir)(projectPath), PARALLEL_LEDGER_FILE);
295
+ }
296
+ function initConflictLedger(projectPath, sessionId) {
297
+ (0, continuity_1.ensureCmDir)(projectPath);
298
+ const ledger = {
299
+ sessionId,
300
+ startedAt: new Date().toISOString(),
301
+ entries: {},
302
+ conflicts: [],
303
+ };
304
+ fs_1.default.writeFileSync(getLedgerPath(projectPath), JSON.stringify(ledger, null, 2));
305
+ }
306
+ function readConflictLedger(projectPath) {
307
+ const ledgerPath = getLedgerPath(projectPath);
308
+ try {
309
+ if (fs_1.default.existsSync(ledgerPath)) {
310
+ return JSON.parse(fs_1.default.readFileSync(ledgerPath, 'utf-8'));
311
+ }
312
+ }
313
+ catch ( /* empty */_a) { /* empty */ }
314
+ return { sessionId: '', startedAt: '', entries: {}, conflicts: [] };
315
+ }
316
+ function registerExpectedFiles(projectPath, taskId, files) {
317
+ const ledger = readConflictLedger(projectPath);
318
+ ledger.entries[taskId] = files;
319
+ fs_1.default.writeFileSync(getLedgerPath(projectPath), JSON.stringify(ledger, null, 2));
320
+ }
321
+ function reportModifiedFiles(projectPath, taskId, actualFiles) {
322
+ const ledger = readConflictLedger(projectPath);
323
+ ledger.entries[taskId] = actualFiles;
324
+ // Detect conflicts after update
325
+ const conflicts = detectConflicts(ledger);
326
+ ledger.conflicts = conflicts;
327
+ fs_1.default.writeFileSync(getLedgerPath(projectPath), JSON.stringify(ledger, null, 2));
328
+ return conflicts;
329
+ }
330
+ function clearConflictLedger(projectPath) {
331
+ const ledgerPath = getLedgerPath(projectPath);
332
+ if (fs_1.default.existsSync(ledgerPath)) {
333
+ fs_1.default.unlinkSync(ledgerPath);
334
+ }
335
+ }
336
+ // ─── Parallel History Persistence ───────────────────────────────────────────
337
+ function getHistoryPath(projectPath) {
338
+ return path_1.default.join((0, continuity_1.getCmDir)(projectPath), PARALLEL_HISTORY_FILE);
339
+ }
340
+ function readParallelHistory(projectPath) {
341
+ const historyPath = getHistoryPath(projectPath);
342
+ try {
343
+ if (fs_1.default.existsSync(historyPath)) {
344
+ return JSON.parse(fs_1.default.readFileSync(historyPath, 'utf-8'));
345
+ }
346
+ }
347
+ catch ( /* empty */_a) { /* empty */ }
348
+ return { sessions: [] };
349
+ }
350
+ function recordParallelSession(projectPath, session) {
351
+ (0, continuity_1.ensureCmDir)(projectPath);
352
+ const history = readParallelHistory(projectPath);
353
+ history.sessions.push(session);
354
+ // Keep max 50 sessions
355
+ if (history.sessions.length > 50) {
356
+ history.sessions = history.sessions.slice(-50);
357
+ }
358
+ fs_1.default.writeFileSync(getHistoryPath(projectPath), JSON.stringify(history, null, 2));
359
+ }