@programinglive/dev-workflow-mcp-server 1.7.17 → 1.8.1

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
@@ -2,6 +2,22 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
4
4
 
5
+ ### [1.8.1](https://github.com/programinglive/dev-workflow-mcp-server/compare/v1.8.0...v1.8.1) (2025-12-26)
6
+
7
+
8
+ ### 📝 Documentation
9
+
10
+ * add release notes for v1.8.0 ([5a4025b](https://github.com/programinglive/dev-workflow-mcp-server/commit/5a4025b8cc6bbd4aa389c7435d585ee15cd3416b))
11
+ * refresh PRD and README for v1.8.0 ([d7ff89e](https://github.com/programinglive/dev-workflow-mcp-server/commit/d7ff89eaf2c8bf89e52110f91b8b84fa26a9ceed))
12
+
13
+ ## [1.8.0](https://github.com/programinglive/dev-workflow-mcp-server/compare/v1.7.17...v1.8.0) (2025-12-26)
14
+
15
+
16
+ ### ♻️ Refactors
17
+
18
+ * complete handlers.js modularization and fix all tests ([af5b3d6](https://github.com/programinglive/dev-workflow-mcp-server/commit/af5b3d60db025611e9a84a27ccc78f5999d0ead7))
19
+ * split handlers.test.js into smaller focused test modules ([321bbe5](https://github.com/programinglive/dev-workflow-mcp-server/commit/321bbe50d34348202f9e096e5b1903cae519dac6))
20
+
5
21
  ### [1.7.17](https://github.com/programinglive/dev-workflow-mcp-server/compare/v1.7.16...v1.7.17) (2025-12-26)
6
22
 
7
23
 
package/README.md CHANGED
@@ -25,6 +25,14 @@ This MCP server guides you through a disciplined development workflow:
25
25
  6. **Commit & Push** - Let the server stage, commit, **and push** your changes once verification passes (if you make new edits afterward, the workflow moves back to this step automatically)
26
26
  7. **Release** - After the push succeeds, record the release details before closing out the task
27
27
 
28
+ ## 🆕 What's New in v1.8.0
29
+
30
+ - **Modular Handler Architecture** – `tools/handlers.js` now re-exports focused handler modules, improving maintainability and bundler behavior.
31
+ - **Organized Test Suite** – The 1k-line `tests/handlers.test.js` has been split into `handlers-*.test.js` files with shared helpers, reducing duplication and clarifying intent.
32
+ - **Shared Test Utilities** – New `tests/test-helpers.js` centralizes workflow state setup, request builders, and git mocks.
33
+ - **Documentation Refresh** – PRD moved to `docs/PRD.md` root, status bumped to v1.8.0, and release notes updated to reflect the current workflow.
34
+ - **Release Hygiene** – Recommended flow now includes `npm run release:<type>` followed by `git push --follow-tags origin main` to keep stages clean.
35
+
28
36
  ## 🚀 Installation
29
37
 
30
38
  ### Option 1: Install as Dependency in Your Project (Recommended)
@@ -3,8 +3,8 @@
3
3
  ## 1. Overview
4
4
  - **Product**: Development Workflow MCP Server
5
5
  - **Prepared by**: Cascade (AI assistant)
6
- - **Date**: 2025-12-16
7
- - **Status**: Live v1.7.15
6
+ - **Date**: 2025-12-27
7
+ - **Status**: Live v1.8.0
8
8
 
9
9
  ## 2. Problem Statement
10
10
  Developers need structured guidance to maintain disciplined workflows across projects. Existing tooling lacks enforcement of sequential best practices (testing, documentation, release hygiene) and offers limited visibility into historical task execution.
@@ -42,6 +42,9 @@ Developers need structured guidance to maintain disciplined workflows across pro
42
42
  - [x] **Multi-Database Support**: SQLite, MySQL, and PostgreSQL adapters implemented and verified.
43
43
  - [x] **Environment Configuration**: `.env` file support added.
44
44
  - [x] **Comprehensive Testing**: Automated tests for DB adapters and environment loading.
45
+ - [x] **Modular Architecture**: Refactored handlers.js into focused handler modules for better maintainability.
46
+ - [x] **Test Organization**: Split monolithic test file into focused test modules with shared utilities.
47
+ - [x] **PRD Location**: Moved PRD.md to docs/ root for easier access.
45
48
  - **Multi-Database Support**: Abstract the storage layer to support:
46
49
  - SQLite (default/local)
47
50
  - MySQL
@@ -4,6 +4,8 @@ Authoritative history of user-visible changes for the Development Workflow MCP S
4
4
 
5
5
  | Version | Date | Notes |
6
6
  |---------|------|-------|
7
+ | 1.8.0 | 2025-12-27 | See CHANGELOG for details. |
8
+ | 1.7.17 | 2025-12-26 | update release notes for v1.7.16 (0afd96b) |
7
9
  | 1.7.16 | 2025-12-24 | align database schema with dashboard and improve user ID handling (69e7f38) |
8
10
  | 1.7.15 | 2025-12-19 | optimize startup performance and add database connection resilience (bff2714) |
9
11
  | 1.7.14 | 2025-12-19 | add API dependencies and update login to use API client (94bb42f) |
@@ -44,6 +46,22 @@ Authoritative history of user-visible changes for the Development Workflow MCP S
44
46
 
45
47
 
46
48
 
49
+
50
+
51
+
52
+ ## 1.8.0
53
+
54
+ Released on **2025-12-27**.
55
+
56
+ - See CHANGELOG for details.
57
+
58
+ ## 1.7.17 – 📝 Documentation
59
+
60
+ Released on **2025-12-26**.
61
+
62
+ - update release notes for v1.7.16 (0afd96b)
63
+ - allow skipping release step (004e4fa)
64
+ - add @programinglive/commiter setup (1d2a19d)
47
65
 
48
66
  ## 1.7.16 – 🐛 Bug Fixes
49
67
 
package/git-helpers.js CHANGED
@@ -151,6 +151,15 @@ export async function getCurrentBranch() {
151
151
  }
152
152
  }
153
153
 
154
+ export async function getStatusOutput() {
155
+ try {
156
+ const { stdout } = await exec("git status --porcelain");
157
+ return stdout;
158
+ } catch (error) {
159
+ return "";
160
+ }
161
+ }
162
+
154
163
  export async function getPrimaryBranch() {
155
164
  try {
156
165
  // Check if 'main' exists on origin
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@programinglive/dev-workflow-mcp-server",
3
- "version": "1.7.17",
3
+ "version": "1.8.1",
4
4
  "description": "MCP server to enforce development workflow discipline",
5
5
  "homepage": "https://devworkflow.programinglive.com/",
6
6
  "mcpName": "io.github.programinglive/dev-workflow-mcp-server",
@@ -0,0 +1,174 @@
1
+ import test from "node:test";
2
+ import assert from "node:assert/strict";
3
+ import { handleToolCall } from "../tools/handlers.js";
4
+ import { withWorkflowState, testUtils, createRequest, createGitMock } from "./test-helpers.js";
5
+
6
+ test("commit_and_push commits changes and pushes", async () => {
7
+ await withWorkflowState(async (workflowState) => {
8
+ workflowState.state.readyToCommit = true;
9
+ workflowState.state.readyCheckCompleted = true;
10
+ workflowState.state.testsSkipped = false;
11
+ workflowState.state.testsCreated = true;
12
+ workflowState.state.testsPassed = true;
13
+ workflowState.state.currentPhase = "commit";
14
+ await workflowState.save();
15
+
16
+ const commands = [];
17
+ const execStub = async (command) => {
18
+ commands.push(command);
19
+ return { stdout: "" };
20
+ };
21
+
22
+ const response = await handleToolCall({
23
+ request: createRequest("commit_and_push", { commitMessage: "" }),
24
+ normalizeRequestArgs: (args) => ({ args, error: null }),
25
+ workflowState,
26
+ exec: execStub,
27
+ git: createGitMock({
28
+ hasWorkingChanges: async () => true,
29
+ getStagedChanges: async () => [{ status: "M", path: "src/index.js" }],
30
+ getStatusOutput: async () => "M tests/handlers.test.js\nM src/index.js",
31
+ containsTestFilesInStatus: (statusOutput) => statusOutput.includes("tests/"),
32
+ }),
33
+ utils: testUtils,
34
+ });
35
+
36
+ const pushCommand = commands.find((command) => command.startsWith("git push"));
37
+ assert.ok(pushCommand, "git push should be executed during commit");
38
+ assert.ok(
39
+ pushCommand.startsWith("git push origin"),
40
+ "push command should target origin"
41
+ );
42
+ assert.equal(
43
+ commands.some((command) => command.startsWith("git commit")),
44
+ true,
45
+ "git commit should be executed"
46
+ );
47
+ assert.ok(
48
+ response.content[0].text.includes("Commit and push completed!"),
49
+ "response should confirm commit and push"
50
+ );
51
+ assert.equal(workflowState.state.commitAndPushCompleted, true);
52
+ assert.equal(workflowState.state.lastCommitMessage.length > 0, true);
53
+ assert.equal(workflowState.state.currentPhase, "release");
54
+ });
55
+ });
56
+
57
+ test("commit_and_push uses primary branch when no branch specified", async () => {
58
+ await withWorkflowState(async (workflowState) => {
59
+ workflowState.state.readyToCommit = true;
60
+ workflowState.state.readyCheckCompleted = true;
61
+ workflowState.state.testsSkipped = false;
62
+ workflowState.state.testsCreated = true;
63
+ workflowState.state.testsPassed = true;
64
+ workflowState.state.currentPhase = "commit";
65
+ await workflowState.save();
66
+
67
+ const commands = [];
68
+ const execStub = async (command) => {
69
+ commands.push(command);
70
+ return { stdout: "" };
71
+ };
72
+
73
+ const response = await handleToolCall({
74
+ request: createRequest("commit_and_push", { commitMessage: "feat: test" }),
75
+ normalizeRequestArgs: (args) => ({ args, error: null }),
76
+ workflowState,
77
+ exec: execStub,
78
+ git: createGitMock({
79
+ hasWorkingChanges: async () => true,
80
+ getStagedChanges: async () => [{ status: "M", path: "src/index.js" }],
81
+ getCurrentBranch: async () => "feature/test",
82
+ getStatusOutput: async () => "M tests/handlers.test.js\nM src/index.js",
83
+ containsTestFilesInStatus: (statusOutput) => statusOutput.includes("tests/"),
84
+ }),
85
+ utils: testUtils,
86
+ });
87
+
88
+ const pushCommand = commands.find((command) => command.startsWith("git push"));
89
+ assert.ok(pushCommand, "git push should be executed");
90
+ assert.ok(
91
+ /origin\s+['"]?main['"]?/.test(pushCommand),
92
+ "push should use primary branch (main) when no branch specified"
93
+ );
94
+ });
95
+ });
96
+
97
+ test("commit_and_push falls back to master when main not found", async () => {
98
+ await withWorkflowState(async (workflowState) => {
99
+ workflowState.state.readyToCommit = true;
100
+ workflowState.state.readyCheckCompleted = true;
101
+ workflowState.state.testsSkipped = false;
102
+ workflowState.state.testsCreated = true;
103
+ workflowState.state.testsPassed = true;
104
+ workflowState.state.currentPhase = "commit";
105
+ await workflowState.save();
106
+
107
+ const commands = [];
108
+ const execStub = async (command) => {
109
+ commands.push(command);
110
+ return { stdout: "" };
111
+ };
112
+
113
+ const response = await handleToolCall({
114
+ request: createRequest("commit_and_push", { commitMessage: "feat: test" }),
115
+ normalizeRequestArgs: (args) => ({ args, error: null }),
116
+ workflowState,
117
+ exec: execStub,
118
+ git: createGitMock({
119
+ hasWorkingChanges: async () => true,
120
+ getStagedChanges: async () => [{ status: "M", path: "src/index.js" }],
121
+ getPrimaryBranch: async () => "master",
122
+ getStatusOutput: async () => "M tests/handlers.test.js\nM src/index.js",
123
+ containsTestFilesInStatus: (statusOutput) => statusOutput.includes("tests/"),
124
+ }),
125
+ utils: testUtils,
126
+ });
127
+
128
+ const pushCommand = commands.find((command) => command.startsWith("git push"));
129
+ assert.ok(pushCommand, "git push should be executed");
130
+ assert.ok(
131
+ /origin\s+['"]?master['"]?/.test(pushCommand),
132
+ "push should use master when main not found"
133
+ );
134
+ });
135
+ });
136
+
137
+ test("commit_and_push recognizes already committed work", async () => {
138
+ await withWorkflowState(async (workflowState) => {
139
+ workflowState.state.readyToCommit = true;
140
+ workflowState.state.readyCheckCompleted = true;
141
+ workflowState.state.testsSkipped = false;
142
+ workflowState.state.testsCreated = true;
143
+ workflowState.state.testsPassed = true;
144
+ workflowState.state.currentPhase = "commit";
145
+ await workflowState.save();
146
+
147
+ const commands = [];
148
+ const execStub = async (command) => {
149
+ commands.push(command);
150
+ return { stdout: "" };
151
+ };
152
+
153
+ const response = await handleToolCall({
154
+ request: createRequest("commit_and_push", { commitMessage: "" }),
155
+ normalizeRequestArgs: (args) => ({ args, error: null }),
156
+ workflowState,
157
+ exec: execStub,
158
+ git: createGitMock({
159
+ hasWorkingChanges: async () => false,
160
+ getLastCommitMessage: async () => "fix: previous work",
161
+ getStatusOutput: async () => "",
162
+ containsTestFilesInStatus: (statusOutput) => statusOutput.includes("tests/"),
163
+ }),
164
+ utils: testUtils,
165
+ });
166
+
167
+ assert.ok(
168
+ response.content[0].text.includes("No changes detected"),
169
+ "response should indicate no changes"
170
+ );
171
+ assert.equal(workflowState.state.commitAndPushCompleted, true);
172
+ assert.equal(workflowState.state.currentPhase, "release");
173
+ });
174
+ });
@@ -0,0 +1,212 @@
1
+ import test from "node:test";
2
+ import assert from "node:assert/strict";
3
+ import { handleToolCall } from "../tools/handlers.js";
4
+ import { withWorkflowState, testUtils, createRequest, createGitMock } from "./test-helpers.js";
5
+
6
+ test("perform_release runs release command before pushing with tags", async () => {
7
+ await withWorkflowState(async (workflowState) => {
8
+ workflowState.state.currentPhase = "release";
9
+ workflowState.state.commitAndPushCompleted = true;
10
+ workflowState.state.readyCheckCompleted = true;
11
+ workflowState.state.lastPushBranch = "feature/split";
12
+ workflowState.state.lastCommitMessage = "fix: address issue";
13
+ await workflowState.save();
14
+
15
+ const commands = [];
16
+ const execStub = async (command) => {
17
+ commands.push(command);
18
+ if (command === "git status --porcelain") {
19
+ return { stdout: "" };
20
+ }
21
+ return { stdout: "" };
22
+ };
23
+
24
+ const response = await handleToolCall({
25
+ request: createRequest("perform_release", { command: "npm run release" }),
26
+ normalizeRequestArgs: (args) => ({ args, error: null }),
27
+ workflowState,
28
+ exec: execStub,
29
+ git: createGitMock(),
30
+ utils: testUtils,
31
+ });
32
+
33
+ const releaseCommand = commands.find((command) => command.startsWith("npm run release"));
34
+ assert.ok(releaseCommand, "release command should run");
35
+ assert.ok(
36
+ commands.some((command) => command.startsWith("git push --follow-tags")),
37
+ "release should push tags"
38
+ );
39
+ });
40
+ });
41
+
42
+ test("perform_release accepts shorthand patch command", async () => {
43
+ await withWorkflowState(async (workflowState) => {
44
+ workflowState.state.currentPhase = "release";
45
+ workflowState.state.commitAndPushCompleted = true;
46
+ workflowState.state.readyCheckCompleted = true;
47
+ workflowState.state.lastCommitMessage = "fix: adjust labels";
48
+ await workflowState.save();
49
+
50
+ const commands = [];
51
+ const execStub = async (command) => {
52
+ commands.push(command);
53
+ if (command === "git status --porcelain") {
54
+ return { stdout: "" };
55
+ }
56
+ return { stdout: "" };
57
+ };
58
+
59
+ await handleToolCall({
60
+ request: createRequest("perform_release", { command: "patch" }),
61
+ normalizeRequestArgs: (args) => ({ args, error: null }),
62
+ workflowState,
63
+ exec: execStub,
64
+ git: createGitMock(),
65
+ utils: testUtils,
66
+ });
67
+
68
+ const releaseCommand = commands.find((command) => command.startsWith("npm run release"));
69
+ assert.ok(releaseCommand, "release command should run with patch");
70
+ });
71
+ });
72
+
73
+ test("perform_release respects explicit releaseType option", async () => {
74
+ await withWorkflowState(async (workflowState) => {
75
+ workflowState.state.currentPhase = "release";
76
+ workflowState.state.commitAndPushCompleted = true;
77
+ workflowState.state.readyCheckCompleted = true;
78
+ await workflowState.save();
79
+
80
+ const commands = [];
81
+ const execStub = async (command) => {
82
+ commands.push(command);
83
+ if (command === "git status --porcelain") {
84
+ return { stdout: "" };
85
+ }
86
+ return { stdout: "" };
87
+ };
88
+
89
+ await handleToolCall({
90
+ request: createRequest("perform_release", {
91
+ command: "npm run release",
92
+ releaseType: "minor",
93
+ }),
94
+ normalizeRequestArgs: (args) => ({ args, error: null }),
95
+ workflowState,
96
+ exec: execStub,
97
+ git: createGitMock(),
98
+ utils: testUtils,
99
+ });
100
+
101
+ const releaseCommand = commands.find((command) => command.startsWith("npm run release"));
102
+ assert.ok(releaseCommand, "release command should run");
103
+ assert.ok(
104
+ releaseCommand.includes("-- --release-as minor"),
105
+ "release command should append provided releaseType"
106
+ );
107
+ });
108
+ });
109
+
110
+ test("perform_release blocks when new changes detected", async () => {
111
+ await withWorkflowState(async (workflowState) => {
112
+ workflowState.state.currentPhase = "release";
113
+ workflowState.state.commitAndPushCompleted = true;
114
+ workflowState.state.readyCheckCompleted = true;
115
+ await workflowState.save();
116
+
117
+ const commands = [];
118
+ const execStub = async (command) => {
119
+ commands.push(command);
120
+ if (command === "git status --porcelain") {
121
+ return { stdout: "?? new-file.js" };
122
+ }
123
+ return { stdout: "" };
124
+ };
125
+
126
+ const response = await handleToolCall({
127
+ request: createRequest("perform_release", { command: "patch" }),
128
+ normalizeRequestArgs: (args) => ({ args, error: null }),
129
+ workflowState,
130
+ exec: execStub,
131
+ git: createGitMock({
132
+ hasWorkingChanges: async () => true,
133
+ getStatusOutput: async () => "?? new-file.js",
134
+ containsTestFilesInStatus: (statusOutput) => statusOutput.includes("tests/"),
135
+ workingTreeSummary: () => ({ hasChanges: true, lines: ["?? new-file.js"] }),
136
+ }),
137
+ utils: testUtils,
138
+ });
139
+
140
+ assert.ok(
141
+ response.content[0].text.includes("run 'commit_and_push' again"),
142
+ "response should instruct to recommit"
143
+ );
144
+ assert.equal(workflowState.state.currentPhase, "commit");
145
+ assert.equal(workflowState.state.commitAndPushCompleted, false);
146
+ });
147
+ });
148
+
149
+ test("perform_release requires commit_and_push completion when tree is clean", async () => {
150
+ await withWorkflowState(async (workflowState) => {
151
+ workflowState.state.currentPhase = "release";
152
+ workflowState.state.commitAndPushCompleted = false;
153
+ workflowState.state.readyCheckCompleted = true;
154
+ workflowState.state.lastPushBranch = "";
155
+ workflowState.state.lastCommitMessage = "";
156
+ await workflowState.save();
157
+
158
+ const commands = [];
159
+ const execStub = async (command) => {
160
+ commands.push(command);
161
+ return { stdout: "" };
162
+ };
163
+
164
+ const response = await handleToolCall({
165
+ request: createRequest("perform_release", { command: "npm run release" }),
166
+ normalizeRequestArgs: (args) => ({ args, error: null }),
167
+ workflowState,
168
+ exec: execStub,
169
+ git: createGitMock({
170
+ getLastCommitMessage: async () => "chore: already pushed",
171
+ getStatusOutput: async () => "",
172
+ containsTestFilesInStatus: (statusOutput) => statusOutput.includes("tests/"),
173
+ }),
174
+ utils: testUtils,
175
+ });
176
+
177
+ assert.ok(
178
+ response.content[0].text.includes("commit_and_push"),
179
+ "response should mention commit_and_push requirement"
180
+ );
181
+ });
182
+ });
183
+
184
+ test("skip_release records justification and advances to completion phase", async () => {
185
+ await withWorkflowState(async (workflowState) => {
186
+ workflowState.state.currentPhase = "release";
187
+ workflowState.state.commitAndPushCompleted = true;
188
+ workflowState.state.readyCheckCompleted = true;
189
+ workflowState.state.lastCommitMessage = "chore: docs";
190
+ workflowState.state.releaseSkipped = false;
191
+ workflowState.state.released = false;
192
+ workflowState.state.releaseCommand = "";
193
+ await workflowState.save();
194
+
195
+ const response = await handleToolCall({
196
+ request: createRequest("skip_release", { reason: "Python project – no npm release" }),
197
+ normalizeRequestArgs: (args) => ({ args, error: null }),
198
+ workflowState,
199
+ exec: async () => ({ stdout: "" }),
200
+ git: createGitMock(),
201
+ utils: testUtils,
202
+ });
203
+
204
+ const text = response.content[0].text;
205
+ assert.ok(text.includes("Release step skipped"), "response should mention release was skipped");
206
+ assert.equal(workflowState.state.releaseSkipped, true);
207
+ assert.equal(workflowState.state.releaseSkippedReason, "Python project – no npm release");
208
+ assert.equal(workflowState.state.releaseCommand, "(skipped)");
209
+ assert.equal(workflowState.state.currentPhase, "ready_to_complete");
210
+ assert.equal(workflowState.state.released, false);
211
+ });
212
+ });
@@ -0,0 +1,68 @@
1
+ import test from "node:test";
2
+ import assert from "node:assert/strict";
3
+ import { handleToolCall } from "../tools/handlers.js";
4
+ import { withWorkflowState, testUtils, createRequest, createGitMock } from "./test-helpers.js";
5
+
6
+ test("run_tests guidance mentions core documentation types", async () => {
7
+ await withWorkflowState(async (workflowState) => {
8
+ workflowState.state.bugFixed = true;
9
+ workflowState.state.testsCreated = true;
10
+ await workflowState.save();
11
+
12
+ const response = await handleToolCall({
13
+ request: createRequest("run_tests", {
14
+ passed: true,
15
+ testCommand: "npm test",
16
+ }),
17
+ normalizeRequestArgs: (args) => ({ args, error: null }),
18
+ workflowState,
19
+ exec: async () => ({ stdout: "" }),
20
+ git: createGitMock(),
21
+ utils: testUtils,
22
+ });
23
+
24
+ const text = response.content[0].text;
25
+ assert.ok(
26
+ text.includes("create or update documentation using 'create_documentation'"),
27
+ "run_tests guidance should mention create or update documentation",
28
+ );
29
+ assert.ok(
30
+ text.includes('"PRD", "README", "RELEASE_NOTES"'),
31
+ "run_tests guidance should list core documentation types",
32
+ );
33
+ });
34
+ });
35
+
36
+ test("create_documentation verifies PRD file exists", async () => {
37
+ await withWorkflowState(async (workflowState) => {
38
+ workflowState.state.testsPassed = true;
39
+ await workflowState.save();
40
+
41
+ const response = await handleToolCall({
42
+ request: createRequest("create_documentation", {
43
+ documentationType: "PRD",
44
+ summary: "Updated PRD for documentation workflow expectations",
45
+ }),
46
+ normalizeRequestArgs: (args) => ({ args, error: null }),
47
+ workflowState,
48
+ exec: async () => ({ stdout: "" }),
49
+ git: createGitMock(),
50
+ utils: testUtils,
51
+ });
52
+
53
+ assert.equal(workflowState.state.documentationCreated, true);
54
+ assert.equal(workflowState.state.documentationType, "PRD");
55
+ assert.equal(
56
+ workflowState.state.documentationSummary,
57
+ "Updated PRD for documentation workflow expectations",
58
+ );
59
+ assert.ok(
60
+ response.content[0].text.includes("Documentation created/updated!"),
61
+ "create_documentation response should mention created/updated",
62
+ );
63
+ assert.ok(
64
+ response.content[0].text.includes("PRD verified"),
65
+ "create_documentation response should verify PRD file",
66
+ );
67
+ });
68
+ });