gsd-pi 2.38.0-dev.96dc7fb → 2.38.0-dev.98b44dc

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 (217) hide show
  1. package/README.md +15 -11
  2. package/dist/app-paths.js +1 -1
  3. package/dist/extension-registry.js +2 -2
  4. package/dist/remote-questions-config.js +2 -2
  5. package/dist/resource-loader.js +34 -1
  6. package/dist/resources/extensions/browser-tools/index.js +3 -1
  7. package/dist/resources/extensions/browser-tools/tools/verify.js +97 -0
  8. package/dist/resources/extensions/env-utils.js +29 -0
  9. package/dist/resources/extensions/get-secrets-from-user.js +5 -24
  10. package/dist/resources/extensions/github-sync/cli.js +284 -0
  11. package/dist/resources/extensions/github-sync/index.js +73 -0
  12. package/dist/resources/extensions/github-sync/mapping.js +67 -0
  13. package/dist/resources/extensions/github-sync/sync.js +424 -0
  14. package/dist/resources/extensions/github-sync/templates.js +118 -0
  15. package/dist/resources/extensions/github-sync/types.js +7 -0
  16. package/dist/resources/extensions/gsd/auto/session.js +6 -23
  17. package/dist/resources/extensions/gsd/auto-dispatch.js +8 -9
  18. package/dist/resources/extensions/gsd/auto-loop.js +636 -594
  19. package/dist/resources/extensions/gsd/auto-post-unit.js +99 -70
  20. package/dist/resources/extensions/gsd/auto-prompts.js +202 -48
  21. package/dist/resources/extensions/gsd/auto-start.js +7 -1
  22. package/dist/resources/extensions/gsd/auto-worktree-sync.js +2 -1
  23. package/dist/resources/extensions/gsd/auto-worktree.js +3 -3
  24. package/dist/resources/extensions/gsd/auto.js +143 -96
  25. package/dist/resources/extensions/gsd/commands-extensions.js +3 -2
  26. package/dist/resources/extensions/gsd/commands-prefs-wizard.js +1 -1
  27. package/dist/resources/extensions/gsd/commands.js +4 -2
  28. package/dist/resources/extensions/gsd/context-budget.js +2 -10
  29. package/dist/resources/extensions/gsd/detection.js +1 -2
  30. package/dist/resources/extensions/gsd/docs/preferences-reference.md +0 -2
  31. package/dist/resources/extensions/gsd/doctor-providers.js +30 -11
  32. package/dist/resources/extensions/gsd/doctor.js +20 -1
  33. package/dist/resources/extensions/gsd/exit-command.js +2 -1
  34. package/dist/resources/extensions/gsd/export.js +1 -1
  35. package/dist/resources/extensions/gsd/files.js +48 -9
  36. package/dist/resources/extensions/gsd/forensics.js +1 -1
  37. package/dist/resources/extensions/gsd/git-service.js +30 -12
  38. package/dist/resources/extensions/gsd/gitignore.js +16 -3
  39. package/dist/resources/extensions/gsd/guided-flow.js +149 -38
  40. package/dist/resources/extensions/gsd/health-widget-core.js +32 -70
  41. package/dist/resources/extensions/gsd/health-widget.js +3 -86
  42. package/dist/resources/extensions/gsd/index.js +24 -20
  43. package/dist/resources/extensions/gsd/migrate/parsers.js +1 -1
  44. package/dist/resources/extensions/gsd/migrate-external.js +18 -1
  45. package/dist/resources/extensions/gsd/native-git-bridge.js +37 -0
  46. package/dist/resources/extensions/gsd/paths.js +3 -0
  47. package/dist/resources/extensions/gsd/preferences-models.js +0 -12
  48. package/dist/resources/extensions/gsd/preferences-types.js +1 -1
  49. package/dist/resources/extensions/gsd/preferences-validation.js +59 -11
  50. package/dist/resources/extensions/gsd/preferences.js +22 -11
  51. package/dist/resources/extensions/gsd/prompt-loader.js +6 -2
  52. package/dist/resources/extensions/gsd/prompts/complete-milestone.md +1 -1
  53. package/dist/resources/extensions/gsd/prompts/complete-slice.md +1 -1
  54. package/dist/resources/extensions/gsd/prompts/discuss.md +11 -14
  55. package/dist/resources/extensions/gsd/prompts/execute-task.md +5 -3
  56. package/dist/resources/extensions/gsd/prompts/guided-complete-slice.md +1 -1
  57. package/dist/resources/extensions/gsd/prompts/guided-discuss-milestone.md +11 -12
  58. package/dist/resources/extensions/gsd/prompts/guided-discuss-slice.md +8 -10
  59. package/dist/resources/extensions/gsd/prompts/guided-execute-task.md +1 -1
  60. package/dist/resources/extensions/gsd/prompts/guided-plan-milestone.md +1 -1
  61. package/dist/resources/extensions/gsd/prompts/guided-plan-slice.md +1 -1
  62. package/dist/resources/extensions/gsd/prompts/guided-research-slice.md +1 -1
  63. package/dist/resources/extensions/gsd/prompts/guided-resume-task.md +1 -1
  64. package/dist/resources/extensions/gsd/prompts/plan-milestone.md +1 -1
  65. package/dist/resources/extensions/gsd/prompts/plan-slice.md +1 -1
  66. package/dist/resources/extensions/gsd/prompts/queue.md +4 -8
  67. package/dist/resources/extensions/gsd/prompts/reactive-execute.md +11 -8
  68. package/dist/resources/extensions/gsd/prompts/reassess-roadmap.md +1 -1
  69. package/dist/resources/extensions/gsd/prompts/research-milestone.md +1 -1
  70. package/dist/resources/extensions/gsd/prompts/research-slice.md +1 -1
  71. package/dist/resources/extensions/gsd/prompts/run-uat.md +28 -11
  72. package/dist/resources/extensions/gsd/prompts/workflow-start.md +2 -2
  73. package/dist/resources/extensions/gsd/repo-identity.js +21 -4
  74. package/dist/resources/extensions/gsd/resource-version.js +2 -1
  75. package/dist/resources/extensions/gsd/roadmap-mutations.js +24 -0
  76. package/dist/resources/extensions/gsd/state.js +42 -23
  77. package/dist/resources/extensions/gsd/templates/runtime.md +21 -0
  78. package/dist/resources/extensions/gsd/templates/task-plan.md +3 -0
  79. package/dist/resources/extensions/gsd/visualizer-data.js +1 -1
  80. package/dist/resources/extensions/mcp-client/index.js +14 -1
  81. package/dist/resources/extensions/remote-questions/status.js +4 -1
  82. package/dist/resources/extensions/remote-questions/store.js +4 -1
  83. package/dist/resources/extensions/search-the-web/provider.js +2 -1
  84. package/dist/resources/extensions/shared/frontmatter.js +1 -1
  85. package/dist/resources/extensions/subagent/isolation.js +2 -1
  86. package/dist/resources/extensions/ttsr/rule-loader.js +2 -1
  87. package/package.json +1 -1
  88. package/packages/pi-ai/dist/utils/oauth/anthropic.js +2 -2
  89. package/packages/pi-ai/dist/utils/oauth/anthropic.js.map +1 -1
  90. package/packages/pi-ai/src/utils/oauth/anthropic.ts +2 -2
  91. package/packages/pi-coding-agent/dist/core/extensions/loader.d.ts.map +1 -1
  92. package/packages/pi-coding-agent/dist/core/extensions/loader.js +205 -7
  93. package/packages/pi-coding-agent/dist/core/extensions/loader.js.map +1 -1
  94. package/packages/pi-coding-agent/dist/core/skills.d.ts +1 -0
  95. package/packages/pi-coding-agent/dist/core/skills.d.ts.map +1 -1
  96. package/packages/pi-coding-agent/dist/core/skills.js +6 -1
  97. package/packages/pi-coding-agent/dist/core/skills.js.map +1 -1
  98. package/packages/pi-coding-agent/dist/index.d.ts +1 -1
  99. package/packages/pi-coding-agent/dist/index.d.ts.map +1 -1
  100. package/packages/pi-coding-agent/dist/index.js +1 -1
  101. package/packages/pi-coding-agent/dist/index.js.map +1 -1
  102. package/packages/pi-coding-agent/src/core/extensions/loader.ts +223 -7
  103. package/packages/pi-coding-agent/src/core/skills.ts +9 -1
  104. package/packages/pi-coding-agent/src/index.ts +1 -0
  105. package/src/resources/extensions/browser-tools/index.ts +3 -0
  106. package/src/resources/extensions/browser-tools/tools/verify.ts +117 -0
  107. package/src/resources/extensions/env-utils.ts +31 -0
  108. package/src/resources/extensions/get-secrets-from-user.ts +5 -24
  109. package/src/resources/extensions/github-sync/cli.ts +364 -0
  110. package/src/resources/extensions/github-sync/index.ts +93 -0
  111. package/src/resources/extensions/github-sync/mapping.ts +81 -0
  112. package/src/resources/extensions/github-sync/sync.ts +556 -0
  113. package/src/resources/extensions/github-sync/templates.ts +183 -0
  114. package/src/resources/extensions/github-sync/tests/cli.test.ts +20 -0
  115. package/src/resources/extensions/github-sync/tests/commit-linking.test.ts +39 -0
  116. package/src/resources/extensions/github-sync/tests/mapping.test.ts +104 -0
  117. package/src/resources/extensions/github-sync/tests/templates.test.ts +110 -0
  118. package/src/resources/extensions/github-sync/types.ts +47 -0
  119. package/src/resources/extensions/gsd/auto/session.ts +7 -25
  120. package/src/resources/extensions/gsd/auto-dispatch.ts +7 -9
  121. package/src/resources/extensions/gsd/auto-loop.ts +526 -545
  122. package/src/resources/extensions/gsd/auto-post-unit.ts +80 -44
  123. package/src/resources/extensions/gsd/auto-prompts.ts +247 -50
  124. package/src/resources/extensions/gsd/auto-start.ts +11 -1
  125. package/src/resources/extensions/gsd/auto-worktree-sync.ts +3 -1
  126. package/src/resources/extensions/gsd/auto-worktree.ts +3 -3
  127. package/src/resources/extensions/gsd/auto.ts +139 -101
  128. package/src/resources/extensions/gsd/commands-extensions.ts +4 -2
  129. package/src/resources/extensions/gsd/commands-prefs-wizard.ts +1 -1
  130. package/src/resources/extensions/gsd/commands.ts +5 -3
  131. package/src/resources/extensions/gsd/context-budget.ts +2 -12
  132. package/src/resources/extensions/gsd/detection.ts +2 -2
  133. package/src/resources/extensions/gsd/docs/preferences-reference.md +0 -2
  134. package/src/resources/extensions/gsd/doctor-providers.ts +30 -9
  135. package/src/resources/extensions/gsd/doctor.ts +22 -1
  136. package/src/resources/extensions/gsd/exit-command.ts +2 -2
  137. package/src/resources/extensions/gsd/export.ts +1 -1
  138. package/src/resources/extensions/gsd/files.ts +51 -11
  139. package/src/resources/extensions/gsd/forensics.ts +1 -1
  140. package/src/resources/extensions/gsd/git-service.ts +44 -10
  141. package/src/resources/extensions/gsd/gitignore.ts +17 -3
  142. package/src/resources/extensions/gsd/guided-flow.ts +177 -44
  143. package/src/resources/extensions/gsd/health-widget-core.ts +28 -80
  144. package/src/resources/extensions/gsd/health-widget.ts +3 -89
  145. package/src/resources/extensions/gsd/index.ts +24 -17
  146. package/src/resources/extensions/gsd/migrate/parsers.ts +1 -1
  147. package/src/resources/extensions/gsd/migrate-external.ts +18 -1
  148. package/src/resources/extensions/gsd/native-git-bridge.ts +37 -0
  149. package/src/resources/extensions/gsd/paths.ts +4 -0
  150. package/src/resources/extensions/gsd/preferences-models.ts +0 -12
  151. package/src/resources/extensions/gsd/preferences-types.ts +4 -4
  152. package/src/resources/extensions/gsd/preferences-validation.ts +51 -11
  153. package/src/resources/extensions/gsd/preferences.ts +25 -11
  154. package/src/resources/extensions/gsd/prompt-loader.ts +7 -2
  155. package/src/resources/extensions/gsd/prompts/complete-milestone.md +1 -1
  156. package/src/resources/extensions/gsd/prompts/complete-slice.md +1 -1
  157. package/src/resources/extensions/gsd/prompts/discuss.md +11 -14
  158. package/src/resources/extensions/gsd/prompts/execute-task.md +5 -3
  159. package/src/resources/extensions/gsd/prompts/guided-complete-slice.md +1 -1
  160. package/src/resources/extensions/gsd/prompts/guided-discuss-milestone.md +11 -12
  161. package/src/resources/extensions/gsd/prompts/guided-discuss-slice.md +8 -10
  162. package/src/resources/extensions/gsd/prompts/guided-execute-task.md +1 -1
  163. package/src/resources/extensions/gsd/prompts/guided-plan-milestone.md +1 -1
  164. package/src/resources/extensions/gsd/prompts/guided-plan-slice.md +1 -1
  165. package/src/resources/extensions/gsd/prompts/guided-research-slice.md +1 -1
  166. package/src/resources/extensions/gsd/prompts/guided-resume-task.md +1 -1
  167. package/src/resources/extensions/gsd/prompts/plan-milestone.md +1 -1
  168. package/src/resources/extensions/gsd/prompts/plan-slice.md +1 -1
  169. package/src/resources/extensions/gsd/prompts/queue.md +4 -8
  170. package/src/resources/extensions/gsd/prompts/reactive-execute.md +11 -8
  171. package/src/resources/extensions/gsd/prompts/reassess-roadmap.md +1 -1
  172. package/src/resources/extensions/gsd/prompts/research-milestone.md +1 -1
  173. package/src/resources/extensions/gsd/prompts/research-slice.md +1 -1
  174. package/src/resources/extensions/gsd/prompts/run-uat.md +28 -11
  175. package/src/resources/extensions/gsd/prompts/workflow-start.md +2 -2
  176. package/src/resources/extensions/gsd/repo-identity.ts +23 -4
  177. package/src/resources/extensions/gsd/resource-version.ts +3 -1
  178. package/src/resources/extensions/gsd/roadmap-mutations.ts +29 -0
  179. package/src/resources/extensions/gsd/state.ts +39 -21
  180. package/src/resources/extensions/gsd/templates/runtime.md +21 -0
  181. package/src/resources/extensions/gsd/templates/task-plan.md +3 -0
  182. package/src/resources/extensions/gsd/tests/agent-end-retry.test.ts +21 -18
  183. package/src/resources/extensions/gsd/tests/auto-loop.test.ts +122 -68
  184. package/src/resources/extensions/gsd/tests/auto-worktree-milestone-merge.test.ts +4 -3
  185. package/src/resources/extensions/gsd/tests/derive-state.test.ts +43 -0
  186. package/src/resources/extensions/gsd/tests/doctor-providers.test.ts +86 -3
  187. package/src/resources/extensions/gsd/tests/gitignore-tracked-gsd.test.ts +50 -0
  188. package/src/resources/extensions/gsd/tests/health-widget.test.ts +16 -54
  189. package/src/resources/extensions/gsd/tests/parsers.test.ts +131 -14
  190. package/src/resources/extensions/gsd/tests/plan-slice-prompt.test.ts +209 -0
  191. package/src/resources/extensions/gsd/tests/preferences.test.ts +2 -7
  192. package/src/resources/extensions/gsd/tests/prompt-contracts.test.ts +59 -0
  193. package/src/resources/extensions/gsd/tests/repo-identity-worktree.test.ts +21 -1
  194. package/src/resources/extensions/gsd/tests/run-uat.test.ts +16 -4
  195. package/src/resources/extensions/gsd/tests/skill-activation.test.ts +140 -0
  196. package/src/resources/extensions/gsd/types.ts +18 -1
  197. package/src/resources/extensions/gsd/verification-evidence.ts +16 -0
  198. package/src/resources/extensions/gsd/visualizer-data.ts +1 -1
  199. package/src/resources/extensions/mcp-client/index.ts +17 -1
  200. package/src/resources/extensions/remote-questions/status.ts +5 -1
  201. package/src/resources/extensions/remote-questions/store.ts +5 -1
  202. package/src/resources/extensions/search-the-web/provider.ts +2 -1
  203. package/src/resources/extensions/shared/frontmatter.ts +1 -1
  204. package/src/resources/extensions/subagent/isolation.ts +3 -1
  205. package/src/resources/extensions/ttsr/rule-loader.ts +3 -1
  206. package/dist/resources/extensions/gsd/prompt-compressor.js +0 -393
  207. package/dist/resources/extensions/gsd/semantic-chunker.js +0 -254
  208. package/dist/resources/extensions/gsd/summary-distiller.js +0 -212
  209. package/src/resources/extensions/gsd/prompt-compressor.ts +0 -508
  210. package/src/resources/extensions/gsd/semantic-chunker.ts +0 -336
  211. package/src/resources/extensions/gsd/summary-distiller.ts +0 -258
  212. package/src/resources/extensions/gsd/tests/context-compression.test.ts +0 -193
  213. package/src/resources/extensions/gsd/tests/prompt-compressor.test.ts +0 -529
  214. package/src/resources/extensions/gsd/tests/semantic-chunker.test.ts +0 -426
  215. package/src/resources/extensions/gsd/tests/summary-distiller.test.ts +0 -323
  216. package/src/resources/extensions/gsd/tests/token-optimization-benchmark.test.ts +0 -1272
  217. package/src/resources/extensions/gsd/tests/token-optimization-prefs.test.ts +0 -164
@@ -1,529 +0,0 @@
1
- import test from "node:test";
2
- import assert from "node:assert/strict";
3
-
4
- import {
5
- compressPrompt,
6
- compressToTarget,
7
- } from "../prompt-compressor.js";
8
- import type {
9
- CompressionLevel,
10
- CompressionResult,
11
- CompressionOptions,
12
- } from "../prompt-compressor.js";
13
-
14
- // ─── Test Fixtures ──────────────────────────────────────────────────────────
15
-
16
- const WHITESPACE_HEAVY = `# Section One
17
-
18
- Some content here.
19
-
20
-
21
-
22
- Another paragraph here.
23
-
24
-
25
- Yet another paragraph.
26
-
27
-
28
-
29
- # Section Two
30
-
31
- More content.`;
32
-
33
- const MARKDOWN_COMMENTS = `# Title
34
-
35
- <!-- This is a comment that should be removed -->
36
-
37
- Some content here.
38
-
39
- <!-- Another
40
- multi-line
41
- comment -->
42
-
43
- More content.`;
44
-
45
- const HORIZONTAL_RULES = `# Section One
46
-
47
- Some content.
48
-
49
- ---
50
-
51
- # Section Two
52
-
53
- More content.
54
-
55
- ***
56
-
57
- # Section Three
58
-
59
- Final content.`;
60
-
61
- const VERBOSE_PROSE = `In order to implement this feature, it is important to note that the following
62
- requirements must be met. Due to the fact that the system operates in real-time,
63
- prior to deployment we need to verify all components. In addition to the main
64
- module, a number of auxiliary services are required. In the event that a service
65
- fails, subsequent to the failure, the system should recover. For the purpose of
66
- monitoring, in accordance with our SLA, with regard to uptime, at this point in
67
- time we achieve 99.9%. On the basis of recent data, in the case of peak traffic,
68
- as mentioned previously, the system scales automatically.`;
69
-
70
- const BOILERPLATE_CONTENT = `# Requirements
71
-
72
- ## Feature A
73
- Must support pagination.
74
-
75
- ## Feature B
76
- N/A
77
-
78
- ## Feature C
79
- (none)
80
-
81
- ## Feature D
82
- (empty)
83
-
84
- ## Feature E
85
- (not applicable)
86
-
87
- ## Feature F
88
- Must handle errors gracefully.`;
89
-
90
- const DUPLICATE_LINES = `Status: active
91
- Status: active
92
- Status: active
93
- Priority: high
94
- Name: test project
95
- Name: test project`;
96
-
97
- const EMPHASIS_CONTENT = `This is **bold text** and this is *italic text*.
98
- Also __underline bold__ and _underline italic_.
99
- Check [this link](https://example.com) and [another](https://test.org).`;
100
-
101
- const CODE_BLOCK_CONTENT = `# Setup Guide
102
-
103
- In order to configure the system, run the following command:
104
-
105
- \`\`\`typescript
106
- const config = {
107
- debug: true,
108
- verbose: false,
109
- timeout: 3000,
110
- };
111
- \`\`\`
112
-
113
- Due to the fact that configuration is loaded at startup, prior to
114
- running the application, verify the config file exists.
115
-
116
- \`\`\`bash
117
- ls -la config.json
118
- \`\`\`
119
-
120
- The following steps complete the setup.`;
121
-
122
- const HEADING_CONTENT = `# Main Title
123
-
124
- ## Subsection A
125
-
126
- In order to do something, the following steps are needed.
127
-
128
- ## Subsection B
129
-
130
- More content here with **emphasis** and [a link](https://example.com).
131
-
132
- ### Sub-subsection
133
-
134
- Details here.`;
135
-
136
- const REALISTIC_GSD_CONTENT = `# Project: GSD Task Manager
137
-
138
- <!-- Generated by GSD v2.1.0 -->
139
-
140
- ## Decisions
141
-
142
- | Decision ID | Title | Status | Date |
143
- |---------------|------------------------------|------------|--------------|
144
- | DEC-001 | Use TypeScript | Approved | 2024-01-15 |
145
- | DEC-002 | Adopt monorepo | Approved | 2024-01-20 |
146
- | DEC-003 | Use node:test | Approved | 2024-02-01 |
147
-
148
- ## Requirements
149
-
150
- ### Must-Have
151
-
152
- In order to support the core workflow, it is important to note that the following
153
- requirements are non-negotiable. Due to the fact that the system must operate in
154
- CI environments, prior to any release, all tests must pass.
155
-
156
- - The system must handle concurrent operations
157
- - The system must handle concurrent operations
158
- - Error recovery must be automatic
159
- - Configuration must be file-based
160
- - Configuration must be file-based
161
-
162
- ### Nice-to-Have
163
-
164
- N/A
165
-
166
- ### Out of Scope
167
-
168
- (none)
169
-
170
- ---
171
-
172
- ## Implementation Notes
173
-
174
- > In accordance with our coding standards, all modules should follow
175
- > the single responsibility principle. With regard to testing, a number of
176
- > integration tests should supplement unit tests.
177
-
178
- For the purpose of maintaining code quality, at this point in time we require
179
- 100% branch coverage on critical paths. In the event that coverage drops below
180
- the threshold, subsequent to the detection, the CI pipeline should fail.
181
-
182
- **Important**: The following constraints apply:
183
- - *Memory usage* must stay under 512MB
184
- - *CPU usage* must not exceed 80% sustained
185
- - Response times under 100ms for the 95th percentile
186
-
187
- In addition to the above, the system should support plugin architecture.
188
- As mentioned previously, this was decided in DEC-001.
189
-
190
- ---
191
-
192
- ## Status
193
-
194
- Status: active
195
- Status: active
196
- Priority: high
197
- Sprint: 14
198
- Sprint: 14
199
- Milestone: v2.1.0`;
200
-
201
- const LONG_LINE = "This is a very long line that goes on and on. It contains multiple sentences that discuss various topics. The purpose of this line is to test the truncation functionality. When lines exceed 300 characters, they should be truncated at a sentence boundary. This ensures that the compressed output remains readable. Additional text is added here to make sure we exceed the 300 character limit for testing purposes. Even more text follows to pad the line further.";
202
-
203
- const BLOCKQUOTE_CONTENT = `> This is a blockquote
204
- > with multiple lines
205
- > that should have markers removed.
206
-
207
- Normal paragraph here.
208
-
209
- > Another blockquote.`;
210
-
211
- const BULLET_LIST = `Some intro text:
212
-
213
- - First item in the list
214
- - Second item in the list
215
- * Third item with star
216
- + Fourth item with plus
217
- 1. Numbered item one
218
- 2. Numbered item two
219
-
220
- Closing text.`;
221
-
222
- // ─── Light Compression Tests ────────────────────────────────────────────────
223
-
224
- test("light compression removes extra whitespace", () => {
225
- const result = compressPrompt(WHITESPACE_HEAVY, { level: "light" });
226
- assert.ok(result.compressedChars < result.originalChars, "should reduce size");
227
- assert.ok(!result.content.includes(" \n"), "should not have trailing spaces");
228
- // Should not have 3+ consecutive blank lines
229
- assert.ok(!result.content.match(/\n\s*\n\s*\n\s*\n/), "should not have 3+ blank lines");
230
- assert.equal(result.level, "light");
231
- });
232
-
233
- test("light compression removes markdown comments", () => {
234
- const result = compressPrompt(MARKDOWN_COMMENTS, { level: "light" });
235
- assert.ok(!result.content.includes("<!--"), "should not contain comment start");
236
- assert.ok(!result.content.includes("-->"), "should not contain comment end");
237
- assert.ok(result.content.includes("# Title"), "should preserve heading");
238
- assert.ok(result.content.includes("Some content here."), "should preserve normal content");
239
- });
240
-
241
- test("light compression removes horizontal rules", () => {
242
- const result = compressPrompt(HORIZONTAL_RULES, { level: "light" });
243
- assert.ok(!result.content.match(/^---$/m), "should not contain ---");
244
- assert.ok(!result.content.match(/^\*\*\*$/m), "should not contain ***");
245
- assert.ok(result.content.includes("# Section One"), "should preserve headings");
246
- assert.ok(result.content.includes("# Section Two"), "should preserve headings");
247
- });
248
-
249
- test("light compression preserves code blocks", () => {
250
- const result = compressPrompt(CODE_BLOCK_CONTENT, { level: "light" });
251
- assert.ok(result.content.includes("const config = {"), "should preserve code block content");
252
- assert.ok(result.content.includes("```typescript"), "should preserve code fence");
253
- assert.ok(result.content.includes("```bash"), "should preserve code fence");
254
- });
255
-
256
- // ─── Moderate Compression Tests ─────────────────────────────────────────────
257
-
258
- test("moderate compression abbreviates verbose phrases", () => {
259
- const result = compressPrompt(VERBOSE_PROSE, { level: "moderate" });
260
- assert.ok(result.content.includes("To implement"), "should abbreviate 'In order to'");
261
- assert.ok(result.content.includes("Because"), "should abbreviate 'Due to the fact that'");
262
- assert.ok(result.content.includes("Before deployment"), "should abbreviate 'Prior to'");
263
- assert.ok(result.content.includes("Also,"), "should abbreviate 'In addition to'");
264
- assert.ok(result.content.includes("Several"), "should abbreviate 'A number of'");
265
- assert.ok(result.content.includes("If"), "should abbreviate 'In the event that'");
266
- assert.ok(result.content.includes("After"), "should abbreviate 'Subsequent to'");
267
- assert.ok(!result.content.includes("For the purpose of"), "should abbreviate 'For the purpose of'");
268
- assert.ok(result.content.includes("Per"), "should abbreviate 'In accordance with'");
269
- assert.ok(result.content.includes("Re:"), "should abbreviate 'With regard to'");
270
- assert.ok(result.content.includes("Now"), "should abbreviate 'At this point in time'");
271
- assert.ok(result.content.includes("Based on"), "should abbreviate 'On the basis of'");
272
- assert.ok(result.content.includes("(see above)"), "should abbreviate 'As mentioned previously'");
273
- assert.ok(result.compressedChars < result.originalChars, "should reduce size");
274
- });
275
-
276
- test("moderate compression deduplicates consecutive lines", () => {
277
- const input = "Line one\nLine one\nLine one\nLine two\nLine three\nLine three";
278
- const result = compressPrompt(input, { level: "moderate" });
279
- const lines = result.content.split("\n").filter((l) => l.trim() !== "");
280
- // Count occurrences of "Line one"
281
- const lineOneCount = lines.filter((l) => l === "Line one").length;
282
- assert.equal(lineOneCount, 1, "should deduplicate 'Line one'");
283
- const lineThreeCount = lines.filter((l) => l === "Line three").length;
284
- assert.equal(lineThreeCount, 1, "should deduplicate 'Line three'");
285
- });
286
-
287
- test("moderate compression removes boilerplate", () => {
288
- const result = compressPrompt(BOILERPLATE_CONTENT, { level: "moderate" });
289
- assert.ok(!result.content.match(/^\s*N\/A\s*$/m), "should remove N/A lines");
290
- assert.ok(!result.content.includes("(none)"), "should remove (none)");
291
- assert.ok(!result.content.includes("(empty)"), "should remove (empty)");
292
- assert.ok(!result.content.includes("(not applicable)"), "should remove (not applicable)");
293
- assert.ok(result.content.includes("Must support pagination"), "should keep real content");
294
- assert.ok(result.content.includes("Must handle errors"), "should keep real content");
295
- });
296
-
297
- test("moderate compression collapses table formatting", () => {
298
- const table = `| Name | Value | Status |
299
- | foo | bar | active |`;
300
- const result = compressPrompt(table, { level: "moderate" });
301
- // Should have reduced padding
302
- assert.ok(result.compressedChars < result.originalChars, "should reduce table padding");
303
- });
304
-
305
- // ─── Aggressive Compression Tests ───────────────────────────────────────────
306
-
307
- test("aggressive compression removes emphasis and links", () => {
308
- const result = compressPrompt(EMPHASIS_CONTENT, { level: "aggressive" });
309
- assert.ok(!result.content.includes("**"), "should remove bold markers");
310
- assert.ok(!result.content.includes("__"), "should remove underline bold markers");
311
- assert.ok(result.content.includes("bold text"), "should keep bold text content");
312
- assert.ok(result.content.includes("italic text"), "should keep italic text content");
313
- assert.ok(result.content.includes("this link"), "should keep link text");
314
- assert.ok(!result.content.includes("https://example.com"), "should remove link URLs");
315
- assert.ok(!result.content.includes("https://test.org"), "should remove link URLs");
316
- });
317
-
318
- test("aggressive compression removes bullet markers", () => {
319
- const result = compressPrompt(BULLET_LIST, { level: "aggressive" });
320
- assert.ok(!result.content.match(/^- /m), "should remove dash bullets");
321
- assert.ok(!result.content.match(/^\* /m), "should remove star bullets");
322
- assert.ok(!result.content.match(/^\+ /m), "should remove plus bullets");
323
- assert.ok(!result.content.match(/^\d+\. /m), "should remove numbered bullets");
324
- assert.ok(result.content.includes("First item"), "should keep bullet content");
325
- assert.ok(result.content.includes("Numbered item"), "should keep numbered content");
326
- });
327
-
328
- test("aggressive compression removes blockquote markers", () => {
329
- const result = compressPrompt(BLOCKQUOTE_CONTENT, { level: "aggressive" });
330
- assert.ok(!result.content.match(/^> /m), "should remove blockquote markers");
331
- assert.ok(result.content.includes("This is a blockquote"), "should keep blockquote content");
332
- assert.ok(result.content.includes("Normal paragraph"), "should keep normal content");
333
- });
334
-
335
- test("aggressive compression truncates long lines", () => {
336
- const result = compressPrompt(LONG_LINE, { level: "aggressive" });
337
- const lines = result.content.split("\n");
338
- for (const line of lines) {
339
- assert.ok(line.length <= 300, `line should be <= 300 chars, got ${line.length}`);
340
- }
341
- });
342
-
343
- test("aggressive compression deduplicates structural patterns", () => {
344
- const result = compressPrompt(DUPLICATE_LINES, { level: "aggressive" });
345
- const lines = result.content.split("\n").filter((l) => l.trim() !== "");
346
- const statusCount = lines.filter((l) => l.includes("Status: active")).length;
347
- assert.equal(statusCount, 1, "should keep only one Status: active");
348
- const nameCount = lines.filter((l) => l.includes("Name: test project")).length;
349
- assert.equal(nameCount, 1, "should keep only one Name: test project");
350
- });
351
-
352
- // ─── Preservation Tests ─────────────────────────────────────────────────────
353
-
354
- test("code block preservation protects code from compression", () => {
355
- const result = compressPrompt(CODE_BLOCK_CONTENT, {
356
- level: "aggressive",
357
- preserveCodeBlocks: true,
358
- });
359
- // Code blocks should be untouched
360
- assert.ok(result.content.includes("const config = {"), "code block preserved");
361
- assert.ok(result.content.includes("debug: true,"), "code block details preserved");
362
- assert.ok(result.content.includes("ls -la config.json"), "bash code block preserved");
363
- // But surrounding prose should be compressed
364
- assert.ok(!result.content.includes("In order to"), "prose should be compressed");
365
- assert.ok(!result.content.includes("Due to the fact that"), "prose should be compressed");
366
- });
367
-
368
- test("code block preservation can be disabled", () => {
369
- const result = compressPrompt(CODE_BLOCK_CONTENT, {
370
- level: "aggressive",
371
- preserveCodeBlocks: false,
372
- });
373
- // Phrase abbreviation still works on surrounding text
374
- assert.ok(result.compressedChars < result.originalChars, "should still compress");
375
- });
376
-
377
- test("heading preservation keeps headings intact", () => {
378
- const result = compressPrompt(HEADING_CONTENT, {
379
- level: "aggressive",
380
- preserveHeadings: true,
381
- });
382
- assert.ok(result.content.includes("# Main Title"), "should preserve h1");
383
- assert.ok(result.content.includes("## Subsection A"), "should preserve h2");
384
- assert.ok(result.content.includes("## Subsection B"), "should preserve h2");
385
- assert.ok(result.content.includes("### Sub-subsection"), "should preserve h3");
386
- });
387
-
388
- // ─── compressToTarget Tests ─────────────────────────────────────────────────
389
-
390
- test("compressToTarget tries progressively harder levels", () => {
391
- // Set a target that light compression cannot reach
392
- const lightResult = compressPrompt(REALISTIC_GSD_CONTENT, { level: "light" });
393
- const moderateResult = compressPrompt(REALISTIC_GSD_CONTENT, { level: "moderate" });
394
-
395
- // Target between light and moderate results
396
- const target = Math.floor((lightResult.compressedChars + moderateResult.compressedChars) / 2);
397
- const result = compressToTarget(REALISTIC_GSD_CONTENT, target);
398
-
399
- // Should have used at least moderate
400
- assert.ok(
401
- result.level === "moderate" || result.level === "aggressive",
402
- `should use moderate or aggressive, got ${result.level}`,
403
- );
404
- assert.ok(result.compressedChars <= target, "should meet target");
405
- });
406
-
407
- test("compressToTarget returns best effort when target unreachable", () => {
408
- // Set an impossibly small target
409
- const result = compressToTarget(REALISTIC_GSD_CONTENT, 10);
410
- assert.equal(result.level, "aggressive", "should try aggressive as last resort");
411
- assert.ok(result.compressedChars > 10, "cannot reach impossibly small target");
412
- assert.ok(
413
- result.compressedChars < REALISTIC_GSD_CONTENT.length,
414
- "should still compress as much as possible",
415
- );
416
- });
417
-
418
- test("compressToTarget returns unchanged if already under target", () => {
419
- const result = compressToTarget("short text", 1000);
420
- assert.equal(result.content, "short text");
421
- assert.equal(result.savingsPercent, 0);
422
- assert.equal(result.transformationsApplied, 0);
423
- });
424
-
425
- // ─── Realistic GSD Content Test ─────────────────────────────────────────────
426
-
427
- test("realistic GSD content compresses significantly", () => {
428
- const result = compressPrompt(REALISTIC_GSD_CONTENT, { level: "aggressive" });
429
-
430
- // Should achieve meaningful compression
431
- assert.ok(result.savingsPercent > 15, `should achieve >15% savings, got ${result.savingsPercent}%`);
432
- assert.ok(result.transformationsApplied > 3, "should apply multiple transformations");
433
-
434
- // Key content preserved
435
- assert.ok(result.content.includes("# Project: GSD Task Manager"), "title preserved");
436
- assert.ok(result.content.includes("DEC-001"), "decision IDs preserved");
437
- assert.ok(result.content.includes("TypeScript"), "decision content preserved");
438
- assert.ok(result.content.includes("## Decisions"), "section headings preserved");
439
- assert.ok(result.content.includes("## Requirements"), "section headings preserved");
440
-
441
- // Comments removed
442
- assert.ok(!result.content.includes("<!--"), "comments removed");
443
-
444
- // Verbose phrases abbreviated
445
- assert.ok(!result.content.includes("In order to"), "verbose phrases compressed");
446
- assert.ok(!result.content.includes("Due to the fact that"), "verbose phrases compressed");
447
-
448
- // Boilerplate removed
449
- assert.ok(!result.content.match(/^\s*N\/A\s*$/m), "N/A removed");
450
- assert.ok(!result.content.includes("(none)"), "(none) removed");
451
- });
452
-
453
- // ─── Accuracy and Edge Cases ────────────────────────────────────────────────
454
-
455
- test("savingsPercent is accurate", () => {
456
- const result = compressPrompt(VERBOSE_PROSE, { level: "moderate" });
457
- const expectedPercent =
458
- Math.round(((result.originalChars - result.compressedChars) / result.originalChars) * 10000) / 100;
459
- assert.equal(result.savingsPercent, expectedPercent, "savings percent should be accurate");
460
- });
461
-
462
- test("empty input returns empty output", () => {
463
- const result = compressPrompt("", { level: "aggressive" });
464
- assert.equal(result.content, "");
465
- assert.equal(result.originalChars, 0);
466
- assert.equal(result.compressedChars, 0);
467
- assert.equal(result.savingsPercent, 0);
468
- assert.equal(result.transformationsApplied, 0);
469
- });
470
-
471
- test("already-compressed content is idempotent at same level", () => {
472
- const first = compressPrompt(VERBOSE_PROSE, { level: "moderate" });
473
- const second = compressPrompt(first.content, { level: "moderate" });
474
-
475
- assert.equal(first.content, second.content, "double compression should produce same result");
476
- });
477
-
478
- test("content with only code blocks is unchanged", () => {
479
- const codeOnly = "```typescript\nconst x = 1;\nconst y = 2;\n```";
480
- const result = compressPrompt(codeOnly, {
481
- level: "aggressive",
482
- preserveCodeBlocks: true,
483
- });
484
- assert.equal(result.content, codeOnly, "code-only content should be unchanged");
485
- });
486
-
487
- test("compression result contains correct metadata", () => {
488
- const result = compressPrompt(VERBOSE_PROSE, { level: "moderate" });
489
- assert.equal(result.originalChars, VERBOSE_PROSE.length);
490
- assert.equal(result.compressedChars, result.content.length);
491
- assert.equal(result.level, "moderate");
492
- assert.ok(result.transformationsApplied > 0, "should report transformations");
493
- assert.ok(result.savingsPercent > 0, "should have positive savings");
494
- assert.ok(result.savingsPercent < 100, "savings should be less than 100%");
495
- });
496
-
497
- test("light compression with defaults", () => {
498
- // Test that default options work (moderate level, preserve headings/code)
499
- const result = compressPrompt(REALISTIC_GSD_CONTENT);
500
- assert.equal(result.level, "moderate", "default level should be moderate");
501
- assert.ok(result.content.includes("# Project:"), "headings preserved by default");
502
- assert.ok(result.compressedChars < result.originalChars, "should compress");
503
- });
504
-
505
- test("multiple code blocks are all preserved", () => {
506
- const multiCode = `Some text.
507
-
508
- \`\`\`js
509
- function a() { return 1; }
510
- \`\`\`
511
-
512
- Middle text with **emphasis**.
513
-
514
- \`\`\`python
515
- def b():
516
- return 2
517
- \`\`\`
518
-
519
- End text.`;
520
-
521
- const result = compressPrompt(multiCode, {
522
- level: "aggressive",
523
- preserveCodeBlocks: true,
524
- });
525
- assert.ok(result.content.includes("function a()"), "first code block preserved");
526
- assert.ok(result.content.includes("def b():"), "second code block preserved");
527
- assert.ok(result.content.includes("emphasis"), "emphasis text kept (markers removed)");
528
- assert.ok(!result.content.includes("**emphasis**"), "emphasis markers removed");
529
- });