@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,120 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Trace Module Export
|
|
3
|
+
* Central export for all tracing functionality
|
|
4
|
+
*/
|
|
5
|
+
export { trace, TraceContext, Trace, TraceClass, TraceCritical, } from './debug-trace.js';
|
|
6
|
+
export { wrapCommand, wrapProgram, traceStep, traceQuery, traceAPI, } from './cli-trace-wrapper.js';
|
|
7
|
+
export { createTracedDatabase, wrapDatabase, getQueryStatistics, createTracedTransaction, } from './db-trace-wrapper.js';
|
|
8
|
+
export { TraceLinearAPI, createTracedFetch, wrapGraphQLClient, } from './linear-api-wrapper.js';
|
|
9
|
+
/**
|
|
10
|
+
* Initialize tracing based on environment configuration
|
|
11
|
+
*/
|
|
12
|
+
export function initializeTracing() {
|
|
13
|
+
const config = {
|
|
14
|
+
// Main control
|
|
15
|
+
DEBUG_TRACE: process.env.DEBUG_TRACE === 'true',
|
|
16
|
+
STACKMEMORY_DEBUG: process.env.STACKMEMORY_DEBUG === 'true',
|
|
17
|
+
// Output control
|
|
18
|
+
TRACE_OUTPUT: process.env.TRACE_OUTPUT || 'console', // console|file|both
|
|
19
|
+
TRACE_VERBOSITY: process.env.TRACE_VERBOSITY || 'full', // full|errors|summary
|
|
20
|
+
// Content control
|
|
21
|
+
TRACE_PARAMS: process.env.TRACE_PARAMS !== 'false', // Include parameters
|
|
22
|
+
TRACE_RESULTS: process.env.TRACE_RESULTS !== 'false', // Include results
|
|
23
|
+
TRACE_MASK_SENSITIVE: process.env.TRACE_MASK_SENSITIVE !== 'false', // Mask sensitive data
|
|
24
|
+
// Performance
|
|
25
|
+
TRACE_PERF_THRESHOLD: parseInt(process.env.TRACE_PERF_THRESHOLD || '100'), // ms
|
|
26
|
+
TRACE_MEMORY: process.env.TRACE_MEMORY === 'true', // Track memory usage
|
|
27
|
+
TRACE_MAX_DEPTH: parseInt(process.env.TRACE_MAX_DEPTH || '20'), // Max call depth
|
|
28
|
+
// Database specific
|
|
29
|
+
TRACE_DB: process.env.TRACE_DB === 'true', // Enable database tracing
|
|
30
|
+
TRACE_DB_SLOW: parseInt(process.env.TRACE_DB_SLOW || '100'), // Slow query threshold
|
|
31
|
+
// API specific
|
|
32
|
+
TRACE_API: process.env.TRACE_API === 'true', // Enable API tracing
|
|
33
|
+
TRACE_API_SLOW: parseInt(process.env.TRACE_API_SLOW || '1000'), // Slow API threshold
|
|
34
|
+
};
|
|
35
|
+
// Log configuration if debugging is enabled
|
|
36
|
+
if (config.DEBUG_TRACE || config.STACKMEMORY_DEBUG) {
|
|
37
|
+
console.log('š Trace Configuration:', {
|
|
38
|
+
enabled: true,
|
|
39
|
+
output: config.TRACE_OUTPUT,
|
|
40
|
+
verbosity: config.TRACE_VERBOSITY,
|
|
41
|
+
includeParams: config.TRACE_PARAMS,
|
|
42
|
+
includeResults: config.TRACE_RESULTS,
|
|
43
|
+
maskSensitive: config.TRACE_MASK_SENSITIVE,
|
|
44
|
+
performanceThreshold: config.TRACE_PERF_THRESHOLD,
|
|
45
|
+
captureMemory: config.TRACE_MEMORY,
|
|
46
|
+
maxDepth: config.TRACE_MAX_DEPTH,
|
|
47
|
+
database: {
|
|
48
|
+
enabled: config.TRACE_DB,
|
|
49
|
+
slowThreshold: config.TRACE_DB_SLOW,
|
|
50
|
+
},
|
|
51
|
+
api: {
|
|
52
|
+
enabled: config.TRACE_API,
|
|
53
|
+
slowThreshold: config.TRACE_API_SLOW,
|
|
54
|
+
},
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Helper to enable tracing for a specific scope
|
|
60
|
+
*/
|
|
61
|
+
export function withTracing(fn, options) {
|
|
62
|
+
const originalEnv = process.env.DEBUG_TRACE;
|
|
63
|
+
try {
|
|
64
|
+
// Temporarily enable tracing
|
|
65
|
+
process.env.DEBUG_TRACE = 'true';
|
|
66
|
+
// Apply custom options if provided
|
|
67
|
+
if (options) {
|
|
68
|
+
if (options.output)
|
|
69
|
+
process.env.TRACE_OUTPUT = options.output;
|
|
70
|
+
if (options.verbosity)
|
|
71
|
+
process.env.TRACE_VERBOSITY = options.verbosity;
|
|
72
|
+
if (options.includeParams !== undefined) {
|
|
73
|
+
process.env.TRACE_PARAMS = String(options.includeParams);
|
|
74
|
+
}
|
|
75
|
+
if (options.includeResults !== undefined) {
|
|
76
|
+
process.env.TRACE_RESULTS = String(options.includeResults);
|
|
77
|
+
}
|
|
78
|
+
if (options.performanceThreshold !== undefined) {
|
|
79
|
+
process.env.TRACE_PERF_THRESHOLD = String(options.performanceThreshold);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
return fn();
|
|
83
|
+
}
|
|
84
|
+
finally {
|
|
85
|
+
// Restore original environment
|
|
86
|
+
if (originalEnv === undefined) {
|
|
87
|
+
delete process.env.DEBUG_TRACE;
|
|
88
|
+
}
|
|
89
|
+
else {
|
|
90
|
+
process.env.DEBUG_TRACE = originalEnv;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Quick enable/disable functions for debugging
|
|
96
|
+
*/
|
|
97
|
+
export const enableTracing = () => {
|
|
98
|
+
process.env.DEBUG_TRACE = 'true';
|
|
99
|
+
console.log('ā
Tracing enabled');
|
|
100
|
+
};
|
|
101
|
+
export const disableTracing = () => {
|
|
102
|
+
delete process.env.DEBUG_TRACE;
|
|
103
|
+
console.log('ā Tracing disabled');
|
|
104
|
+
};
|
|
105
|
+
export const enableVerboseTracing = () => {
|
|
106
|
+
process.env.DEBUG_TRACE = 'true';
|
|
107
|
+
process.env.TRACE_VERBOSITY = 'full';
|
|
108
|
+
process.env.TRACE_PARAMS = 'true';
|
|
109
|
+
process.env.TRACE_RESULTS = 'true';
|
|
110
|
+
process.env.TRACE_MEMORY = 'true';
|
|
111
|
+
console.log('ā
Verbose tracing enabled');
|
|
112
|
+
};
|
|
113
|
+
export const enableMinimalTracing = () => {
|
|
114
|
+
process.env.DEBUG_TRACE = 'true';
|
|
115
|
+
process.env.TRACE_VERBOSITY = 'summary';
|
|
116
|
+
process.env.TRACE_PARAMS = 'false';
|
|
117
|
+
process.env.TRACE_RESULTS = 'false';
|
|
118
|
+
process.env.TRACE_MEMORY = 'false';
|
|
119
|
+
console.log('ā
Minimal tracing enabled');
|
|
120
|
+
};
|
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Linear API Trace Wrapper
|
|
3
|
+
* Wraps Linear API client with comprehensive tracing for debugging
|
|
4
|
+
*/
|
|
5
|
+
import { trace } from './debug-trace.js';
|
|
6
|
+
import { logger } from '../monitoring/logger.js';
|
|
7
|
+
/**
|
|
8
|
+
* Decorator to trace Linear API GraphQL calls
|
|
9
|
+
*/
|
|
10
|
+
export function TraceLinearAPI(target, propertyKey, descriptor) {
|
|
11
|
+
const originalMethod = descriptor.value;
|
|
12
|
+
const isAsync = originalMethod.constructor.name === 'AsyncFunction';
|
|
13
|
+
if (isAsync) {
|
|
14
|
+
descriptor.value = async function (...args) {
|
|
15
|
+
const className = target.constructor.name;
|
|
16
|
+
const methodName = `${className}.${propertyKey}`;
|
|
17
|
+
// Extract meaningful context from arguments
|
|
18
|
+
const context = extractAPIContext(propertyKey, args);
|
|
19
|
+
return trace.traceAsync('api', methodName, context, async () => {
|
|
20
|
+
const startTime = Date.now();
|
|
21
|
+
try {
|
|
22
|
+
// Log API call start
|
|
23
|
+
logger.debug(`Linear API Call: ${methodName}`, context);
|
|
24
|
+
const result = await originalMethod.apply(this, args);
|
|
25
|
+
const duration = Date.now() - startTime;
|
|
26
|
+
// Log successful completion with timing
|
|
27
|
+
logger.info(`Linear API Success: ${methodName}`, {
|
|
28
|
+
duration,
|
|
29
|
+
resultType: Array.isArray(result) ? `array[${result.length}]` : typeof result,
|
|
30
|
+
hasData: result != null,
|
|
31
|
+
});
|
|
32
|
+
// Warn about slow API calls
|
|
33
|
+
if (duration > 1000) {
|
|
34
|
+
logger.warn(`Slow Linear API call: ${methodName} took ${duration}ms`, {
|
|
35
|
+
...context,
|
|
36
|
+
duration,
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
return result;
|
|
40
|
+
}
|
|
41
|
+
catch (error) {
|
|
42
|
+
const duration = Date.now() - startTime;
|
|
43
|
+
// Enhanced error logging for API failures
|
|
44
|
+
logger.error(`Linear API Failed: ${methodName}`, error, {
|
|
45
|
+
...context,
|
|
46
|
+
duration,
|
|
47
|
+
errorCode: error.code,
|
|
48
|
+
statusCode: error.statusCode,
|
|
49
|
+
graphQLErrors: error.errors,
|
|
50
|
+
});
|
|
51
|
+
// Add debugging hints based on error type
|
|
52
|
+
if (error.message?.includes('rate limit')) {
|
|
53
|
+
logger.warn('Rate limit hit - consider implementing backoff', {
|
|
54
|
+
method: methodName,
|
|
55
|
+
suggestion: 'Implement exponential backoff or request queuing',
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
else if (error.message?.includes('network')) {
|
|
59
|
+
logger.warn('Network error - check connectivity', {
|
|
60
|
+
method: methodName,
|
|
61
|
+
suggestion: 'Verify API endpoint and network connectivity',
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
else if (error.message?.includes('unauthorized')) {
|
|
65
|
+
logger.warn('Authorization error - check API key', {
|
|
66
|
+
method: methodName,
|
|
67
|
+
suggestion: 'Verify LINEAR_API_KEY is set and valid',
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
throw error;
|
|
71
|
+
}
|
|
72
|
+
});
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
else {
|
|
76
|
+
descriptor.value = function (...args) {
|
|
77
|
+
const className = target.constructor.name;
|
|
78
|
+
const methodName = `${className}.${propertyKey}`;
|
|
79
|
+
const context = extractAPIContext(propertyKey, args);
|
|
80
|
+
return trace.traceSync('api', methodName, context, () => {
|
|
81
|
+
return originalMethod.apply(this, args);
|
|
82
|
+
});
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
return descriptor;
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Extract meaningful context from API method arguments
|
|
89
|
+
*/
|
|
90
|
+
function extractAPIContext(methodName, args) {
|
|
91
|
+
const context = {};
|
|
92
|
+
// Handle different Linear API methods
|
|
93
|
+
if (methodName === 'createIssue' && args[0]) {
|
|
94
|
+
context.title = args[0].title;
|
|
95
|
+
context.teamId = args[0].teamId;
|
|
96
|
+
context.priority = args[0].priority;
|
|
97
|
+
}
|
|
98
|
+
else if (methodName === 'updateIssue' && args[0]) {
|
|
99
|
+
context.issueId = args[0];
|
|
100
|
+
context.updates = Object.keys(args[1] || {});
|
|
101
|
+
}
|
|
102
|
+
else if (methodName === 'getIssue') {
|
|
103
|
+
context.issueId = args[0];
|
|
104
|
+
}
|
|
105
|
+
else if (methodName === 'getIssues' && args[0]) {
|
|
106
|
+
context.filter = args[0];
|
|
107
|
+
}
|
|
108
|
+
else if (methodName === 'graphql') {
|
|
109
|
+
// For raw GraphQL queries
|
|
110
|
+
const query = args[0];
|
|
111
|
+
if (query) {
|
|
112
|
+
// Extract operation name from query
|
|
113
|
+
const match = query.match(/(?:query|mutation)\s+(\w+)/);
|
|
114
|
+
context.operation = match ? match[1] : 'unknown';
|
|
115
|
+
context.queryLength = query.length;
|
|
116
|
+
context.variables = args[1] ? Object.keys(args[1]) : [];
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
return context;
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Wrap fetch with tracing for HTTP-level debugging
|
|
123
|
+
*/
|
|
124
|
+
export function createTracedFetch(baseFetch = fetch) {
|
|
125
|
+
return async function tracedFetch(input, init) {
|
|
126
|
+
const url = typeof input === 'string' ? input : input.toString();
|
|
127
|
+
const method = init?.method || 'GET';
|
|
128
|
+
// Mask sensitive headers
|
|
129
|
+
const headers = init?.headers ? { ...init.headers } : {};
|
|
130
|
+
if (headers.Authorization) {
|
|
131
|
+
headers.Authorization = headers.Authorization.substring(0, 20) + '...[MASKED]';
|
|
132
|
+
}
|
|
133
|
+
const context = {
|
|
134
|
+
method,
|
|
135
|
+
url: url.length > 100 ? url.substring(0, 100) + '...' : url,
|
|
136
|
+
headers: Object.keys(headers),
|
|
137
|
+
bodySize: init?.body ? JSON.stringify(init.body).length : 0,
|
|
138
|
+
};
|
|
139
|
+
return trace.api(method, url, context, async () => {
|
|
140
|
+
const startTime = Date.now();
|
|
141
|
+
try {
|
|
142
|
+
const response = await baseFetch(input, init);
|
|
143
|
+
const duration = Date.now() - startTime;
|
|
144
|
+
// Log response details
|
|
145
|
+
logger.debug(`HTTP ${method} ${response.status}`, {
|
|
146
|
+
url: url.substring(0, 100),
|
|
147
|
+
status: response.status,
|
|
148
|
+
duration,
|
|
149
|
+
headers: {
|
|
150
|
+
'content-type': response.headers.get('content-type'),
|
|
151
|
+
'x-ratelimit-remaining': response.headers.get('x-ratelimit-remaining'),
|
|
152
|
+
'x-ratelimit-reset': response.headers.get('x-ratelimit-reset'),
|
|
153
|
+
},
|
|
154
|
+
});
|
|
155
|
+
// Warn about rate limiting
|
|
156
|
+
const remaining = response.headers.get('x-ratelimit-remaining');
|
|
157
|
+
if (remaining && parseInt(remaining) < 10) {
|
|
158
|
+
logger.warn(`Low rate limit remaining: ${remaining}`, {
|
|
159
|
+
url: url.substring(0, 100),
|
|
160
|
+
resetAt: response.headers.get('x-ratelimit-reset'),
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
// Warn about slow responses
|
|
164
|
+
if (duration > 2000) {
|
|
165
|
+
logger.warn(`Slow HTTP response: ${duration}ms`, {
|
|
166
|
+
method,
|
|
167
|
+
url: url.substring(0, 100),
|
|
168
|
+
status: response.status,
|
|
169
|
+
});
|
|
170
|
+
}
|
|
171
|
+
return response;
|
|
172
|
+
}
|
|
173
|
+
catch (error) {
|
|
174
|
+
const duration = Date.now() - startTime;
|
|
175
|
+
logger.error(`HTTP ${method} failed`, error, {
|
|
176
|
+
url: url.substring(0, 100),
|
|
177
|
+
duration,
|
|
178
|
+
errorType: error.constructor.name,
|
|
179
|
+
errno: error.errno,
|
|
180
|
+
code: error.code,
|
|
181
|
+
});
|
|
182
|
+
throw error;
|
|
183
|
+
}
|
|
184
|
+
});
|
|
185
|
+
};
|
|
186
|
+
}
|
|
187
|
+
/**
|
|
188
|
+
* Create a traced GraphQL client wrapper
|
|
189
|
+
*/
|
|
190
|
+
export function wrapGraphQLClient(client) {
|
|
191
|
+
const prototype = Object.getPrototypeOf(client);
|
|
192
|
+
const propertyNames = Object.getOwnPropertyNames(prototype);
|
|
193
|
+
for (const propertyName of propertyNames) {
|
|
194
|
+
if (propertyName === 'constructor')
|
|
195
|
+
continue;
|
|
196
|
+
const descriptor = Object.getOwnPropertyDescriptor(prototype, propertyName);
|
|
197
|
+
if (!descriptor || typeof descriptor.value !== 'function')
|
|
198
|
+
continue;
|
|
199
|
+
// Apply tracing to all methods
|
|
200
|
+
TraceLinearAPI(prototype, propertyName, descriptor);
|
|
201
|
+
Object.defineProperty(prototype, propertyName, descriptor);
|
|
202
|
+
}
|
|
203
|
+
return client;
|
|
204
|
+
}
|
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Update Linear task status based on actual implementation status
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import 'dotenv/config';
|
|
8
|
+
|
|
9
|
+
const API_KEY = process.env.LINEAR_OAUTH_TOKEN || process.env.LINEAR_API_KEY;
|
|
10
|
+
if (!API_KEY) {
|
|
11
|
+
console.error('ā LINEAR_OAUTH_TOKEN or LINEAR_API_KEY environment variable not set');
|
|
12
|
+
console.log('Please set LINEAR_OAUTH_TOKEN or LINEAR_API_KEY in your .env file or export it in your shell');
|
|
13
|
+
process.exit(1);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
// Tasks that should be marked as DONE based on commits and documentation
|
|
17
|
+
const COMPLETED_TASKS = {
|
|
18
|
+
// Phase 1: Core Runtime - COMPLETE
|
|
19
|
+
'STA-279': 'Implement LLM-Driven Context Retrieval', // Implemented in llm-context-retrieval.ts
|
|
20
|
+
|
|
21
|
+
// Phase 2: Intelligence Layer - COMPLETE
|
|
22
|
+
'STA-280': 'Complete Hybrid Digest Generation (60/40)', // Implemented in hybrid-digest-generator.ts
|
|
23
|
+
'STA-281': 'Implement Smart Trace Detection and Bundling', // Implemented in trace detection
|
|
24
|
+
'STA-282': 'Implement Configurable Tool Scoring System', // Implemented with weight profiles
|
|
25
|
+
|
|
26
|
+
// Phase 3: Collaboration - COMPLETE
|
|
27
|
+
'STA-283': 'Implement Dual Stack Architecture', // Implemented in dual-stack-manager.ts
|
|
28
|
+
'STA-284': 'Build Frame Handoff Mechanism', // Implemented in frame-handoff-manager.ts (v0.3.4)
|
|
29
|
+
'STA-271': '[STA-99] Phase 3: Dual Stack Architecture', // Completed in commit 111e51b
|
|
30
|
+
'STA-275': '[STA-100] Phase 3: Frame Handoff Mechanism', // Completed in commit b21574c
|
|
31
|
+
'STA-285': 'Implement Merge Conflict Resolution', // Implemented in stack-merge-resolver.ts
|
|
32
|
+
'STA-286': 'Build Team Analytics', // Basic analytics implemented
|
|
33
|
+
|
|
34
|
+
// Additional completed features
|
|
35
|
+
'STA-276': '[STA-91] Finalize Session Persistence Design', // Implemented and documented
|
|
36
|
+
'STA-277': '[STA-90] Complete Linear MCP Integration Documentation', // MCP integration complete
|
|
37
|
+
'STA-155': '[STA-89] Complete Context Frame Manager Tests', // Tests completed
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
// Tasks in progress
|
|
41
|
+
const IN_PROGRESS_TASKS = {
|
|
42
|
+
'STA-287': 'Implement Remote Infinite Storage System', // Railway storage partially done
|
|
43
|
+
'STA-288': 'Build Incremental Garbage Collection', // Basic GC implemented, needs enhancement
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
// Tasks to cancel (duplicates or no longer needed)
|
|
47
|
+
const CANCEL_TASKS = {
|
|
48
|
+
'STA-272': 'Engineering x Marketing Team', // Meeting task
|
|
49
|
+
'STA-273': 'Engineering x Operations Team', // Meeting task
|
|
50
|
+
'STA-274': 'Engineering x Success Team', // Meeting task
|
|
51
|
+
'STA-268': 'Task Analytics Dashboard', // Duplicate/outdated
|
|
52
|
+
'STA-264': 'Complete Documentation TODOs', // Low priority cleanup
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
async function getStateId(stateName) {
|
|
56
|
+
const query = `
|
|
57
|
+
query GetStates {
|
|
58
|
+
workflowStates {
|
|
59
|
+
nodes {
|
|
60
|
+
id
|
|
61
|
+
name
|
|
62
|
+
type
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
`;
|
|
67
|
+
|
|
68
|
+
const response = await fetch('https://api.linear.app/graphql', {
|
|
69
|
+
method: 'POST',
|
|
70
|
+
headers: {
|
|
71
|
+
'Authorization': `Bearer ${API_KEY}`,
|
|
72
|
+
'Content-Type': 'application/json'
|
|
73
|
+
},
|
|
74
|
+
body: JSON.stringify({ query })
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
const result = await response.json();
|
|
78
|
+
const state = result.data.workflowStates.nodes.find(s =>
|
|
79
|
+
s.name.toLowerCase() === stateName.toLowerCase() ||
|
|
80
|
+
(stateName === 'Done' && s.type === 'completed') ||
|
|
81
|
+
(stateName === 'In Progress' && s.type === 'started') ||
|
|
82
|
+
(stateName === 'Canceled' && s.type === 'canceled')
|
|
83
|
+
);
|
|
84
|
+
|
|
85
|
+
return state?.id;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
async function updateTaskStatus(taskId, stateId, description = null) {
|
|
89
|
+
const mutation = `
|
|
90
|
+
mutation UpdateIssue($id: String!, $stateId: String!, $description: String) {
|
|
91
|
+
issueUpdate(
|
|
92
|
+
id: $id,
|
|
93
|
+
input: {
|
|
94
|
+
stateId: $stateId
|
|
95
|
+
${description ? ', description: $description' : ''}
|
|
96
|
+
}
|
|
97
|
+
) {
|
|
98
|
+
success
|
|
99
|
+
issue {
|
|
100
|
+
identifier
|
|
101
|
+
title
|
|
102
|
+
state {
|
|
103
|
+
name
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
`;
|
|
109
|
+
|
|
110
|
+
const variables = { id: taskId, stateId };
|
|
111
|
+
if (description) variables.description = description;
|
|
112
|
+
|
|
113
|
+
const response = await fetch('https://api.linear.app/graphql', {
|
|
114
|
+
method: 'POST',
|
|
115
|
+
headers: {
|
|
116
|
+
'Authorization': `Bearer ${API_KEY}`,
|
|
117
|
+
'Content-Type': 'application/json'
|
|
118
|
+
},
|
|
119
|
+
body: JSON.stringify({ query: mutation, variables })
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
return response.json();
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
async function getTaskByIdentifier(identifier) {
|
|
126
|
+
const query = `
|
|
127
|
+
query GetIssue($identifier: String!) {
|
|
128
|
+
issue(id: $identifier) {
|
|
129
|
+
id
|
|
130
|
+
identifier
|
|
131
|
+
title
|
|
132
|
+
state {
|
|
133
|
+
name
|
|
134
|
+
type
|
|
135
|
+
}
|
|
136
|
+
description
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
`;
|
|
140
|
+
|
|
141
|
+
const response = await fetch('https://api.linear.app/graphql', {
|
|
142
|
+
method: 'POST',
|
|
143
|
+
headers: {
|
|
144
|
+
'Authorization': `Bearer ${API_KEY}`,
|
|
145
|
+
'Content-Type': 'application/json'
|
|
146
|
+
},
|
|
147
|
+
body: JSON.stringify({
|
|
148
|
+
query,
|
|
149
|
+
variables: { identifier }
|
|
150
|
+
})
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
const result = await response.json();
|
|
154
|
+
return result.data?.issue;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
async function updateLinearTasks() {
|
|
158
|
+
console.log('š Updating Linear task states based on actual implementation...\n');
|
|
159
|
+
|
|
160
|
+
// Get state IDs
|
|
161
|
+
const doneStateId = await getStateId('Done');
|
|
162
|
+
const inProgressStateId = await getStateId('In Progress');
|
|
163
|
+
const canceledStateId = await getStateId('Canceled');
|
|
164
|
+
|
|
165
|
+
if (!doneStateId || !inProgressStateId) {
|
|
166
|
+
console.error('ā Could not find required workflow states');
|
|
167
|
+
return;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
let updated = 0;
|
|
171
|
+
let failed = 0;
|
|
172
|
+
|
|
173
|
+
// Update completed tasks
|
|
174
|
+
console.log('ā
Marking completed tasks as Done:\n');
|
|
175
|
+
for (const [identifier, title] of Object.entries(COMPLETED_TASKS)) {
|
|
176
|
+
const task = await getTaskByIdentifier(identifier);
|
|
177
|
+
if (!task) {
|
|
178
|
+
console.log(` ā ļø ${identifier} not found`);
|
|
179
|
+
continue;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
if (task.state.type === 'completed') {
|
|
183
|
+
console.log(` ā ${identifier} already Done`);
|
|
184
|
+
continue;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
const result = await updateTaskStatus(task.id, doneStateId);
|
|
188
|
+
if (result.data?.issueUpdate?.success) {
|
|
189
|
+
console.log(` ā
${identifier}: ${title.substring(0, 40)}... ā Done`);
|
|
190
|
+
updated++;
|
|
191
|
+
} else {
|
|
192
|
+
console.log(` ā ${identifier}: Failed to update`);
|
|
193
|
+
failed++;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
// Small delay to avoid rate limits
|
|
197
|
+
await new Promise(r => setTimeout(r, 500));
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
// Update in-progress tasks
|
|
201
|
+
console.log('\nš Marking in-progress tasks:\n');
|
|
202
|
+
for (const [identifier, title] of Object.entries(IN_PROGRESS_TASKS)) {
|
|
203
|
+
const task = await getTaskByIdentifier(identifier);
|
|
204
|
+
if (!task) {
|
|
205
|
+
console.log(` ā ļø ${identifier} not found`);
|
|
206
|
+
continue;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
if (task.state.type === 'started') {
|
|
210
|
+
console.log(` ā ${identifier} already In Progress`);
|
|
211
|
+
continue;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
const result = await updateTaskStatus(task.id, inProgressStateId);
|
|
215
|
+
if (result.data?.issueUpdate?.success) {
|
|
216
|
+
console.log(` š ${identifier}: ${title.substring(0, 40)}... ā In Progress`);
|
|
217
|
+
updated++;
|
|
218
|
+
} else {
|
|
219
|
+
console.log(` ā ${identifier}: Failed to update`);
|
|
220
|
+
failed++;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
await new Promise(r => setTimeout(r, 500));
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
// Cancel obsolete tasks
|
|
227
|
+
if (canceledStateId) {
|
|
228
|
+
console.log('\nā Canceling obsolete tasks:\n');
|
|
229
|
+
for (const [identifier, title] of Object.entries(CANCEL_TASKS)) {
|
|
230
|
+
const task = await getTaskByIdentifier(identifier);
|
|
231
|
+
if (!task) {
|
|
232
|
+
console.log(` ā ļø ${identifier} not found`);
|
|
233
|
+
continue;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
if (task.state.type === 'canceled') {
|
|
237
|
+
console.log(` ā ${identifier} already Canceled`);
|
|
238
|
+
continue;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
const result = await updateTaskStatus(task.id, canceledStateId);
|
|
242
|
+
if (result.data?.issueUpdate?.success) {
|
|
243
|
+
console.log(` ā ${identifier}: ${title.substring(0, 40)}... ā Canceled`);
|
|
244
|
+
updated++;
|
|
245
|
+
} else {
|
|
246
|
+
console.log(` ā ${identifier}: Failed to update`);
|
|
247
|
+
failed++;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
await new Promise(r => setTimeout(r, 500));
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
// Summary
|
|
255
|
+
console.log('\n' + '='.repeat(60));
|
|
256
|
+
console.log('š UPDATE SUMMARY');
|
|
257
|
+
console.log('='.repeat(60));
|
|
258
|
+
console.log(`ā
Successfully updated: ${updated} tasks`);
|
|
259
|
+
console.log(`ā Failed: ${failed} tasks`);
|
|
260
|
+
console.log('\nLinear backlog now reflects actual implementation status.');
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
// Run if called directly
|
|
264
|
+
if (import.meta.url === `file://${process.argv[1]}`) {
|
|
265
|
+
updateLinearTasks().catch(console.error);
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
export { updateLinearTasks };
|