gsd-pi 2.23.0 → 2.25.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -1
- package/dist/cli.js +12 -3
- package/dist/headless.d.ts +4 -0
- package/dist/headless.js +118 -10
- package/dist/help-text.js +22 -7
- package/dist/models-resolver.d.ts +0 -11
- package/dist/models-resolver.js +0 -15
- package/dist/resource-loader.d.ts +0 -1
- package/dist/resource-loader.js +64 -18
- package/dist/resources/GSD-WORKFLOW.md +12 -9
- package/dist/resources/extensions/bg-shell/overlay.ts +18 -17
- package/dist/resources/extensions/get-secrets-from-user.ts +5 -23
- package/dist/resources/extensions/gsd/activity-log.ts +5 -3
- package/dist/resources/extensions/gsd/auto-dispatch.ts +51 -2
- package/dist/resources/extensions/gsd/auto-prompts.ts +87 -0
- package/dist/resources/extensions/gsd/auto-recovery.ts +41 -2
- package/dist/resources/extensions/gsd/auto-worktree.ts +134 -4
- package/dist/resources/extensions/gsd/auto.ts +307 -77
- package/dist/resources/extensions/gsd/cache.ts +3 -1
- package/dist/resources/extensions/gsd/commands.ts +176 -10
- package/dist/resources/extensions/gsd/complexity.ts +1 -0
- package/dist/resources/extensions/gsd/dashboard-overlay.ts +38 -0
- package/dist/resources/extensions/gsd/doctor.ts +58 -11
- package/dist/resources/extensions/gsd/exit-command.ts +2 -2
- package/dist/resources/extensions/gsd/git-service.ts +74 -14
- package/dist/resources/extensions/gsd/gitignore.ts +1 -0
- package/dist/resources/extensions/gsd/gsd-db.ts +78 -1
- package/dist/resources/extensions/gsd/guided-flow.ts +109 -12
- package/dist/resources/extensions/gsd/index.ts +48 -2
- package/dist/resources/extensions/gsd/memory-extractor.ts +352 -0
- package/dist/resources/extensions/gsd/memory-store.ts +441 -0
- package/dist/resources/extensions/gsd/migrate/command.ts +2 -2
- package/dist/resources/extensions/gsd/parallel-eligibility.ts +233 -0
- package/dist/resources/extensions/gsd/parallel-merge.ts +156 -0
- package/dist/resources/extensions/gsd/parallel-orchestrator.ts +496 -0
- package/dist/resources/extensions/gsd/preferences.ts +65 -1
- package/dist/resources/extensions/gsd/prompts/complete-slice.md +1 -1
- package/dist/resources/extensions/gsd/prompts/discuss-headless.md +86 -0
- package/dist/resources/extensions/gsd/prompts/discuss.md +4 -4
- package/dist/resources/extensions/gsd/prompts/execute-task.md +1 -1
- package/dist/resources/extensions/gsd/prompts/guided-discuss-milestone.md +1 -1
- package/dist/resources/extensions/gsd/prompts/guided-discuss-slice.md +1 -1
- package/dist/resources/extensions/gsd/prompts/plan-slice.md +1 -1
- package/dist/resources/extensions/gsd/prompts/queue.md +1 -1
- package/dist/resources/extensions/gsd/prompts/reassess-roadmap.md +1 -1
- package/dist/resources/extensions/gsd/prompts/research-slice.md +1 -1
- package/dist/resources/extensions/gsd/prompts/validate-milestone.md +40 -61
- package/dist/resources/extensions/gsd/provider-error-pause.ts +29 -2
- package/dist/resources/extensions/gsd/session-status-io.ts +197 -0
- package/dist/resources/extensions/gsd/state.ts +72 -30
- package/dist/resources/extensions/gsd/tests/agent-end-provider-error.test.ts +81 -0
- package/dist/resources/extensions/gsd/tests/auto-budget-alerts.test.ts +20 -3
- package/dist/resources/extensions/gsd/tests/auto-preflight.test.ts +1 -0
- package/dist/resources/extensions/gsd/tests/auto-recovery.test.ts +256 -2
- package/dist/resources/extensions/gsd/tests/auto-worktree-milestone-merge.test.ts +34 -0
- package/dist/resources/extensions/gsd/tests/auto-worktree.test.ts +58 -0
- package/dist/resources/extensions/gsd/tests/complete-milestone.test.ts +8 -1
- package/dist/resources/extensions/gsd/tests/derive-state-db.test.ts +9 -15
- package/dist/resources/extensions/gsd/tests/derive-state-deps.test.ts +9 -0
- package/dist/resources/extensions/gsd/tests/derive-state-draft.test.ts +8 -0
- package/dist/resources/extensions/gsd/tests/derive-state.test.ts +14 -0
- package/dist/resources/extensions/gsd/tests/git-service.test.ts +70 -4
- package/dist/resources/extensions/gsd/tests/gsd-db.test.ts +2 -2
- package/dist/resources/extensions/gsd/tests/integration-mixed-milestones.test.ts +8 -0
- package/dist/resources/extensions/gsd/tests/md-importer.test.ts +2 -3
- package/dist/resources/extensions/gsd/tests/memory-extractor.test.ts +180 -0
- package/dist/resources/extensions/gsd/tests/memory-store.test.ts +345 -0
- package/dist/resources/extensions/gsd/tests/migrate-writer-integration.test.ts +5 -5
- package/dist/resources/extensions/gsd/tests/parallel-orchestration.test.ts +656 -0
- package/dist/resources/extensions/gsd/tests/parallel-workers-multi-milestone-e2e.test.ts +354 -0
- package/dist/resources/extensions/gsd/tests/queue-reorder-e2e.test.ts +1 -0
- package/dist/resources/extensions/gsd/tests/smart-entry-draft.test.ts +1 -1
- package/dist/resources/extensions/gsd/tests/validate-milestone.test.ts +316 -0
- package/dist/resources/extensions/gsd/tests/visualizer-data.test.ts +147 -2
- package/dist/resources/extensions/gsd/tests/visualizer-overlay.test.ts +88 -10
- package/dist/resources/extensions/gsd/tests/visualizer-views.test.ts +314 -87
- package/dist/resources/extensions/gsd/tests/worker-registry.test.ts +148 -0
- package/dist/resources/extensions/gsd/triage-ui.ts +1 -1
- package/dist/resources/extensions/gsd/types.ts +15 -1
- package/dist/resources/extensions/gsd/visualizer-data.ts +291 -10
- package/dist/resources/extensions/gsd/visualizer-overlay.ts +237 -28
- package/dist/resources/extensions/gsd/visualizer-views.ts +462 -48
- package/dist/resources/extensions/gsd/worktree.ts +9 -2
- package/dist/resources/extensions/search-the-web/native-search.ts +15 -5
- package/dist/resources/extensions/subagent/index.ts +5 -0
- package/dist/resources/extensions/subagent/worker-registry.ts +99 -0
- package/dist/update-check.d.ts +9 -0
- package/dist/update-check.js +97 -0
- package/package.json +6 -1
- package/packages/pi-agent-core/dist/agent-loop.js +2 -0
- package/packages/pi-agent-core/dist/agent-loop.js.map +1 -1
- package/packages/pi-agent-core/src/agent-loop.ts +2 -0
- package/packages/pi-ai/dist/providers/anthropic.d.ts.map +1 -1
- package/packages/pi-ai/dist/providers/anthropic.js +55 -7
- package/packages/pi-ai/dist/providers/anthropic.js.map +1 -1
- package/packages/pi-ai/dist/providers/azure-openai-responses.d.ts.map +1 -1
- package/packages/pi-ai/dist/providers/azure-openai-responses.js +12 -4
- package/packages/pi-ai/dist/providers/azure-openai-responses.js.map +1 -1
- package/packages/pi-ai/dist/providers/google-vertex.d.ts.map +1 -1
- package/packages/pi-ai/dist/providers/google-vertex.js +21 -9
- package/packages/pi-ai/dist/providers/google-vertex.js.map +1 -1
- package/packages/pi-ai/dist/providers/mistral.js +3 -0
- package/packages/pi-ai/dist/providers/mistral.js.map +1 -1
- package/packages/pi-ai/dist/providers/openai-completions.d.ts.map +1 -1
- package/packages/pi-ai/dist/providers/openai-completions.js +12 -4
- package/packages/pi-ai/dist/providers/openai-completions.js.map +1 -1
- package/packages/pi-ai/dist/providers/openai-responses.d.ts.map +1 -1
- package/packages/pi-ai/dist/providers/openai-responses.js +12 -4
- package/packages/pi-ai/dist/providers/openai-responses.js.map +1 -1
- package/packages/pi-ai/dist/types.d.ts +23 -1
- package/packages/pi-ai/dist/types.d.ts.map +1 -1
- package/packages/pi-ai/dist/types.js.map +1 -1
- package/packages/pi-ai/src/providers/anthropic.ts +59 -9
- package/packages/pi-ai/src/providers/azure-openai-responses.ts +16 -4
- package/packages/pi-ai/src/providers/google-vertex.ts +32 -17
- package/packages/pi-ai/src/providers/mistral.ts +3 -0
- package/packages/pi-ai/src/providers/openai-completions.ts +16 -4
- package/packages/pi-ai/src/providers/openai-responses.ts +16 -4
- package/packages/pi-ai/src/types.ts +19 -1
- package/packages/pi-coding-agent/dist/core/agent-session.js +1 -1
- package/packages/pi-coding-agent/dist/core/agent-session.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/settings-manager.js +1 -1
- package/packages/pi-coding-agent/dist/core/settings-manager.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js +17 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts +4 -0
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js +72 -0
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/packages/pi-coding-agent/src/core/agent-session.ts +1 -1
- package/packages/pi-coding-agent/src/core/settings-manager.ts +2 -2
- package/packages/pi-coding-agent/src/modes/interactive/components/tool-execution.ts +18 -0
- package/packages/pi-coding-agent/src/modes/interactive/interactive-mode.ts +84 -0
- package/scripts/postinstall.js +7 -109
- package/src/resources/GSD-WORKFLOW.md +12 -9
- package/src/resources/extensions/bg-shell/overlay.ts +18 -17
- package/src/resources/extensions/get-secrets-from-user.ts +5 -23
- package/src/resources/extensions/gsd/activity-log.ts +5 -3
- package/src/resources/extensions/gsd/auto-dispatch.ts +51 -2
- package/src/resources/extensions/gsd/auto-prompts.ts +87 -0
- package/src/resources/extensions/gsd/auto-recovery.ts +41 -2
- package/src/resources/extensions/gsd/auto-worktree.ts +134 -4
- package/src/resources/extensions/gsd/auto.ts +307 -77
- package/src/resources/extensions/gsd/cache.ts +3 -1
- package/src/resources/extensions/gsd/commands.ts +176 -10
- package/src/resources/extensions/gsd/complexity.ts +1 -0
- package/src/resources/extensions/gsd/dashboard-overlay.ts +38 -0
- package/src/resources/extensions/gsd/doctor.ts +58 -11
- package/src/resources/extensions/gsd/exit-command.ts +2 -2
- package/src/resources/extensions/gsd/git-service.ts +74 -14
- package/src/resources/extensions/gsd/gitignore.ts +1 -0
- package/src/resources/extensions/gsd/gsd-db.ts +78 -1
- package/src/resources/extensions/gsd/guided-flow.ts +109 -12
- package/src/resources/extensions/gsd/index.ts +48 -2
- package/src/resources/extensions/gsd/memory-extractor.ts +352 -0
- package/src/resources/extensions/gsd/memory-store.ts +441 -0
- package/src/resources/extensions/gsd/migrate/command.ts +2 -2
- package/src/resources/extensions/gsd/parallel-eligibility.ts +233 -0
- package/src/resources/extensions/gsd/parallel-merge.ts +156 -0
- package/src/resources/extensions/gsd/parallel-orchestrator.ts +496 -0
- package/src/resources/extensions/gsd/preferences.ts +65 -1
- package/src/resources/extensions/gsd/prompts/complete-slice.md +1 -1
- package/src/resources/extensions/gsd/prompts/discuss-headless.md +86 -0
- package/src/resources/extensions/gsd/prompts/discuss.md +4 -4
- package/src/resources/extensions/gsd/prompts/execute-task.md +1 -1
- package/src/resources/extensions/gsd/prompts/guided-discuss-milestone.md +1 -1
- package/src/resources/extensions/gsd/prompts/guided-discuss-slice.md +1 -1
- package/src/resources/extensions/gsd/prompts/plan-slice.md +1 -1
- package/src/resources/extensions/gsd/prompts/queue.md +1 -1
- package/src/resources/extensions/gsd/prompts/reassess-roadmap.md +1 -1
- package/src/resources/extensions/gsd/prompts/research-slice.md +1 -1
- package/src/resources/extensions/gsd/prompts/validate-milestone.md +40 -61
- package/src/resources/extensions/gsd/provider-error-pause.ts +29 -2
- package/src/resources/extensions/gsd/session-status-io.ts +197 -0
- package/src/resources/extensions/gsd/state.ts +72 -30
- package/src/resources/extensions/gsd/tests/agent-end-provider-error.test.ts +81 -0
- package/src/resources/extensions/gsd/tests/auto-budget-alerts.test.ts +20 -3
- package/src/resources/extensions/gsd/tests/auto-preflight.test.ts +1 -0
- package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +256 -2
- package/src/resources/extensions/gsd/tests/auto-worktree-milestone-merge.test.ts +34 -0
- package/src/resources/extensions/gsd/tests/auto-worktree.test.ts +58 -0
- package/src/resources/extensions/gsd/tests/complete-milestone.test.ts +8 -1
- package/src/resources/extensions/gsd/tests/derive-state-db.test.ts +9 -15
- package/src/resources/extensions/gsd/tests/derive-state-deps.test.ts +9 -0
- package/src/resources/extensions/gsd/tests/derive-state-draft.test.ts +8 -0
- package/src/resources/extensions/gsd/tests/derive-state.test.ts +14 -0
- package/src/resources/extensions/gsd/tests/git-service.test.ts +70 -4
- package/src/resources/extensions/gsd/tests/gsd-db.test.ts +2 -2
- package/src/resources/extensions/gsd/tests/integration-mixed-milestones.test.ts +8 -0
- package/src/resources/extensions/gsd/tests/md-importer.test.ts +2 -3
- package/src/resources/extensions/gsd/tests/memory-extractor.test.ts +180 -0
- package/src/resources/extensions/gsd/tests/memory-store.test.ts +345 -0
- package/src/resources/extensions/gsd/tests/migrate-writer-integration.test.ts +5 -5
- package/src/resources/extensions/gsd/tests/parallel-orchestration.test.ts +656 -0
- package/src/resources/extensions/gsd/tests/parallel-workers-multi-milestone-e2e.test.ts +354 -0
- package/src/resources/extensions/gsd/tests/queue-reorder-e2e.test.ts +1 -0
- package/src/resources/extensions/gsd/tests/smart-entry-draft.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/validate-milestone.test.ts +316 -0
- package/src/resources/extensions/gsd/tests/visualizer-data.test.ts +147 -2
- package/src/resources/extensions/gsd/tests/visualizer-overlay.test.ts +88 -10
- package/src/resources/extensions/gsd/tests/visualizer-views.test.ts +314 -87
- package/src/resources/extensions/gsd/tests/worker-registry.test.ts +148 -0
- package/src/resources/extensions/gsd/triage-ui.ts +1 -1
- package/src/resources/extensions/gsd/types.ts +15 -1
- package/src/resources/extensions/gsd/visualizer-data.ts +291 -10
- package/src/resources/extensions/gsd/visualizer-overlay.ts +237 -28
- package/src/resources/extensions/gsd/visualizer-views.ts +462 -48
- package/src/resources/extensions/gsd/worktree.ts +9 -2
- package/src/resources/extensions/search-the-web/native-search.ts +15 -5
- package/src/resources/extensions/subagent/index.ts +5 -0
- package/src/resources/extensions/subagent/worker-registry.ts +99 -0
|
@@ -0,0 +1,345 @@
|
|
|
1
|
+
import { createTestContext } from './test-helpers.ts';
|
|
2
|
+
import {
|
|
3
|
+
openDatabase,
|
|
4
|
+
closeDatabase,
|
|
5
|
+
isDbAvailable,
|
|
6
|
+
_getAdapter,
|
|
7
|
+
} from '../gsd-db.ts';
|
|
8
|
+
import {
|
|
9
|
+
getActiveMemories,
|
|
10
|
+
getActiveMemoriesRanked,
|
|
11
|
+
nextMemoryId,
|
|
12
|
+
createMemory,
|
|
13
|
+
updateMemoryContent,
|
|
14
|
+
reinforceMemory,
|
|
15
|
+
supersedeMemory,
|
|
16
|
+
isUnitProcessed,
|
|
17
|
+
markUnitProcessed,
|
|
18
|
+
decayStaleMemories,
|
|
19
|
+
enforceMemoryCap,
|
|
20
|
+
applyMemoryActions,
|
|
21
|
+
formatMemoriesForPrompt,
|
|
22
|
+
} from '../memory-store.ts';
|
|
23
|
+
import type { MemoryAction } from '../memory-store.ts';
|
|
24
|
+
|
|
25
|
+
const { assertEq, assertTrue, assertMatch, report } = createTestContext();
|
|
26
|
+
|
|
27
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
28
|
+
// memory-store: fallback when DB not open
|
|
29
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
30
|
+
|
|
31
|
+
console.log('\n=== memory-store: fallback returns empty when DB not open ===');
|
|
32
|
+
{
|
|
33
|
+
closeDatabase();
|
|
34
|
+
assertTrue(!isDbAvailable(), 'DB should not be available');
|
|
35
|
+
|
|
36
|
+
assertEq(getActiveMemories(), [], 'getActiveMemories returns [] when DB closed');
|
|
37
|
+
assertEq(getActiveMemoriesRanked(), [], 'getActiveMemoriesRanked returns [] when DB closed');
|
|
38
|
+
assertEq(nextMemoryId(), 'MEM001', 'nextMemoryId returns MEM001 when DB closed');
|
|
39
|
+
assertEq(createMemory({ category: 'test', content: 'test' }), null, 'createMemory returns null when DB closed');
|
|
40
|
+
assertTrue(!reinforceMemory('MEM001'), 'reinforceMemory returns false when DB closed');
|
|
41
|
+
assertTrue(!isUnitProcessed('test/key'), 'isUnitProcessed returns false when DB closed');
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
45
|
+
// memory-store: CRUD operations
|
|
46
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
47
|
+
|
|
48
|
+
console.log('\n=== memory-store: create and query memories ===');
|
|
49
|
+
{
|
|
50
|
+
openDatabase(':memory:');
|
|
51
|
+
|
|
52
|
+
// Create memories
|
|
53
|
+
const id1 = createMemory({ category: 'gotcha', content: 'esbuild drops .node binaries' });
|
|
54
|
+
assertTrue(id1 !== null, 'createMemory should return an ID');
|
|
55
|
+
assertEq(id1, 'MEM001', 'first memory ID should be MEM001');
|
|
56
|
+
|
|
57
|
+
const id2 = createMemory({ category: 'convention', content: 'use :memory: for tests', confidence: 0.9 });
|
|
58
|
+
assertEq(id2, 'MEM002', 'second memory ID should be MEM002');
|
|
59
|
+
|
|
60
|
+
const id3 = createMemory({ category: 'architecture', content: 'extensions discovered from src/resources/' });
|
|
61
|
+
assertEq(id3, 'MEM003', 'third memory ID should be MEM003');
|
|
62
|
+
|
|
63
|
+
// Query all active
|
|
64
|
+
const active = getActiveMemories();
|
|
65
|
+
assertEq(active.length, 3, 'should have 3 active memories');
|
|
66
|
+
assertEq(active[0].category, 'gotcha', 'first memory category');
|
|
67
|
+
assertEq(active[0].content, 'esbuild drops .node binaries', 'first memory content');
|
|
68
|
+
assertEq(active[1].confidence, 0.9, 'second memory confidence');
|
|
69
|
+
|
|
70
|
+
closeDatabase();
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
74
|
+
// memory-store: update and reinforce
|
|
75
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
76
|
+
|
|
77
|
+
console.log('\n=== memory-store: update and reinforce ===');
|
|
78
|
+
{
|
|
79
|
+
openDatabase(':memory:');
|
|
80
|
+
|
|
81
|
+
createMemory({ category: 'gotcha', content: 'original content' });
|
|
82
|
+
|
|
83
|
+
// Update content
|
|
84
|
+
const updated = updateMemoryContent('MEM001', 'revised content', 0.95);
|
|
85
|
+
assertTrue(updated, 'updateMemoryContent should return true');
|
|
86
|
+
|
|
87
|
+
const active = getActiveMemories();
|
|
88
|
+
assertEq(active[0].content, 'revised content', 'content should be updated');
|
|
89
|
+
assertEq(active[0].confidence, 0.95, 'confidence should be updated');
|
|
90
|
+
|
|
91
|
+
// Reinforce
|
|
92
|
+
const reinforced = reinforceMemory('MEM001');
|
|
93
|
+
assertTrue(reinforced, 'reinforceMemory should return true');
|
|
94
|
+
|
|
95
|
+
const after = getActiveMemories();
|
|
96
|
+
assertEq(after[0].hit_count, 1, 'hit_count should be 1 after reinforce');
|
|
97
|
+
|
|
98
|
+
// Reinforce again
|
|
99
|
+
reinforceMemory('MEM001');
|
|
100
|
+
const after2 = getActiveMemories();
|
|
101
|
+
assertEq(after2[0].hit_count, 2, 'hit_count should be 2 after second reinforce');
|
|
102
|
+
|
|
103
|
+
closeDatabase();
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
107
|
+
// memory-store: supersede
|
|
108
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
109
|
+
|
|
110
|
+
console.log('\n=== memory-store: supersede ===');
|
|
111
|
+
{
|
|
112
|
+
openDatabase(':memory:');
|
|
113
|
+
|
|
114
|
+
createMemory({ category: 'convention', content: 'old convention' });
|
|
115
|
+
createMemory({ category: 'convention', content: 'new convention' });
|
|
116
|
+
|
|
117
|
+
supersedeMemory('MEM001', 'MEM002');
|
|
118
|
+
|
|
119
|
+
const active = getActiveMemories();
|
|
120
|
+
assertEq(active.length, 1, 'should have 1 active memory after supersede');
|
|
121
|
+
assertEq(active[0].id, 'MEM002', 'active memory should be MEM002');
|
|
122
|
+
|
|
123
|
+
closeDatabase();
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
127
|
+
// memory-store: ranked query ordering
|
|
128
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
129
|
+
|
|
130
|
+
console.log('\n=== memory-store: ranked query ordering ===');
|
|
131
|
+
{
|
|
132
|
+
openDatabase(':memory:');
|
|
133
|
+
|
|
134
|
+
// Low confidence, no hits
|
|
135
|
+
createMemory({ category: 'pattern', content: 'low ranking', confidence: 0.5 });
|
|
136
|
+
// High confidence, no hits
|
|
137
|
+
createMemory({ category: 'gotcha', content: 'high confidence', confidence: 0.95 });
|
|
138
|
+
// Medium confidence, many hits
|
|
139
|
+
createMemory({ category: 'convention', content: 'frequently used', confidence: 0.7 });
|
|
140
|
+
|
|
141
|
+
// Reinforce MEM003 multiple times to boost its ranking
|
|
142
|
+
for (let i = 0; i < 10; i++) reinforceMemory('MEM003');
|
|
143
|
+
|
|
144
|
+
const ranked = getActiveMemoriesRanked(10);
|
|
145
|
+
assertEq(ranked.length, 3, 'should have 3 ranked memories');
|
|
146
|
+
// MEM003: 0.7 * (1 + 10*0.1) = 0.7 * 2.0 = 1.4
|
|
147
|
+
// MEM002: 0.95 * (1 + 0*0.1) = 0.95
|
|
148
|
+
// MEM001: 0.5 * (1 + 0*0.1) = 0.5
|
|
149
|
+
assertEq(ranked[0].id, 'MEM003', 'highest ranked should be MEM003 (reinforced)');
|
|
150
|
+
assertEq(ranked[1].id, 'MEM002', 'second ranked should be MEM002 (high confidence)');
|
|
151
|
+
assertEq(ranked[2].id, 'MEM001', 'lowest ranked should be MEM001');
|
|
152
|
+
|
|
153
|
+
// Test limit
|
|
154
|
+
const limited = getActiveMemoriesRanked(2);
|
|
155
|
+
assertEq(limited.length, 2, 'limit should cap results');
|
|
156
|
+
|
|
157
|
+
closeDatabase();
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
161
|
+
// memory-store: processed unit tracking
|
|
162
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
163
|
+
|
|
164
|
+
console.log('\n=== memory-store: processed unit tracking ===');
|
|
165
|
+
{
|
|
166
|
+
openDatabase(':memory:');
|
|
167
|
+
|
|
168
|
+
assertTrue(!isUnitProcessed('execute-task/M001/S01/T01'), 'should not be processed initially');
|
|
169
|
+
|
|
170
|
+
markUnitProcessed('execute-task/M001/S01/T01', '/path/to/activity.jsonl');
|
|
171
|
+
|
|
172
|
+
assertTrue(isUnitProcessed('execute-task/M001/S01/T01'), 'should be processed after marking');
|
|
173
|
+
assertTrue(!isUnitProcessed('execute-task/M001/S01/T02'), 'different key should not be processed');
|
|
174
|
+
|
|
175
|
+
closeDatabase();
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
179
|
+
// memory-store: enforce memory cap
|
|
180
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
181
|
+
|
|
182
|
+
console.log('\n=== memory-store: enforce memory cap ===');
|
|
183
|
+
{
|
|
184
|
+
openDatabase(':memory:');
|
|
185
|
+
|
|
186
|
+
// Create 5 memories with varying confidence
|
|
187
|
+
createMemory({ category: 'gotcha', content: 'mem 1', confidence: 0.9 });
|
|
188
|
+
createMemory({ category: 'gotcha', content: 'mem 2', confidence: 0.5 });
|
|
189
|
+
createMemory({ category: 'gotcha', content: 'mem 3', confidence: 0.3 });
|
|
190
|
+
createMemory({ category: 'gotcha', content: 'mem 4', confidence: 0.95 });
|
|
191
|
+
createMemory({ category: 'gotcha', content: 'mem 5', confidence: 0.7 });
|
|
192
|
+
|
|
193
|
+
// Enforce cap of 3
|
|
194
|
+
enforceMemoryCap(3);
|
|
195
|
+
|
|
196
|
+
const active = getActiveMemories();
|
|
197
|
+
assertEq(active.length, 3, 'should have 3 active memories after cap enforcement');
|
|
198
|
+
|
|
199
|
+
// The 2 lowest-ranked (MEM003=0.3 and MEM002=0.5) should be superseded
|
|
200
|
+
const ids = active.map(m => m.id).sort();
|
|
201
|
+
assertTrue(ids.includes('MEM001'), 'MEM001 (0.9) should survive');
|
|
202
|
+
assertTrue(ids.includes('MEM004'), 'MEM004 (0.95) should survive');
|
|
203
|
+
assertTrue(ids.includes('MEM005'), 'MEM005 (0.7) should survive');
|
|
204
|
+
|
|
205
|
+
closeDatabase();
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
209
|
+
// memory-store: applyMemoryActions transaction
|
|
210
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
211
|
+
|
|
212
|
+
console.log('\n=== memory-store: applyMemoryActions ===');
|
|
213
|
+
{
|
|
214
|
+
openDatabase(':memory:');
|
|
215
|
+
|
|
216
|
+
const actions: MemoryAction[] = [
|
|
217
|
+
{ action: 'CREATE', category: 'gotcha', content: 'first gotcha', confidence: 0.8 },
|
|
218
|
+
{ action: 'CREATE', category: 'convention', content: 'first convention', confidence: 0.9 },
|
|
219
|
+
];
|
|
220
|
+
|
|
221
|
+
applyMemoryActions(actions, 'execute-task', 'M001/S01/T01');
|
|
222
|
+
|
|
223
|
+
let active = getActiveMemories();
|
|
224
|
+
assertEq(active.length, 2, 'should have 2 memories after CREATE actions');
|
|
225
|
+
|
|
226
|
+
// Now apply UPDATE + REINFORCE
|
|
227
|
+
const updateActions: MemoryAction[] = [
|
|
228
|
+
{ action: 'UPDATE', id: 'MEM001', content: 'updated gotcha' },
|
|
229
|
+
{ action: 'REINFORCE', id: 'MEM002' },
|
|
230
|
+
];
|
|
231
|
+
|
|
232
|
+
applyMemoryActions(updateActions, 'execute-task', 'M001/S01/T02');
|
|
233
|
+
|
|
234
|
+
active = getActiveMemories();
|
|
235
|
+
assertEq(active.find(m => m.id === 'MEM001')?.content, 'updated gotcha', 'MEM001 should be updated');
|
|
236
|
+
assertEq(active.find(m => m.id === 'MEM002')?.hit_count, 1, 'MEM002 should be reinforced');
|
|
237
|
+
|
|
238
|
+
// SUPERSEDE
|
|
239
|
+
const supersedeActions: MemoryAction[] = [
|
|
240
|
+
{ action: 'CREATE', category: 'gotcha', content: 'better gotcha', confidence: 0.95 },
|
|
241
|
+
{ action: 'SUPERSEDE', id: 'MEM001', superseded_by: 'MEM003' },
|
|
242
|
+
];
|
|
243
|
+
|
|
244
|
+
applyMemoryActions(supersedeActions, 'execute-task', 'M001/S01/T03');
|
|
245
|
+
|
|
246
|
+
active = getActiveMemories();
|
|
247
|
+
assertEq(active.length, 2, 'should have 2 active after supersede');
|
|
248
|
+
assertTrue(!active.find(m => m.id === 'MEM001'), 'MEM001 should be superseded');
|
|
249
|
+
assertTrue(!!active.find(m => m.id === 'MEM003'), 'MEM003 should be active');
|
|
250
|
+
|
|
251
|
+
closeDatabase();
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
255
|
+
// memory-store: formatMemoriesForPrompt
|
|
256
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
257
|
+
|
|
258
|
+
console.log('\n=== memory-store: formatMemoriesForPrompt ===');
|
|
259
|
+
{
|
|
260
|
+
openDatabase(':memory:');
|
|
261
|
+
|
|
262
|
+
createMemory({ category: 'gotcha', content: 'esbuild drops .node binaries' });
|
|
263
|
+
createMemory({ category: 'convention', content: 'use :memory: for tests' });
|
|
264
|
+
createMemory({ category: 'architecture', content: 'extensions in src/resources/' });
|
|
265
|
+
createMemory({ category: 'gotcha', content: 'TypeScript path aliases need .js' });
|
|
266
|
+
|
|
267
|
+
const memories = getActiveMemoriesRanked(30);
|
|
268
|
+
const formatted = formatMemoriesForPrompt(memories);
|
|
269
|
+
|
|
270
|
+
assertTrue(formatted.includes('## Project Memory (auto-learned)'), 'should have header');
|
|
271
|
+
assertTrue(formatted.includes('### Gotcha'), 'should have gotcha category');
|
|
272
|
+
assertTrue(formatted.includes('### Convention'), 'should have convention category');
|
|
273
|
+
assertTrue(formatted.includes('### Architecture'), 'should have architecture category');
|
|
274
|
+
assertTrue(formatted.includes('- esbuild drops .node binaries'), 'should have gotcha content');
|
|
275
|
+
assertTrue(formatted.includes('- use :memory: for tests'), 'should have convention content');
|
|
276
|
+
|
|
277
|
+
// Test empty memories
|
|
278
|
+
closeDatabase();
|
|
279
|
+
openDatabase(':memory:');
|
|
280
|
+
const emptyFormatted = formatMemoriesForPrompt([]);
|
|
281
|
+
assertEq(emptyFormatted, '', 'empty memories should return empty string');
|
|
282
|
+
|
|
283
|
+
// Test token budget truncation
|
|
284
|
+
closeDatabase();
|
|
285
|
+
openDatabase(':memory:');
|
|
286
|
+
for (let i = 0; i < 20; i++) {
|
|
287
|
+
createMemory({ category: 'pattern', content: `A very long memory entry that takes up space #${i}: ${'x'.repeat(200)}` });
|
|
288
|
+
}
|
|
289
|
+
const budgetMemories = getActiveMemoriesRanked(30);
|
|
290
|
+
const truncated = formatMemoriesForPrompt(budgetMemories, 500);
|
|
291
|
+
assertTrue(truncated.length < 2500, `formatted length ${truncated.length} should be under budget`);
|
|
292
|
+
|
|
293
|
+
closeDatabase();
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
297
|
+
// memory-store: ID generation
|
|
298
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
299
|
+
|
|
300
|
+
console.log('\n=== memory-store: ID generation ===');
|
|
301
|
+
{
|
|
302
|
+
openDatabase(':memory:');
|
|
303
|
+
|
|
304
|
+
assertEq(nextMemoryId(), 'MEM001', 'first ID should be MEM001');
|
|
305
|
+
|
|
306
|
+
createMemory({ category: 'test', content: 'test' });
|
|
307
|
+
assertEq(nextMemoryId(), 'MEM002', 'after first create, next should be MEM002');
|
|
308
|
+
|
|
309
|
+
// Create several more
|
|
310
|
+
for (let i = 0; i < 98; i++) createMemory({ category: 'test', content: `test ${i}` });
|
|
311
|
+
assertEq(nextMemoryId(), 'MEM100', 'after 99 creates, next should be MEM100');
|
|
312
|
+
|
|
313
|
+
closeDatabase();
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
317
|
+
// memory-store: schema migration (v2 → v3)
|
|
318
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
319
|
+
|
|
320
|
+
console.log('\n=== memory-store: schema includes memories table ===');
|
|
321
|
+
{
|
|
322
|
+
openDatabase(':memory:');
|
|
323
|
+
|
|
324
|
+
const adapter = _getAdapter()!;
|
|
325
|
+
|
|
326
|
+
// Verify memories table exists
|
|
327
|
+
const memCount = adapter.prepare('SELECT count(*) as cnt FROM memories').get();
|
|
328
|
+
assertEq(memCount?.['cnt'], 0, 'memories table should exist and be empty');
|
|
329
|
+
|
|
330
|
+
// Verify memory_processed_units table exists
|
|
331
|
+
const procCount = adapter.prepare('SELECT count(*) as cnt FROM memory_processed_units').get();
|
|
332
|
+
assertEq(procCount?.['cnt'], 0, 'memory_processed_units table should exist and be empty');
|
|
333
|
+
|
|
334
|
+
// Verify active_memories view exists
|
|
335
|
+
const viewCount = adapter.prepare('SELECT count(*) as cnt FROM active_memories').get();
|
|
336
|
+
assertEq(viewCount?.['cnt'], 0, 'active_memories view should exist');
|
|
337
|
+
|
|
338
|
+
// Verify schema version is 3
|
|
339
|
+
const version = adapter.prepare('SELECT MAX(version) as v FROM schema_version').get();
|
|
340
|
+
assertEq(version?.['v'], 3, 'schema version should be 3');
|
|
341
|
+
|
|
342
|
+
closeDatabase();
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
report();
|
|
@@ -263,12 +263,12 @@ async function main(): Promise<void> {
|
|
|
263
263
|
// No REQUIREMENTS.md since empty requirements
|
|
264
264
|
assertTrue(!existsSync(join(base, '.gsd', 'REQUIREMENTS.md')), 'complete: REQUIREMENTS.md NOT written (empty)');
|
|
265
265
|
|
|
266
|
-
// deriveState: all slices done, all tasks done — needs milestone summary
|
|
267
|
-
// Without
|
|
266
|
+
// deriveState: all slices done, all tasks done — needs validation then milestone summary
|
|
267
|
+
// Without VALIDATION file, it should be 'validating-milestone'
|
|
268
268
|
const state = await deriveState(base);
|
|
269
|
-
// All slices are done in roadmap.
|
|
270
|
-
// deriveState should return '
|
|
271
|
-
assertEq(state.phase, '
|
|
269
|
+
// All slices are done in roadmap. No VALIDATION or SUMMARY exists.
|
|
270
|
+
// deriveState should return 'validating-milestone' since validation gate precedes completion.
|
|
271
|
+
assertEq(state.phase, 'validating-milestone', 'complete: deriveState phase is validating-milestone');
|
|
272
272
|
assertTrue(state.activeMilestone !== null, 'complete: deriveState has activeMilestone');
|
|
273
273
|
assertEq(state.activeMilestone!.id, 'M001', 'complete: deriveState activeMilestone is M001');
|
|
274
274
|
|