From a8d4af0d77b30700f872c750676cac9a9a2608fa Mon Sep 17 00:00:00 2001 From: Jimisola Laursen Date: Mon, 22 Jun 2026 09:32:55 +0200 Subject: [PATCH 1/2] fix(openspec): handle reqstool mcp spawn/exit failures in McpStdioClient Pending JSON-RPC promises (including the constructor's ready promise) previously hung forever if the reqstool mcp child process failed to spawn or exited unexpectedly, instead of rejecting so onReadDocument's catch block could surface a diagnostic. Also guard enrich()'s response shape before indexing, for a clearer error on malformed responses. Closes #33 Signed-off-by: Jimisola Laursen --- .claude-plugin/marketplace.json | 2 +- .../.claude-plugin/plugin.json | 2 +- .../references/openspecui.hooks.ts | 19 ++++++++++++++++--- 3 files changed, 18 insertions(+), 5 deletions(-) diff --git a/.claude-plugin/marketplace.json b/.claude-plugin/marketplace.json index d295e4c..46f6fe2 100644 --- a/.claude-plugin/marketplace.json +++ b/.claude-plugin/marketplace.json @@ -5,7 +5,7 @@ "url": "https://github.com/reqstool" }, "metadata": { - "version": "0.5.0", + "version": "0.5.1", "description": "AI-assisted reqstool requirements traceability — skills and commands for managing requirements, SVCs, and filters, with optional OpenSpec integration." }, "plugins": [ diff --git a/plugins/reqstool-openspec/.claude-plugin/plugin.json b/plugins/reqstool-openspec/.claude-plugin/plugin.json index 3e9c4b6..f6ef03a 100644 --- a/plugins/reqstool-openspec/.claude-plugin/plugin.json +++ b/plugins/reqstool-openspec/.claude-plugin/plugin.json @@ -1,7 +1,7 @@ { "name": "reqstool-openspec", "description": "OpenSpec integration for reqstool — conventions for referencing reqstool IDs in OpenSpec files, plus an openspecui hook that enriches all OpenSpec documents with reqstool requirement/SVC titles and descriptions at read time.", - "version": "0.2.1", + "version": "0.2.2", "author": { "name": "reqstool", "url": "https://github.com/reqstool" diff --git a/plugins/reqstool-openspec/skills/reqstool-openspec-init/references/openspecui.hooks.ts b/plugins/reqstool-openspec/skills/reqstool-openspec-init/references/openspecui.hooks.ts index 49a96ee..4c6b92b 100644 --- a/plugins/reqstool-openspec/skills/reqstool-openspec-init/references/openspecui.hooks.ts +++ b/plugins/reqstool-openspec/skills/reqstool-openspec-init/references/openspecui.hooks.ts @@ -1,4 +1,4 @@ -// @reqstool-openspec-hooks: 0.1.1 +// @reqstool-openspec-hooks: 0.1.2 import { spawn, ChildProcess } from "child_process"; import type { OnReadDocumentHookV1 } from "openspecui/hooks"; @@ -28,9 +28,18 @@ class McpStdioClient { if (line) this.handle(line); } }); + this.proc.on("error", (err) => this.failPending(err)); + this.proc.on("exit", (code, signal) => + this.failPending(new Error(`reqstool mcp exited (code=${code}, signal=${signal})`)), + ); this.ready = this.init(); } + private failPending(err: Error) { + for (const { reject } of this.pending.values()) reject(err); + this.pending.clear(); + } + private handle(line: string) { try { const msg = JSON.parse(line) as { id?: number; result?: unknown; error?: { message: string } }; @@ -72,8 +81,12 @@ class McpStdioClient { const result = (await this.send("tools/call", { name: "enrich_document", arguments: { content, preset }, - })) as { content: { text: string }[] }; - return result.content[0].text; + })) as { content?: { text: string }[] }; + const text = result.content?.[0]?.text; + if (text === undefined) { + throw new Error(`reqstool mcp returned an unexpected enrich_document response: ${JSON.stringify(result)}`); + } + return text; } close() { From b2514ef70f87022308aaf26a241f8b16179003c8 Mon Sep 17 00:00:00 2001 From: Jimisola Laursen Date: Wed, 5 Aug 2026 09:04:18 +0200 Subject: [PATCH 2/2] refactor(reqstool-openspec): use node: prefix and type-only ChildProcess import MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Import ChildProcess with `import type` since it is only used as a type annotation, and use the `node:` prefix for the built-in module. Note: ChildProcess is a genuine runtime export of child_process, so the previous form was not a runtime hazard — this is a style/emit cleanup for projects using verbatimModuleSyntax. Bumps template header to 0.1.3, plugin to 0.2.3, marketplace to 0.5.2. Signed-off-by: Jimisola Laursen --- .claude-plugin/marketplace.json | 2 +- plugins/reqstool-openspec/.claude-plugin/plugin.json | 2 +- .../reqstool-openspec-init/references/openspecui.hooks.ts | 5 +++-- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/.claude-plugin/marketplace.json b/.claude-plugin/marketplace.json index 46f6fe2..272968c 100644 --- a/.claude-plugin/marketplace.json +++ b/.claude-plugin/marketplace.json @@ -5,7 +5,7 @@ "url": "https://github.com/reqstool" }, "metadata": { - "version": "0.5.1", + "version": "0.5.2", "description": "AI-assisted reqstool requirements traceability — skills and commands for managing requirements, SVCs, and filters, with optional OpenSpec integration." }, "plugins": [ diff --git a/plugins/reqstool-openspec/.claude-plugin/plugin.json b/plugins/reqstool-openspec/.claude-plugin/plugin.json index f6ef03a..e093125 100644 --- a/plugins/reqstool-openspec/.claude-plugin/plugin.json +++ b/plugins/reqstool-openspec/.claude-plugin/plugin.json @@ -1,7 +1,7 @@ { "name": "reqstool-openspec", "description": "OpenSpec integration for reqstool — conventions for referencing reqstool IDs in OpenSpec files, plus an openspecui hook that enriches all OpenSpec documents with reqstool requirement/SVC titles and descriptions at read time.", - "version": "0.2.2", + "version": "0.2.3", "author": { "name": "reqstool", "url": "https://github.com/reqstool" diff --git a/plugins/reqstool-openspec/skills/reqstool-openspec-init/references/openspecui.hooks.ts b/plugins/reqstool-openspec/skills/reqstool-openspec-init/references/openspecui.hooks.ts index 4c6b92b..16dbb99 100644 --- a/plugins/reqstool-openspec/skills/reqstool-openspec-init/references/openspecui.hooks.ts +++ b/plugins/reqstool-openspec/skills/reqstool-openspec-init/references/openspecui.hooks.ts @@ -1,5 +1,6 @@ -// @reqstool-openspec-hooks: 0.1.2 -import { spawn, ChildProcess } from "child_process"; +// @reqstool-openspec-hooks: 0.1.3 +import { spawn } from "node:child_process"; +import type { ChildProcess } from "node:child_process"; import type { OnReadDocumentHookV1 } from "openspecui/hooks"; // Minimal MCP client over stdio (JSON-RPC 2.0, newline-delimited).