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,323 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Tests for summary-distiller.ts — the summary distillation module.
|
|
3
|
-
* Verifies frontmatter extraction, compact formatting, budget enforcement,
|
|
4
|
-
* and progressive field dropping.
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
import { describe, it } from "node:test";
|
|
8
|
-
import assert from "node:assert/strict";
|
|
9
|
-
|
|
10
|
-
import { distillSingle, distillSummaries } from "../summary-distiller.js";
|
|
11
|
-
|
|
12
|
-
// ─── Fixtures ────────────────────────────────────────────────────────────────
|
|
13
|
-
|
|
14
|
-
const REALISTIC_SUMMARY = `---
|
|
15
|
-
id: S01
|
|
16
|
-
parent: M001
|
|
17
|
-
milestone: M001
|
|
18
|
-
provides:
|
|
19
|
-
- Core type definitions
|
|
20
|
-
- File I/O utilities
|
|
21
|
-
requires: []
|
|
22
|
-
affects:
|
|
23
|
-
- All downstream slices
|
|
24
|
-
key_files:
|
|
25
|
-
- src/types.ts
|
|
26
|
-
- src/files.ts
|
|
27
|
-
- src/paths.ts
|
|
28
|
-
key_decisions:
|
|
29
|
-
- D001
|
|
30
|
-
- D003
|
|
31
|
-
patterns_established:
|
|
32
|
-
- Pure function modules
|
|
33
|
-
- Dependency injection via parameters
|
|
34
|
-
drill_down_paths:
|
|
35
|
-
- src/types.ts for interface contracts
|
|
36
|
-
observability_surfaces:
|
|
37
|
-
- Unit test coverage > 90%
|
|
38
|
-
duration: 45m
|
|
39
|
-
verification_result: pass
|
|
40
|
-
completed_at: 2025-03-15T10:00:00Z
|
|
41
|
-
blocker_discovered: false
|
|
42
|
-
---
|
|
43
|
-
|
|
44
|
-
# S01: Core Type Definitions and File I/O
|
|
45
|
-
|
|
46
|
-
Foundation types and file operations for the GSD extension.
|
|
47
|
-
|
|
48
|
-
## What Happened
|
|
49
|
-
|
|
50
|
-
Implemented 12 core interfaces spanning roadmap parsing, slice plans, summaries,
|
|
51
|
-
and continuation state. Added file I/O utilities for reading, parsing, and writing
|
|
52
|
-
GSD artifact files. Established the path resolution module for computing absolute
|
|
53
|
-
and relative paths to milestone, slice, and task artifacts.
|
|
54
|
-
|
|
55
|
-
## Deviations
|
|
56
|
-
|
|
57
|
-
Minor deviation from plan: added \`filesModified\` field to Summary interface that
|
|
58
|
-
was not in the original design, based on the realization that tracking modified
|
|
59
|
-
files in summaries enables better diff-context prioritization.
|
|
60
|
-
|
|
61
|
-
## Files Modified
|
|
62
|
-
|
|
63
|
-
- \`src/types.ts\` — 12 interfaces, 4 type aliases
|
|
64
|
-
- \`src/files.ts\` — 8 parser functions, 3 writer functions
|
|
65
|
-
- \`src/paths.ts\` — 14 path resolver functions
|
|
66
|
-
`;
|
|
67
|
-
|
|
68
|
-
const SECOND_SUMMARY = `---
|
|
69
|
-
id: S02
|
|
70
|
-
parent: M001
|
|
71
|
-
milestone: M001
|
|
72
|
-
provides:
|
|
73
|
-
- Roadmap parser
|
|
74
|
-
- Slice dependency resolver
|
|
75
|
-
requires:
|
|
76
|
-
- Core type definitions
|
|
77
|
-
key_files:
|
|
78
|
-
- src/roadmap.ts
|
|
79
|
-
- src/deps.ts
|
|
80
|
-
key_decisions:
|
|
81
|
-
- D004
|
|
82
|
-
patterns_established:
|
|
83
|
-
- DAG-based ordering
|
|
84
|
-
drill_down_paths:
|
|
85
|
-
- src/deps.ts for topological sort
|
|
86
|
-
duration: 30m
|
|
87
|
-
verification_result: pass
|
|
88
|
-
completed_at: 2025-03-15T11:00:00Z
|
|
89
|
-
---
|
|
90
|
-
|
|
91
|
-
# S02: Roadmap Parser and Dependency Resolution
|
|
92
|
-
|
|
93
|
-
Built the roadmap parser and DAG-based dependency resolver.
|
|
94
|
-
|
|
95
|
-
## What Happened
|
|
96
|
-
|
|
97
|
-
Created a Markdown-based roadmap parser that extracts slice metadata from
|
|
98
|
-
structured headings and bullet lists. Implemented a topological sort for
|
|
99
|
-
resolving slice execution order based on declared dependencies.
|
|
100
|
-
|
|
101
|
-
## Files Modified
|
|
102
|
-
|
|
103
|
-
- \`src/roadmap.ts\` — parser with regex-based extraction
|
|
104
|
-
- \`src/deps.ts\` — DAG builder and topological sort
|
|
105
|
-
`;
|
|
106
|
-
|
|
107
|
-
const NO_FRONTMATTER = `# S99: Quick Fix
|
|
108
|
-
|
|
109
|
-
A quick patch with no frontmatter at all.
|
|
110
|
-
|
|
111
|
-
## What Happened
|
|
112
|
-
|
|
113
|
-
Fixed a typo.
|
|
114
|
-
`;
|
|
115
|
-
|
|
116
|
-
const EMPTY_ARRAYS_SUMMARY = `---
|
|
117
|
-
id: S03
|
|
118
|
-
provides: []
|
|
119
|
-
requires: []
|
|
120
|
-
key_files: []
|
|
121
|
-
key_decisions: []
|
|
122
|
-
patterns_established: []
|
|
123
|
-
---
|
|
124
|
-
|
|
125
|
-
# S03: Empty Slice
|
|
126
|
-
|
|
127
|
-
Nothing to provide or require.
|
|
128
|
-
`;
|
|
129
|
-
|
|
130
|
-
// ─── distillSingle ──────────────────────────────────────────────────────────
|
|
131
|
-
|
|
132
|
-
describe("summary-distiller: distillSingle", () => {
|
|
133
|
-
it("extracts frontmatter fields from a realistic summary", () => {
|
|
134
|
-
const result = distillSingle(REALISTIC_SUMMARY);
|
|
135
|
-
assert.ok(result.includes("## S01:"), "should include the id header");
|
|
136
|
-
assert.ok(result.includes("provides: Core type definitions, File I/O utilities"),
|
|
137
|
-
"should list provides");
|
|
138
|
-
assert.ok(result.includes("key_files: src/types.ts, src/files.ts, src/paths.ts"),
|
|
139
|
-
"should list key_files");
|
|
140
|
-
assert.ok(result.includes("key_decisions: D001, D003"),
|
|
141
|
-
"should list key_decisions");
|
|
142
|
-
assert.ok(result.includes("patterns: Pure function modules, Dependency injection via parameters"),
|
|
143
|
-
"should list patterns");
|
|
144
|
-
});
|
|
145
|
-
|
|
146
|
-
it("extracts the one-liner from the title line", () => {
|
|
147
|
-
const result = distillSingle(REALISTIC_SUMMARY);
|
|
148
|
-
// The title line "# S01: Core Type Definitions and File I/O" provides the one-liner
|
|
149
|
-
assert.ok(
|
|
150
|
-
result.includes("Core Type Definitions and File I/O"),
|
|
151
|
-
"should include one-liner from title",
|
|
152
|
-
);
|
|
153
|
-
});
|
|
154
|
-
|
|
155
|
-
it("falls back to first paragraph when title has no inline text", () => {
|
|
156
|
-
const summary = `---
|
|
157
|
-
id: S10
|
|
158
|
-
provides:
|
|
159
|
-
- Widget API
|
|
160
|
-
---
|
|
161
|
-
|
|
162
|
-
# S10:
|
|
163
|
-
|
|
164
|
-
Widget API for rendering dashboard components.
|
|
165
|
-
|
|
166
|
-
## What Happened
|
|
167
|
-
|
|
168
|
-
Built the widget system.
|
|
169
|
-
`;
|
|
170
|
-
const result = distillSingle(summary);
|
|
171
|
-
assert.ok(
|
|
172
|
-
result.includes("Widget API for rendering"),
|
|
173
|
-
"should use first paragraph as one-liner when title text is empty",
|
|
174
|
-
);
|
|
175
|
-
});
|
|
176
|
-
|
|
177
|
-
it("drops verbose prose sections", () => {
|
|
178
|
-
const result = distillSingle(REALISTIC_SUMMARY);
|
|
179
|
-
assert.ok(!result.includes("What Happened"), "should not include What Happened heading");
|
|
180
|
-
assert.ok(!result.includes("Implemented 12 core"), "should not include prose body");
|
|
181
|
-
assert.ok(!result.includes("Deviations"), "should not include Deviations");
|
|
182
|
-
assert.ok(!result.includes("filesModified"), "should not include deviation details");
|
|
183
|
-
assert.ok(!result.includes("drill_down_paths"), "should not include drill_down_paths label");
|
|
184
|
-
assert.ok(!result.includes("duration"), "should not include duration");
|
|
185
|
-
assert.ok(!result.includes("verification_result"), "should not include verification_result");
|
|
186
|
-
assert.ok(!result.includes("completed_at"), "should not include completed_at");
|
|
187
|
-
});
|
|
188
|
-
|
|
189
|
-
it("handles array fields in provides/requires", () => {
|
|
190
|
-
const result = distillSingle(SECOND_SUMMARY);
|
|
191
|
-
assert.ok(result.includes("provides: Roadmap parser, Slice dependency resolver"),
|
|
192
|
-
"should join provides array");
|
|
193
|
-
assert.ok(result.includes("requires: Core type definitions"),
|
|
194
|
-
"should join requires array");
|
|
195
|
-
});
|
|
196
|
-
|
|
197
|
-
it("omits empty requires when none declared", () => {
|
|
198
|
-
const result = distillSingle(REALISTIC_SUMMARY);
|
|
199
|
-
assert.ok(!result.includes("requires:"), "should omit requires when empty");
|
|
200
|
-
});
|
|
201
|
-
|
|
202
|
-
it("handles missing frontmatter gracefully", () => {
|
|
203
|
-
const result = distillSingle(NO_FRONTMATTER);
|
|
204
|
-
assert.ok(result.includes("## S99:"), "should extract id from title");
|
|
205
|
-
assert.ok(result.includes("Quick Fix"), "should include title text");
|
|
206
|
-
});
|
|
207
|
-
|
|
208
|
-
it("handles empty array frontmatter fields", () => {
|
|
209
|
-
const result = distillSingle(EMPTY_ARRAYS_SUMMARY);
|
|
210
|
-
assert.ok(result.includes("## S03:"), "should have the id");
|
|
211
|
-
assert.ok(!result.includes("provides:"), "should omit empty provides");
|
|
212
|
-
assert.ok(!result.includes("requires:"), "should omit empty requires");
|
|
213
|
-
assert.ok(!result.includes("key_files:"), "should omit empty key_files");
|
|
214
|
-
assert.ok(!result.includes("key_decisions:"), "should omit empty key_decisions");
|
|
215
|
-
assert.ok(!result.includes("patterns:"), "should omit empty patterns");
|
|
216
|
-
});
|
|
217
|
-
|
|
218
|
-
it("produces significantly shorter output than input", () => {
|
|
219
|
-
const result = distillSingle(REALISTIC_SUMMARY);
|
|
220
|
-
assert.ok(
|
|
221
|
-
result.length < REALISTIC_SUMMARY.length * 0.5,
|
|
222
|
-
`distilled (${result.length}) should be <50% of original (${REALISTIC_SUMMARY.length})`,
|
|
223
|
-
);
|
|
224
|
-
});
|
|
225
|
-
});
|
|
226
|
-
|
|
227
|
-
// ─── distillSummaries ────────────────────────────────────────────────────────
|
|
228
|
-
|
|
229
|
-
describe("summary-distiller: distillSummaries", () => {
|
|
230
|
-
it("combines multiple summaries into structured blocks", () => {
|
|
231
|
-
const result = distillSummaries([REALISTIC_SUMMARY, SECOND_SUMMARY], 10_000);
|
|
232
|
-
assert.equal(result.summaryCount, 2);
|
|
233
|
-
assert.ok(result.content.includes("## S01:"), "should include first summary");
|
|
234
|
-
assert.ok(result.content.includes("## S02:"), "should include second summary");
|
|
235
|
-
});
|
|
236
|
-
|
|
237
|
-
it("reports positive savings percentage", () => {
|
|
238
|
-
const result = distillSummaries([REALISTIC_SUMMARY, SECOND_SUMMARY], 10_000);
|
|
239
|
-
assert.ok(result.savingsPercent > 0, `savings should be positive, got ${result.savingsPercent}%`);
|
|
240
|
-
assert.ok(result.distilledChars < result.originalChars,
|
|
241
|
-
"distilled chars should be less than original");
|
|
242
|
-
});
|
|
243
|
-
|
|
244
|
-
it("fits content within budgetChars when budget is generous", () => {
|
|
245
|
-
const result = distillSummaries([REALISTIC_SUMMARY, SECOND_SUMMARY], 10_000);
|
|
246
|
-
assert.ok(
|
|
247
|
-
result.content.length <= 10_000,
|
|
248
|
-
`content length ${result.content.length} should be within budget 10000`,
|
|
249
|
-
);
|
|
250
|
-
assert.ok(!result.content.includes("[...truncated]"), "should not truncate with generous budget");
|
|
251
|
-
});
|
|
252
|
-
|
|
253
|
-
it("enforces budget with truncation when needed", () => {
|
|
254
|
-
const result = distillSummaries([REALISTIC_SUMMARY, SECOND_SUMMARY], 200);
|
|
255
|
-
assert.ok(
|
|
256
|
-
result.content.length <= 215, // allow some slack for truncation marker
|
|
257
|
-
`content length ${result.content.length} should be near budget 200`,
|
|
258
|
-
);
|
|
259
|
-
assert.ok(result.content.includes("[...truncated]"), "should include truncation marker");
|
|
260
|
-
});
|
|
261
|
-
|
|
262
|
-
it("progressively drops fields when budget is tight", () => {
|
|
263
|
-
// With a budget that can fit the header lines but not all fields,
|
|
264
|
-
// patterns should be dropped first, then key_decisions, then key_files
|
|
265
|
-
const full = distillSummaries([REALISTIC_SUMMARY], 100_000);
|
|
266
|
-
assert.ok(full.content.includes("patterns:"), "full output should have patterns");
|
|
267
|
-
|
|
268
|
-
// Find a budget that forces dropping patterns but keeps key_decisions
|
|
269
|
-
const withoutPatterns = full.content.replace(/patterns:.*$/m, "").length;
|
|
270
|
-
const withPatterns = full.content.length;
|
|
271
|
-
|
|
272
|
-
if (withPatterns > withoutPatterns) {
|
|
273
|
-
const tightBudget = withoutPatterns + 5;
|
|
274
|
-
const tight = distillSummaries([REALISTIC_SUMMARY], tightBudget);
|
|
275
|
-
assert.ok(!tight.content.includes("patterns:"),
|
|
276
|
-
"tight budget should drop patterns first");
|
|
277
|
-
assert.ok(tight.content.includes("key_decisions:"),
|
|
278
|
-
"tight budget should still have key_decisions");
|
|
279
|
-
}
|
|
280
|
-
});
|
|
281
|
-
|
|
282
|
-
it("handles a single summary", () => {
|
|
283
|
-
const result = distillSummaries([REALISTIC_SUMMARY], 10_000);
|
|
284
|
-
assert.equal(result.summaryCount, 1);
|
|
285
|
-
assert.ok(result.content.includes("## S01:"), "should include the single summary");
|
|
286
|
-
});
|
|
287
|
-
|
|
288
|
-
it("handles empty input array", () => {
|
|
289
|
-
const result = distillSummaries([], 10_000);
|
|
290
|
-
assert.equal(result.summaryCount, 0);
|
|
291
|
-
assert.equal(result.content, "");
|
|
292
|
-
assert.equal(result.savingsPercent, 0);
|
|
293
|
-
assert.equal(result.originalChars, 0);
|
|
294
|
-
assert.equal(result.distilledChars, 0);
|
|
295
|
-
});
|
|
296
|
-
|
|
297
|
-
it("handles malformed content gracefully", () => {
|
|
298
|
-
const malformed = "this is not a valid summary at all\nno frontmatter\nno headings";
|
|
299
|
-
const result = distillSummaries([malformed], 10_000);
|
|
300
|
-
assert.equal(result.summaryCount, 1);
|
|
301
|
-
// Should not throw, should produce some output
|
|
302
|
-
assert.ok(result.content.length > 0, "should produce output even for malformed input");
|
|
303
|
-
});
|
|
304
|
-
|
|
305
|
-
it("handles very tight budget (100 chars) with truncation", () => {
|
|
306
|
-
const result = distillSummaries([REALISTIC_SUMMARY, SECOND_SUMMARY], 100);
|
|
307
|
-
assert.ok(
|
|
308
|
-
result.content.length <= 115, // small slack for marker
|
|
309
|
-
`content (${result.content.length}) should be near budget 100`,
|
|
310
|
-
);
|
|
311
|
-
assert.ok(result.content.includes("[...truncated]"), "should truncate at very tight budget");
|
|
312
|
-
assert.ok(result.savingsPercent > 80, `savings should be very high, got ${result.savingsPercent}%`);
|
|
313
|
-
});
|
|
314
|
-
|
|
315
|
-
it("tracks original and distilled character counts accurately", () => {
|
|
316
|
-
const summaries = [REALISTIC_SUMMARY, SECOND_SUMMARY];
|
|
317
|
-
const totalOriginal = summaries.reduce((s, c) => s + c.length, 0);
|
|
318
|
-
const result = distillSummaries(summaries, 10_000);
|
|
319
|
-
assert.equal(result.originalChars, totalOriginal, "originalChars should match input total");
|
|
320
|
-
assert.equal(result.distilledChars, result.content.length,
|
|
321
|
-
"distilledChars should match content length");
|
|
322
|
-
});
|
|
323
|
-
});
|