gitmem-mcp 1.0.2 → 1.0.4
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 +20 -6
- package/README.md +30 -9
- 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.d.ts +4 -4
- 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 +12 -0
- package/dist/services/agent-briefing.js +81 -0
- package/dist/services/agent-detection.d.ts +2 -1
- package/dist/services/agent-detection.js +23 -14
- 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 +16 -10
- 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/tier.d.ts +2 -0
- package/dist/services/tier.js +4 -0
- package/dist/services/transcript-chunker.d.ts +1 -1
- package/dist/services/transcript-chunker.js +1 -1
- package/dist/services/triple-writer.d.ts +4 -4
- package/dist/services/triple-writer.js +11 -20
- 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 +4 -0
- 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.d.ts +280 -58
- package/dist/tools/definitions.js +127 -87
- 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 +20 -17
- 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 +2 -2
- package/dist/tools/recall.d.ts +5 -4
- package/dist/tools/recall.js +37 -28
- 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 +58 -57
- package/dist/tools/session-start.d.ts +5 -5
- package/dist/tools/session-start.js +63 -61
- package/dist/types/index.d.ts +17 -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/schema/starter-scars.json +3 -153
- 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-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
|
@@ -20,30 +20,21 @@ const HALF_LIFE_PROCESS = 9999;
|
|
|
20
20
|
* Canonical persona name map.
|
|
21
21
|
* Raw personas_involved values may contain full names or contextual suffixes.
|
|
22
22
|
* This ensures consistent node identity in the knowledge graph.
|
|
23
|
+
*
|
|
24
|
+
* Users can populate this with their own team/persona names.
|
|
25
|
+
* Keys are lowercase, values are canonical display names.
|
|
23
26
|
*/
|
|
24
|
-
const CANONICAL_PERSONA_NAMES = {
|
|
25
|
-
"elena vos": "Elena",
|
|
26
|
-
"elena": "Elena",
|
|
27
|
-
"marcus thorne": "Marcus",
|
|
28
|
-
"marcus": "Marcus",
|
|
29
|
-
"reiko tanaka": "Reiko",
|
|
30
|
-
"reiko": "Reiko",
|
|
31
|
-
"jax": "Jax",
|
|
32
|
-
"jax dimitri": "Jax",
|
|
33
|
-
"jax reed": "Jax",
|
|
34
|
-
"chris crawford": "Chris Crawford",
|
|
35
|
-
"chris": "Chris Crawford",
|
|
36
|
-
};
|
|
27
|
+
const CANONICAL_PERSONA_NAMES = {};
|
|
37
28
|
/**
|
|
38
29
|
* Normalize a persona label to its canonical form.
|
|
39
30
|
* Strips contextual suffixes like " - UX navigation clarity" or ": Prefers non-invasive..."
|
|
40
31
|
* Then maps to canonical short name if known.
|
|
41
32
|
*
|
|
42
33
|
* Examples:
|
|
43
|
-
* "
|
|
44
|
-
* "
|
|
45
|
-
* "
|
|
46
|
-
* "
|
|
34
|
+
* "Alice Smith" → "Alice" (if mapped)
|
|
35
|
+
* "Bob - Architectural pattern" → "Bob" (if mapped)
|
|
36
|
+
* "Alice: Prefers non-invasive instrumentation" → "Alice" (if mapped)
|
|
37
|
+
* "Unknown Developer - Process decision" → "Unknown Developer" (passthrough)
|
|
47
38
|
*/
|
|
48
39
|
export function normalizePersonaLabel(raw) {
|
|
49
40
|
// Strip contextual suffix after " - " or ": "
|
|
@@ -54,11 +45,11 @@ export function normalizePersonaLabel(raw) {
|
|
|
54
45
|
const canonical = CANONICAL_PERSONA_NAMES[name.toLowerCase()];
|
|
55
46
|
return canonical || name;
|
|
56
47
|
}
|
|
57
|
-
/** Set of canonical persona names (
|
|
48
|
+
/** Set of canonical persona names (team members). */
|
|
58
49
|
const KNOWN_PERSONAS = new Set(Object.values(CANONICAL_PERSONA_NAMES));
|
|
59
50
|
/**
|
|
60
|
-
* Determine if a name refers to
|
|
61
|
-
* Returns true for
|
|
51
|
+
* Determine if a name refers to a known persona vs an agent.
|
|
52
|
+
* Returns true for names in the CANONICAL_PERSONA_NAMES map.
|
|
62
53
|
*/
|
|
63
54
|
function isPersonaName(name) {
|
|
64
55
|
return KNOWN_PERSONAS.has(normalizePersonaLabel(name));
|
|
@@ -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,12 +176,16 @@ export async function confirmScars(params) {
|
|
|
176
176
|
errors.push(error);
|
|
177
177
|
}
|
|
178
178
|
else {
|
|
179
|
+
// Derive default relevance from decision if not provided
|
|
180
|
+
const relevance = conf.relevance ??
|
|
181
|
+
(conf.decision === "APPLYING" ? "high" : conf.decision === "N_A" ? "low" : "low");
|
|
179
182
|
validConfirmations.push({
|
|
180
183
|
scar_id: conf.scar_id,
|
|
181
184
|
scar_title: scar.scar_title,
|
|
182
185
|
decision: conf.decision,
|
|
183
186
|
evidence: conf.evidence.trim(),
|
|
184
187
|
confirmed_at: new Date().toISOString(),
|
|
188
|
+
relevance,
|
|
185
189
|
});
|
|
186
190
|
confirmedIds.add(conf.scar_id);
|
|
187
191
|
}
|
|
@@ -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
|
|
@@ -0,0 +1,197 @@
|
|
|
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 * as fs from "fs";
|
|
14
|
+
import { v4 as uuidv4 } from "uuid";
|
|
15
|
+
import { getGitmemPath } from "../services/gitmem-dir.js";
|
|
16
|
+
import { Timer, buildPerformanceData, recordMetrics, } from "../services/metrics.js";
|
|
17
|
+
import { getEffectTracker } from "../services/effect-tracker.js";
|
|
18
|
+
const LINEAR_API_URL = "https://api.linear.app/graphql";
|
|
19
|
+
/** GraphQL mutation — request only the fields needed for the slim response */
|
|
20
|
+
const ISSUE_CREATE_MUTATION = `
|
|
21
|
+
mutation IssueCreate($input: IssueCreateInput!) {
|
|
22
|
+
issueCreate(input: $input) {
|
|
23
|
+
success
|
|
24
|
+
issue {
|
|
25
|
+
id
|
|
26
|
+
identifier
|
|
27
|
+
url
|
|
28
|
+
state {
|
|
29
|
+
name
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
`;
|
|
35
|
+
/**
|
|
36
|
+
* Create a Linear issue via GraphQL API with slim response.
|
|
37
|
+
*/
|
|
38
|
+
export async function createLinearIssue(params) {
|
|
39
|
+
const timer = new Timer();
|
|
40
|
+
const metricsId = uuidv4();
|
|
41
|
+
// 1. Check LINEAR_API_KEY
|
|
42
|
+
const apiKey = process.env.LINEAR_API_KEY;
|
|
43
|
+
if (!apiKey) {
|
|
44
|
+
const latencyMs = timer.stop();
|
|
45
|
+
return {
|
|
46
|
+
success: false,
|
|
47
|
+
error: "LINEAR_API_KEY environment variable is not set. Add it to your MCP server configuration.",
|
|
48
|
+
performance: buildPerformanceData("create_linear_issue", latencyMs, 0),
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
// 2. Load file-based payload (same pattern as session_close)
|
|
52
|
+
const payloadPath = params.payload_path || getGitmemPath("issue-payload.json");
|
|
53
|
+
let filePayload = {};
|
|
54
|
+
try {
|
|
55
|
+
if (fs.existsSync(payloadPath)) {
|
|
56
|
+
filePayload = JSON.parse(fs.readFileSync(payloadPath, "utf-8"));
|
|
57
|
+
console.error(`[create_linear_issue] Loaded payload from ${payloadPath}`);
|
|
58
|
+
// Clean up payload file after reading
|
|
59
|
+
try {
|
|
60
|
+
fs.unlinkSync(payloadPath);
|
|
61
|
+
}
|
|
62
|
+
catch {
|
|
63
|
+
/* ignore cleanup errors */
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
catch (error) {
|
|
68
|
+
console.error("[create_linear_issue] Failed to read issue-payload.json:", error);
|
|
69
|
+
}
|
|
70
|
+
// 3. Merge: inline params override file payload
|
|
71
|
+
const teamId = params.teamId || filePayload.teamId;
|
|
72
|
+
const title = params.title || filePayload.title;
|
|
73
|
+
if (!teamId || !title) {
|
|
74
|
+
const latencyMs = timer.stop();
|
|
75
|
+
return {
|
|
76
|
+
success: false,
|
|
77
|
+
error: "teamId and title are required. Provide inline or in .gitmem/issue-payload.json.",
|
|
78
|
+
performance: buildPerformanceData("create_linear_issue", latencyMs, 0),
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
// 4. Build IssueCreateInput for GraphQL
|
|
82
|
+
const input = {
|
|
83
|
+
teamId,
|
|
84
|
+
title,
|
|
85
|
+
};
|
|
86
|
+
// Description only comes from file payload (the large field)
|
|
87
|
+
if (filePayload.description) {
|
|
88
|
+
input.description = filePayload.description;
|
|
89
|
+
}
|
|
90
|
+
// Merge optional fields — inline overrides file
|
|
91
|
+
if (params.priority !== undefined || filePayload.priority !== undefined) {
|
|
92
|
+
input.priority = params.priority ?? filePayload.priority;
|
|
93
|
+
}
|
|
94
|
+
if (params.labelIds?.length || filePayload.labelIds?.length) {
|
|
95
|
+
input.labelIds = params.labelIds || filePayload.labelIds;
|
|
96
|
+
}
|
|
97
|
+
if (params.projectId || filePayload.projectId) {
|
|
98
|
+
input.projectId = params.projectId || filePayload.projectId;
|
|
99
|
+
}
|
|
100
|
+
if (params.assigneeId || filePayload.assigneeId) {
|
|
101
|
+
input.assigneeId = params.assigneeId || filePayload.assigneeId;
|
|
102
|
+
}
|
|
103
|
+
if (params.parentId || filePayload.parentId) {
|
|
104
|
+
input.parentId = params.parentId || filePayload.parentId;
|
|
105
|
+
}
|
|
106
|
+
if (params.stateId || filePayload.stateId) {
|
|
107
|
+
input.stateId = params.stateId || filePayload.stateId;
|
|
108
|
+
}
|
|
109
|
+
if (params.estimate !== undefined || filePayload.estimate !== undefined) {
|
|
110
|
+
input.estimate = params.estimate ?? filePayload.estimate;
|
|
111
|
+
}
|
|
112
|
+
// 5. Call Linear GraphQL API
|
|
113
|
+
try {
|
|
114
|
+
const response = await fetch(LINEAR_API_URL, {
|
|
115
|
+
method: "POST",
|
|
116
|
+
headers: {
|
|
117
|
+
"Content-Type": "application/json",
|
|
118
|
+
Authorization: apiKey,
|
|
119
|
+
},
|
|
120
|
+
body: JSON.stringify({
|
|
121
|
+
query: ISSUE_CREATE_MUTATION,
|
|
122
|
+
variables: { input },
|
|
123
|
+
}),
|
|
124
|
+
});
|
|
125
|
+
if (!response.ok) {
|
|
126
|
+
const text = await response.text();
|
|
127
|
+
const latencyMs = timer.stop();
|
|
128
|
+
return {
|
|
129
|
+
success: false,
|
|
130
|
+
error: `Linear API HTTP ${response.status}: ${text.slice(0, 200)}`,
|
|
131
|
+
performance: buildPerformanceData("create_linear_issue", latencyMs, 0),
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
const data = (await response.json());
|
|
135
|
+
// Handle GraphQL errors
|
|
136
|
+
if (data.errors?.length) {
|
|
137
|
+
const latencyMs = timer.stop();
|
|
138
|
+
return {
|
|
139
|
+
success: false,
|
|
140
|
+
error: `Linear GraphQL error: ${data.errors.map((e) => e.message).join("; ")}`,
|
|
141
|
+
performance: buildPerformanceData("create_linear_issue", latencyMs, 0),
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
const issueCreate = data.data?.issueCreate;
|
|
145
|
+
if (!issueCreate?.success || !issueCreate.issue) {
|
|
146
|
+
const latencyMs = timer.stop();
|
|
147
|
+
return {
|
|
148
|
+
success: false,
|
|
149
|
+
error: "Linear API returned unsuccessful issueCreate",
|
|
150
|
+
performance: buildPerformanceData("create_linear_issue", latencyMs, 0),
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
const issue = issueCreate.issue;
|
|
154
|
+
const latencyMs = timer.stop();
|
|
155
|
+
// 6. Fire-and-forget metrics recording
|
|
156
|
+
getEffectTracker().track("metrics", "create_linear_issue", () => recordMetrics({
|
|
157
|
+
id: metricsId,
|
|
158
|
+
tool_name: "create_linear_issue",
|
|
159
|
+
latency_ms: latencyMs,
|
|
160
|
+
result_count: 1,
|
|
161
|
+
metadata: {
|
|
162
|
+
identifier: issue.identifier,
|
|
163
|
+
teamId,
|
|
164
|
+
has_description: !!filePayload.description,
|
|
165
|
+
},
|
|
166
|
+
}));
|
|
167
|
+
// 7. Return slim response (~50 tokens vs ~1400)
|
|
168
|
+
return {
|
|
169
|
+
success: true,
|
|
170
|
+
identifier: issue.identifier,
|
|
171
|
+
url: issue.url,
|
|
172
|
+
id: issue.id,
|
|
173
|
+
state: issue.state?.name,
|
|
174
|
+
performance: buildPerformanceData("create_linear_issue", latencyMs, 1, {
|
|
175
|
+
breakdown: {
|
|
176
|
+
upsert: {
|
|
177
|
+
latency_ms: latencyMs,
|
|
178
|
+
source: "supabase",
|
|
179
|
+
cache_status: "not_applicable",
|
|
180
|
+
network_call: true,
|
|
181
|
+
},
|
|
182
|
+
},
|
|
183
|
+
}),
|
|
184
|
+
};
|
|
185
|
+
}
|
|
186
|
+
catch (error) {
|
|
187
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
188
|
+
console.error("[create_linear_issue] Failed:", error);
|
|
189
|
+
const latencyMs = timer.stop();
|
|
190
|
+
return {
|
|
191
|
+
success: false,
|
|
192
|
+
error: `Linear API call failed: ${errorMessage}`,
|
|
193
|
+
performance: buildPerformanceData("create_linear_issue", latencyMs, 0),
|
|
194
|
+
};
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
//# sourceMappingURL=create-linear-issue.js.map
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* Create an open thread outside of session close. Threads track
|
|
5
5
|
* unresolved work items that carry across sessions.
|
|
6
6
|
*
|
|
7
|
-
*
|
|
7
|
+
* Writes to Supabase (source of truth) + local file (cache).
|
|
8
8
|
* Falls back to local-only if Supabase is unavailable.
|
|
9
9
|
*
|
|
10
10
|
* Phase 3: Semantic dedup gate — before creating, checks existing open
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* Create an open thread outside of session close. Threads track
|
|
5
5
|
* unresolved work items that carry across sessions.
|
|
6
6
|
*
|
|
7
|
-
*
|
|
7
|
+
* Writes to Supabase (source of truth) + local file (cache).
|
|
8
8
|
* Falls back to local-only if Supabase is unavailable.
|
|
9
9
|
*
|
|
10
10
|
* Phase 3: Semantic dedup gate — before creating, checks existing open
|
|
@@ -123,7 +123,7 @@ export async function createThread(params) {
|
|
|
123
123
|
created_at: new Date().toISOString(),
|
|
124
124
|
...(sessionId && { source_session: sessionId }),
|
|
125
125
|
};
|
|
126
|
-
//
|
|
126
|
+
// Write to Supabase (source of truth) with embedding — non-blocking on failure
|
|
127
127
|
let supabaseSynced = false;
|
|
128
128
|
const embeddingJson = newEmbedding ? JSON.stringify(newEmbedding) : null;
|
|
129
129
|
const supabaseResult = await createThreadInSupabase(thread, project, embeddingJson);
|