@stackmemoryai/stackmemory 0.3.17 ā 0.3.18
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/dist/cli/commands/skills.js +15 -2
- package/dist/cli/commands/skills.js.map +2 -2
- package/dist/cli/index.js +113 -834
- package/dist/cli/index.js.map +3 -3
- package/dist/core/context/dual-stack-manager.js +1 -1
- package/dist/core/context/dual-stack-manager.js.map +1 -1
- package/dist/core/context/frame-manager.js +3 -0
- package/dist/core/context/frame-manager.js.map +2 -2
- package/dist/integrations/claude-code/subagent-client.js +106 -3
- package/dist/integrations/claude-code/subagent-client.js.map +2 -2
- package/dist/servers/railway/config.js +51 -0
- package/dist/servers/railway/config.js.map +7 -0
- package/dist/servers/railway/index-enhanced.js +156 -0
- package/dist/servers/railway/index-enhanced.js.map +7 -0
- package/dist/servers/railway/minimal.js +48 -3
- package/dist/servers/railway/minimal.js.map +2 -2
- package/dist/servers/railway/storage-test.js +455 -0
- package/dist/servers/railway/storage-test.js.map +7 -0
- package/dist/skills/claude-skills.js +13 -12
- package/dist/skills/claude-skills.js.map +2 -2
- package/dist/skills/recursive-agent-orchestrator.js +27 -18
- package/dist/skills/recursive-agent-orchestrator.js.map +2 -2
- package/dist/skills/unified-rlm-orchestrator.js.map +2 -2
- package/package.json +6 -18
- package/scripts/README-TESTING.md +186 -0
- package/scripts/analyze-cli-security.js +288 -0
- package/scripts/archive/add-phase-tasks-to-linear.js +163 -0
- package/scripts/archive/analyze-linear-duplicates.js +214 -0
- package/scripts/archive/analyze-remaining-duplicates.js +230 -0
- package/scripts/archive/analyze-sta-duplicates.js +292 -0
- package/scripts/archive/analyze-sta-graphql.js +399 -0
- package/scripts/archive/cancel-duplicate-tasks.ts +246 -0
- package/scripts/archive/check-all-duplicates.ts +419 -0
- package/scripts/archive/clean-duplicate-tasks.js +114 -0
- package/scripts/archive/cleanup-duplicate-tasks.ts +286 -0
- package/scripts/archive/create-phase-tasks.js +387 -0
- package/scripts/archive/delete-linear-duplicates.js +182 -0
- package/scripts/archive/delete-remaining-duplicates.js +158 -0
- package/scripts/archive/delete-sta-duplicates.js +201 -0
- package/scripts/archive/delete-sta-oauth.js +201 -0
- package/scripts/archive/export-sta-tasks.js +62 -0
- package/scripts/archive/install-auto-sync.js +266 -0
- package/scripts/archive/install-chromadb-hooks.sh +133 -0
- package/scripts/archive/install-enhanced-clear-hooks.sh +431 -0
- package/scripts/archive/install-post-task-hooks.sh +289 -0
- package/scripts/archive/install-stackmemory-hooks.sh +420 -0
- package/scripts/archive/merge-linear-duplicates-safe.ts +362 -0
- package/scripts/archive/merge-linear-duplicates.ts +180 -0
- package/scripts/archive/remove-sta-tasks.js +70 -0
- package/scripts/archive/setup-background-sync.sh +168 -0
- package/scripts/archive/setup-claude-auto-triggers.sh +181 -0
- package/scripts/archive/setup-claude-autostart.sh +305 -0
- package/scripts/archive/setup-git-hooks.sh +25 -0
- package/scripts/archive/setup-linear-oauth.sh +46 -0
- package/scripts/archive/setup-mcp.sh +113 -0
- package/scripts/archive/setup-railway-deployment.sh +81 -0
- package/scripts/auto-handoff.sh +262 -0
- package/scripts/background-sync-manager.js +416 -0
- package/scripts/benchmark-performance.ts +57 -0
- package/scripts/check-redis.ts +48 -0
- package/scripts/chromadb-auto-loader.sh +128 -0
- package/scripts/chromadb-context-loader.js +479 -0
- package/scripts/claude-chromadb-hook.js +460 -0
- package/scripts/claude-code-wrapper.sh +66 -0
- package/scripts/claude-linear-skill.js +455 -0
- package/scripts/claude-pre-commit.sh +302 -0
- package/scripts/claude-sm-autostart.js +532 -0
- package/scripts/claude-sm-setup.sh +367 -0
- package/scripts/claude-with-chromadb.sh +69 -0
- package/scripts/claude-worktree-manager.sh +323 -0
- package/scripts/claude-worktree-monitor.sh +371 -0
- package/scripts/claude-worktree-setup.sh +327 -0
- package/scripts/clean-linear-backlog.js +273 -0
- package/scripts/cleanup-old-sessions.sh +57 -0
- package/scripts/codex-wrapper.sh +88 -0
- package/scripts/create-sandbox.sh +269 -0
- package/scripts/debug-linear-update.js +174 -0
- package/scripts/delete-linear-tasks.js +167 -0
- package/scripts/deploy.sh +89 -0
- package/scripts/deployment/railway.sh +352 -0
- package/scripts/deployment/test-deployment.js +194 -0
- package/scripts/detect-and-rehydrate.js +162 -0
- package/scripts/detect-and-rehydrate.mjs +165 -0
- package/scripts/development/create-demo-tasks.js +143 -0
- package/scripts/development/debug-frame-test.js +16 -0
- package/scripts/development/demo-auto-sync.js +128 -0
- package/scripts/development/fix-all-imports.js +213 -0
- package/scripts/development/fix-imports.js +229 -0
- package/scripts/development/fix-lint-loop.cjs +103 -0
- package/scripts/development/fix-project-id.ts +161 -0
- package/scripts/development/fix-strict-mode-issues.ts +291 -0
- package/scripts/development/reorganize-structure.sh +228 -0
- package/scripts/development/test-persistence-direct.js +148 -0
- package/scripts/development/test-persistence.js +114 -0
- package/scripts/development/test-tasks.js +93 -0
- package/scripts/development/update-imports.js +212 -0
- package/scripts/fetch-linear-status.js +125 -0
- package/scripts/git-hooks/README.md +310 -0
- package/scripts/git-hooks/branch-context-manager.sh +342 -0
- package/scripts/git-hooks/post-checkout-stackmemory.sh +63 -0
- package/scripts/git-hooks/post-commit-stackmemory.sh +305 -0
- package/scripts/git-hooks/pre-commit-stackmemory.sh +275 -0
- package/scripts/hooks/cleanup-shell.sh +130 -0
- package/scripts/hooks/task-complete.sh +114 -0
- package/scripts/initialize.ts +129 -0
- package/scripts/install-claude-hooks-auto.js +104 -0
- package/scripts/install-claude-hooks.sh +133 -0
- package/scripts/install-global.sh +296 -0
- package/scripts/install.sh +235 -0
- package/scripts/linear-auto-sync.js +262 -0
- package/scripts/linear-auto-sync.sh +161 -0
- package/scripts/linear-sync-daemon.js +150 -0
- package/scripts/linear-task-review.js +237 -0
- package/scripts/list-linear-tasks.ts +178 -0
- package/scripts/mcp-proxy.js +66 -0
- package/scripts/opencode-wrapper.sh +85 -0
- package/scripts/publish-local.js +74 -0
- package/scripts/query-chromadb.ts +201 -0
- package/scripts/railway-env-setup.sh +39 -0
- package/scripts/reconcile-local-tasks.js +170 -0
- package/scripts/recreate-frames-db.js +89 -0
- package/scripts/setup/claude-integration.js +138 -0
- package/scripts/setup/configure-alias.js +125 -0
- package/scripts/setup/configure-codex-alias.js +161 -0
- package/scripts/setup/configure-opencode-alias.js +175 -0
- package/scripts/setup-claude-integration.js +204 -0
- package/scripts/setup-claude-integration.sh +183 -0
- package/scripts/setup.sh +31 -0
- package/scripts/show-linear-summary.ts +172 -0
- package/scripts/stackmemory-auto-handoff.sh +231 -0
- package/scripts/stackmemory-daemon.sh +40 -0
- package/scripts/start-linear-sync-daemon.sh +141 -0
- package/scripts/start-temporal-paradox.sh +214 -0
- package/scripts/status.ts +159 -0
- package/scripts/sync-and-clean-tasks.js +258 -0
- package/scripts/sync-frames-from-railway.js +228 -0
- package/scripts/sync-linear-graphql.js +303 -0
- package/scripts/sync-linear-tasks.js +186 -0
- package/scripts/test-auto-triggers.sh +57 -0
- package/scripts/test-browser-mcp.js +74 -0
- package/scripts/test-chromadb-full.js +115 -0
- package/scripts/test-chromadb-hooks.sh +28 -0
- package/scripts/test-chromadb-sync.ts +245 -0
- package/scripts/test-cli-security.js +293 -0
- package/scripts/test-hooks-persistence.sh +220 -0
- package/scripts/test-installation-scenarios.sh +359 -0
- package/scripts/test-installation.sh +224 -0
- package/scripts/test-mcp.js +163 -0
- package/scripts/test-pre-publish-quick.sh +75 -0
- package/scripts/test-quality-gates.sh +263 -0
- package/scripts/test-railway-db.js +222 -0
- package/scripts/test-redis-storage.ts +490 -0
- package/scripts/test-rlm-basic.sh +122 -0
- package/scripts/test-rlm-comprehensive.sh +260 -0
- package/scripts/test-rlm-e2e.sh +268 -0
- package/scripts/test-rlm-simple.js +90 -0
- package/scripts/test-rlm.js +110 -0
- package/scripts/test-session-handoff.sh +165 -0
- package/scripts/test-shell-integration.sh +275 -0
- package/scripts/testing/ab-test-runner.ts +508 -0
- package/scripts/testing/collect-metrics.ts +457 -0
- package/scripts/testing/quick-effectiveness-demo.js +187 -0
- package/scripts/testing/real-performance-test.js +422 -0
- package/scripts/testing/run-effectiveness-tests.sh +176 -0
- package/scripts/testing/scripts/testing/ab-test-runner.js +363 -0
- package/scripts/testing/scripts/testing/collect-metrics.js +292 -0
- package/scripts/testing/simple-effectiveness-test.js +310 -0
- package/scripts/testing/src/core/context/context-bridge.js +253 -0
- package/scripts/testing/src/core/context/frame-manager.js +746 -0
- package/scripts/testing/src/core/context/shared-context-layer.js +437 -0
- package/scripts/testing/src/core/database/database-adapter.js +54 -0
- package/scripts/testing/src/core/errors/index.js +291 -0
- package/scripts/testing/src/core/errors/recovery.js +268 -0
- package/scripts/testing/src/core/monitoring/logger.js +145 -0
- package/scripts/testing/src/core/retrieval/context-retriever.js +516 -0
- package/scripts/testing/src/core/session/index.js +1 -0
- package/scripts/testing/src/core/session/session-manager.js +323 -0
- package/scripts/testing/src/core/trace/cli-trace-wrapper.js +140 -0
- package/scripts/testing/src/core/trace/db-trace-wrapper.js +251 -0
- package/scripts/testing/src/core/trace/debug-trace.js +398 -0
- package/scripts/testing/src/core/trace/index.js +120 -0
- package/scripts/testing/src/core/trace/linear-api-wrapper.js +204 -0
- package/scripts/update-linear-status.js +268 -0
- package/scripts/update-linear-tasks-fixed.js +284 -0
- package/templates/claude-hooks/hooks.json +5 -0
- package/templates/claude-hooks/on-clear.js +56 -0
- package/templates/claude-hooks/on-startup.js +56 -0
- package/templates/claude-hooks/tool-use-trace.js +67 -0
- package/dist/features/tui/components/analytics-panel.js +0 -157
- package/dist/features/tui/components/analytics-panel.js.map +0 -7
- package/dist/features/tui/components/frame-visualizer.js +0 -377
- package/dist/features/tui/components/frame-visualizer.js.map +0 -7
- package/dist/features/tui/components/pr-tracker.js +0 -135
- package/dist/features/tui/components/pr-tracker.js.map +0 -7
- package/dist/features/tui/components/session-monitor.js +0 -299
- package/dist/features/tui/components/session-monitor.js.map +0 -7
- package/dist/features/tui/components/subagent-fleet.js +0 -395
- package/dist/features/tui/components/subagent-fleet.js.map +0 -7
- package/dist/features/tui/components/task-board.js +0 -1139
- package/dist/features/tui/components/task-board.js.map +0 -7
- package/dist/features/tui/index.js +0 -408
- package/dist/features/tui/index.js.map +0 -7
- package/dist/features/tui/services/data-service.js +0 -641
- package/dist/features/tui/services/data-service.js.map +0 -7
- package/dist/features/tui/services/linear-task-reader.js +0 -102
- package/dist/features/tui/services/linear-task-reader.js.map +0 -7
- package/dist/features/tui/services/websocket-client.js +0 -162
- package/dist/features/tui/services/websocket-client.js.map +0 -7
- package/dist/features/tui/terminal-compat.js +0 -220
- package/dist/features/tui/terminal-compat.js.map +0 -7
- package/dist/features/tui/types.js +0 -1
- package/dist/features/tui/types.js.map +0 -7
|
@@ -0,0 +1,286 @@
|
|
|
1
|
+
#!/usr/bin/env npx tsx
|
|
2
|
+
/**
|
|
3
|
+
* Cleanup duplicate tasks from local JSONL storage
|
|
4
|
+
*
|
|
5
|
+
* This script:
|
|
6
|
+
* 1. Identifies duplicate tasks by title/Linear ID
|
|
7
|
+
* 2. Keeps the most recent version of each task
|
|
8
|
+
* 3. Removes redundant Linear-imported duplicates
|
|
9
|
+
* 4. Cleans up orphaned task mappings
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import { readFileSync, writeFileSync, existsSync } from 'fs';
|
|
13
|
+
import { join } from 'path';
|
|
14
|
+
|
|
15
|
+
interface TaskEvent {
|
|
16
|
+
id: string;
|
|
17
|
+
type: 'task_create' | 'task_update';
|
|
18
|
+
timestamp: number;
|
|
19
|
+
title: string;
|
|
20
|
+
status?: string;
|
|
21
|
+
frame_id?: string;
|
|
22
|
+
description?: string;
|
|
23
|
+
priority?: string;
|
|
24
|
+
[key: string]: unknown;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
interface TaskMapping {
|
|
28
|
+
stackmemoryId: string;
|
|
29
|
+
linearId: string;
|
|
30
|
+
linearIdentifier: string;
|
|
31
|
+
lastSyncTimestamp: number;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const projectRoot = process.cwd();
|
|
35
|
+
const tasksPath = join(projectRoot, '.stackmemory', 'tasks.jsonl');
|
|
36
|
+
const mappingsPath = join(projectRoot, '.stackmemory', 'linear-mappings.json');
|
|
37
|
+
|
|
38
|
+
function loadTasks(): TaskEvent[] {
|
|
39
|
+
if (!existsSync(tasksPath)) {
|
|
40
|
+
console.log('No tasks file found');
|
|
41
|
+
return [];
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const content = readFileSync(tasksPath, 'utf8');
|
|
45
|
+
const lines = content
|
|
46
|
+
.trim()
|
|
47
|
+
.split('\n')
|
|
48
|
+
.filter((l) => l.trim());
|
|
49
|
+
|
|
50
|
+
return lines
|
|
51
|
+
.map((line) => {
|
|
52
|
+
try {
|
|
53
|
+
return JSON.parse(line) as TaskEvent;
|
|
54
|
+
} catch {
|
|
55
|
+
console.warn('Failed to parse line:', line.substring(0, 50));
|
|
56
|
+
return null;
|
|
57
|
+
}
|
|
58
|
+
})
|
|
59
|
+
.filter((t): t is TaskEvent => t !== null);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function loadMappings(): TaskMapping[] {
|
|
63
|
+
if (!existsSync(mappingsPath)) {
|
|
64
|
+
return [];
|
|
65
|
+
}
|
|
66
|
+
try {
|
|
67
|
+
return JSON.parse(readFileSync(mappingsPath, 'utf8'));
|
|
68
|
+
} catch {
|
|
69
|
+
return [];
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
function extractLinearId(title: string): string | null {
|
|
74
|
+
// Match patterns like [STA-123], [ENG-123], etc.
|
|
75
|
+
const match = title.match(/\[([A-Z]+-\d+)\]/);
|
|
76
|
+
return match ? match[1] : null;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
function normalizeTitle(title: string): string {
|
|
80
|
+
// Remove Linear ID prefix for comparison
|
|
81
|
+
return title
|
|
82
|
+
.replace(/^\[[A-Z]+-\d+\]\s*/, '')
|
|
83
|
+
.trim()
|
|
84
|
+
.toLowerCase();
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
function cleanupTasks(): void {
|
|
88
|
+
console.log('š§¹ Starting task cleanup...\n');
|
|
89
|
+
|
|
90
|
+
const events = loadTasks();
|
|
91
|
+
const mappings = loadMappings();
|
|
92
|
+
|
|
93
|
+
console.log(`š Found ${events.length} task events`);
|
|
94
|
+
console.log(`š Found ${mappings.length} Linear mappings\n`);
|
|
95
|
+
|
|
96
|
+
// First, deduplicate events:
|
|
97
|
+
// 1. Remove exact duplicates (same id + type + timestamp)
|
|
98
|
+
// 2. Keep only one task_create per task ID (the earliest one)
|
|
99
|
+
const seenExact = new Set<string>();
|
|
100
|
+
const seenTaskCreate = new Map<string, TaskEvent>(); // id -> earliest create event
|
|
101
|
+
const dedupedEvents: TaskEvent[] = [];
|
|
102
|
+
let exactDupes = 0;
|
|
103
|
+
let createDupes = 0;
|
|
104
|
+
|
|
105
|
+
// First pass: identify the earliest task_create for each task
|
|
106
|
+
for (const event of events) {
|
|
107
|
+
if (event.type === 'task_create') {
|
|
108
|
+
const existing = seenTaskCreate.get(event.id);
|
|
109
|
+
if (!existing || (event.timestamp || 0) < (existing.timestamp || 0)) {
|
|
110
|
+
seenTaskCreate.set(event.id, event);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// Second pass: build deduped list
|
|
116
|
+
for (const event of events) {
|
|
117
|
+
const exactKey = `${event.id}:${event.type}:${event.timestamp}`;
|
|
118
|
+
|
|
119
|
+
// Skip exact duplicates
|
|
120
|
+
if (seenExact.has(exactKey)) {
|
|
121
|
+
exactDupes++;
|
|
122
|
+
continue;
|
|
123
|
+
}
|
|
124
|
+
seenExact.add(exactKey);
|
|
125
|
+
|
|
126
|
+
// For task_create, only keep the earliest one per ID
|
|
127
|
+
if (event.type === 'task_create') {
|
|
128
|
+
const earliest = seenTaskCreate.get(event.id);
|
|
129
|
+
if (
|
|
130
|
+
earliest &&
|
|
131
|
+
earliest !== event &&
|
|
132
|
+
earliest.timestamp !== event.timestamp
|
|
133
|
+
) {
|
|
134
|
+
createDupes++;
|
|
135
|
+
continue;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
dedupedEvents.push(event);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
if (exactDupes > 0) {
|
|
143
|
+
console.log(`š Removed ${exactDupes} exact duplicate events`);
|
|
144
|
+
}
|
|
145
|
+
if (createDupes > 0) {
|
|
146
|
+
console.log(`š Removed ${createDupes} duplicate task_create events\n`);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
// Group events by task ID
|
|
150
|
+
const taskById = new Map<string, TaskEvent[]>();
|
|
151
|
+
for (const event of dedupedEvents) {
|
|
152
|
+
const existing = taskById.get(event.id) || [];
|
|
153
|
+
existing.push(event);
|
|
154
|
+
taskById.set(event.id, existing);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
// Find the latest state for each task
|
|
158
|
+
const latestTaskState = new Map<string, TaskEvent>();
|
|
159
|
+
for (const [id, taskEvents] of taskById) {
|
|
160
|
+
// Get the latest event (highest timestamp)
|
|
161
|
+
const latest = taskEvents.reduce((a, b) =>
|
|
162
|
+
(a.timestamp || 0) > (b.timestamp || 0) ? a : b
|
|
163
|
+
);
|
|
164
|
+
latestTaskState.set(id, latest);
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
console.log(`š Found ${latestTaskState.size} unique tasks\n`);
|
|
168
|
+
|
|
169
|
+
// Identify duplicates by normalized title
|
|
170
|
+
const tasksByNormalizedTitle = new Map<string, TaskEvent[]>();
|
|
171
|
+
for (const task of latestTaskState.values()) {
|
|
172
|
+
const normalized = normalizeTitle(task.title);
|
|
173
|
+
const existing = tasksByNormalizedTitle.get(normalized) || [];
|
|
174
|
+
existing.push(task);
|
|
175
|
+
tasksByNormalizedTitle.set(normalized, existing);
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
// Find duplicate groups
|
|
179
|
+
const duplicateGroups: TaskEvent[][] = [];
|
|
180
|
+
for (const [, tasks] of tasksByNormalizedTitle) {
|
|
181
|
+
if (tasks.length > 1) {
|
|
182
|
+
duplicateGroups.push(tasks);
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
console.log(
|
|
187
|
+
`š Found ${duplicateGroups.length} groups of duplicate tasks:\n`
|
|
188
|
+
);
|
|
189
|
+
|
|
190
|
+
// Determine which tasks to keep
|
|
191
|
+
const tasksToRemove = new Set<string>();
|
|
192
|
+
|
|
193
|
+
for (const group of duplicateGroups) {
|
|
194
|
+
// Sort by: prefer non-linear-import frame, then by timestamp (newest first)
|
|
195
|
+
group.sort((a, b) => {
|
|
196
|
+
const aIsImport = a.frame_id === 'linear-import';
|
|
197
|
+
const bIsImport = b.frame_id === 'linear-import';
|
|
198
|
+
|
|
199
|
+
if (aIsImport !== bIsImport) {
|
|
200
|
+
return aIsImport ? 1 : -1; // Prefer non-import
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
return (b.timestamp || 0) - (a.timestamp || 0); // Prefer newer
|
|
204
|
+
});
|
|
205
|
+
|
|
206
|
+
// Keep the first (best) task, remove the rest
|
|
207
|
+
const keeper = group[0];
|
|
208
|
+
console.log(` ā Keeping: ${keeper.title.substring(0, 60)}...`);
|
|
209
|
+
console.log(` ID: ${keeper.id}, Frame: ${keeper.frame_id}`);
|
|
210
|
+
|
|
211
|
+
for (let i = 1; i < group.length; i++) {
|
|
212
|
+
const dupe = group[i];
|
|
213
|
+
tasksToRemove.add(dupe.id);
|
|
214
|
+
console.log(` ā Removing: ${dupe.id} (${dupe.frame_id})`);
|
|
215
|
+
}
|
|
216
|
+
console.log('');
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
// Also identify Linear-imported tasks that duplicate each other
|
|
220
|
+
const linearIdCounts = new Map<string, TaskEvent[]>();
|
|
221
|
+
for (const task of latestTaskState.values()) {
|
|
222
|
+
const linearId = extractLinearId(task.title);
|
|
223
|
+
if (linearId) {
|
|
224
|
+
const existing = linearIdCounts.get(linearId) || [];
|
|
225
|
+
existing.push(task);
|
|
226
|
+
linearIdCounts.set(linearId, existing);
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
// Find tasks with same Linear ID
|
|
231
|
+
for (const [linearId, tasks] of linearIdCounts) {
|
|
232
|
+
if (tasks.length > 1) {
|
|
233
|
+
// Sort by timestamp (newest first)
|
|
234
|
+
tasks.sort((a, b) => (b.timestamp || 0) - (a.timestamp || 0));
|
|
235
|
+
|
|
236
|
+
console.log(`š Duplicate Linear ID ${linearId}:`);
|
|
237
|
+
console.log(` ā Keeping: ${tasks[0].id}`);
|
|
238
|
+
|
|
239
|
+
for (let i = 1; i < tasks.length; i++) {
|
|
240
|
+
tasksToRemove.add(tasks[i].id);
|
|
241
|
+
console.log(` ā Removing: ${tasks[i].id}`);
|
|
242
|
+
}
|
|
243
|
+
console.log('');
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
// Filter out removed tasks (use dedupedEvents to include exact-dupe removal)
|
|
248
|
+
const cleanedEvents = dedupedEvents.filter((e) => !tasksToRemove.has(e.id));
|
|
249
|
+
|
|
250
|
+
// Write cleaned tasks
|
|
251
|
+
const cleanedContent =
|
|
252
|
+
cleanedEvents.map((e) => JSON.stringify(e)).join('\n') + '\n';
|
|
253
|
+
|
|
254
|
+
// Backup original
|
|
255
|
+
const backupPath = tasksPath + '.backup.' + Date.now();
|
|
256
|
+
writeFileSync(backupPath, readFileSync(tasksPath));
|
|
257
|
+
console.log(`š¾ Backed up original to: ${backupPath}\n`);
|
|
258
|
+
|
|
259
|
+
// Write cleaned file
|
|
260
|
+
writeFileSync(tasksPath, cleanedContent);
|
|
261
|
+
|
|
262
|
+
// Clean up orphaned mappings
|
|
263
|
+
const validTaskIds = new Set(cleanedEvents.map((e) => e.id));
|
|
264
|
+
const cleanedMappings = mappings.filter((m) =>
|
|
265
|
+
validTaskIds.has(m.stackmemoryId)
|
|
266
|
+
);
|
|
267
|
+
|
|
268
|
+
if (cleanedMappings.length < mappings.length) {
|
|
269
|
+
writeFileSync(mappingsPath, JSON.stringify(cleanedMappings, null, 2));
|
|
270
|
+
console.log(
|
|
271
|
+
`šļø Removed ${mappings.length - cleanedMappings.length} orphaned mappings`
|
|
272
|
+
);
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
console.log('\nā
Cleanup complete!');
|
|
276
|
+
console.log(` Original events: ${events.length}`);
|
|
277
|
+
console.log(` After exact dedup: ${dedupedEvents.length}`);
|
|
278
|
+
console.log(` Final cleaned: ${cleanedEvents.length}`);
|
|
279
|
+
console.log(
|
|
280
|
+
` Total removed: ${events.length - cleanedEvents.length} events`
|
|
281
|
+
);
|
|
282
|
+
console.log(` Unique tasks removed: ${tasksToRemove.size}`);
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
// Run cleanup
|
|
286
|
+
cleanupTasks();
|
|
@@ -0,0 +1,387 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Create Linear tasks for uncompleted StackMemory phases
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import fs from 'fs';
|
|
8
|
+
|
|
9
|
+
// Phase tasks to be created in Linear
|
|
10
|
+
const phaseTasks = {
|
|
11
|
+
"Phase 2: Intelligence Layer": [
|
|
12
|
+
{
|
|
13
|
+
title: "STA-301: Implement LLM-Driven Context Retrieval",
|
|
14
|
+
description: `Implement smart context retrieval using LLM analysis as specified in SPEC.md Section 4.1
|
|
15
|
+
|
|
16
|
+
## Acceptance Criteria
|
|
17
|
+
- [ ] Create compressed summary generation for recent sessions
|
|
18
|
+
- [ ] Implement LLM analysis of context queries
|
|
19
|
+
- [ ] Build queryable indices (by error type, timeframe, contributor)
|
|
20
|
+
- [ ] Add visible/auditable reasoning output
|
|
21
|
+
- [ ] Support natural language and structured queries
|
|
22
|
+
- [ ] Target p50 latency: 50ms, p99: 500ms
|
|
23
|
+
|
|
24
|
+
## Technical Details
|
|
25
|
+
- Replace current simple retrieval with LLM-driven analysis
|
|
26
|
+
- Support query language from SPEC.md Section 4.2
|
|
27
|
+
- Generate compressed summaries for LLM input
|
|
28
|
+
- Implement confidence scoring for retrieval results
|
|
29
|
+
|
|
30
|
+
Priority: High
|
|
31
|
+
Estimate: 8 points`,
|
|
32
|
+
priority: 2
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
title: "STA-302: Complete Hybrid Digest Generation (60/40 Split)",
|
|
36
|
+
description: `Finalize the hybrid digest generation system with 60% deterministic, 40% AI-generated content
|
|
37
|
+
|
|
38
|
+
## Current Status
|
|
39
|
+
- ā
EnhancedHybridDigestGenerator implemented
|
|
40
|
+
- ā ļø Needs optimization and production readiness
|
|
41
|
+
|
|
42
|
+
## Acceptance Criteria
|
|
43
|
+
- [ ] Ensure 60% deterministic fields work correctly
|
|
44
|
+
- [ ] Optimize AI summary generation (max 200 tokens)
|
|
45
|
+
- [ ] Add batch processing during idle time
|
|
46
|
+
- [ ] Implement fallback to deterministic-only mode
|
|
47
|
+
- [ ] Add digest quality metrics and validation
|
|
48
|
+
|
|
49
|
+
## Technical Details
|
|
50
|
+
- Review current implementation in enhanced-hybrid-digest.ts
|
|
51
|
+
- Add performance monitoring for digest generation
|
|
52
|
+
- Implement proper error handling and fallbacks
|
|
53
|
+
- Add configuration for digest generation timing
|
|
54
|
+
|
|
55
|
+
Priority: Medium
|
|
56
|
+
Estimate: 5 points`,
|
|
57
|
+
priority: 3
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
title: "STA-303: Implement Smart Trace Detection and Bundling",
|
|
61
|
+
description: `Build intelligent trace detection to bundle related tool calls as specified in SPEC.md Section 4.3
|
|
62
|
+
|
|
63
|
+
## Acceptance Criteria
|
|
64
|
+
- [ ] Detect chains of related tool calls within 30s proximity
|
|
65
|
+
- [ ] Bundle tools targeting same file/directory
|
|
66
|
+
- [ ] Identify causal relationships (error ā fix ā test)
|
|
67
|
+
- [ ] Compress traces with single scoring using max(all_tools)
|
|
68
|
+
- [ ] Add trace boundary detection algorithms
|
|
69
|
+
|
|
70
|
+
## Examples
|
|
71
|
+
- Raw: "Search ā Read(10) ā Edit(3) ā Test ā Fix ā Test"
|
|
72
|
+
- Compressed: "Fixed auth bug via search-driven refactor [0.95]"
|
|
73
|
+
|
|
74
|
+
## Technical Details
|
|
75
|
+
- Implement time proximity detection (30s window)
|
|
76
|
+
- Build causal relationship analysis
|
|
77
|
+
- Create trace compression algorithms
|
|
78
|
+
- Add trace scoring and bundling logic
|
|
79
|
+
|
|
80
|
+
Priority: Medium
|
|
81
|
+
Estimate: 6 points`,
|
|
82
|
+
priority: 3
|
|
83
|
+
},
|
|
84
|
+
{
|
|
85
|
+
title: "STA-304: Implement Configurable Tool Scoring System",
|
|
86
|
+
description: `Build flexible tool scoring system with weight profiles as specified in SPEC.md Section 3
|
|
87
|
+
|
|
88
|
+
## Acceptance Criteria
|
|
89
|
+
- [ ] Implement base tool scores from SPEC (search: 0.95, edit: 0.50, etc.)
|
|
90
|
+
- [ ] Add configurable weight system (base: 0.4, impact: 0.3, etc.)
|
|
91
|
+
- [ ] Create predefined profiles (security_focused, exploration_heavy, production_system)
|
|
92
|
+
- [ ] Support per-project score customization
|
|
93
|
+
- [ ] Add scoring formula with multipliers and bonuses
|
|
94
|
+
|
|
95
|
+
## Technical Details
|
|
96
|
+
- Extend current ToolScoringMiddleware
|
|
97
|
+
- Implement weight profiles in config system
|
|
98
|
+
- Add runtime score calculation with configurable weights
|
|
99
|
+
- Support custom tool score overrides per project
|
|
100
|
+
- Add scoring analytics and metrics
|
|
101
|
+
|
|
102
|
+
Priority: Low
|
|
103
|
+
Estimate: 4 points`,
|
|
104
|
+
priority: 4
|
|
105
|
+
}
|
|
106
|
+
],
|
|
107
|
+
|
|
108
|
+
"Phase 3: Collaboration": [
|
|
109
|
+
{
|
|
110
|
+
title: "STA-305: Implement Dual Stack Architecture (Individual + Shared)",
|
|
111
|
+
description: `Build dual stack system supporting individual and shared team stacks as specified in SPEC.md Section 7.1
|
|
112
|
+
|
|
113
|
+
## Acceptance Criteria
|
|
114
|
+
- [ ] Create individual stacks with private visibility
|
|
115
|
+
- [ ] Create shared team stacks with team visibility
|
|
116
|
+
- [ ] Implement frame promotion from individual to shared
|
|
117
|
+
- [ ] Support fork/merge operations between stacks
|
|
118
|
+
- [ ] Track participants and contributors properly
|
|
119
|
+
- [ ] Add stack interaction patterns (promote, fork, merge)
|
|
120
|
+
|
|
121
|
+
## Technical Details
|
|
122
|
+
- Extend current stack management for multiple stack types
|
|
123
|
+
- Implement visibility and permission controls
|
|
124
|
+
- Add frame promotion and fork/merge logic
|
|
125
|
+
- Create team stack management APIs
|
|
126
|
+
- Build stack interaction workflows
|
|
127
|
+
|
|
128
|
+
Priority: High
|
|
129
|
+
Estimate: 12 points`,
|
|
130
|
+
priority: 2
|
|
131
|
+
},
|
|
132
|
+
{
|
|
133
|
+
title: "STA-306: Build Frame Handoff Mechanism with Ownership Tracking",
|
|
134
|
+
description: `Implement frame handoff system for team collaboration as specified in SPEC.md Section 7.2
|
|
135
|
+
|
|
136
|
+
## Acceptance Criteria
|
|
137
|
+
- [ ] Track frame ownership (creator, contributors, last_active)
|
|
138
|
+
- [ ] Support explicit handoff via command
|
|
139
|
+
- [ ] Handle implicit handoff when someone continues work
|
|
140
|
+
- [ ] Auto-release frames after 24h idle time
|
|
141
|
+
- [ ] Implement frame locking to prevent conflicts
|
|
142
|
+
- [ ] Send notifications on handoff events
|
|
143
|
+
|
|
144
|
+
## Technical Details
|
|
145
|
+
- Extend frame metadata with ownership information
|
|
146
|
+
- Build handoff command interface
|
|
147
|
+
- Implement idle timeout and auto-release
|
|
148
|
+
- Add conflict prevention during active work
|
|
149
|
+
- Create team awareness notifications
|
|
150
|
+
- Add frame subscription system
|
|
151
|
+
|
|
152
|
+
Priority: High
|
|
153
|
+
Estimate: 10 points`,
|
|
154
|
+
priority: 2
|
|
155
|
+
},
|
|
156
|
+
{
|
|
157
|
+
title: "STA-307: Implement Merge Conflict Resolution for Shared Frames",
|
|
158
|
+
description: `Build merge conflict resolution system for collaborative frame editing
|
|
159
|
+
|
|
160
|
+
## Acceptance Criteria
|
|
161
|
+
- [ ] Detect conflicting edits to shared frames
|
|
162
|
+
- [ ] Provide merge conflict resolution UI/CLI
|
|
163
|
+
- [ ] Support manual and automatic conflict resolution
|
|
164
|
+
- [ ] Maintain audit trail of conflict resolutions
|
|
165
|
+
- [ ] Add rollback capabilities for failed merges
|
|
166
|
+
|
|
167
|
+
## Technical Details
|
|
168
|
+
- Implement frame diff and conflict detection
|
|
169
|
+
- Build merge resolution algorithms
|
|
170
|
+
- Create CLI interface for conflict resolution
|
|
171
|
+
- Add automatic resolution for non-conflicting changes
|
|
172
|
+
- Implement merge history and audit logging
|
|
173
|
+
|
|
174
|
+
Priority: Medium
|
|
175
|
+
Estimate: 8 points`,
|
|
176
|
+
priority: 3
|
|
177
|
+
},
|
|
178
|
+
{
|
|
179
|
+
title: "STA-308: Build Team Analytics and Collaboration Metrics",
|
|
180
|
+
description: `Create analytics dashboard for team collaboration insights
|
|
181
|
+
|
|
182
|
+
## Acceptance Criteria
|
|
183
|
+
- [ ] Track frame collaboration patterns
|
|
184
|
+
- [ ] Show handoff frequency and success rates
|
|
185
|
+
- [ ] Display team productivity metrics
|
|
186
|
+
- [ ] Add frame ownership and contribution analytics
|
|
187
|
+
- [ ] Generate team collaboration reports
|
|
188
|
+
|
|
189
|
+
## Technical Details
|
|
190
|
+
- Extend current analytics system for team metrics
|
|
191
|
+
- Add collaboration pattern detection
|
|
192
|
+
- Build team dashboard components
|
|
193
|
+
- Implement collaboration scoring algorithms
|
|
194
|
+
- Create reporting and export capabilities
|
|
195
|
+
|
|
196
|
+
Priority: Low
|
|
197
|
+
Estimate: 6 points`,
|
|
198
|
+
priority: 4
|
|
199
|
+
}
|
|
200
|
+
],
|
|
201
|
+
|
|
202
|
+
"Phase 4: Scale & Enterprise": [
|
|
203
|
+
{
|
|
204
|
+
title: "STA-309: Implement Remote Infinite Storage System",
|
|
205
|
+
description: `Build remote storage system for infinite retention as specified in SPEC.md Section 2.1
|
|
206
|
+
|
|
207
|
+
## Acceptance Criteria
|
|
208
|
+
- [ ] Implement TimeSeries DB + S3 backend storage
|
|
209
|
+
- [ ] Add Redis cache layer for fast retrieval
|
|
210
|
+
- [ ] Build automatic migration from local to remote
|
|
211
|
+
- [ ] Support multiple storage tiers (hot/warm/cold/archive)
|
|
212
|
+
- [ ] Achieve target latencies: p50: 50ms, p99: 500ms
|
|
213
|
+
|
|
214
|
+
## Technical Details
|
|
215
|
+
- Integrate ClickHouse/TimescaleDB for timeseries data
|
|
216
|
+
- Implement S3 storage with lifecycle management
|
|
217
|
+
- Build Redis caching with intelligent prefetching
|
|
218
|
+
- Add background migration workers
|
|
219
|
+
- Create storage tier management system
|
|
220
|
+
|
|
221
|
+
Priority: High
|
|
222
|
+
Estimate: 15 points`,
|
|
223
|
+
priority: 2
|
|
224
|
+
},
|
|
225
|
+
{
|
|
226
|
+
title: "STA-310: Build Incremental Garbage Collection System",
|
|
227
|
+
description: `Implement incremental GC to avoid stop-the-world pauses as specified in SPEC.md Section 5
|
|
228
|
+
|
|
229
|
+
## Current Status
|
|
230
|
+
- ā ļø Phase 4 task mentioned in existing Linear tasks but not implemented
|
|
231
|
+
|
|
232
|
+
## Acceptance Criteria
|
|
233
|
+
- [ ] Process 100 frames per cycle every 60 seconds
|
|
234
|
+
- [ ] Implement generational strategies (young, mature, old)
|
|
235
|
+
- [ ] Protect current session, pinned frames, unsynced changes
|
|
236
|
+
- [ ] Evict low-score and orphaned frames first
|
|
237
|
+
- [ ] Handle frame corruption recovery at any depth
|
|
238
|
+
- [ ] Add integrity checks during idle time
|
|
239
|
+
|
|
240
|
+
## Technical Details
|
|
241
|
+
- Build incremental GC scheduler
|
|
242
|
+
- Implement generational collection strategies
|
|
243
|
+
- Add frame protection mechanisms
|
|
244
|
+
- Create corruption detection and recovery
|
|
245
|
+
- Build idle-time integrity verification
|
|
246
|
+
|
|
247
|
+
Priority: Medium
|
|
248
|
+
Estimate: 10 points`,
|
|
249
|
+
priority: 3
|
|
250
|
+
},
|
|
251
|
+
{
|
|
252
|
+
title: "STA-311: Performance Optimization and SLA Achievement",
|
|
253
|
+
description: `Optimize system performance to meet SPEC.md targets in Section 11
|
|
254
|
+
|
|
255
|
+
## Target SLAs
|
|
256
|
+
- [ ] Retrieval: p50: 50ms, p95: 200ms, p99: 500ms
|
|
257
|
+
- [ ] Storage: 10K events/sec write throughput
|
|
258
|
+
- [ ] Batch upload: 100MB/min
|
|
259
|
+
- [ ] Uptime: 99.9%
|
|
260
|
+
- [ ] Max frames: 10,000 per project
|
|
261
|
+
|
|
262
|
+
## Acceptance Criteria
|
|
263
|
+
- [ ] Profile and optimize hot paths
|
|
264
|
+
- [ ] Implement connection pooling and caching
|
|
265
|
+
- [ ] Add performance monitoring and alerting
|
|
266
|
+
- [ ] Optimize database queries and indexes
|
|
267
|
+
- [ ] Implement horizontal scaling capabilities
|
|
268
|
+
|
|
269
|
+
Priority: Medium
|
|
270
|
+
Estimate: 8 points`,
|
|
271
|
+
priority: 3
|
|
272
|
+
},
|
|
273
|
+
{
|
|
274
|
+
title: "STA-312: Enterprise Security and Privacy Features",
|
|
275
|
+
description: `Implement enterprise-grade security features as specified in SPEC.md Section 10
|
|
276
|
+
|
|
277
|
+
## Acceptance Criteria
|
|
278
|
+
- [ ] Add real-time secret detection with pattern matching
|
|
279
|
+
- [ ] Implement AES-256 encryption at rest
|
|
280
|
+
- [ ] Add TLS 1.3 encryption in transit
|
|
281
|
+
- [ ] Build configurable data residency controls
|
|
282
|
+
- [ ] Add audit trails and compliance reporting
|
|
283
|
+
- [ ] Implement GDPR/CCPA data deletion
|
|
284
|
+
|
|
285
|
+
## Technical Details
|
|
286
|
+
- Integrate secret scanning engines
|
|
287
|
+
- Add encryption key management
|
|
288
|
+
- Build compliance reporting system
|
|
289
|
+
- Implement data residency configuration
|
|
290
|
+
- Create audit logging and retention policies
|
|
291
|
+
|
|
292
|
+
Priority: Low
|
|
293
|
+
Estimate: 12 points`,
|
|
294
|
+
priority: 4
|
|
295
|
+
}
|
|
296
|
+
],
|
|
297
|
+
|
|
298
|
+
"Code Quality & Maintenance": [
|
|
299
|
+
{
|
|
300
|
+
title: "STA-313: Complete All TODO Comments and Code Cleanup",
|
|
301
|
+
description: `Address all TODO comments found in codebase and improve code quality
|
|
302
|
+
|
|
303
|
+
## Found TODOs to Address
|
|
304
|
+
- [ ] MCP Linear handlers: Implement updateLinearIssue, getLinearIssues methods
|
|
305
|
+
- [ ] Context handlers: Implement getRelevantContext method
|
|
306
|
+
- [ ] Task store: Implement due dates functionality
|
|
307
|
+
- [ ] Frame corruption handling improvements
|
|
308
|
+
- [ ] Test coverage for incomplete modules
|
|
309
|
+
|
|
310
|
+
## Acceptance Criteria
|
|
311
|
+
- [ ] Resolve all TODO/FIXME/XXX comments in code
|
|
312
|
+
- [ ] Add comprehensive JSDoc documentation
|
|
313
|
+
- [ ] Improve test coverage to >90%
|
|
314
|
+
- [ ] Add integration tests for all major workflows
|
|
315
|
+
- [ ] Update API documentation
|
|
316
|
+
|
|
317
|
+
Priority: Medium
|
|
318
|
+
Estimate: 6 points`,
|
|
319
|
+
priority: 3
|
|
320
|
+
},
|
|
321
|
+
{
|
|
322
|
+
title: "STA-314: Improve Error Handling and System Resilience",
|
|
323
|
+
description: `Enhance error handling, logging, and system resilience
|
|
324
|
+
|
|
325
|
+
## Acceptance Criteria
|
|
326
|
+
- [ ] Add comprehensive error handling for all async operations
|
|
327
|
+
- [ ] Implement circuit breakers for external service calls
|
|
328
|
+
- [ ] Add proper logging levels and structured logging
|
|
329
|
+
- [ ] Build retry mechanisms with exponential backoff
|
|
330
|
+
- [ ] Add health checks and monitoring endpoints
|
|
331
|
+
|
|
332
|
+
## Technical Details
|
|
333
|
+
- Standardize error handling patterns
|
|
334
|
+
- Add monitoring and alerting for critical failures
|
|
335
|
+
- Implement graceful degradation for service outages
|
|
336
|
+
- Build automated recovery mechanisms
|
|
337
|
+
- Add comprehensive logging and tracing
|
|
338
|
+
|
|
339
|
+
Priority: Medium
|
|
340
|
+
Estimate: 5 points`,
|
|
341
|
+
priority: 3
|
|
342
|
+
}
|
|
343
|
+
]
|
|
344
|
+
};
|
|
345
|
+
|
|
346
|
+
// Generate tasks file
|
|
347
|
+
const output = {
|
|
348
|
+
generated: new Date().toISOString(),
|
|
349
|
+
totalTasks: 0,
|
|
350
|
+
phases: {}
|
|
351
|
+
};
|
|
352
|
+
|
|
353
|
+
for (const [phase, tasks] of Object.entries(phaseTasks)) {
|
|
354
|
+
output.phases[phase] = tasks;
|
|
355
|
+
output.totalTasks += tasks.length;
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
// Write to file
|
|
359
|
+
const filename = `stackmemory-phase-tasks-${new Date().toISOString().split('T')[0]}.json`;
|
|
360
|
+
fs.writeFileSync(filename, JSON.stringify(output, null, 2));
|
|
361
|
+
|
|
362
|
+
console.log(`ā
Generated ${output.totalTasks} phase tasks across ${Object.keys(phaseTasks).length} phases`);
|
|
363
|
+
console.log(`š Saved to: ${filename}`);
|
|
364
|
+
|
|
365
|
+
// Show summary
|
|
366
|
+
console.log('\nš Task Summary by Phase:');
|
|
367
|
+
for (const [phase, tasks] of Object.entries(phaseTasks)) {
|
|
368
|
+
console.log(` ${phase}: ${tasks.length} tasks`);
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
// Show priority breakdown
|
|
372
|
+
const priorityCounts = Object.values(phaseTasks).flat().reduce((acc, task) => {
|
|
373
|
+
const priority = task.priority;
|
|
374
|
+
acc[priority] = (acc[priority] || 0) + 1;
|
|
375
|
+
return acc;
|
|
376
|
+
}, {});
|
|
377
|
+
|
|
378
|
+
console.log('\nšÆ Priority Distribution:');
|
|
379
|
+
console.log(` High Priority (2): ${priorityCounts[2] || 0} tasks`);
|
|
380
|
+
console.log(` Medium Priority (3): ${priorityCounts[3] || 0} tasks`);
|
|
381
|
+
console.log(` Low Priority (4): ${priorityCounts[4] || 0} tasks`);
|
|
382
|
+
|
|
383
|
+
console.log('\nš” Next Steps:');
|
|
384
|
+
console.log(' 1. Wait for Linear rate limits to reset');
|
|
385
|
+
console.log(' 2. Use the task creation commands to add these to Linear:');
|
|
386
|
+
console.log(' node dist/cli/index.js linear:create --api-key <key> --title "..." --description "..." --priority N');
|
|
387
|
+
console.log(' 3. Start with Phase 2 high priority tasks for immediate impact');
|