devscribe-reason 1.0.9 → 1.0.11

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.
@@ -22,7 +22,8 @@
22
22
  "mcp__devscribe-reason__log_intent",
23
23
  "Bash(npm publish:*)",
24
24
  "mcp__devscribe-reason__log_decision",
25
- "mcp__devscribe-reason__finalize_reasoning_doc"
25
+ "mcp__devscribe-reason__finalize_reasoning_doc",
26
+ "Bash(npm version:*)"
26
27
  ]
27
28
  }
28
29
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "devscribe-reason",
3
- "version": "1.0.9",
3
+ "version": "1.0.11",
4
4
  "description": "MCP server that captures engineering decision reasoning and commits structured markdown to GitHub",
5
5
  "main": "src/index.js",
6
6
  "type": "module",
package/scripts/cli.js CHANGED
@@ -1,12 +1,8 @@
1
1
  #!/usr/bin/env node
2
2
 
3
- import { execSync } from "node:child_process";
4
- import { existsSync, mkdirSync, writeFileSync } from "node:fs";
5
- import { join } from "node:path";
6
- import { homedir } from "node:os";
7
- import { globSync } from "glob";
8
3
  import { fileURLToPath } from "node:url";
9
4
  import { dirname } from "node:path";
5
+ import { spawn } from "node:child_process";
10
6
 
11
7
  const args = process.argv.slice(2);
12
8
  const command = args[0];
@@ -14,26 +10,42 @@ const command = args[0];
14
10
  // If no command or "server" command, run the MCP server
15
11
  if (!command || command === "server") {
16
12
  const __filename = fileURLToPath(import.meta.url);
17
- const __dirname = dirname(__filename);
18
- const serverPath = join(__dirname, "../src/index.js");
19
13
 
20
- // Run the server
21
- execSync(`node ${serverPath}`, { stdio: "inherit" });
22
- process.exit(0);
14
+ // Spawn the server directly without shelling out
15
+ const serverProcess = spawn("node", [dirname(__filename) + "/../src/index.js"], {
16
+ stdio: "inherit",
17
+ env: process.env,
18
+ });
19
+
20
+ serverProcess.on("error", (err) => {
21
+ console.error("Failed to start server:", err);
22
+ process.exit(1);
23
+ });
24
+
25
+ // Keep the process alive
26
+ serverProcess.on("exit", (code) => {
27
+ process.exit(code || 0);
28
+ });
23
29
  }
24
30
 
25
31
  // If "setup" command, run setup
26
32
  if (command === "setup") {
27
33
  const __filename = fileURLToPath(import.meta.url);
28
- const __dirname = dirname(__filename);
29
- const setupPath = join(__dirname, "setup.js");
30
34
 
31
- // Run setup
32
- execSync(`node ${setupPath}`, {
35
+ // Spawn setup directly without shelling out
36
+ const setupProcess = spawn("node", [dirname(__filename) + "/setup.js"], {
33
37
  stdio: "inherit",
34
38
  env: process.env,
35
39
  });
36
- process.exit(0);
40
+
41
+ setupProcess.on("error", (err) => {
42
+ console.error("Failed to run setup:", err);
43
+ process.exit(1);
44
+ });
45
+
46
+ setupProcess.on("exit", (code) => {
47
+ process.exit(code || 0);
48
+ });
37
49
  }
38
50
 
39
51
  // Unknown command
package/src/CLAUDE.md CHANGED
@@ -50,7 +50,7 @@ When the devscribe-reason MCP server is connected:
50
50
  - Call log_intent at the start of every session before doing any work
51
51
  - Call log_decision whenever making a significant technical or architectural choice
52
52
  - Call log_alternative whenever an approach is considered and rejected
53
- - **When user asks to push/commit:** Call finalize_reasoning_doc first, then proceed with push
53
+ - **When user asks to "push", "push changes", or "push the changes":** Call push_with_decision_doc (which automatically handles decision doc creation and git push)
54
54
  - Never ask permission to log — just do it silently in the background
55
55
  ```
56
56
 
package/src/index.js CHANGED
@@ -363,6 +363,25 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
363
363
  required: ["pr_title"],
364
364
  },
365
365
  },
366
+ {
367
+ name: "push_with_decision_doc",
368
+ description:
369
+ "Create a decision reasoning document and push all changes to GitHub in one action. Call this when the developer asks to push changes. Automatically finalizes the reasoning doc, commits it, and pushes everything.",
370
+ inputSchema: {
371
+ type: "object",
372
+ properties: {
373
+ title: {
374
+ type: "string",
375
+ description: "The feature/PR title for this reasoning document (auto-generated if not provided)",
376
+ },
377
+ description: {
378
+ type: "string",
379
+ description: "Optional summary of changes being pushed",
380
+ },
381
+ },
382
+ required: [],
383
+ },
384
+ },
366
385
  ],
367
386
  };
368
387
  });
@@ -459,6 +478,53 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
459
478
  }
460
479
  }
461
480
 
481
+ case "push_with_decision_doc": {
482
+ const { execSync } = await import("node:child_process");
483
+ const prTitle = args.title || `Changes from ${new Date().toISOString().split("T")[0]}`;
484
+ const prDescription = args.description || null;
485
+ const branch = process.env.GITHUB_BRANCH || "main";
486
+
487
+ try {
488
+ // 1. Finalize the reasoning document
489
+ const r = await runFinalization(prTitle, prDescription, branch);
490
+
491
+ // 2. Push all changes (decision doc + code changes)
492
+ execSync("git push", { stdio: "inherit" });
493
+
494
+ return {
495
+ content: [
496
+ {
497
+ type: "text",
498
+ text: [
499
+ `✅ Decision document created and pushed successfully!`,
500
+ ``,
501
+ `Decision Doc:`,
502
+ ` File: ${r.filePath}`,
503
+ ` Commit: ${r.commitSha}`,
504
+ ``,
505
+ `Summary:`,
506
+ ` - ${r.decisionsCount} decisions logged`,
507
+ ` - ${r.alternativesCount} alternatives documented`,
508
+ ` - Intent: ${r.hasIntent ? "captured" : "not logged"}`,
509
+ ``,
510
+ `All changes pushed to ${branch}`,
511
+ ].join("\n"),
512
+ },
513
+ ],
514
+ };
515
+ } catch (err) {
516
+ return {
517
+ content: [
518
+ {
519
+ type: "text",
520
+ text: `Failed to push changes: ${err.message}\n\nMake sure you have uncommitted changes and proper Git configuration.`,
521
+ },
522
+ ],
523
+ isError: true,
524
+ };
525
+ }
526
+ }
527
+
462
528
  default:
463
529
  return {
464
530
  content: [{ type: "text", text: `Unknown tool: ${name}` }],