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.
- package/README.md +15 -11
- package/dist/app-paths.js +1 -1
- package/dist/extension-registry.js +2 -2
- package/dist/remote-questions-config.js +2 -2
- package/dist/resource-loader.js +34 -1
- package/dist/resources/extensions/browser-tools/index.js +3 -1
- package/dist/resources/extensions/browser-tools/tools/verify.js +97 -0
- package/dist/resources/extensions/env-utils.js +29 -0
- package/dist/resources/extensions/get-secrets-from-user.js +5 -24
- package/dist/resources/extensions/github-sync/cli.js +284 -0
- package/dist/resources/extensions/github-sync/index.js +73 -0
- package/dist/resources/extensions/github-sync/mapping.js +67 -0
- package/dist/resources/extensions/github-sync/sync.js +424 -0
- package/dist/resources/extensions/github-sync/templates.js +118 -0
- package/dist/resources/extensions/github-sync/types.js +7 -0
- package/dist/resources/extensions/gsd/auto/session.js +6 -23
- package/dist/resources/extensions/gsd/auto-dispatch.js +8 -9
- package/dist/resources/extensions/gsd/auto-loop.js +636 -594
- package/dist/resources/extensions/gsd/auto-post-unit.js +99 -70
- package/dist/resources/extensions/gsd/auto-prompts.js +202 -48
- package/dist/resources/extensions/gsd/auto-start.js +7 -1
- package/dist/resources/extensions/gsd/auto-worktree-sync.js +2 -1
- package/dist/resources/extensions/gsd/auto-worktree.js +3 -3
- package/dist/resources/extensions/gsd/auto.js +143 -96
- package/dist/resources/extensions/gsd/commands-extensions.js +3 -2
- package/dist/resources/extensions/gsd/commands-prefs-wizard.js +1 -1
- package/dist/resources/extensions/gsd/commands.js +4 -2
- package/dist/resources/extensions/gsd/context-budget.js +2 -10
- package/dist/resources/extensions/gsd/detection.js +1 -2
- package/dist/resources/extensions/gsd/docs/preferences-reference.md +0 -2
- package/dist/resources/extensions/gsd/doctor-providers.js +30 -11
- package/dist/resources/extensions/gsd/doctor.js +20 -1
- package/dist/resources/extensions/gsd/exit-command.js +2 -1
- package/dist/resources/extensions/gsd/export.js +1 -1
- package/dist/resources/extensions/gsd/files.js +48 -9
- package/dist/resources/extensions/gsd/forensics.js +1 -1
- package/dist/resources/extensions/gsd/git-service.js +30 -12
- package/dist/resources/extensions/gsd/gitignore.js +16 -3
- package/dist/resources/extensions/gsd/guided-flow.js +149 -38
- package/dist/resources/extensions/gsd/health-widget-core.js +32 -70
- package/dist/resources/extensions/gsd/health-widget.js +3 -86
- package/dist/resources/extensions/gsd/index.js +24 -20
- package/dist/resources/extensions/gsd/migrate/parsers.js +1 -1
- package/dist/resources/extensions/gsd/migrate-external.js +18 -1
- package/dist/resources/extensions/gsd/native-git-bridge.js +37 -0
- package/dist/resources/extensions/gsd/paths.js +3 -0
- package/dist/resources/extensions/gsd/preferences-models.js +0 -12
- package/dist/resources/extensions/gsd/preferences-types.js +1 -1
- package/dist/resources/extensions/gsd/preferences-validation.js +59 -11
- package/dist/resources/extensions/gsd/preferences.js +22 -11
- package/dist/resources/extensions/gsd/prompt-loader.js +6 -2
- package/dist/resources/extensions/gsd/prompts/complete-milestone.md +1 -1
- package/dist/resources/extensions/gsd/prompts/complete-slice.md +1 -1
- package/dist/resources/extensions/gsd/prompts/discuss.md +11 -14
- package/dist/resources/extensions/gsd/prompts/execute-task.md +5 -3
- package/dist/resources/extensions/gsd/prompts/guided-complete-slice.md +1 -1
- package/dist/resources/extensions/gsd/prompts/guided-discuss-milestone.md +11 -12
- package/dist/resources/extensions/gsd/prompts/guided-discuss-slice.md +8 -10
- package/dist/resources/extensions/gsd/prompts/guided-execute-task.md +1 -1
- package/dist/resources/extensions/gsd/prompts/guided-plan-milestone.md +1 -1
- package/dist/resources/extensions/gsd/prompts/guided-plan-slice.md +1 -1
- package/dist/resources/extensions/gsd/prompts/guided-research-slice.md +1 -1
- package/dist/resources/extensions/gsd/prompts/guided-resume-task.md +1 -1
- package/dist/resources/extensions/gsd/prompts/plan-milestone.md +1 -1
- package/dist/resources/extensions/gsd/prompts/plan-slice.md +1 -1
- package/dist/resources/extensions/gsd/prompts/queue.md +4 -8
- package/dist/resources/extensions/gsd/prompts/reactive-execute.md +11 -8
- package/dist/resources/extensions/gsd/prompts/reassess-roadmap.md +1 -1
- package/dist/resources/extensions/gsd/prompts/research-milestone.md +1 -1
- package/dist/resources/extensions/gsd/prompts/research-slice.md +1 -1
- package/dist/resources/extensions/gsd/prompts/run-uat.md +28 -11
- package/dist/resources/extensions/gsd/prompts/workflow-start.md +2 -2
- package/dist/resources/extensions/gsd/repo-identity.js +21 -4
- package/dist/resources/extensions/gsd/resource-version.js +2 -1
- package/dist/resources/extensions/gsd/roadmap-mutations.js +24 -0
- package/dist/resources/extensions/gsd/state.js +42 -23
- package/dist/resources/extensions/gsd/templates/runtime.md +21 -0
- package/dist/resources/extensions/gsd/templates/task-plan.md +3 -0
- package/dist/resources/extensions/gsd/visualizer-data.js +1 -1
- package/dist/resources/extensions/mcp-client/index.js +14 -1
- package/dist/resources/extensions/remote-questions/status.js +4 -1
- package/dist/resources/extensions/remote-questions/store.js +4 -1
- package/dist/resources/extensions/search-the-web/provider.js +2 -1
- package/dist/resources/extensions/shared/frontmatter.js +1 -1
- package/dist/resources/extensions/subagent/isolation.js +2 -1
- package/dist/resources/extensions/ttsr/rule-loader.js +2 -1
- package/package.json +1 -1
- package/packages/pi-ai/dist/utils/oauth/anthropic.js +2 -2
- package/packages/pi-ai/dist/utils/oauth/anthropic.js.map +1 -1
- package/packages/pi-ai/src/utils/oauth/anthropic.ts +2 -2
- package/packages/pi-coding-agent/dist/core/extensions/loader.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/loader.js +205 -7
- package/packages/pi-coding-agent/dist/core/extensions/loader.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/skills.d.ts +1 -0
- package/packages/pi-coding-agent/dist/core/skills.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/skills.js +6 -1
- package/packages/pi-coding-agent/dist/core/skills.js.map +1 -1
- package/packages/pi-coding-agent/dist/index.d.ts +1 -1
- package/packages/pi-coding-agent/dist/index.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/index.js +1 -1
- package/packages/pi-coding-agent/dist/index.js.map +1 -1
- package/packages/pi-coding-agent/src/core/extensions/loader.ts +223 -7
- package/packages/pi-coding-agent/src/core/skills.ts +9 -1
- package/packages/pi-coding-agent/src/index.ts +1 -0
- package/src/resources/extensions/browser-tools/index.ts +3 -0
- package/src/resources/extensions/browser-tools/tools/verify.ts +117 -0
- package/src/resources/extensions/env-utils.ts +31 -0
- package/src/resources/extensions/get-secrets-from-user.ts +5 -24
- package/src/resources/extensions/github-sync/cli.ts +364 -0
- package/src/resources/extensions/github-sync/index.ts +93 -0
- package/src/resources/extensions/github-sync/mapping.ts +81 -0
- package/src/resources/extensions/github-sync/sync.ts +556 -0
- package/src/resources/extensions/github-sync/templates.ts +183 -0
- package/src/resources/extensions/github-sync/tests/cli.test.ts +20 -0
- package/src/resources/extensions/github-sync/tests/commit-linking.test.ts +39 -0
- package/src/resources/extensions/github-sync/tests/mapping.test.ts +104 -0
- package/src/resources/extensions/github-sync/tests/templates.test.ts +110 -0
- package/src/resources/extensions/github-sync/types.ts +47 -0
- package/src/resources/extensions/gsd/auto/session.ts +7 -25
- package/src/resources/extensions/gsd/auto-dispatch.ts +7 -9
- package/src/resources/extensions/gsd/auto-loop.ts +526 -545
- package/src/resources/extensions/gsd/auto-post-unit.ts +80 -44
- package/src/resources/extensions/gsd/auto-prompts.ts +247 -50
- package/src/resources/extensions/gsd/auto-start.ts +11 -1
- package/src/resources/extensions/gsd/auto-worktree-sync.ts +3 -1
- package/src/resources/extensions/gsd/auto-worktree.ts +3 -3
- package/src/resources/extensions/gsd/auto.ts +139 -101
- package/src/resources/extensions/gsd/commands-extensions.ts +4 -2
- package/src/resources/extensions/gsd/commands-prefs-wizard.ts +1 -1
- package/src/resources/extensions/gsd/commands.ts +5 -3
- package/src/resources/extensions/gsd/context-budget.ts +2 -12
- package/src/resources/extensions/gsd/detection.ts +2 -2
- package/src/resources/extensions/gsd/docs/preferences-reference.md +0 -2
- package/src/resources/extensions/gsd/doctor-providers.ts +30 -9
- package/src/resources/extensions/gsd/doctor.ts +22 -1
- package/src/resources/extensions/gsd/exit-command.ts +2 -2
- package/src/resources/extensions/gsd/export.ts +1 -1
- package/src/resources/extensions/gsd/files.ts +51 -11
- package/src/resources/extensions/gsd/forensics.ts +1 -1
- package/src/resources/extensions/gsd/git-service.ts +44 -10
- package/src/resources/extensions/gsd/gitignore.ts +17 -3
- package/src/resources/extensions/gsd/guided-flow.ts +177 -44
- package/src/resources/extensions/gsd/health-widget-core.ts +28 -80
- package/src/resources/extensions/gsd/health-widget.ts +3 -89
- package/src/resources/extensions/gsd/index.ts +24 -17
- package/src/resources/extensions/gsd/migrate/parsers.ts +1 -1
- package/src/resources/extensions/gsd/migrate-external.ts +18 -1
- package/src/resources/extensions/gsd/native-git-bridge.ts +37 -0
- package/src/resources/extensions/gsd/paths.ts +4 -0
- package/src/resources/extensions/gsd/preferences-models.ts +0 -12
- package/src/resources/extensions/gsd/preferences-types.ts +4 -4
- package/src/resources/extensions/gsd/preferences-validation.ts +51 -11
- package/src/resources/extensions/gsd/preferences.ts +25 -11
- package/src/resources/extensions/gsd/prompt-loader.ts +7 -2
- package/src/resources/extensions/gsd/prompts/complete-milestone.md +1 -1
- package/src/resources/extensions/gsd/prompts/complete-slice.md +1 -1
- package/src/resources/extensions/gsd/prompts/discuss.md +11 -14
- package/src/resources/extensions/gsd/prompts/execute-task.md +5 -3
- package/src/resources/extensions/gsd/prompts/guided-complete-slice.md +1 -1
- package/src/resources/extensions/gsd/prompts/guided-discuss-milestone.md +11 -12
- package/src/resources/extensions/gsd/prompts/guided-discuss-slice.md +8 -10
- package/src/resources/extensions/gsd/prompts/guided-execute-task.md +1 -1
- package/src/resources/extensions/gsd/prompts/guided-plan-milestone.md +1 -1
- package/src/resources/extensions/gsd/prompts/guided-plan-slice.md +1 -1
- package/src/resources/extensions/gsd/prompts/guided-research-slice.md +1 -1
- package/src/resources/extensions/gsd/prompts/guided-resume-task.md +1 -1
- package/src/resources/extensions/gsd/prompts/plan-milestone.md +1 -1
- package/src/resources/extensions/gsd/prompts/plan-slice.md +1 -1
- package/src/resources/extensions/gsd/prompts/queue.md +4 -8
- package/src/resources/extensions/gsd/prompts/reactive-execute.md +11 -8
- package/src/resources/extensions/gsd/prompts/reassess-roadmap.md +1 -1
- package/src/resources/extensions/gsd/prompts/research-milestone.md +1 -1
- package/src/resources/extensions/gsd/prompts/research-slice.md +1 -1
- package/src/resources/extensions/gsd/prompts/run-uat.md +28 -11
- package/src/resources/extensions/gsd/prompts/workflow-start.md +2 -2
- package/src/resources/extensions/gsd/repo-identity.ts +23 -4
- package/src/resources/extensions/gsd/resource-version.ts +3 -1
- package/src/resources/extensions/gsd/roadmap-mutations.ts +29 -0
- package/src/resources/extensions/gsd/state.ts +39 -21
- package/src/resources/extensions/gsd/templates/runtime.md +21 -0
- package/src/resources/extensions/gsd/templates/task-plan.md +3 -0
- package/src/resources/extensions/gsd/tests/agent-end-retry.test.ts +21 -18
- package/src/resources/extensions/gsd/tests/auto-loop.test.ts +122 -68
- package/src/resources/extensions/gsd/tests/auto-worktree-milestone-merge.test.ts +4 -3
- package/src/resources/extensions/gsd/tests/derive-state.test.ts +43 -0
- package/src/resources/extensions/gsd/tests/doctor-providers.test.ts +86 -3
- package/src/resources/extensions/gsd/tests/gitignore-tracked-gsd.test.ts +50 -0
- package/src/resources/extensions/gsd/tests/health-widget.test.ts +16 -54
- package/src/resources/extensions/gsd/tests/parsers.test.ts +131 -14
- package/src/resources/extensions/gsd/tests/plan-slice-prompt.test.ts +209 -0
- package/src/resources/extensions/gsd/tests/preferences.test.ts +2 -7
- package/src/resources/extensions/gsd/tests/prompt-contracts.test.ts +59 -0
- package/src/resources/extensions/gsd/tests/repo-identity-worktree.test.ts +21 -1
- package/src/resources/extensions/gsd/tests/run-uat.test.ts +16 -4
- package/src/resources/extensions/gsd/tests/skill-activation.test.ts +140 -0
- package/src/resources/extensions/gsd/types.ts +18 -1
- package/src/resources/extensions/gsd/verification-evidence.ts +16 -0
- package/src/resources/extensions/gsd/visualizer-data.ts +1 -1
- package/src/resources/extensions/mcp-client/index.ts +17 -1
- package/src/resources/extensions/remote-questions/status.ts +5 -1
- package/src/resources/extensions/remote-questions/store.ts +5 -1
- package/src/resources/extensions/search-the-web/provider.ts +2 -1
- package/src/resources/extensions/shared/frontmatter.ts +1 -1
- package/src/resources/extensions/subagent/isolation.ts +3 -1
- package/src/resources/extensions/ttsr/rule-loader.ts +3 -1
- package/dist/resources/extensions/gsd/prompt-compressor.js +0 -393
- package/dist/resources/extensions/gsd/semantic-chunker.js +0 -254
- package/dist/resources/extensions/gsd/summary-distiller.js +0 -212
- package/src/resources/extensions/gsd/prompt-compressor.ts +0 -508
- package/src/resources/extensions/gsd/semantic-chunker.ts +0 -336
- package/src/resources/extensions/gsd/summary-distiller.ts +0 -258
- package/src/resources/extensions/gsd/tests/context-compression.test.ts +0 -193
- package/src/resources/extensions/gsd/tests/prompt-compressor.test.ts +0 -529
- package/src/resources/extensions/gsd/tests/semantic-chunker.test.ts +0 -426
- package/src/resources/extensions/gsd/tests/summary-distiller.test.ts +0 -323
- package/src/resources/extensions/gsd/tests/token-optimization-benchmark.test.ts +0 -1272
- 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
|
-
});
|