gitmem-mcp 1.0.3 → 1.0.5
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/CHANGELOG.md +14 -14
- package/dist/commands/check.d.ts +1 -1
- package/dist/commands/check.js +4 -3
- package/dist/diagnostics/anonymizer.d.ts +1 -1
- package/dist/diagnostics/anonymizer.js +1 -1
- package/dist/diagnostics/channels.d.ts +1 -1
- package/dist/diagnostics/channels.js +1 -1
- package/dist/diagnostics/collector.d.ts +1 -1
- package/dist/diagnostics/collector.js +1 -1
- package/dist/diagnostics/index.d.ts +1 -1
- package/dist/diagnostics/index.js +1 -1
- package/dist/hooks/quick-retrieve.js +2 -1
- package/dist/index.js +0 -0
- package/dist/schemas/active-sessions.d.ts +9 -9
- package/dist/schemas/active-sessions.js +1 -1
- package/dist/schemas/common.d.ts +2 -5
- package/dist/schemas/common.js +13 -7
- package/dist/schemas/create-learning.js +1 -1
- package/dist/schemas/session-close.d.ts +5 -8
- package/dist/schemas/session-close.js +7 -3
- package/dist/schemas/session-start.d.ts +4 -4
- package/dist/schemas/session-start.js +1 -1
- package/dist/schemas/thread.d.ts +1 -1
- package/dist/schemas/thread.js +1 -1
- package/dist/server.d.ts +2 -2
- package/dist/server.js +21 -10
- package/dist/services/active-sessions.js +3 -2
- package/dist/services/agent-briefing.d.ts +1 -1
- package/dist/services/agent-briefing.js +1 -1
- package/dist/services/agent-detection.d.ts +1 -0
- package/dist/services/agent-detection.js +21 -12
- package/dist/services/analytics.d.ts +1 -1
- package/dist/services/analytics.js +3 -3
- package/dist/services/behavioral-decay.js +2 -2
- package/dist/services/cache.d.ts +1 -1
- package/dist/services/cache.js +1 -1
- package/dist/services/compliance-validator.d.ts +1 -1
- package/dist/services/compliance-validator.js +5 -5
- package/dist/services/config.d.ts +1 -1
- package/dist/services/config.js +1 -1
- package/dist/services/file-lock.js +12 -0
- package/dist/services/gitmem-dir.d.ts +17 -4
- package/dist/services/gitmem-dir.js +43 -9
- package/dist/services/local-file-storage.d.ts +1 -1
- package/dist/services/local-file-storage.js +4 -3
- package/dist/services/local-vector-search.d.ts +1 -1
- package/dist/services/local-vector-search.js +2 -2
- package/dist/services/metrics.d.ts +6 -6
- package/dist/services/metrics.js +8 -8
- package/dist/services/session-state.d.ts +7 -7
- package/dist/services/session-state.js +19 -7
- package/dist/services/startup.d.ts +1 -1
- package/dist/services/startup.js +3 -2
- package/dist/services/supabase-client.d.ts +17 -6
- package/dist/services/supabase-client.js +44 -8
- package/dist/services/thread-manager.d.ts +1 -1
- package/dist/services/thread-manager.js +5 -5
- package/dist/services/thread-supabase.d.ts +1 -1
- package/dist/services/thread-supabase.js +2 -2
- package/dist/services/transcript-chunker.d.ts +1 -1
- package/dist/services/transcript-chunker.js +1 -1
- package/dist/services/variant-assignment.d.ts +6 -6
- package/dist/services/variant-assignment.js +9 -8
- package/dist/tools/analyze.d.ts +2 -2
- package/dist/tools/analyze.js +2 -2
- package/dist/tools/archive-learning.js +36 -22
- package/dist/tools/confirm-scars.js +1 -1
- package/dist/tools/create-decision.d.ts +1 -1
- package/dist/tools/create-decision.js +2 -2
- package/dist/tools/create-learning.d.ts +1 -1
- package/dist/tools/create-learning.js +4 -4
- package/dist/tools/create-linear-issue.d.ts +18 -0
- package/dist/tools/create-linear-issue.js +197 -0
- package/dist/tools/create-thread.d.ts +1 -1
- package/dist/tools/create-thread.js +2 -2
- package/dist/tools/definitions.js +50 -48
- package/dist/tools/get-transcript.d.ts +1 -1
- package/dist/tools/get-transcript.js +1 -1
- package/dist/tools/graph-traverse.d.ts +1 -1
- package/dist/tools/graph-traverse.js +18 -16
- package/dist/tools/list-threads.d.ts +2 -2
- package/dist/tools/list-threads.js +4 -4
- package/dist/tools/log.d.ts +1 -1
- package/dist/tools/log.js +1 -1
- package/dist/tools/prepare-context.d.ts +1 -1
- package/dist/tools/prepare-context.js +1 -1
- package/dist/tools/recall.d.ts +4 -4
- package/dist/tools/recall.js +25 -25
- package/dist/tools/record-scar-usage-batch.js +2 -2
- package/dist/tools/record-scar-usage.d.ts +1 -1
- package/dist/tools/record-scar-usage.js +3 -3
- package/dist/tools/resolve-thread.d.ts +2 -2
- package/dist/tools/resolve-thread.js +3 -3
- package/dist/tools/save-transcript.d.ts +1 -1
- package/dist/tools/save-transcript.js +1 -1
- package/dist/tools/search.d.ts +1 -1
- package/dist/tools/search.js +1 -1
- package/dist/tools/session-close.d.ts +1 -1
- package/dist/tools/session-close.js +31 -31
- package/dist/tools/session-start.d.ts +5 -5
- package/dist/tools/session-start.js +63 -61
- package/dist/types/index.d.ts +13 -13
- package/hooks/.claude-plugin/plugin.json +1 -1
- package/hooks/scripts/post-tool-use.sh +1 -1
- package/hooks/scripts/recall-check.sh +1 -1
- package/hooks/scripts/session-close-check.sh +1 -1
- package/hooks/scripts/session-start.sh +1 -1
- package/package.json +6 -3
- package/dist/commands/check.d.ts.map +0 -1
- package/dist/commands/check.js.map +0 -1
- package/dist/constants/closing-questions.d.ts.map +0 -1
- package/dist/constants/closing-questions.js.map +0 -1
- package/dist/diagnostics/anonymizer.d.ts.map +0 -1
- package/dist/diagnostics/anonymizer.js.map +0 -1
- package/dist/diagnostics/channels.d.ts.map +0 -1
- package/dist/diagnostics/channels.js.map +0 -1
- package/dist/diagnostics/collector.d.ts.map +0 -1
- package/dist/diagnostics/collector.js.map +0 -1
- package/dist/diagnostics/index.d.ts.map +0 -1
- package/dist/diagnostics/index.js.map +0 -1
- package/dist/hooks/format-utils.d.ts.map +0 -1
- package/dist/hooks/format-utils.js.map +0 -1
- package/dist/hooks/quick-retrieve.d.ts.map +0 -1
- package/dist/hooks/quick-retrieve.js.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/schemas/absorb-observations.d.ts.map +0 -1
- package/dist/schemas/absorb-observations.js.map +0 -1
- package/dist/schemas/active-sessions.d.ts.map +0 -1
- package/dist/schemas/active-sessions.js.map +0 -1
- package/dist/schemas/analyze.d.ts.map +0 -1
- package/dist/schemas/analyze.js.map +0 -1
- package/dist/schemas/common.d.ts.map +0 -1
- package/dist/schemas/common.js.map +0 -1
- package/dist/schemas/create-decision.d.ts.map +0 -1
- package/dist/schemas/create-decision.js.map +0 -1
- package/dist/schemas/create-learning.d.ts.map +0 -1
- package/dist/schemas/create-learning.js.map +0 -1
- package/dist/schemas/get-transcript.d.ts.map +0 -1
- package/dist/schemas/get-transcript.js.map +0 -1
- package/dist/schemas/index.d.ts.map +0 -1
- package/dist/schemas/index.js.map +0 -1
- package/dist/schemas/log.d.ts.map +0 -1
- package/dist/schemas/log.js.map +0 -1
- package/dist/schemas/prepare-context.d.ts.map +0 -1
- package/dist/schemas/prepare-context.js.map +0 -1
- package/dist/schemas/recall.d.ts.map +0 -1
- package/dist/schemas/recall.js.map +0 -1
- package/dist/schemas/record-scar-usage-batch.d.ts.map +0 -1
- package/dist/schemas/record-scar-usage-batch.js.map +0 -1
- package/dist/schemas/record-scar-usage.d.ts.map +0 -1
- package/dist/schemas/record-scar-usage.js.map +0 -1
- package/dist/schemas/registry.d.ts.map +0 -1
- package/dist/schemas/registry.js.map +0 -1
- package/dist/schemas/save-transcript.d.ts.map +0 -1
- package/dist/schemas/save-transcript.js.map +0 -1
- package/dist/schemas/search-transcripts.d.ts.map +0 -1
- package/dist/schemas/search-transcripts.js.map +0 -1
- package/dist/schemas/search.d.ts.map +0 -1
- package/dist/schemas/search.js.map +0 -1
- package/dist/schemas/session-close.d.ts.map +0 -1
- package/dist/schemas/session-close.js.map +0 -1
- package/dist/schemas/session-start.d.ts.map +0 -1
- package/dist/schemas/session-start.js.map +0 -1
- package/dist/schemas/thread.d.ts.map +0 -1
- package/dist/schemas/thread.js.map +0 -1
- package/dist/server.d.ts.map +0 -1
- package/dist/server.js.map +0 -1
- package/dist/services/active-sessions.d.ts.map +0 -1
- package/dist/services/active-sessions.js.map +0 -1
- package/dist/services/agent-briefing.d.ts.map +0 -1
- package/dist/services/agent-briefing.js.map +0 -1
- package/dist/services/agent-detection.d.ts.map +0 -1
- package/dist/services/agent-detection.js.map +0 -1
- package/dist/services/analytics.d.ts.map +0 -1
- package/dist/services/analytics.js.map +0 -1
- package/dist/services/behavioral-decay.d.ts.map +0 -1
- package/dist/services/behavioral-decay.js.map +0 -1
- package/dist/services/bm25.d.ts.map +0 -1
- package/dist/services/bm25.js.map +0 -1
- package/dist/services/cache.d.ts.map +0 -1
- package/dist/services/cache.js.map +0 -1
- package/dist/services/cache.test.d.ts +0 -8
- package/dist/services/cache.test.d.ts.map +0 -1
- package/dist/services/cache.test.js +0 -267
- package/dist/services/cache.test.js.map +0 -1
- package/dist/services/compliance-validator.d.ts.map +0 -1
- package/dist/services/compliance-validator.js.map +0 -1
- package/dist/services/config.d.ts.map +0 -1
- package/dist/services/config.js.map +0 -1
- package/dist/services/display-protocol.d.ts.map +0 -1
- package/dist/services/display-protocol.js.map +0 -1
- package/dist/services/effect-tracker.d.ts.map +0 -1
- package/dist/services/effect-tracker.js.map +0 -1
- package/dist/services/embedding.d.ts.map +0 -1
- package/dist/services/embedding.js.map +0 -1
- package/dist/services/file-lock.d.ts.map +0 -1
- package/dist/services/file-lock.js.map +0 -1
- package/dist/services/gitmem-dir.d.ts.map +0 -1
- package/dist/services/gitmem-dir.js.map +0 -1
- package/dist/services/local-file-storage.d.ts.map +0 -1
- package/dist/services/local-file-storage.js.map +0 -1
- package/dist/services/local-vector-search.d.ts.map +0 -1
- package/dist/services/local-vector-search.js.map +0 -1
- package/dist/services/metrics.d.ts.map +0 -1
- package/dist/services/metrics.js.map +0 -1
- package/dist/services/session-state.d.ts.map +0 -1
- package/dist/services/session-state.js.map +0 -1
- package/dist/services/startup.d.ts.map +0 -1
- package/dist/services/startup.js.map +0 -1
- package/dist/services/storage.d.ts.map +0 -1
- package/dist/services/storage.js.map +0 -1
- package/dist/services/supabase-client.d.ts.map +0 -1
- package/dist/services/supabase-client.js.map +0 -1
- package/dist/services/thread-dedup.d.ts.map +0 -1
- package/dist/services/thread-dedup.js.map +0 -1
- package/dist/services/thread-manager.d.ts.map +0 -1
- package/dist/services/thread-manager.js.map +0 -1
- package/dist/services/thread-suggestions.d.ts.map +0 -1
- package/dist/services/thread-suggestions.js.map +0 -1
- package/dist/services/thread-supabase.d.ts.map +0 -1
- package/dist/services/thread-supabase.js.map +0 -1
- package/dist/services/thread-vitality.d.ts.map +0 -1
- package/dist/services/thread-vitality.js.map +0 -1
- package/dist/services/tier.d.ts.map +0 -1
- package/dist/services/tier.js.map +0 -1
- package/dist/services/timezone.d.ts.map +0 -1
- package/dist/services/timezone.js.map +0 -1
- package/dist/services/transcript-chunker.d.ts.map +0 -1
- package/dist/services/transcript-chunker.js.map +0 -1
- package/dist/services/triple-writer.d.ts.map +0 -1
- package/dist/services/triple-writer.js.map +0 -1
- package/dist/services/variant-assignment.d.ts.map +0 -1
- package/dist/services/variant-assignment.js.map +0 -1
- package/dist/services/variant-generation.d.ts.map +0 -1
- package/dist/services/variant-generation.js.map +0 -1
- package/dist/tools/absorb-observations.d.ts.map +0 -1
- package/dist/tools/absorb-observations.js.map +0 -1
- package/dist/tools/analyze.d.ts.map +0 -1
- package/dist/tools/analyze.js.map +0 -1
- package/dist/tools/archive-learning.d.ts.map +0 -1
- package/dist/tools/archive-learning.js.map +0 -1
- package/dist/tools/cleanup-threads.d.ts.map +0 -1
- package/dist/tools/cleanup-threads.js.map +0 -1
- package/dist/tools/confirm-scars.d.ts.map +0 -1
- package/dist/tools/confirm-scars.js.map +0 -1
- package/dist/tools/create-decision.d.ts.map +0 -1
- package/dist/tools/create-decision.js.map +0 -1
- package/dist/tools/create-learning.d.ts.map +0 -1
- package/dist/tools/create-learning.js.map +0 -1
- package/dist/tools/create-thread.d.ts.map +0 -1
- package/dist/tools/create-thread.js.map +0 -1
- package/dist/tools/definitions.d.ts.map +0 -1
- package/dist/tools/definitions.js.map +0 -1
- package/dist/tools/dismiss-suggestion.d.ts.map +0 -1
- package/dist/tools/dismiss-suggestion.js.map +0 -1
- package/dist/tools/get-transcript.d.ts.map +0 -1
- package/dist/tools/get-transcript.js.map +0 -1
- package/dist/tools/graph-traverse.d.ts.map +0 -1
- package/dist/tools/graph-traverse.js.map +0 -1
- package/dist/tools/list-threads.d.ts.map +0 -1
- package/dist/tools/list-threads.js.map +0 -1
- package/dist/tools/log.d.ts.map +0 -1
- package/dist/tools/log.js.map +0 -1
- package/dist/tools/prepare-context.d.ts.map +0 -1
- package/dist/tools/prepare-context.js.map +0 -1
- package/dist/tools/promote-suggestion.d.ts.map +0 -1
- package/dist/tools/promote-suggestion.js.map +0 -1
- package/dist/tools/recall.d.ts.map +0 -1
- package/dist/tools/recall.js.map +0 -1
- package/dist/tools/recall.test.d.ts +0 -5
- package/dist/tools/recall.test.d.ts.map +0 -1
- package/dist/tools/recall.test.js +0 -155
- package/dist/tools/recall.test.js.map +0 -1
- package/dist/tools/record-scar-usage-batch.d.ts.map +0 -1
- package/dist/tools/record-scar-usage-batch.js.map +0 -1
- package/dist/tools/record-scar-usage.d.ts.map +0 -1
- package/dist/tools/record-scar-usage.js.map +0 -1
- package/dist/tools/resolve-thread.d.ts.map +0 -1
- package/dist/tools/resolve-thread.js.map +0 -1
- package/dist/tools/save-transcript.d.ts.map +0 -1
- package/dist/tools/save-transcript.js.map +0 -1
- package/dist/tools/search-transcripts.d.ts.map +0 -1
- package/dist/tools/search-transcripts.js.map +0 -1
- package/dist/tools/search.d.ts.map +0 -1
- package/dist/tools/search.js.map +0 -1
- package/dist/tools/session-close.d.ts.map +0 -1
- package/dist/tools/session-close.js.map +0 -1
- package/dist/tools/session-start.d.ts.map +0 -1
- package/dist/tools/session-start.js.map +0 -1
- package/dist/types/index.d.ts.map +0 -1
- package/dist/types/index.js.map +0 -1
- package/hooks/tests/test-hooks.sh +0 -577
package/dist/services/startup.js
CHANGED
|
@@ -10,11 +10,12 @@
|
|
|
10
10
|
* - 500-employees-at-8AM (no Supabase contention during session_start)
|
|
11
11
|
* - Cross-container consistency (same data = same results)
|
|
12
12
|
*
|
|
13
|
-
*
|
|
13
|
+
*
|
|
14
14
|
*/
|
|
15
15
|
import * as fs from "fs";
|
|
16
16
|
import * as path from "path";
|
|
17
17
|
import { isConfigured, loadScarsWithEmbeddings } from "./supabase-client.js";
|
|
18
|
+
import { getGitmemDir } from "./gitmem-dir.js";
|
|
18
19
|
import { initializeLocalSearch, reinitializeLocalSearch, isLocalSearchReady, getLocalVectorSearch, getCacheMetadata, setCacheTtl, } from "./local-vector-search.js";
|
|
19
20
|
import { getConfig, shouldUseLocalSearch } from "./config.js";
|
|
20
21
|
// Track startup state — unified cache, no per-project partitioning
|
|
@@ -32,7 +33,7 @@ let backgroundRefreshInterval = null;
|
|
|
32
33
|
*/
|
|
33
34
|
function persistScarsForHooks(scars) {
|
|
34
35
|
try {
|
|
35
|
-
const gitmemDir = path.join(
|
|
36
|
+
const gitmemDir = path.join(getGitmemDir(), "cache");
|
|
36
37
|
if (!fs.existsSync(gitmemDir)) {
|
|
37
38
|
fs.mkdirSync(gitmemDir, { recursive: true });
|
|
38
39
|
}
|
|
@@ -5,9 +5,20 @@
|
|
|
5
5
|
* agents/coda/src/services/supabase-mcp.js
|
|
6
6
|
*
|
|
7
7
|
* Uses JSON-RPC 2.0 protocol over HTTPS.
|
|
8
|
-
* Integrates with CacheService for performance
|
|
8
|
+
* Integrates with CacheService for performance.
|
|
9
9
|
*/
|
|
10
10
|
import type { Project, SupabaseListOptions, SupabaseSearchOptions } from "../types/index.js";
|
|
11
|
+
/**
|
|
12
|
+
* Build a safe PostgREST `in.(...)` filter from an array of UUIDs.
|
|
13
|
+
* Rejects any non-UUID values to prevent filter injection via comma-splitting.
|
|
14
|
+
*/
|
|
15
|
+
export declare function safeInFilter(ids: string[]): string;
|
|
16
|
+
/**
|
|
17
|
+
* Escape PostgREST special characters in a value used within filter expressions.
|
|
18
|
+
* Prevents injection via characters that have structural meaning in PostgREST syntax:
|
|
19
|
+
* parentheses (group operators), commas (value separators), dots (operator delimiters).
|
|
20
|
+
*/
|
|
21
|
+
export declare function escapePostgRESTValue(value: string): string;
|
|
11
22
|
/**
|
|
12
23
|
* Check if Supabase is configured
|
|
13
24
|
*/
|
|
@@ -54,7 +65,7 @@ export declare function directQueryAll<T = unknown>(table: string, options?: {
|
|
|
54
65
|
order?: string;
|
|
55
66
|
}, pageSize?: number, maxRows?: number): Promise<T[]>;
|
|
56
67
|
/**
|
|
57
|
-
* Knowledge triple from knowledge_triples table
|
|
68
|
+
* Knowledge triple from knowledge_triples table
|
|
58
69
|
*/
|
|
59
70
|
export interface KnowledgeTriple {
|
|
60
71
|
subject: string;
|
|
@@ -67,7 +78,7 @@ export interface KnowledgeTriple {
|
|
|
67
78
|
source_id: string;
|
|
68
79
|
}
|
|
69
80
|
/**
|
|
70
|
-
* Fetch related knowledge triples for a set of scar IDs
|
|
81
|
+
* Fetch related knowledge triples for a set of scar IDs
|
|
71
82
|
*
|
|
72
83
|
* Queries knowledge_triples table where source_id matches any of the provided scar IDs.
|
|
73
84
|
* Returns triples grouped by source_id for easy attachment to scars.
|
|
@@ -99,7 +110,7 @@ export declare function directPatch<T = unknown>(table: string, filters: Record<
|
|
|
99
110
|
* This bypasses ww-mcp because we need the embedding vectors for local search.
|
|
100
111
|
* Returns learnings (scars, patterns, wins, anti-patterns) with full embedding data.
|
|
101
112
|
*
|
|
102
|
-
* NOTE: Changed from "scars only" to "all learning types"
|
|
113
|
+
* NOTE: Changed from "scars only" to "all learning types"
|
|
103
114
|
*/
|
|
104
115
|
export declare function loadScarsWithEmbeddings<T = unknown>(project?: string, limit?: number): Promise<T[]>;
|
|
105
116
|
/**
|
|
@@ -107,7 +118,7 @@ export declare function loadScarsWithEmbeddings<T = unknown>(project?: string, l
|
|
|
107
118
|
*/
|
|
108
119
|
export declare function scarSearch<T = unknown>(query: string, matchCount?: number, project?: Project): Promise<T[]>;
|
|
109
120
|
/**
|
|
110
|
-
* Scar search with caching
|
|
121
|
+
* Scar search with caching
|
|
111
122
|
*
|
|
112
123
|
* Returns cached results if available, otherwise fetches and caches.
|
|
113
124
|
*/
|
|
@@ -117,7 +128,7 @@ export declare function cachedScarSearch<T = unknown>(query: string, matchCount?
|
|
|
117
128
|
cache_age_ms?: number;
|
|
118
129
|
}>;
|
|
119
130
|
/**
|
|
120
|
-
* List records with caching for decisions
|
|
131
|
+
* List records with caching for decisions
|
|
121
132
|
*/
|
|
122
133
|
export declare function cachedListDecisions<T = unknown>(project?: Project, limit?: number): Promise<{
|
|
123
134
|
data: T[];
|
|
@@ -5,9 +5,45 @@
|
|
|
5
5
|
* agents/coda/src/services/supabase-mcp.js
|
|
6
6
|
*
|
|
7
7
|
* Uses JSON-RPC 2.0 protocol over HTTPS.
|
|
8
|
-
* Integrates with CacheService for performance
|
|
8
|
+
* Integrates with CacheService for performance.
|
|
9
9
|
*/
|
|
10
10
|
import { getCache } from "./cache.js";
|
|
11
|
+
// --- PostgREST Input Sanitization ---
|
|
12
|
+
const UUID_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
13
|
+
/**
|
|
14
|
+
* Validate that a value is a UUID. Used to prevent injection in `in.(...)` filters
|
|
15
|
+
* where array elements are joined with commas.
|
|
16
|
+
*/
|
|
17
|
+
function isValidUUID(value) {
|
|
18
|
+
return UUID_PATTERN.test(value);
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Build a safe PostgREST `in.(...)` filter from an array of UUIDs.
|
|
22
|
+
* Rejects any non-UUID values to prevent filter injection via comma-splitting.
|
|
23
|
+
*/
|
|
24
|
+
export function safeInFilter(ids) {
|
|
25
|
+
const valid = ids.filter(id => isValidUUID(id));
|
|
26
|
+
if (valid.length !== ids.length) {
|
|
27
|
+
console.warn(`[supabase-client] safeInFilter rejected ${ids.length - valid.length} non-UUID values`);
|
|
28
|
+
}
|
|
29
|
+
if (valid.length === 0)
|
|
30
|
+
return "in.()";
|
|
31
|
+
return `in.(${valid.join(",")})`;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Escape PostgREST special characters in a value used within filter expressions.
|
|
35
|
+
* Prevents injection via characters that have structural meaning in PostgREST syntax:
|
|
36
|
+
* parentheses (group operators), commas (value separators), dots (operator delimiters).
|
|
37
|
+
*/
|
|
38
|
+
export function escapePostgRESTValue(value) {
|
|
39
|
+
// Reject null bytes
|
|
40
|
+
if (value.includes("\0")) {
|
|
41
|
+
throw new Error("PostgREST value must not contain null bytes");
|
|
42
|
+
}
|
|
43
|
+
// For ilike patterns, escape structural PostgREST chars that could break OR groups
|
|
44
|
+
// PostgREST uses ( ) , as structural delimiters in or=() expressions
|
|
45
|
+
return value.replace(/[(),]/g, "");
|
|
46
|
+
}
|
|
11
47
|
// Configuration from environment
|
|
12
48
|
const SUPABASE_URL = process.env.SUPABASE_URL || "";
|
|
13
49
|
const SUPABASE_KEY = process.env.SUPABASE_SERVICE_ROLE_KEY || process.env.SUPABASE_KEY || "";
|
|
@@ -228,7 +264,7 @@ export async function directQueryAll(table, options = {}, pageSize = 1000, maxRo
|
|
|
228
264
|
return allRows;
|
|
229
265
|
}
|
|
230
266
|
/**
|
|
231
|
-
* Fetch related knowledge triples for a set of scar IDs
|
|
267
|
+
* Fetch related knowledge triples for a set of scar IDs
|
|
232
268
|
*
|
|
233
269
|
* Queries knowledge_triples table where source_id matches any of the provided scar IDs.
|
|
234
270
|
* Returns triples grouped by source_id for easy attachment to scars.
|
|
@@ -242,7 +278,7 @@ export async function fetchRelatedTriples(scarIds) {
|
|
|
242
278
|
const triples = await directQuery("knowledge_triples", {
|
|
243
279
|
select: "subject,predicate,object,event_time,decay_weight,half_life_days,decay_floor,source_id",
|
|
244
280
|
filters: {
|
|
245
|
-
source_id:
|
|
281
|
+
source_id: safeInFilter(scarIds),
|
|
246
282
|
},
|
|
247
283
|
});
|
|
248
284
|
for (const triple of triples) {
|
|
@@ -283,7 +319,7 @@ export async function directUpsert(table, data) {
|
|
|
283
319
|
throw new Error(`Supabase upsert error: ${response.status} - ${text.slice(0, 200)}`);
|
|
284
320
|
}
|
|
285
321
|
const result = await response.json();
|
|
286
|
-
//
|
|
322
|
+
// Validate that write actually happened
|
|
287
323
|
// Supabase can return 200 OK with empty array [] when:
|
|
288
324
|
// - RLS policy blocks the write
|
|
289
325
|
// - Constraint violation handled gracefully
|
|
@@ -341,7 +377,7 @@ export async function directPatch(table, filters, data) {
|
|
|
341
377
|
* This bypasses ww-mcp because we need the embedding vectors for local search.
|
|
342
378
|
* Returns learnings (scars, patterns, wins, anti-patterns) with full embedding data.
|
|
343
379
|
*
|
|
344
|
-
* NOTE: Changed from "scars only" to "all learning types"
|
|
380
|
+
* NOTE: Changed from "scars only" to "all learning types"
|
|
345
381
|
*/
|
|
346
382
|
export async function loadScarsWithEmbeddings(project, limit = 500) {
|
|
347
383
|
console.error(`[supabase-direct] Loading learnings with embeddings${project ? ` for project: ${project}` : " (all projects)"}`);
|
|
@@ -384,7 +420,7 @@ export async function scarSearch(query, matchCount = 5, project) {
|
|
|
384
420
|
return result.results || [];
|
|
385
421
|
}
|
|
386
422
|
/**
|
|
387
|
-
* Scar search with caching
|
|
423
|
+
* Scar search with caching
|
|
388
424
|
*
|
|
389
425
|
* Returns cached results if available, otherwise fetches and caches.
|
|
390
426
|
*/
|
|
@@ -394,7 +430,7 @@ export async function cachedScarSearch(query, matchCount = 5, project = "default
|
|
|
394
430
|
return { results: data, cache_hit, cache_age_ms };
|
|
395
431
|
}
|
|
396
432
|
/**
|
|
397
|
-
* List records with caching for decisions
|
|
433
|
+
* List records with caching for decisions
|
|
398
434
|
*/
|
|
399
435
|
export async function cachedListDecisions(project = "default", limit = 5) {
|
|
400
436
|
const cache = getCache();
|
|
@@ -424,7 +460,7 @@ export async function cachedListWins(project = "default", limit = 8, columns) {
|
|
|
424
460
|
return { data, cache_hit, cache_age_ms };
|
|
425
461
|
}
|
|
426
462
|
// ============================================================================
|
|
427
|
-
// STORAGE API
|
|
463
|
+
// STORAGE API
|
|
428
464
|
// ============================================================================
|
|
429
465
|
const TRANSCRIPT_BUCKET = "session-transcripts";
|
|
430
466
|
/**
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Thread Lifecycle Manager (
|
|
2
|
+
* Thread Lifecycle Manager ()
|
|
3
3
|
*
|
|
4
4
|
* Core logic for thread lifecycle management:
|
|
5
5
|
* - ID generation, migration from plain strings to ThreadObject
|
|
@@ -11,6 +11,7 @@ import * as fs from "fs";
|
|
|
11
11
|
import * as path from "path";
|
|
12
12
|
import * as crypto from "crypto";
|
|
13
13
|
import { normalizeText } from "./thread-dedup.js";
|
|
14
|
+
import { getGitmemDir } from "./gitmem-dir.js";
|
|
14
15
|
// ---------- ID Generation ----------
|
|
15
16
|
/**
|
|
16
17
|
* Generate a thread ID: "t-" + 8 hex chars
|
|
@@ -123,7 +124,7 @@ export function aggregateThreads(sessions, maxSessions = 5, maxAgeDays = 14) {
|
|
|
123
124
|
const rawThreads = session.open_threads || [];
|
|
124
125
|
const normalized = normalizeThreads(rawThreads, session.id);
|
|
125
126
|
for (const thread of normalized) {
|
|
126
|
-
// Skip PROJECT STATE threads
|
|
127
|
+
// Skip PROJECT STATE threads
|
|
127
128
|
if (thread.text.startsWith("PROJECT STATE:"))
|
|
128
129
|
continue;
|
|
129
130
|
// Deduplicate by both thread ID and normalized text content
|
|
@@ -184,8 +185,7 @@ export function resolveThread(threads, options) {
|
|
|
184
185
|
// ---------- Local File Persistence ----------
|
|
185
186
|
const THREADS_FILENAME = "threads.json";
|
|
186
187
|
function getThreadsFilePath() {
|
|
187
|
-
|
|
188
|
-
return path.join(gitmemDir, THREADS_FILENAME);
|
|
188
|
+
return path.join(getGitmemDir(), THREADS_FILENAME);
|
|
189
189
|
}
|
|
190
190
|
/**
|
|
191
191
|
* Load threads from .gitmem/threads.json.
|
|
@@ -210,7 +210,7 @@ export function loadThreadsFile() {
|
|
|
210
210
|
* Save threads to .gitmem/threads.json.
|
|
211
211
|
*/
|
|
212
212
|
export function saveThreadsFile(threads) {
|
|
213
|
-
const gitmemDir =
|
|
213
|
+
const gitmemDir = getGitmemDir();
|
|
214
214
|
if (!fs.existsSync(gitmemDir)) {
|
|
215
215
|
fs.mkdirSync(gitmemDir, { recursive: true });
|
|
216
216
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Thread Supabase Service
|
|
2
|
+
* Thread Supabase Service
|
|
3
3
|
*
|
|
4
4
|
* Provides Supabase CRUD operations for the orchestra_threads table.
|
|
5
5
|
* Supabase is the source of truth; local .gitmem/threads.json is a cache.
|
|
@@ -318,7 +318,7 @@ export async function syncThreadsToSupabase(threads, project = "default", sessio
|
|
|
318
318
|
if (!hasSupabase() || !supabase.isConfigured() || threads.length === 0) {
|
|
319
319
|
return;
|
|
320
320
|
}
|
|
321
|
-
//
|
|
321
|
+
// Load existing open threads once upfront for text-based dedup.
|
|
322
322
|
// Prevents duplicate creation when closing ceremony generates new thread IDs
|
|
323
323
|
// for threads that already exist with the same (or similar) text.
|
|
324
324
|
let existingOpenThreads = [];
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* Parses JSONL session transcripts, chunks them intelligently,
|
|
5
5
|
* generates embeddings, and stores in orchestra_transcript_chunks.
|
|
6
6
|
*
|
|
7
|
-
*
|
|
7
|
+
*
|
|
8
8
|
*/
|
|
9
9
|
// OpenRouter API configuration (same as local-vector-search)
|
|
10
10
|
const OPENROUTER_API_URL = "https://openrouter.ai/api/v1/embeddings";
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Scar Variant Assignment Service
|
|
3
|
-
*
|
|
4
|
-
*
|
|
3
|
+
* Integrates variant assignment into enforcement engine
|
|
4
|
+
* Switched from issue-keyed to agent-keyed assignment
|
|
5
5
|
*
|
|
6
6
|
* Handles:
|
|
7
7
|
* - Random variant assignment for scars with variants
|
|
@@ -29,7 +29,7 @@ export interface ScarVariant {
|
|
|
29
29
|
}
|
|
30
30
|
/**
|
|
31
31
|
* Assignment record
|
|
32
|
-
*
|
|
32
|
+
* Primary key is (agent_id, scar_id), issue_id/session_id are metadata
|
|
33
33
|
*/
|
|
34
34
|
export interface VariantAssignment {
|
|
35
35
|
id: string;
|
|
@@ -55,12 +55,12 @@ export interface ScarWithVariant {
|
|
|
55
55
|
export declare function getActiveVariants(scarId: string): Promise<ScarVariant[]>;
|
|
56
56
|
/**
|
|
57
57
|
* Get existing assignment for an agent + scar pair
|
|
58
|
-
*
|
|
58
|
+
* Changed from issue-keyed to agent-keyed lookup
|
|
59
59
|
*/
|
|
60
60
|
export declare function getExistingAssignment(agentId: string, scarId: string): Promise<VariantAssignment | null>;
|
|
61
61
|
/**
|
|
62
62
|
* Create random variant assignment
|
|
63
|
-
*
|
|
63
|
+
* Agent-keyed with optional issue/session metadata
|
|
64
64
|
*/
|
|
65
65
|
export declare function createVariantAssignment(agentId: string, scarId: string, variants: ScarVariant[], metadata?: {
|
|
66
66
|
issueId?: string;
|
|
@@ -70,7 +70,7 @@ export declare function createVariantAssignment(agentId: string, scarId: string,
|
|
|
70
70
|
* Get or create variant assignment for a scar
|
|
71
71
|
* This is the main entry point for enforcement integration
|
|
72
72
|
*
|
|
73
|
-
*
|
|
73
|
+
* Changed from issue-keyed to agent-keyed assignment.
|
|
74
74
|
* Agent identity is always available, so variants are always assigned.
|
|
75
75
|
*
|
|
76
76
|
* @param agentId - Agent identity (e.g., 'CLI', 'DAC', 'CODA-1')
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Scar Variant Assignment Service
|
|
3
|
-
*
|
|
4
|
-
*
|
|
3
|
+
* Integrates variant assignment into enforcement engine
|
|
4
|
+
* Switched from issue-keyed to agent-keyed assignment
|
|
5
5
|
*
|
|
6
6
|
* Handles:
|
|
7
7
|
* - Random variant assignment for scars with variants
|
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
* - Legacy scar fallback (scars without variants use original description)
|
|
10
10
|
* - Blind testing (agent doesn't know which variant they received)
|
|
11
11
|
*/
|
|
12
|
+
import { randomInt } from "crypto";
|
|
12
13
|
import * as supabase from "./supabase-client.js";
|
|
13
14
|
/**
|
|
14
15
|
* Get active variants for a scar
|
|
@@ -35,7 +36,7 @@ export async function getActiveVariants(scarId) {
|
|
|
35
36
|
}
|
|
36
37
|
/**
|
|
37
38
|
* Get existing assignment for an agent + scar pair
|
|
38
|
-
*
|
|
39
|
+
* Changed from issue-keyed to agent-keyed lookup
|
|
39
40
|
*/
|
|
40
41
|
export async function getExistingAssignment(agentId, scarId) {
|
|
41
42
|
if (!supabase.isConfigured()) {
|
|
@@ -60,15 +61,15 @@ export async function getExistingAssignment(agentId, scarId) {
|
|
|
60
61
|
}
|
|
61
62
|
/**
|
|
62
63
|
* Create random variant assignment
|
|
63
|
-
*
|
|
64
|
+
* Agent-keyed with optional issue/session metadata
|
|
64
65
|
*/
|
|
65
66
|
export async function createVariantAssignment(agentId, scarId, variants, metadata) {
|
|
66
67
|
if (!supabase.isConfigured() || variants.length === 0) {
|
|
67
68
|
return null;
|
|
68
69
|
}
|
|
69
70
|
try {
|
|
70
|
-
//
|
|
71
|
-
const randomIndex =
|
|
71
|
+
// Cryptographically secure random selection for blind A/B testing integrity
|
|
72
|
+
const randomIndex = randomInt(0, variants.length);
|
|
72
73
|
const selectedVariant = variants[randomIndex];
|
|
73
74
|
const result = await supabase.directUpsert("variant_assignments", {
|
|
74
75
|
agent_id: agentId,
|
|
@@ -86,7 +87,7 @@ export async function createVariantAssignment(agentId, scarId, variants, metadat
|
|
|
86
87
|
console.error(`[variant-assignment] Assignment already exists (race condition), fetching...`);
|
|
87
88
|
return await getExistingAssignment(agentId, scarId);
|
|
88
89
|
}
|
|
89
|
-
console.error(`[variant-assignment]
|
|
90
|
+
console.error(`[variant-assignment] Failed to create assignment for scar ${scarId}`);
|
|
90
91
|
return null;
|
|
91
92
|
}
|
|
92
93
|
}
|
|
@@ -94,7 +95,7 @@ export async function createVariantAssignment(agentId, scarId, variants, metadat
|
|
|
94
95
|
* Get or create variant assignment for a scar
|
|
95
96
|
* This is the main entry point for enforcement integration
|
|
96
97
|
*
|
|
97
|
-
*
|
|
98
|
+
* Changed from issue-keyed to agent-keyed assignment.
|
|
98
99
|
* Agent identity is always available, so variants are always assigned.
|
|
99
100
|
*
|
|
100
101
|
* @param agentId - Agent identity (e.g., 'CLI', 'DAC', 'CODA-1')
|
package/dist/tools/analyze.d.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* analyze Tool
|
|
2
|
+
* analyze Tool
|
|
3
3
|
*
|
|
4
4
|
* Session analytics and insights engine. Provides structured analysis
|
|
5
5
|
* of session history, closing reflections, agent patterns, and more.
|
|
6
6
|
*
|
|
7
7
|
* Starts with "summary" lens; expanded with additional lenses in
|
|
8
|
-
*
|
|
8
|
+
* (Tier 1).
|
|
9
9
|
*
|
|
10
10
|
* Performance target: 3000ms
|
|
11
11
|
*/
|
package/dist/tools/analyze.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* analyze Tool
|
|
2
|
+
* analyze Tool
|
|
3
3
|
*
|
|
4
4
|
* Session analytics and insights engine. Provides structured analysis
|
|
5
5
|
* of session history, closing reflections, agent patterns, and more.
|
|
6
6
|
*
|
|
7
7
|
* Starts with "summary" lens; expanded with additional lenses in
|
|
8
|
-
*
|
|
8
|
+
* (Tier 1).
|
|
9
9
|
*
|
|
10
10
|
* Performance target: 3000ms
|
|
11
11
|
*/
|
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
*/
|
|
11
11
|
import { directPatch, isConfigured } from "../services/supabase-client.js";
|
|
12
12
|
import { hasSupabase } from "../services/tier.js";
|
|
13
|
+
import { getStorage } from "../services/storage.js";
|
|
13
14
|
import { flushCache } from "../services/startup.js";
|
|
14
15
|
import { Timer } from "../services/metrics.js";
|
|
15
16
|
import { wrapDisplay } from "../services/display-protocol.js";
|
|
@@ -26,35 +27,48 @@ export async function archiveLearning(params) {
|
|
|
26
27
|
performance_ms: timer.stop(),
|
|
27
28
|
};
|
|
28
29
|
}
|
|
29
|
-
if (!hasSupabase() || !isConfigured()) {
|
|
30
|
-
const msg = "archive_learning requires Supabase (pro/dev tier)";
|
|
31
|
-
return {
|
|
32
|
-
success: false,
|
|
33
|
-
id: params.id,
|
|
34
|
-
cache_flushed: false,
|
|
35
|
-
display: wrapDisplay(msg),
|
|
36
|
-
error: msg,
|
|
37
|
-
performance_ms: timer.stop(),
|
|
38
|
-
};
|
|
39
|
-
}
|
|
40
30
|
try {
|
|
41
31
|
const archivedAt = new Date().toISOString();
|
|
42
|
-
await directPatch("orchestra_learnings", { id: `eq.${params.id}` }, {
|
|
43
|
-
is_active: false,
|
|
44
|
-
archived_at: archivedAt,
|
|
45
|
-
});
|
|
46
|
-
// Flush local cache so archived scar is immediately excluded
|
|
47
32
|
let cacheFlushed = false;
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
33
|
+
if (hasSupabase() && isConfigured()) {
|
|
34
|
+
// Pro/dev: patch in Supabase
|
|
35
|
+
await directPatch("orchestra_learnings", { id: `eq.${params.id}` }, {
|
|
36
|
+
is_active: false,
|
|
37
|
+
archived_at: archivedAt,
|
|
38
|
+
});
|
|
39
|
+
try {
|
|
40
|
+
await flushCache();
|
|
41
|
+
cacheFlushed = true;
|
|
42
|
+
}
|
|
43
|
+
catch {
|
|
44
|
+
console.error("[archive-learning] Cache flush failed (non-fatal)");
|
|
45
|
+
}
|
|
51
46
|
}
|
|
52
|
-
|
|
53
|
-
|
|
47
|
+
else {
|
|
48
|
+
// Free tier: update in local JSON
|
|
49
|
+
const storage = getStorage();
|
|
50
|
+
const existing = await storage.get("learnings", params.id);
|
|
51
|
+
if (!existing) {
|
|
52
|
+
const msg = `Learning ${params.id} not found in local storage`;
|
|
53
|
+
return {
|
|
54
|
+
success: false,
|
|
55
|
+
id: params.id,
|
|
56
|
+
cache_flushed: false,
|
|
57
|
+
display: wrapDisplay(msg),
|
|
58
|
+
error: msg,
|
|
59
|
+
performance_ms: timer.stop(),
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
await storage.upsert("learnings", {
|
|
63
|
+
...existing,
|
|
64
|
+
id: params.id,
|
|
65
|
+
is_active: false,
|
|
66
|
+
archived_at: archivedAt,
|
|
67
|
+
});
|
|
54
68
|
}
|
|
55
69
|
const latencyMs = timer.stop();
|
|
56
70
|
const reasonText = params.reason ? ` Reason: ${params.reason}` : "";
|
|
57
|
-
const display = `Archived learning ${params.id}.${reasonText}\
|
|
71
|
+
const display = `Archived learning ${params.id}.${reasonText}\n(${latencyMs}ms)`;
|
|
58
72
|
return {
|
|
59
73
|
success: true,
|
|
60
74
|
id: params.id,
|
|
@@ -176,7 +176,7 @@ export async function confirmScars(params) {
|
|
|
176
176
|
errors.push(error);
|
|
177
177
|
}
|
|
178
178
|
else {
|
|
179
|
-
//
|
|
179
|
+
// Derive default relevance from decision if not provided
|
|
180
180
|
const relevance = conf.relevance ??
|
|
181
181
|
(conf.decision === "APPLYING" ? "high" : conf.decision === "N_A" ? "low" : "low");
|
|
182
182
|
validConfirmations.push({
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* Generates embeddings client-side and writes directly to Supabase REST API,
|
|
6
6
|
* eliminating the ww-mcp Edge Function dependency.
|
|
7
7
|
*
|
|
8
|
-
* Performance target: <3000ms
|
|
8
|
+
* Performance target: <3000ms
|
|
9
9
|
*/
|
|
10
10
|
import type { CreateDecisionParams, CreateDecisionResult } from "../types/index.js";
|
|
11
11
|
/**
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* Generates embeddings client-side and writes directly to Supabase REST API,
|
|
6
6
|
* eliminating the ww-mcp Edge Function dependency.
|
|
7
7
|
*
|
|
8
|
-
* Performance target: <3000ms
|
|
8
|
+
* Performance target: <3000ms
|
|
9
9
|
*/
|
|
10
10
|
import { v4 as uuidv4 } from "uuid";
|
|
11
11
|
import * as supabase from "../services/supabase-client.js";
|
|
@@ -74,7 +74,7 @@ export async function createDecision(params) {
|
|
|
74
74
|
cache_status: "not_applicable",
|
|
75
75
|
network_call: true,
|
|
76
76
|
};
|
|
77
|
-
//
|
|
77
|
+
// Auto-create knowledge triples (tracked fire-and-forget)
|
|
78
78
|
getEffectTracker().track("triple_write", "decision", () => writeTriplesForDecision({
|
|
79
79
|
id: decisionId,
|
|
80
80
|
title: params.title,
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* Generates embeddings client-side and writes directly to Supabase REST API,
|
|
6
6
|
* eliminating the ww-mcp Edge Function dependency.
|
|
7
7
|
*
|
|
8
|
-
* Performance target: <3000ms
|
|
8
|
+
* Performance target: <3000ms
|
|
9
9
|
*/
|
|
10
10
|
import type { CreateLearningParams, CreateLearningResult } from "../types/index.js";
|
|
11
11
|
/**
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* Generates embeddings client-side and writes directly to Supabase REST API,
|
|
6
6
|
* eliminating the ww-mcp Edge Function dependency.
|
|
7
7
|
*
|
|
8
|
-
* Performance target: <3000ms
|
|
8
|
+
* Performance target: <3000ms
|
|
9
9
|
*/
|
|
10
10
|
import { v4 as uuidv4 } from "uuid";
|
|
11
11
|
import * as supabase from "../services/supabase-client.js";
|
|
@@ -87,7 +87,7 @@ export async function createLearning(params) {
|
|
|
87
87
|
created_at: new Date().toISOString(),
|
|
88
88
|
persona_name: agentIdentity,
|
|
89
89
|
source_date: new Date().toISOString().split("T")[0],
|
|
90
|
-
//
|
|
90
|
+
// LLM-cooperative enforcement fields (optional)
|
|
91
91
|
...(params.why_this_matters && { why_this_matters: params.why_this_matters }),
|
|
92
92
|
...(params.action_protocol && { action_protocol: params.action_protocol }),
|
|
93
93
|
...(params.self_check_criteria && { self_check_criteria: params.self_check_criteria }),
|
|
@@ -151,14 +151,14 @@ export async function createLearning(params) {
|
|
|
151
151
|
cache_status: "not_applicable",
|
|
152
152
|
network_call: true,
|
|
153
153
|
};
|
|
154
|
-
//
|
|
154
|
+
// Defense in depth - verify write succeeded
|
|
155
155
|
// directUpsert now throws on empty result, but explicit check documents expectation
|
|
156
156
|
if (!writeResult || !writeResult.id) {
|
|
157
157
|
throw new Error(`Write verification failed: directUpsert returned ${writeResult ? 'record without id' : 'null/undefined'}. ` +
|
|
158
158
|
`Expected record with id field.`);
|
|
159
159
|
}
|
|
160
160
|
console.error(`[create_learning] directUpsert succeeded, verified ID: ${writeResult.id}`);
|
|
161
|
-
//
|
|
161
|
+
// Auto-create knowledge triples (tracked fire-and-forget)
|
|
162
162
|
getEffectTracker().track("triple_write", "learning", () => writeTriplesForLearning({
|
|
163
163
|
id: learningId,
|
|
164
164
|
learning_type: params.learning_type,
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* create_linear_issue Tool (OD-611)
|
|
3
|
+
*
|
|
4
|
+
* Proxy Linear issue creation via GraphQL API.
|
|
5
|
+
* Returns slim response (~50 tokens) instead of Linear MCP's ~1400 tokens.
|
|
6
|
+
*
|
|
7
|
+
* Pattern: File-based payload handoff (same as session_close).
|
|
8
|
+
* Agent writes description to .gitmem/issue-payload.json, then calls this
|
|
9
|
+
* tool with title + teamId inline. Tool reads, merges, calls Linear, deletes file.
|
|
10
|
+
*
|
|
11
|
+
* Performance target: <2000ms (one network call)
|
|
12
|
+
*/
|
|
13
|
+
import type { CreateLinearIssueParams, CreateLinearIssueResult } from "../types/index.js";
|
|
14
|
+
/**
|
|
15
|
+
* Create a Linear issue via GraphQL API with slim response.
|
|
16
|
+
*/
|
|
17
|
+
export declare function createLinearIssue(params: CreateLinearIssueParams): Promise<CreateLinearIssueResult>;
|
|
18
|
+
//# sourceMappingURL=create-linear-issue.d.ts.map
|