@ktpartners/dgs-platform 2.6.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 (256) hide show
  1. package/LICENSE +38 -0
  2. package/README.md +851 -0
  3. package/agents/dgs-codebase-cross-analyzer.md +183 -0
  4. package/agents/dgs-codebase-mapper.md +782 -0
  5. package/agents/dgs-codebase-synthesizer.md +156 -0
  6. package/agents/dgs-debugger.md +1256 -0
  7. package/agents/dgs-executor.md +550 -0
  8. package/agents/dgs-integration-checker.md +481 -0
  9. package/agents/dgs-nyquist-auditor.md +178 -0
  10. package/agents/dgs-phase-researcher.md +563 -0
  11. package/agents/dgs-phase-verifier.md +450 -0
  12. package/agents/dgs-plan-checker.md +708 -0
  13. package/agents/dgs-planner.md +1324 -0
  14. package/agents/dgs-project-researcher.md +631 -0
  15. package/agents/dgs-research-synthesizer.md +249 -0
  16. package/agents/dgs-roadmapper.md +652 -0
  17. package/agents/dgs-verifier.md +607 -0
  18. package/bin/install.js +2073 -0
  19. package/commands/dgs/add-doc.md +45 -0
  20. package/commands/dgs/add-idea.md +38 -0
  21. package/commands/dgs/add-phase.md +43 -0
  22. package/commands/dgs/add-repo.md +54 -0
  23. package/commands/dgs/add-tests.md +41 -0
  24. package/commands/dgs/add-todo.md +47 -0
  25. package/commands/dgs/approve-spec.md +38 -0
  26. package/commands/dgs/audit-milestone.md +36 -0
  27. package/commands/dgs/audit-phase.md +37 -0
  28. package/commands/dgs/cancel-job.md +23 -0
  29. package/commands/dgs/capture-principle.md +143 -0
  30. package/commands/dgs/check-todos.md +45 -0
  31. package/commands/dgs/cleanup.md +18 -0
  32. package/commands/dgs/complete-milestone.md +136 -0
  33. package/commands/dgs/complete-project.md +70 -0
  34. package/commands/dgs/consolidate-ideas.md +50 -0
  35. package/commands/dgs/create-milestone-job.md +37 -0
  36. package/commands/dgs/debug.md +164 -0
  37. package/commands/dgs/develop-idea.md +53 -0
  38. package/commands/dgs/discuss-idea.md +41 -0
  39. package/commands/dgs/discuss-phase.md +83 -0
  40. package/commands/dgs/execute-phase.md +41 -0
  41. package/commands/dgs/fast.md +38 -0
  42. package/commands/dgs/find-related-ideas.md +43 -0
  43. package/commands/dgs/health.md +28 -0
  44. package/commands/dgs/help.md +22 -0
  45. package/commands/dgs/import-spec.md +36 -0
  46. package/commands/dgs/init-product.md +28 -0
  47. package/commands/dgs/insert-phase.md +32 -0
  48. package/commands/dgs/join-discord.md +18 -0
  49. package/commands/dgs/list-docs.md +40 -0
  50. package/commands/dgs/list-ideas.md +42 -0
  51. package/commands/dgs/list-jobs.md +22 -0
  52. package/commands/dgs/list-phase-assumptions.md +46 -0
  53. package/commands/dgs/list-projects.md +57 -0
  54. package/commands/dgs/list-specs.md +40 -0
  55. package/commands/dgs/map-codebase.md +92 -0
  56. package/commands/dgs/new-milestone.md +44 -0
  57. package/commands/dgs/new-project.md +42 -0
  58. package/commands/dgs/node-repair.md +26 -0
  59. package/commands/dgs/overlap-check.md +20 -0
  60. package/commands/dgs/pause-work.md +38 -0
  61. package/commands/dgs/plan-milestone-gaps.md +34 -0
  62. package/commands/dgs/plan-phase.md +44 -0
  63. package/commands/dgs/progress.md +24 -0
  64. package/commands/dgs/quick.md +41 -0
  65. package/commands/dgs/reactivate-project.md +70 -0
  66. package/commands/dgs/reapply-patches.md +110 -0
  67. package/commands/dgs/refine-spec.md +38 -0
  68. package/commands/dgs/reject-idea.md +43 -0
  69. package/commands/dgs/remove-doc.md +44 -0
  70. package/commands/dgs/remove-phase.md +31 -0
  71. package/commands/dgs/remove-repo.md +69 -0
  72. package/commands/dgs/research-idea.md +43 -0
  73. package/commands/dgs/research-phase.md +189 -0
  74. package/commands/dgs/restore-idea.md +45 -0
  75. package/commands/dgs/resume-work.md +40 -0
  76. package/commands/dgs/rollback-job.md +24 -0
  77. package/commands/dgs/run-job.md +35 -0
  78. package/commands/dgs/search.md +40 -0
  79. package/commands/dgs/set-profile.md +34 -0
  80. package/commands/dgs/settings.md +38 -0
  81. package/commands/dgs/switch-project.md +58 -0
  82. package/commands/dgs/undo-consolidation.md +42 -0
  83. package/commands/dgs/update-idea.md +44 -0
  84. package/commands/dgs/update.md +37 -0
  85. package/commands/dgs/validate-phase.md +35 -0
  86. package/commands/dgs/verify-work.md +39 -0
  87. package/commands/dgs/write-spec.md +49 -0
  88. package/deliver-great-systems/.planning/phases/09-backend-wiring-and-error-handling/09-01-SUMMARY.md +84 -0
  89. package/deliver-great-systems/.planning/phases/09-backend-wiring-and-error-handling/09-02-SUMMARY.md +86 -0
  90. package/deliver-great-systems/.planning/phases/10-v1-to-v2-migration-flow/10-01-SUMMARY.md +85 -0
  91. package/deliver-great-systems/bin/dgs-tools.cjs +1444 -0
  92. package/deliver-great-systems/bin/lib/auto-test.cjs +1365 -0
  93. package/deliver-great-systems/bin/lib/commands.cjs +570 -0
  94. package/deliver-great-systems/bin/lib/config.cjs +417 -0
  95. package/deliver-great-systems/bin/lib/conflict-agent.cjs +1063 -0
  96. package/deliver-great-systems/bin/lib/conflict-agent.test.cjs +554 -0
  97. package/deliver-great-systems/bin/lib/context.cjs +929 -0
  98. package/deliver-great-systems/bin/lib/context.test.cjs +693 -0
  99. package/deliver-great-systems/bin/lib/core.cjs +744 -0
  100. package/deliver-great-systems/bin/lib/core.test.cjs +822 -0
  101. package/deliver-great-systems/bin/lib/docs.cjs +919 -0
  102. package/deliver-great-systems/bin/lib/docs.test.cjs +211 -0
  103. package/deliver-great-systems/bin/lib/execution.cjs +705 -0
  104. package/deliver-great-systems/bin/lib/execution.test.cjs +1472 -0
  105. package/deliver-great-systems/bin/lib/frontmatter.cjs +324 -0
  106. package/deliver-great-systems/bin/lib/ideas.cjs +1406 -0
  107. package/deliver-great-systems/bin/lib/ideas.test.cjs +1417 -0
  108. package/deliver-great-systems/bin/lib/identity.cjs +125 -0
  109. package/deliver-great-systems/bin/lib/init.cjs +1114 -0
  110. package/deliver-great-systems/bin/lib/init.test.cjs +1271 -0
  111. package/deliver-great-systems/bin/lib/jobs.cjs +2015 -0
  112. package/deliver-great-systems/bin/lib/jobs.test.cjs +2619 -0
  113. package/deliver-great-systems/bin/lib/merge-conflicts.cjs +654 -0
  114. package/deliver-great-systems/bin/lib/merge-conflicts.test.cjs +370 -0
  115. package/deliver-great-systems/bin/lib/migration.cjs +352 -0
  116. package/deliver-great-systems/bin/lib/migration.test.cjs +582 -0
  117. package/deliver-great-systems/bin/lib/milestone.cjs +243 -0
  118. package/deliver-great-systems/bin/lib/overlap.cjs +437 -0
  119. package/deliver-great-systems/bin/lib/overlap.test.cjs +747 -0
  120. package/deliver-great-systems/bin/lib/path-audit.test.cjs +384 -0
  121. package/deliver-great-systems/bin/lib/paths.cjs +144 -0
  122. package/deliver-great-systems/bin/lib/paths.test.cjs +486 -0
  123. package/deliver-great-systems/bin/lib/phase.cjs +910 -0
  124. package/deliver-great-systems/bin/lib/projects.cjs +691 -0
  125. package/deliver-great-systems/bin/lib/projects.test.cjs +871 -0
  126. package/deliver-great-systems/bin/lib/repos.cjs +1432 -0
  127. package/deliver-great-systems/bin/lib/repos.test.cjs +1882 -0
  128. package/deliver-great-systems/bin/lib/roadmap.cjs +305 -0
  129. package/deliver-great-systems/bin/lib/search.cjs +570 -0
  130. package/deliver-great-systems/bin/lib/specs.cjs +1303 -0
  131. package/deliver-great-systems/bin/lib/state.cjs +893 -0
  132. package/deliver-great-systems/bin/lib/template.cjs +228 -0
  133. package/deliver-great-systems/bin/lib/test-helpers.cjs +291 -0
  134. package/deliver-great-systems/bin/lib/verify.cjs +796 -0
  135. package/deliver-great-systems/references/checkpoints.md +776 -0
  136. package/deliver-great-systems/references/conflict-resolution.md +66 -0
  137. package/deliver-great-systems/references/context-tiers.md +166 -0
  138. package/deliver-great-systems/references/continuation-format.md +249 -0
  139. package/deliver-great-systems/references/decimal-phase-calculation.md +67 -0
  140. package/deliver-great-systems/references/git-integration.md +250 -0
  141. package/deliver-great-systems/references/git-planning-commit.md +40 -0
  142. package/deliver-great-systems/references/model-profile-resolution.md +36 -0
  143. package/deliver-great-systems/references/model-profiles.md +95 -0
  144. package/deliver-great-systems/references/phase-argument-parsing.md +61 -0
  145. package/deliver-great-systems/references/planning-config.md +224 -0
  146. package/deliver-great-systems/references/questioning.md +162 -0
  147. package/deliver-great-systems/references/spec-review-loop.md +177 -0
  148. package/deliver-great-systems/references/tdd.md +265 -0
  149. package/deliver-great-systems/references/ui-brand.md +160 -0
  150. package/deliver-great-systems/references/verification-patterns.md +612 -0
  151. package/deliver-great-systems/templates/DEBUG.md +166 -0
  152. package/deliver-great-systems/templates/UAT.md +251 -0
  153. package/deliver-great-systems/templates/VALIDATION.md +95 -0
  154. package/deliver-great-systems/templates/claude-md.md +74 -0
  155. package/deliver-great-systems/templates/codebase/architecture.md +257 -0
  156. package/deliver-great-systems/templates/codebase/concerns.md +312 -0
  157. package/deliver-great-systems/templates/codebase/conventions.md +309 -0
  158. package/deliver-great-systems/templates/codebase/integrations.md +282 -0
  159. package/deliver-great-systems/templates/codebase/stack.md +188 -0
  160. package/deliver-great-systems/templates/codebase/structure.md +287 -0
  161. package/deliver-great-systems/templates/codebase/testing.md +482 -0
  162. package/deliver-great-systems/templates/config.json +38 -0
  163. package/deliver-great-systems/templates/context.md +354 -0
  164. package/deliver-great-systems/templates/continue-here.md +80 -0
  165. package/deliver-great-systems/templates/debug-subagent-prompt.md +93 -0
  166. package/deliver-great-systems/templates/discovery.md +148 -0
  167. package/deliver-great-systems/templates/milestone-archive.md +125 -0
  168. package/deliver-great-systems/templates/milestone.md +117 -0
  169. package/deliver-great-systems/templates/phase-prompt.md +615 -0
  170. package/deliver-great-systems/templates/planner-subagent-prompt.md +119 -0
  171. package/deliver-great-systems/templates/project.md +186 -0
  172. package/deliver-great-systems/templates/requirements.md +233 -0
  173. package/deliver-great-systems/templates/research-project/ARCHITECTURE.md +206 -0
  174. package/deliver-great-systems/templates/research-project/FEATURES.md +149 -0
  175. package/deliver-great-systems/templates/research-project/PITFALLS.md +202 -0
  176. package/deliver-great-systems/templates/research-project/STACK.md +122 -0
  177. package/deliver-great-systems/templates/research-project/SUMMARY.md +172 -0
  178. package/deliver-great-systems/templates/research.md +554 -0
  179. package/deliver-great-systems/templates/retrospective.md +54 -0
  180. package/deliver-great-systems/templates/roadmap.md +204 -0
  181. package/deliver-great-systems/templates/state.md +178 -0
  182. package/deliver-great-systems/templates/summary-complex.md +59 -0
  183. package/deliver-great-systems/templates/summary-minimal.md +41 -0
  184. package/deliver-great-systems/templates/summary-standard.md +48 -0
  185. package/deliver-great-systems/templates/summary.md +253 -0
  186. package/deliver-great-systems/templates/user-setup.md +313 -0
  187. package/deliver-great-systems/templates/verification-report.md +324 -0
  188. package/deliver-great-systems/workflows/add-doc.md +151 -0
  189. package/deliver-great-systems/workflows/add-idea.md +96 -0
  190. package/deliver-great-systems/workflows/add-phase.md +120 -0
  191. package/deliver-great-systems/workflows/add-tests.md +359 -0
  192. package/deliver-great-systems/workflows/add-todo.md +162 -0
  193. package/deliver-great-systems/workflows/approve-spec.md +194 -0
  194. package/deliver-great-systems/workflows/audit-milestone.md +364 -0
  195. package/deliver-great-systems/workflows/audit-phase.md +462 -0
  196. package/deliver-great-systems/workflows/cancel-job.md +108 -0
  197. package/deliver-great-systems/workflows/check-todos.md +181 -0
  198. package/deliver-great-systems/workflows/cleanup.md +247 -0
  199. package/deliver-great-systems/workflows/codereview.md +526 -0
  200. package/deliver-great-systems/workflows/complete-milestone.md +1298 -0
  201. package/deliver-great-systems/workflows/consolidate-ideas.md +365 -0
  202. package/deliver-great-systems/workflows/create-milestone-job.md +177 -0
  203. package/deliver-great-systems/workflows/develop-idea.md +544 -0
  204. package/deliver-great-systems/workflows/diagnose-issues.md +231 -0
  205. package/deliver-great-systems/workflows/discovery-phase.md +301 -0
  206. package/deliver-great-systems/workflows/discuss-idea.md +263 -0
  207. package/deliver-great-systems/workflows/discuss-phase.md +733 -0
  208. package/deliver-great-systems/workflows/execute-phase.md +571 -0
  209. package/deliver-great-systems/workflows/execute-plan.md +592 -0
  210. package/deliver-great-systems/workflows/find-related-ideas.md +271 -0
  211. package/deliver-great-systems/workflows/health.md +173 -0
  212. package/deliver-great-systems/workflows/help.md +997 -0
  213. package/deliver-great-systems/workflows/import-spec.md +381 -0
  214. package/deliver-great-systems/workflows/init-product.md +767 -0
  215. package/deliver-great-systems/workflows/insert-phase.md +138 -0
  216. package/deliver-great-systems/workflows/list-docs.md +119 -0
  217. package/deliver-great-systems/workflows/list-ideas.md +154 -0
  218. package/deliver-great-systems/workflows/list-jobs.md +89 -0
  219. package/deliver-great-systems/workflows/list-phase-assumptions.md +192 -0
  220. package/deliver-great-systems/workflows/list-specs.md +101 -0
  221. package/deliver-great-systems/workflows/map-codebase.md +621 -0
  222. package/deliver-great-systems/workflows/new-milestone.md +591 -0
  223. package/deliver-great-systems/workflows/new-project.md +1113 -0
  224. package/deliver-great-systems/workflows/node-repair.md +94 -0
  225. package/deliver-great-systems/workflows/overlap-check.md +86 -0
  226. package/deliver-great-systems/workflows/pause-work.md +134 -0
  227. package/deliver-great-systems/workflows/plan-milestone-gaps.md +306 -0
  228. package/deliver-great-systems/workflows/plan-phase.md +698 -0
  229. package/deliver-great-systems/workflows/progress.md +386 -0
  230. package/deliver-great-systems/workflows/quick.md +845 -0
  231. package/deliver-great-systems/workflows/refine-spec.md +275 -0
  232. package/deliver-great-systems/workflows/reject-idea.md +109 -0
  233. package/deliver-great-systems/workflows/remove-doc.md +117 -0
  234. package/deliver-great-systems/workflows/remove-phase.md +163 -0
  235. package/deliver-great-systems/workflows/research-idea.md +325 -0
  236. package/deliver-great-systems/workflows/research-phase.md +81 -0
  237. package/deliver-great-systems/workflows/restore-idea.md +101 -0
  238. package/deliver-great-systems/workflows/resume-project.md +311 -0
  239. package/deliver-great-systems/workflows/rollback-job.md +130 -0
  240. package/deliver-great-systems/workflows/run-job.md +498 -0
  241. package/deliver-great-systems/workflows/search.md +130 -0
  242. package/deliver-great-systems/workflows/set-profile.md +83 -0
  243. package/deliver-great-systems/workflows/settings.md +470 -0
  244. package/deliver-great-systems/workflows/transition.md +563 -0
  245. package/deliver-great-systems/workflows/undo-consolidation.md +155 -0
  246. package/deliver-great-systems/workflows/update-idea.md +157 -0
  247. package/deliver-great-systems/workflows/update.md +242 -0
  248. package/deliver-great-systems/workflows/validate-phase.md +177 -0
  249. package/deliver-great-systems/workflows/verify-phase.md +253 -0
  250. package/deliver-great-systems/workflows/verify-work.md +671 -0
  251. package/deliver-great-systems/workflows/write-spec.md +450 -0
  252. package/hooks/dist/dgs-check-update.js +62 -0
  253. package/hooks/dist/dgs-context-monitor.js +141 -0
  254. package/hooks/dist/dgs-statusline.js +115 -0
  255. package/package.json +60 -0
  256. package/scripts/build-hooks.js +43 -0
@@ -0,0 +1,370 @@
1
+ /**
2
+ * Tests for classifyConflictHunks in merge-conflicts.cjs
3
+ *
4
+ * Covers all four conflict types (ADDITIVE, DIVERGENT, STRUCTURAL, DELETION),
5
+ * confidence scoring (HIGH, MEDIUM, LOW), ambiguity flagging, plan-context
6
+ * enhancement, multi-hunk files, and edge cases.
7
+ *
8
+ * Uses Node.js built-in test runner (node:test) and assert (node:assert/strict).
9
+ */
10
+
11
+ const { describe, it } = require('node:test');
12
+ const assert = require('node:assert/strict');
13
+
14
+ const { classifyConflictHunks } = require('./merge-conflicts.cjs');
15
+
16
+ // ─── Helper ──────────────────────────────────────────────────────────────────
17
+
18
+ /**
19
+ * Build a file content string with one or more conflict hunks.
20
+ * @param {Array<{ours: string, theirs: string}>} hunks
21
+ * @returns {string}
22
+ */
23
+ function buildConflictFile(hunks) {
24
+ const parts = ['// preamble'];
25
+ for (const h of hunks) {
26
+ parts.push('<<<<<<< HEAD');
27
+ if (h.ours) parts.push(h.ours);
28
+ parts.push('=======');
29
+ if (h.theirs) parts.push(h.theirs);
30
+ parts.push('>>>>>>> feature-branch');
31
+ }
32
+ parts.push('// postamble');
33
+ return parts.join('\n');
34
+ }
35
+
36
+ // ─── ADDITIVE classification ─────────────────────────────────────────────────
37
+
38
+ describe('classifyConflictHunks', () => {
39
+
40
+ describe('ADDITIVE classification', () => {
41
+
42
+ it('detects ours-empty as ADDITIVE with HIGH confidence', () => {
43
+ const content = buildConflictFile([{
44
+ ours: '',
45
+ theirs: 'const newFeature = true;',
46
+ }]);
47
+ const result = classifyConflictHunks(content, null);
48
+ assert.equal(result.length, 1);
49
+ assert.equal(result[0].type, 'ADDITIVE');
50
+ assert.equal(result[0].confidence, 'HIGH');
51
+ assert.equal(result[0].ambiguous, false);
52
+ });
53
+
54
+ it('detects one-side-superset as ADDITIVE with MEDIUM confidence', () => {
55
+ const content = buildConflictFile([{
56
+ ours: 'const a = 1;',
57
+ theirs: 'const a = 1;\nconst b = 2;',
58
+ }]);
59
+ const result = classifyConflictHunks(content, null);
60
+ assert.equal(result.length, 1);
61
+ assert.equal(result[0].type, 'ADDITIVE');
62
+ assert.equal(result[0].confidence, 'MEDIUM');
63
+ });
64
+
65
+ it('detects ours-is-superset as ADDITIVE with MEDIUM confidence', () => {
66
+ const content = buildConflictFile([{
67
+ ours: 'const x = 10;\nconst y = 20;',
68
+ theirs: 'const x = 10;',
69
+ }]);
70
+ const result = classifyConflictHunks(content, null);
71
+ assert.equal(result.length, 1);
72
+ assert.equal(result[0].type, 'ADDITIVE');
73
+ assert.equal(result[0].confidence, 'MEDIUM');
74
+ });
75
+
76
+ });
77
+
78
+ // ─── DIVERGENT classification ────────────────────────────────────────────────
79
+
80
+ describe('DIVERGENT classification', () => {
81
+
82
+ it('detects both-sides-different as DIVERGENT with LOW confidence', () => {
83
+ const content = buildConflictFile([{
84
+ ours: 'const mode = "dark";',
85
+ theirs: 'const mode = "light";',
86
+ }]);
87
+ const result = classifyConflictHunks(content, null);
88
+ assert.equal(result.length, 1);
89
+ assert.equal(result[0].type, 'DIVERGENT');
90
+ assert.equal(result[0].confidence, 'LOW');
91
+ });
92
+
93
+ it('marks DIVERGENT hunks as ambiguous when neither is superset', () => {
94
+ const content = buildConflictFile([{
95
+ ours: 'const timeout = 3000;',
96
+ theirs: 'const timeout = 5000;',
97
+ }]);
98
+ const result = classifyConflictHunks(content, null);
99
+ assert.equal(result.length, 1);
100
+ assert.equal(result[0].type, 'DIVERGENT');
101
+ assert.equal(result[0].ambiguous, true);
102
+ });
103
+
104
+ it('upgrades DIVERGENT to MEDIUM confidence with plan context', () => {
105
+ const content = buildConflictFile([{
106
+ ours: 'const retries = 3;',
107
+ theirs: 'const retries = 5;',
108
+ }]);
109
+ const planContext = [
110
+ { task_name: 'Update retry config', action_excerpt: 'Changed retry count' },
111
+ ];
112
+ const result = classifyConflictHunks(content, planContext);
113
+ assert.equal(result.length, 1);
114
+ assert.equal(result[0].type, 'DIVERGENT');
115
+ assert.equal(result[0].confidence, 'MEDIUM');
116
+ });
117
+
118
+ });
119
+
120
+ // ─── STRUCTURAL classification ───────────────────────────────────────────────
121
+
122
+ describe('STRUCTURAL classification', () => {
123
+
124
+ it('detects function signature conflicts as STRUCTURAL with HIGH confidence', () => {
125
+ const content = buildConflictFile([{
126
+ ours: 'function processData(input) {',
127
+ theirs: 'function processData(input, options) {',
128
+ }]);
129
+ const result = classifyConflictHunks(content, null);
130
+ assert.equal(result.length, 1);
131
+ assert.equal(result[0].type, 'STRUCTURAL');
132
+ assert.equal(result[0].confidence, 'HIGH');
133
+ });
134
+
135
+ it('detects import/require conflicts as STRUCTURAL with HIGH confidence', () => {
136
+ const content = buildConflictFile([{
137
+ ours: "const utils = require('./utils.cjs');",
138
+ theirs: "const utils = require('./utils-v2.cjs');",
139
+ }]);
140
+ const result = classifyConflictHunks(content, null);
141
+ assert.equal(result.length, 1);
142
+ assert.equal(result[0].type, 'STRUCTURAL');
143
+ assert.equal(result[0].confidence, 'HIGH');
144
+ });
145
+
146
+ it('detects module.exports conflicts as STRUCTURAL with HIGH confidence', () => {
147
+ const content = buildConflictFile([{
148
+ ours: 'module.exports = { foo };',
149
+ theirs: 'module.exports = { foo, bar };',
150
+ }]);
151
+ const result = classifyConflictHunks(content, null);
152
+ assert.equal(result.length, 1);
153
+ assert.equal(result[0].type, 'STRUCTURAL');
154
+ assert.equal(result[0].confidence, 'HIGH');
155
+ });
156
+
157
+ it('detects class declaration conflicts as STRUCTURAL with HIGH confidence', () => {
158
+ const content = buildConflictFile([{
159
+ ours: 'class Parser extends BaseParser {',
160
+ theirs: 'class Parser extends EnhancedParser {',
161
+ }]);
162
+ const result = classifyConflictHunks(content, null);
163
+ assert.equal(result.length, 1);
164
+ assert.equal(result[0].type, 'STRUCTURAL');
165
+ assert.equal(result[0].confidence, 'HIGH');
166
+ });
167
+
168
+ it('detects one-side structural as STRUCTURAL with MEDIUM confidence', () => {
169
+ const content = buildConflictFile([{
170
+ ours: "const helper = require('./helper.cjs');",
171
+ theirs: 'const value = 42;',
172
+ }]);
173
+ const result = classifyConflictHunks(content, null);
174
+ assert.equal(result.length, 1);
175
+ assert.equal(result[0].type, 'STRUCTURAL');
176
+ assert.equal(result[0].confidence, 'MEDIUM');
177
+ });
178
+
179
+ });
180
+
181
+ // ─── DELETION classification ─────────────────────────────────────────────────
182
+
183
+ describe('DELETION classification', () => {
184
+
185
+ it('detects theirs-empty as DELETION with HIGH confidence', () => {
186
+ const content = buildConflictFile([{
187
+ ours: 'const legacy = true;',
188
+ theirs: '',
189
+ }]);
190
+ const result = classifyConflictHunks(content, null);
191
+ assert.equal(result.length, 1);
192
+ assert.equal(result[0].type, 'DELETION');
193
+ assert.equal(result[0].confidence, 'HIGH');
194
+ });
195
+
196
+ it('provides reasoning for DELETION', () => {
197
+ const content = buildConflictFile([{
198
+ ours: 'const deprecated = "old";',
199
+ theirs: '',
200
+ }]);
201
+ const result = classifyConflictHunks(content, null);
202
+ assert.equal(result.length, 1);
203
+ assert.equal(result[0].type, 'DELETION');
204
+ assert.ok(result[0].reasoning.length > 0, 'reasoning should be non-empty');
205
+ });
206
+
207
+ });
208
+
209
+ // ─── Ambiguity detection ─────────────────────────────────────────────────────
210
+
211
+ describe('ambiguity detection', () => {
212
+
213
+ it('flags ambiguous when classification is uncertain (DIVERGENT)', () => {
214
+ const content = buildConflictFile([{
215
+ ours: 'const color = "red";',
216
+ theirs: 'const color = "blue";',
217
+ }]);
218
+ const result = classifyConflictHunks(content, null);
219
+ assert.equal(result[0].ambiguous, true);
220
+ });
221
+
222
+ it('does not flag unambiguous ADDITIVE hunks', () => {
223
+ const content = buildConflictFile([{
224
+ ours: '',
225
+ theirs: 'const added = true;',
226
+ }]);
227
+ const result = classifyConflictHunks(content, null);
228
+ assert.equal(result[0].ambiguous, false);
229
+ });
230
+
231
+ it('does not flag unambiguous STRUCTURAL hunks', () => {
232
+ const content = buildConflictFile([{
233
+ ours: 'function foo() {',
234
+ theirs: 'function foo(arg) {',
235
+ }]);
236
+ const result = classifyConflictHunks(content, null);
237
+ assert.equal(result[0].ambiguous, false);
238
+ });
239
+
240
+ });
241
+
242
+ // ─── Plan context enhancement ────────────────────────────────────────────────
243
+
244
+ describe('plan context enhancement', () => {
245
+
246
+ it('enhances ADDITIVE confidence to HIGH with matching plan context', () => {
247
+ const content = buildConflictFile([{
248
+ ours: 'const base = 1;',
249
+ theirs: 'const base = 1;\nconst extra = 2;',
250
+ }]);
251
+ // Without context: ADDITIVE MEDIUM (superset)
252
+ const withoutCtx = classifyConflictHunks(content, null);
253
+ assert.equal(withoutCtx[0].type, 'ADDITIVE');
254
+ assert.equal(withoutCtx[0].confidence, 'MEDIUM');
255
+
256
+ // With context matching additive intent: confidence upgraded
257
+ const planContext = [
258
+ { task_name: 'Add extra config', action_excerpt: 'create new configuration options' },
259
+ ];
260
+ const withCtx = classifyConflictHunks(content, planContext);
261
+ assert.equal(withCtx[0].type, 'ADDITIVE');
262
+ assert.equal(withCtx[0].confidence, 'HIGH');
263
+ });
264
+
265
+ it('enhances DIVERGENT confidence to MEDIUM with any plan context', () => {
266
+ const content = buildConflictFile([{
267
+ ours: 'const limit = 100;',
268
+ theirs: 'const limit = 200;',
269
+ }]);
270
+ const withoutCtx = classifyConflictHunks(content, null);
271
+ assert.equal(withoutCtx[0].confidence, 'LOW');
272
+
273
+ const planContext = [
274
+ { task_name: 'Increase limits', action_excerpt: 'bump limit values' },
275
+ ];
276
+ const withCtx = classifyConflictHunks(content, planContext);
277
+ assert.equal(withCtx[0].confidence, 'MEDIUM');
278
+ });
279
+
280
+ it('returns results without enhancement when planContext is null', () => {
281
+ const content = buildConflictFile([{
282
+ ours: '',
283
+ theirs: 'const fresh = true;',
284
+ }]);
285
+ const result = classifyConflictHunks(content, null);
286
+ assert.equal(result[0].type, 'ADDITIVE');
287
+ assert.equal(result[0].confidence, 'HIGH');
288
+ assert.ok(!result[0].reasoning.includes('Plan context'));
289
+ });
290
+
291
+ it('returns results without enhancement when planContext is empty array', () => {
292
+ const content = buildConflictFile([{
293
+ ours: '',
294
+ theirs: 'const fresh = true;',
295
+ }]);
296
+ const result = classifyConflictHunks(content, []);
297
+ assert.equal(result[0].type, 'ADDITIVE');
298
+ assert.equal(result[0].confidence, 'HIGH');
299
+ assert.ok(!result[0].reasoning.includes('Plan context'));
300
+ });
301
+
302
+ });
303
+
304
+ // ─── Edge cases ──────────────────────────────────────────────────────────────
305
+
306
+ describe('edge cases', () => {
307
+
308
+ it('returns empty array for file with no conflict markers', () => {
309
+ const content = '// normal file\nconst x = 1;\n';
310
+ const result = classifyConflictHunks(content, null);
311
+ assert.deepEqual(result, []);
312
+ });
313
+
314
+ it('handles multiple conflict hunks in one file', () => {
315
+ const content = buildConflictFile([
316
+ { ours: '', theirs: 'const newA = 1;' },
317
+ { ours: 'const val = "x";', theirs: 'const val = "y";' },
318
+ { ours: 'function run() {', theirs: 'function run(opts) {' },
319
+ ]);
320
+ const result = classifyConflictHunks(content, null);
321
+ assert.equal(result.length, 3);
322
+ assert.equal(result[0].type, 'ADDITIVE');
323
+ assert.equal(result[1].type, 'DIVERGENT');
324
+ assert.equal(result[2].type, 'STRUCTURAL');
325
+ });
326
+
327
+ it('returns start_line and end_line for each hunk', () => {
328
+ const content = buildConflictFile([{
329
+ ours: 'line1',
330
+ theirs: 'line2',
331
+ }]);
332
+ const result = classifyConflictHunks(content, null);
333
+ assert.equal(result.length, 1);
334
+ assert.ok(typeof result[0].start_line === 'number');
335
+ assert.ok(typeof result[0].end_line === 'number');
336
+ assert.ok(result[0].start_line > 0);
337
+ assert.ok(result[0].end_line >= result[0].start_line);
338
+ });
339
+
340
+ it('preserves ours and theirs content in output', () => {
341
+ const content = buildConflictFile([{
342
+ ours: 'const a = 1;',
343
+ theirs: 'const a = 2;',
344
+ }]);
345
+ const result = classifyConflictHunks(content, null);
346
+ assert.equal(result[0].ours, 'const a = 1;');
347
+ assert.equal(result[0].theirs, 'const a = 2;');
348
+ });
349
+
350
+ it('handles empty file content', () => {
351
+ const result = classifyConflictHunks('', null);
352
+ assert.deepEqual(result, []);
353
+ });
354
+
355
+ it('includes reasoning string in every classified hunk', () => {
356
+ const content = buildConflictFile([
357
+ { ours: '', theirs: 'new code' },
358
+ { ours: 'old', theirs: '' },
359
+ { ours: 'x', theirs: 'y' },
360
+ ]);
361
+ const result = classifyConflictHunks(content, null);
362
+ for (const hunk of result) {
363
+ assert.ok(typeof hunk.reasoning === 'string');
364
+ assert.ok(hunk.reasoning.length > 0, `reasoning for ${hunk.type} should be non-empty`);
365
+ }
366
+ });
367
+
368
+ });
369
+
370
+ });