gitmem-mcp 1.0.9 → 1.0.10

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 CHANGED
@@ -7,6 +7,19 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [1.0.10] - 2026-02-16
11
+
12
+ ### Fixed
13
+ - **CI smoke test**: `session_close` test looked for `active-sessions.json` at `process.cwd()` instead of `GITMEM_DIR`, failing in CI where they differ.
14
+ - **CI peer dependencies**: Added `--legacy-peer-deps` to `npm ci` for `zod@4` conflict with `claude-agent-sdk`.
15
+ - **CI unit test**: `quick-retrieve.test.ts` now sets `GITMEM_DIR` so disk cache tests resolve correctly in CI.
16
+
17
+ ## [1.0.9] - 2026-02-16
18
+
19
+ ### Fixed
20
+ - **Closing payload field name mismatch**: `CLAUDE.md.template` documented wrong field names (`institutional_memory` instead of `institutional_memory_items`, bogus `started_at`/`completed_at` in task_completion) causing agents to write payloads that `session_close` couldn't parse. Fixed template and added `institutional_memory` as normalizer alias.
21
+ - **Missing Q8/Q9 in closing template**: Added `collaborative_dynamic` and `rapport_notes` fields to payload example.
22
+
10
23
  ## [1.0.6] - 2026-02-16
11
24
 
12
25
  ### Fixed
@@ -47,17 +47,17 @@ On "closing", "done for now", or "wrapping up":
47
47
  "do_differently": "...",
48
48
  "what_worked": "...",
49
49
  "wrong_assumption": "...",
50
- "scars_applied": "...",
51
- "institutional_memory": "..."
50
+ "scars_applied": ["scar title 1", "scar title 2"],
51
+ "institutional_memory_items": "...",
52
+ "collaborative_dynamic": "Q8: How human preferred to work",
53
+ "rapport_notes": "Q9: What collaborative dynamic worked"
52
54
  },
53
55
  "task_completion": {
54
- "started_at": "ISO timestamp",
55
- "completed_at": "ISO timestamp",
56
56
  "questions_displayed_at": "ISO timestamp",
57
57
  "reflection_completed_at": "ISO timestamp",
58
58
  "human_asked_at": "ISO timestamp",
59
59
  "human_response_at": "ISO timestamp",
60
- "human_response": "human's correction text or empty"
60
+ "human_response": "human's correction text or 'Looks good'"
61
61
  },
62
62
  "human_corrections": "",
63
63
  "scars_to_record": [],
@@ -137,6 +137,7 @@ const REFLECTION_ALIASES = {
137
137
  capture: "institutional_memory_items",
138
138
  capture_as_memory: "institutional_memory_items",
139
139
  memory_items: "institutional_memory_items",
140
+ institutional_memory: "institutional_memory_items",
140
141
  // Q8-Q9 (rapport, not in CLOSING_QUESTIONS but used)
141
142
  q8_human_style: "human_work_style",
142
143
  q9_dynamic: "collaborative_dynamic",
package/dist/index.js CHANGED
File without changes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gitmem-mcp",
3
- "version": "1.0.9",
3
+ "version": "1.0.10",
4
4
  "description": "Institutional memory for AI coding agents. Memory that compounds.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -1,18 +0,0 @@
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
@@ -1,197 +0,0 @@
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