sdd-mcp-server 4.0.0 → 5.0.0
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/README.md +18 -35
- package/dist/adapters/cli/SDDToolAdapter.d.ts +2 -5
- package/dist/adapters/cli/SDDToolAdapter.js +48 -92
- package/dist/adapters/cli/SDDToolAdapter.js.map +1 -1
- package/dist/application/services/ContextCompactionService.d.ts +10 -3
- package/dist/application/services/ContextCompactionService.js +139 -35
- package/dist/application/services/ContextCompactionService.js.map +1 -1
- package/dist/application/services/ProjectService.js +3 -3
- package/dist/application/services/ProjectService.js.map +1 -1
- package/dist/application/services/SpecPathResolver.js +1 -1
- package/dist/application/services/SpecPathResolver.js.map +1 -1
- package/dist/application/services/WorkflowEngineService.d.ts +160 -50
- package/dist/application/services/WorkflowEngineService.js +1404 -429
- package/dist/application/services/WorkflowEngineService.js.map +1 -1
- package/dist/application/services/WorkflowErrors.d.ts +16 -0
- package/dist/application/services/WorkflowErrors.js +53 -0
- package/dist/application/services/WorkflowErrors.js.map +1 -0
- package/dist/application/services/WorkflowValidationService.d.ts +25 -46
- package/dist/application/services/WorkflowValidationService.js +284 -627
- package/dist/application/services/WorkflowValidationService.js.map +1 -1
- package/dist/cli/install-skills.js.map +1 -1
- package/dist/cli/install-target.d.ts +4 -1
- package/dist/cli/install-target.js +4 -0
- package/dist/cli/install-target.js.map +1 -1
- package/dist/cli/tool-support/claude-code.js +7 -3
- package/dist/cli/tool-support/claude-code.js.map +1 -1
- package/dist/cli/tool-support/codex.js +6 -2
- package/dist/cli/tool-support/codex.js.map +1 -1
- package/dist/cli/tool-support/mcp-registration.d.ts +22 -0
- package/dist/cli/tool-support/mcp-registration.js +275 -0
- package/dist/cli/tool-support/mcp-registration.js.map +1 -0
- package/dist/cli/tool-support/omp.js +6 -2
- package/dist/cli/tool-support/omp.js.map +1 -1
- package/dist/cli/tool-support/root-guidance.js +2 -2
- package/dist/cli/tool-support/root-guidance.js.map +1 -1
- package/dist/cli/tool-support/target-installer.d.ts +2 -2
- package/dist/cli/tool-support/target-installer.js +9 -3
- package/dist/cli/tool-support/target-installer.js.map +1 -1
- package/dist/cli/utils/preserving-writer.d.ts +35 -1
- package/dist/cli/utils/preserving-writer.js +479 -108
- package/dist/cli/utils/preserving-writer.js.map +1 -1
- package/dist/domain/types.d.ts +52 -7
- package/dist/domain/types.js +5 -4
- package/dist/domain/types.js.map +1 -1
- package/dist/infrastructure/mcp/MCPServer.js +13 -13
- package/dist/infrastructure/mcp/MCPServer.js.map +1 -1
- package/dist/infrastructure/mcp/ToolRegistry.d.ts +5 -1
- package/dist/infrastructure/mcp/ToolRegistry.js +11 -4
- package/dist/infrastructure/mcp/ToolRegistry.js.map +1 -1
- package/dist/infrastructure/mcp/sddToolDefinitions.js +76 -90
- package/dist/infrastructure/mcp/sddToolDefinitions.js.map +1 -1
- package/dist/infrastructure/schemas/project.schema.d.ts +2 -2
- package/dist/infrastructure/schemas/project.schema.js +2 -2
- package/dist/infrastructure/schemas/project.schema.js.map +1 -1
- package/dist/shared/version.d.ts +3 -0
- package/dist/shared/version.js +4 -0
- package/dist/shared/version.js.map +1 -0
- package/dist/utils/atomicWrite.js +20 -5
- package/dist/utils/atomicWrite.js.map +1 -1
- package/dist/utils/withFilesystemLock.d.ts +22 -0
- package/dist/utils/withFilesystemLock.js +219 -0
- package/dist/utils/withFilesystemLock.js.map +1 -0
- package/package.json +4 -2
- package/skills/sdd-design/REFERENCE.md +16 -0
- package/skills/sdd-design/SKILL.md +22 -13
- package/skills/sdd-implement/REFERENCE.md +4 -0
- package/skills/sdd-implement/SKILL.md +20 -16
- package/skills/sdd-requirements/REFERENCE.md +15 -7
- package/skills/sdd-requirements/SKILL.md +30 -22
- package/skills/sdd-tasks/REFERENCE.md +9 -9
- package/skills/sdd-tasks/SKILL.md +27 -15
- package/templates/CLAUDE.md +6 -12
- package/templates/codex-AGENTS.md +7 -9
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sddToolDefinitions.js","sourceRoot":"","sources":["../../../src/infrastructure/mcp/sddToolDefinitions.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,cAAc,GAAG;IAC5B,UAAU
|
|
1
|
+
{"version":3,"file":"sddToolDefinitions.js","sourceRoot":"","sources":["../../../src/infrastructure/mcp/sddToolDefinitions.ts"],"names":[],"mappings":"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"}
|
|
@@ -15,7 +15,7 @@ export declare const projectSchema: {
|
|
|
15
15
|
};
|
|
16
16
|
readonly phase: {
|
|
17
17
|
readonly type: "string";
|
|
18
|
-
readonly enum: readonly ["init", "requirements
|
|
18
|
+
readonly enum: readonly ["init", "requirements", "design", "tasks", "implementation", "implementation-completed"];
|
|
19
19
|
};
|
|
20
20
|
readonly metadata: {
|
|
21
21
|
readonly type: "object";
|
|
@@ -86,7 +86,7 @@ export declare const projectSchema: {
|
|
|
86
86
|
readonly type: "object";
|
|
87
87
|
readonly properties: {
|
|
88
88
|
readonly reviewTestCases: {
|
|
89
|
-
readonly type: "boolean";
|
|
89
|
+
readonly type: readonly ["boolean", "null"];
|
|
90
90
|
};
|
|
91
91
|
};
|
|
92
92
|
readonly required: readonly ["reviewTestCases"];
|
|
@@ -7,7 +7,7 @@ export const projectSchema = {
|
|
|
7
7
|
path: { type: 'string', minLength: 1 },
|
|
8
8
|
phase: {
|
|
9
9
|
type: 'string',
|
|
10
|
-
enum: ['init', 'requirements
|
|
10
|
+
enum: ['init', 'requirements', 'design', 'tasks', 'implementation', 'implementation-completed']
|
|
11
11
|
},
|
|
12
12
|
metadata: {
|
|
13
13
|
type: 'object',
|
|
@@ -58,7 +58,7 @@ export const projectSchema = {
|
|
|
58
58
|
workflowOptions: {
|
|
59
59
|
type: 'object',
|
|
60
60
|
properties: {
|
|
61
|
-
reviewTestCases: { type: 'boolean' }
|
|
61
|
+
reviewTestCases: { type: ['boolean', 'null'] }
|
|
62
62
|
},
|
|
63
63
|
required: ['reviewTestCases']
|
|
64
64
|
},
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"project.schema.js","sourceRoot":"","sources":["../../../src/infrastructure/schemas/project.schema.ts"],"names":[],"mappings":"AAAA,2CAA2C;AAE3C,MAAM,CAAC,MAAM,aAAa,GAAG;IAC3B,IAAI,EAAE,QAAQ;IACd,UAAU,EAAE;QACV,EAAE,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,SAAS,EAAE,CAAC,EAAE;QACpC,IAAI,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,SAAS,EAAE,CAAC,EAAE;QACtC,IAAI,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,SAAS,EAAE,CAAC,EAAE;QACtC,KAAK,EAAE;YACL,IAAI,EAAE,QAAQ;YACd,IAAI,EAAE,CAAC,MAAM,EAAE,
|
|
1
|
+
{"version":3,"file":"project.schema.js","sourceRoot":"","sources":["../../../src/infrastructure/schemas/project.schema.ts"],"names":[],"mappings":"AAAA,2CAA2C;AAE3C,MAAM,CAAC,MAAM,aAAa,GAAG;IAC3B,IAAI,EAAE,QAAQ;IACd,UAAU,EAAE;QACV,EAAE,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,SAAS,EAAE,CAAC,EAAE;QACpC,IAAI,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,SAAS,EAAE,CAAC,EAAE;QACtC,IAAI,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,SAAS,EAAE,CAAC,EAAE;QACtC,KAAK,EAAE;YACL,IAAI,EAAE,QAAQ;YACd,IAAI,EAAE,CAAC,MAAM,EAAE,cAAc,EAAE,QAAQ,EAAE,OAAO,EAAE,gBAAgB,EAAE,0BAA0B,CAAC;SAChG;QACD,QAAQ,EAAE;YACR,IAAI,EAAE,QAAQ;YACd,UAAU,EAAE;gBACV,SAAS,EAAE;oBACT,KAAK,EAAE;wBACL,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,WAAW,EAAE;wBACvC,EAAE,IAAI,EAAE,QAAQ,EAAE;qBACnB;iBACF;gBACD,SAAS,EAAE;oBACT,KAAK,EAAE;wBACL,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,WAAW,EAAE;wBACvC,EAAE,IAAI,EAAE,QAAQ,EAAE;qBACnB;iBACF;gBACD,QAAQ,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,CAAC,EAAE;gBACzD,SAAS,EAAE;oBACT,IAAI,EAAE,QAAQ;oBACd,UAAU,EAAE;wBACV,YAAY,EAAE;4BACZ,IAAI,EAAE,QAAQ;4BACd,UAAU,EAAE;gCACV,SAAS,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE;gCAC9B,QAAQ,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE;6BAC9B;4BACD,QAAQ,EAAE,CAAC,WAAW,EAAE,UAAU,CAAC;yBACpC;wBACD,MAAM,EAAE;4BACN,IAAI,EAAE,QAAQ;4BACd,UAAU,EAAE;gCACV,SAAS,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE;gCAC9B,QAAQ,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE;6BAC9B;4BACD,QAAQ,EAAE,CAAC,WAAW,EAAE,UAAU,CAAC;yBACpC;wBACD,KAAK,EAAE;4BACL,IAAI,EAAE,QAAQ;4BACd,UAAU,EAAE;gCACV,SAAS,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE;gCAC9B,QAAQ,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE;6BAC9B;4BACD,QAAQ,EAAE,CAAC,WAAW,EAAE,UAAU,CAAC;yBACpC;qBACF;oBACD,QAAQ,EAAE,CAAC,cAAc,EAAE,QAAQ,EAAE,OAAO,CAAC;iBAC9C;gBACD,eAAe,EAAE;oBACf,IAAI,EAAE,QAAQ;oBACd,UAAU,EAAE;wBACV,eAAe,EAAE,EAAE,IAAI,EAAE,CAAC,SAAS,EAAE,MAAM,CAAC,EAAE;qBAC/C;oBACD,QAAQ,EAAE,CAAC,iBAAiB,CAAC;iBAC9B;gBACD,WAAW,EAAE;oBACX,IAAI,EAAE,QAAQ;oBACd,UAAU,EAAE;wBACV,SAAS,EAAE;4BACT,IAAI,EAAE,QAAQ;4BACd,UAAU,EAAE;gCACV,QAAQ,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE;gCAC7B,QAAQ,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE;gCAC7B,UAAU,EAAE;oCACV,KAAK,EAAE;wCACL,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,WAAW,EAAE;wCACvC,EAAE,IAAI,EAAE,QAAQ,EAAE;qCACnB;iCACF;6BACF;4BACD,QAAQ,EAAE,CAAC,UAAU,EAAE,UAAU,CAAC;yBACnC;qBACF;oBACD,QAAQ,EAAE,CAAC,WAAW,CAAC;iBACxB;aACF;YACD,QAAQ,EAAE,CAAC,WAAW,EAAE,WAAW,EAAE,UAAU,EAAE,WAAW,CAAC;SAC9D;KACF;IACD,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,UAAU,CAAC;CAC7C,CAAC;AAEX,MAAM,CAAC,MAAM,iBAAiB,GAAG;IAC/B,IAAI,EAAE,QAAQ;IACd,UAAU,EAAE;QACV,EAAE,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,SAAS,EAAE,CAAC,EAAE;QACpC,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,SAAS,EAAE,CAAC,EAAE;QACvC,SAAS,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,SAAS,EAAE,CAAC,EAAE;QAC3C,kBAAkB,EAAE;YAClB,IAAI,EAAE,OAAO;YACb,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,SAAS,EAAE,CAAC,EAAE;YACvC,QAAQ,EAAE,CAAC;SACZ;KACF;IACD,QAAQ,EAAE,CAAC,IAAI,EAAE,OAAO,EAAE,WAAW,EAAE,oBAAoB,CAAC;CACpD,CAAC;AAEX,MAAM,CAAC,MAAM,UAAU,GAAG;IACxB,IAAI,EAAE,QAAQ;IACd,UAAU,EAAE;QACV,EAAE,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,SAAS,EAAE,CAAC,EAAE;QACpC,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,SAAS,EAAE,CAAC,EAAE;QACvC,WAAW,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,SAAS,EAAE,CAAC,EAAE;QAC7C,YAAY,EAAE;YACZ,IAAI,EAAE,OAAO;YACb,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,SAAS,EAAE,CAAC,EAAE;SACxC;QACD,SAAS,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE;KAC/B;IACD,QAAQ,EAAE,CAAC,IAAI,EAAE,OAAO,EAAE,aAAa,EAAE,cAAc,EAAE,WAAW,CAAC;CAC7D,CAAC;AAEX,MAAM,CAAC,MAAM,mBAAmB,GAAG;IACjC,IAAI,EAAE,QAAQ;IACd,UAAU,EAAE;QACV,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,MAAM,EAAE,UAAU,EAAE,SAAS,CAAC,EAAE;QAChE,MAAM,EAAE;YACN,IAAI,EAAE,OAAO;YACb,KAAK,EAAE;gBACL,IAAI,EAAE,QAAQ;gBACd,UAAU,EAAE;oBACV,IAAI,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,YAAY,EAAE,cAAc,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,cAAc,CAAC,EAAE;oBACnH,OAAO,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,SAAS,EAAE,CAAC,EAAE;oBACzC,QAAQ,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,OAAO,EAAE,SAAS,EAAE,MAAM,CAAC,EAAE;oBAChE,QAAQ,EAAE;wBACR,IAAI,EAAE,QAAQ;wBACd,UAAU,EAAE;4BACV,IAAI,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,SAAS,EAAE,CAAC,EAAE;4BACtC,IAAI,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC,EAAE;4BACpC,MAAM,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC,EAAE;yBACvC;wBACD,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,CAAC;qBACrC;iBACF;gBACD,QAAQ,EAAE,CAAC,MAAM,EAAE,SAAS,EAAE,UAAU,CAAC;aAC1C;SACF;QACD,eAAe,EAAE;YACf,IAAI,EAAE,OAAO;YACb,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,SAAS,EAAE,CAAC,EAAE;SACxC;KACF;IACD,QAAQ,EAAE,CAAC,OAAO,EAAE,QAAQ,EAAE,iBAAiB,CAAC;CACxC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"version.js","sourceRoot":"","sources":["../../src/shared/version.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,eAAe,GAAG,OAAO,CAAC;AACvC,MAAM,CAAC,MAAM,+BAA+B,GAAG,CAAC,CAAC;AACjD,MAAM,CAAC,MAAM,wBAAwB,GAAG,CAAC,CAAC"}
|
|
@@ -1,17 +1,32 @@
|
|
|
1
1
|
import { mkdir } from 'node:fs/promises';
|
|
2
|
-
import { dirname } from 'node:path';
|
|
2
|
+
import { dirname, resolve } from 'node:path';
|
|
3
3
|
import writeFileAtomic from "write-file-atomic";
|
|
4
|
+
const pendingWrites = new Map();
|
|
4
5
|
/**
|
|
5
6
|
* Atomically replaces a file. `write-file-atomic` queues concurrent writes to
|
|
6
7
|
* the same destination, preserves an existing mode by default, cleans its
|
|
7
8
|
* temporary file on failure, and implements replacement on Windows.
|
|
8
9
|
*/
|
|
9
10
|
export async function atomicWriteFile(filePath, content, options = {}) {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
11
|
+
const key = resolve(filePath);
|
|
12
|
+
const prior = pendingWrites.get(key) ?? Promise.resolve();
|
|
13
|
+
const operation = prior
|
|
14
|
+
.catch(() => undefined)
|
|
15
|
+
.then(async () => {
|
|
16
|
+
await mkdir(dirname(filePath), { recursive: true });
|
|
17
|
+
await writeFileAtomic(filePath, content, {
|
|
18
|
+
encoding: options.encoding ?? "utf8",
|
|
19
|
+
mode: options.mode,
|
|
20
|
+
});
|
|
14
21
|
});
|
|
22
|
+
pendingWrites.set(key, operation);
|
|
23
|
+
try {
|
|
24
|
+
await operation;
|
|
25
|
+
}
|
|
26
|
+
finally {
|
|
27
|
+
if (pendingWrites.get(key) === operation)
|
|
28
|
+
pendingWrites.delete(key);
|
|
29
|
+
}
|
|
15
30
|
}
|
|
16
31
|
/**
|
|
17
32
|
* Write JSON content to a file atomically.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"atomicWrite.js","sourceRoot":"","sources":["../../src/utils/atomicWrite.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AACzC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"atomicWrite.js","sourceRoot":"","sources":["../../src/utils/atomicWrite.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AACzC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAC7C,OAAO,eAAe,MAAM,mBAAmB,CAAC;AAEhD,MAAM,aAAa,GAAG,IAAI,GAAG,EAAyB,CAAC;AAOvD;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,QAAgB,EAChB,OAAe,EACf,UAA8B,EAAE;IAEhC,MAAM,GAAG,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;IAC9B,MAAM,KAAK,GAAG,aAAa,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;IAC1D,MAAM,SAAS,GAAG,KAAK;SACpB,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC;SACtB,IAAI,CAAC,KAAK,IAAI,EAAE;QACf,MAAM,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACpD,MAAM,eAAe,CAAC,QAAQ,EAAE,OAAO,EAAE;YACvC,QAAQ,EAAE,OAAO,CAAC,QAAQ,IAAI,MAAM;YACpC,IAAI,EAAE,OAAO,CAAC,IAAI;SACnB,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IACL,aAAa,CAAC,GAAG,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;IAClC,IAAI,CAAC;QACH,MAAM,SAAS,CAAC;IAClB,CAAC;YAAS,CAAC;QACT,IAAI,aAAa,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,SAAS;YAAE,aAAa,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IACtE,CAAC;AACH,CAAC;AAED;;;;;;;;;;;;;;GAcG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,QAAgB,EAChB,IAAa,EACb,OAA6B;IAE7B,MAAM,MAAM,GAAG,OAAO,EAAE,MAAM,IAAI,CAAC,CAAC;IACpC,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC;IACnD,MAAM,eAAe,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;AAC3C,CAAC"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export interface FilesystemLockLease {
|
|
2
|
+
assertHeld(): Promise<void>;
|
|
3
|
+
}
|
|
4
|
+
export interface FilesystemLockOptions {
|
|
5
|
+
timeoutMs?: number;
|
|
6
|
+
retryDelayMs?: number;
|
|
7
|
+
}
|
|
8
|
+
export declare class FilesystemLockTimeoutError extends Error {
|
|
9
|
+
readonly lockPath: string;
|
|
10
|
+
readonly code = "LockTimeout";
|
|
11
|
+
constructor(lockPath: string);
|
|
12
|
+
}
|
|
13
|
+
export declare class FilesystemLockCompromisedError extends Error {
|
|
14
|
+
readonly lockPath: string;
|
|
15
|
+
readonly code = "LockCompromised";
|
|
16
|
+
constructor(lockPath: string);
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Runs an action while holding a token-fenced, cross-process filesystem lease.
|
|
20
|
+
* Call assertHeld immediately after every durable write made by the action.
|
|
21
|
+
*/
|
|
22
|
+
export declare function withFilesystemLock<T>(lockPath: string, action: (lease: FilesystemLockLease) => Promise<T>, options?: FilesystemLockOptions): Promise<T>;
|
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
import { randomUUID } from 'node:crypto';
|
|
2
|
+
import { link, lstat, mkdir, open, rename, unlink } from 'node:fs/promises';
|
|
3
|
+
import { hostname as localHostname } from 'node:os';
|
|
4
|
+
import { basename, dirname, join } from 'node:path';
|
|
5
|
+
export class FilesystemLockTimeoutError extends Error {
|
|
6
|
+
lockPath;
|
|
7
|
+
code = 'LockTimeout';
|
|
8
|
+
constructor(lockPath) {
|
|
9
|
+
super(`Timed out acquiring filesystem lock: ${lockPath}`);
|
|
10
|
+
this.lockPath = lockPath;
|
|
11
|
+
this.name = 'FilesystemLockTimeoutError';
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
export class FilesystemLockCompromisedError extends Error {
|
|
15
|
+
lockPath;
|
|
16
|
+
code = 'LockCompromised';
|
|
17
|
+
constructor(lockPath) {
|
|
18
|
+
super(`Filesystem lock ownership was lost: ${lockPath}`);
|
|
19
|
+
this.lockPath = lockPath;
|
|
20
|
+
this.name = 'FilesystemLockCompromisedError';
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
function parseOwner(bytes) {
|
|
24
|
+
try {
|
|
25
|
+
const value = JSON.parse(bytes);
|
|
26
|
+
if (typeof value.token !== 'string' || value.token.length === 0
|
|
27
|
+
|| !Number.isSafeInteger(value.pid) || value.pid <= 0
|
|
28
|
+
|| typeof value.hostname !== 'string' || value.hostname.length === 0)
|
|
29
|
+
return undefined;
|
|
30
|
+
return value;
|
|
31
|
+
}
|
|
32
|
+
catch {
|
|
33
|
+
return undefined;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
async function readSnapshot(lockPath) {
|
|
37
|
+
let handle;
|
|
38
|
+
try {
|
|
39
|
+
handle = await open(lockPath, 'r');
|
|
40
|
+
}
|
|
41
|
+
catch (error) {
|
|
42
|
+
if (error.code === 'ENOENT')
|
|
43
|
+
return undefined;
|
|
44
|
+
throw error;
|
|
45
|
+
}
|
|
46
|
+
try {
|
|
47
|
+
const stat = await handle.stat({ bigint: true });
|
|
48
|
+
const bytes = stat.size <= 4096n ? await handle.readFile('utf8') : undefined;
|
|
49
|
+
const canonical = await lstat(lockPath, { bigint: true }).catch((error) => {
|
|
50
|
+
if (error.code === 'ENOENT')
|
|
51
|
+
return undefined;
|
|
52
|
+
throw error;
|
|
53
|
+
});
|
|
54
|
+
if (!canonical || canonical.dev !== stat.dev || canonical.ino !== stat.ino)
|
|
55
|
+
return undefined;
|
|
56
|
+
return {
|
|
57
|
+
owner: bytes === undefined ? undefined : parseOwner(bytes),
|
|
58
|
+
identity: { dev: stat.dev, ino: stat.ino },
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
finally {
|
|
62
|
+
await handle.close();
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
function sameIdentity(left, right) {
|
|
66
|
+
return left.dev === right.dev && left.ino === right.ino;
|
|
67
|
+
}
|
|
68
|
+
function ownerIsProvenDead(owner, hostname) {
|
|
69
|
+
if (owner.hostname !== hostname)
|
|
70
|
+
return false;
|
|
71
|
+
try {
|
|
72
|
+
process.kill(owner.pid, 0);
|
|
73
|
+
return false;
|
|
74
|
+
}
|
|
75
|
+
catch (error) {
|
|
76
|
+
return error.code === 'ESRCH';
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
async function removeIfPresent(path) {
|
|
80
|
+
try {
|
|
81
|
+
await unlink(path);
|
|
82
|
+
}
|
|
83
|
+
catch (error) {
|
|
84
|
+
if (error.code !== 'ENOENT')
|
|
85
|
+
throw error;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
async function writeDurableOwner(path, owner) {
|
|
89
|
+
const handle = await open(path, 'wx', 0o600);
|
|
90
|
+
try {
|
|
91
|
+
await handle.writeFile(JSON.stringify(owner), 'utf8');
|
|
92
|
+
await handle.sync();
|
|
93
|
+
}
|
|
94
|
+
finally {
|
|
95
|
+
await handle.close();
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
async function tryEvictDeadOwner(lockPath, observed, hostname) {
|
|
99
|
+
if (!observed.owner || !ownerIsProvenDead(observed.owner, hostname))
|
|
100
|
+
return false;
|
|
101
|
+
const current = await readSnapshot(lockPath);
|
|
102
|
+
if (!current?.owner
|
|
103
|
+
|| current.owner.token !== observed.owner.token
|
|
104
|
+
|| !sameIdentity(current.identity, observed.identity)
|
|
105
|
+
|| !ownerIsProvenDead(current.owner, hostname))
|
|
106
|
+
return false;
|
|
107
|
+
const quarantine = join(dirname(lockPath), `.${basename(lockPath)}.${randomUUID()}.quarantine`);
|
|
108
|
+
try {
|
|
109
|
+
await rename(lockPath, quarantine);
|
|
110
|
+
}
|
|
111
|
+
catch (error) {
|
|
112
|
+
if (error.code === 'ENOENT')
|
|
113
|
+
return true;
|
|
114
|
+
throw error;
|
|
115
|
+
}
|
|
116
|
+
const moved = await readSnapshot(quarantine);
|
|
117
|
+
if (!moved?.owner
|
|
118
|
+
|| moved.owner.token !== observed.owner.token
|
|
119
|
+
|| moved.owner.pid !== observed.owner.pid
|
|
120
|
+
|| moved.owner.hostname !== observed.owner.hostname
|
|
121
|
+
|| !sameIdentity(moved.identity, observed.identity)) {
|
|
122
|
+
try {
|
|
123
|
+
await link(quarantine, lockPath);
|
|
124
|
+
}
|
|
125
|
+
catch {
|
|
126
|
+
// Preserve whichever owner currently occupies the canonical path.
|
|
127
|
+
}
|
|
128
|
+
await removeIfPresent(quarantine);
|
|
129
|
+
return false;
|
|
130
|
+
}
|
|
131
|
+
await removeIfPresent(quarantine);
|
|
132
|
+
return true;
|
|
133
|
+
}
|
|
134
|
+
async function delay(milliseconds) {
|
|
135
|
+
await new Promise((resolve) => setTimeout(resolve, milliseconds));
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Runs an action while holding a token-fenced, cross-process filesystem lease.
|
|
139
|
+
* Call assertHeld immediately after every durable write made by the action.
|
|
140
|
+
*/
|
|
141
|
+
export async function withFilesystemLock(lockPath, action, options = {}) {
|
|
142
|
+
const timeoutMs = options.timeoutMs ?? 2_000;
|
|
143
|
+
const retryDelayMs = options.retryDelayMs ?? 25;
|
|
144
|
+
const deadline = Date.now() + timeoutMs;
|
|
145
|
+
await mkdir(dirname(lockPath), { recursive: true });
|
|
146
|
+
const owner = { token: randomUUID(), pid: process.pid, hostname: localHostname() };
|
|
147
|
+
const tempPath = join(dirname(lockPath), `.${basename(lockPath)}.${owner.token}.tmp`);
|
|
148
|
+
await writeDurableOwner(tempPath, owner);
|
|
149
|
+
let acquired = false;
|
|
150
|
+
try {
|
|
151
|
+
while (!acquired) {
|
|
152
|
+
try {
|
|
153
|
+
await link(tempPath, lockPath);
|
|
154
|
+
acquired = true;
|
|
155
|
+
}
|
|
156
|
+
catch (error) {
|
|
157
|
+
const code = error.code;
|
|
158
|
+
if (code !== 'EEXIST')
|
|
159
|
+
throw error;
|
|
160
|
+
const observed = await readSnapshot(lockPath);
|
|
161
|
+
if (observed)
|
|
162
|
+
await tryEvictDeadOwner(lockPath, observed, owner.hostname);
|
|
163
|
+
if (Date.now() >= deadline)
|
|
164
|
+
throw new FilesystemLockTimeoutError(lockPath);
|
|
165
|
+
await delay(retryDelayMs);
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
finally {
|
|
170
|
+
await removeIfPresent(tempPath);
|
|
171
|
+
}
|
|
172
|
+
const acquiredSnapshot = await readSnapshot(lockPath);
|
|
173
|
+
if (!acquiredSnapshot?.owner || acquiredSnapshot.owner.token !== owner.token) {
|
|
174
|
+
throw new FilesystemLockCompromisedError(lockPath);
|
|
175
|
+
}
|
|
176
|
+
const assertHeld = async () => {
|
|
177
|
+
const current = await readSnapshot(lockPath);
|
|
178
|
+
if (!current?.owner
|
|
179
|
+
|| current.owner.token !== owner.token
|
|
180
|
+
|| !sameIdentity(current.identity, acquiredSnapshot.identity))
|
|
181
|
+
throw new FilesystemLockCompromisedError(lockPath);
|
|
182
|
+
};
|
|
183
|
+
let actionError;
|
|
184
|
+
let value;
|
|
185
|
+
try {
|
|
186
|
+
await assertHeld();
|
|
187
|
+
value = await action({ assertHeld });
|
|
188
|
+
}
|
|
189
|
+
catch (error) {
|
|
190
|
+
actionError = error;
|
|
191
|
+
}
|
|
192
|
+
try {
|
|
193
|
+
await assertHeld();
|
|
194
|
+
const releasePath = join(dirname(lockPath), `.${basename(lockPath)}.${owner.token}.release`);
|
|
195
|
+
await rename(lockPath, releasePath);
|
|
196
|
+
const released = await readSnapshot(releasePath);
|
|
197
|
+
if (!released?.owner
|
|
198
|
+
|| released.owner.token !== owner.token
|
|
199
|
+
|| !sameIdentity(released.identity, acquiredSnapshot.identity)) {
|
|
200
|
+
try {
|
|
201
|
+
await link(releasePath, lockPath);
|
|
202
|
+
}
|
|
203
|
+
catch {
|
|
204
|
+
// Preserve whichever owner currently occupies the canonical path.
|
|
205
|
+
}
|
|
206
|
+
throw new FilesystemLockCompromisedError(lockPath);
|
|
207
|
+
}
|
|
208
|
+
await removeIfPresent(releasePath);
|
|
209
|
+
}
|
|
210
|
+
catch (releaseError) {
|
|
211
|
+
if (actionError === undefined
|
|
212
|
+
|| releaseError instanceof FilesystemLockCompromisedError)
|
|
213
|
+
actionError = releaseError;
|
|
214
|
+
}
|
|
215
|
+
if (actionError !== undefined)
|
|
216
|
+
throw actionError;
|
|
217
|
+
return value;
|
|
218
|
+
}
|
|
219
|
+
//# sourceMappingURL=withFilesystemLock.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"withFilesystemLock.js","sourceRoot":"","sources":["../../src/utils/withFilesystemLock.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sdd-mcp-server",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "5.0.0",
|
|
4
4
|
"description": "MCP server for spec-driven development workflows across AI-agent CLIs and IDEs",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"bin": {
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
"test:e2e": "jest --testPathPattern=e2e.*\\.test\\.ts$",
|
|
39
39
|
"test:watch": "jest --watch",
|
|
40
40
|
"test:coverage": "jest --coverage",
|
|
41
|
-
"test:ci": "jest --coverage --ci --watchAll=false --passWithNoTests",
|
|
41
|
+
"test:ci": "jest --coverage --ci --runInBand --watchAll=false --passWithNoTests",
|
|
42
42
|
"lint": "eslint src --ext .ts",
|
|
43
43
|
"lint:fix": "eslint src --ext .ts --fix",
|
|
44
44
|
"typecheck": "tsc --noEmit",
|
|
@@ -75,8 +75,10 @@
|
|
|
75
75
|
"i18next-fs-backend": "^2.6.0",
|
|
76
76
|
"i18next-http-middleware": "^3.8.0",
|
|
77
77
|
"inversify": "^6.0.2",
|
|
78
|
+
"jsonc-parser": "^3.3.1",
|
|
78
79
|
"os-locale": "^6.0.2",
|
|
79
80
|
"reflect-metadata": "^0.2.2",
|
|
81
|
+
"smol-toml": "^1.7.0",
|
|
80
82
|
"uuid": "^11.1.1",
|
|
81
83
|
"write-file-atomic": "^5.0.1",
|
|
82
84
|
"zod": "^3.23.8"
|
|
@@ -9,6 +9,22 @@ Read only for format help after the mandatory core design workflow is understood
|
|
|
9
9
|
- Event-driven: asynchronous producers and consumers are inherent to the requirement.
|
|
10
10
|
- Service split: independent ownership/deployment is proven; do not choose it merely for fashion.
|
|
11
11
|
|
|
12
|
+
## Exact Document Shape
|
|
13
|
+
|
|
14
|
+
```markdown
|
|
15
|
+
# Design: Feature
|
|
16
|
+
## Requirements Traceability
|
|
17
|
+
## Architecture and Data Flow
|
|
18
|
+
## Components and Interfaces
|
|
19
|
+
### D-1: Decision title
|
|
20
|
+
**Covers:** FR-1, NFR-1
|
|
21
|
+
**Decision:** The chosen mechanism and trade-off.
|
|
22
|
+
**Failure behavior:** The observable safe failure.
|
|
23
|
+
**Verification:** How the decision is tested.
|
|
24
|
+
## Failure Handling
|
|
25
|
+
## Verification
|
|
26
|
+
```
|
|
27
|
+
|
|
12
28
|
## Component Template
|
|
13
29
|
|
|
14
30
|
```markdown
|
|
@@ -6,30 +6,39 @@ disable-model-invocation: true
|
|
|
6
6
|
|
|
7
7
|
# SDD Design
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
The user invokes this Skill; backend lifecycle calls are internal. Never tell the user to call a raw MCP tool or expose revision, hash, fingerprint, or backend JSON except in explicit debug output.
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
- Requirements must be generated and approved. Stop rather than designing from an unapproved draft.
|
|
13
|
-
- Read approved requirements plus relevant product, technology, and structure steering.
|
|
11
|
+
## Resolve and Restore
|
|
14
12
|
|
|
15
|
-
|
|
13
|
+
1. Internally resolve status. If no feature name is supplied, resume the sole incomplete feature or ask the user to select when several exist.
|
|
14
|
+
2. Requirements must be approved. If durable status says otherwise, present the persisted blocker and make no file change.
|
|
15
|
+
3. Load the latest approved compact context before method work. Load an unapproved design draft only with full mode and explicit unapproved inclusion.
|
|
16
|
+
4. If status reports an observed artifact identity for an orphan or manual edit, read that exact design file before revising. Never acknowledge its hash without inspecting and deliberately incorporating or replacing its content.
|
|
17
|
+
|
|
18
|
+
If the runtime is unavailable because of host permission, report an actionable reload/trust or policy blocker; never substitute manual backend instructions.
|
|
19
|
+
|
|
20
|
+
## Method and Artifact Contract
|
|
16
21
|
|
|
17
22
|
1. Map every FR/NFR and constraint to a design decision.
|
|
18
23
|
2. Define data ownership and flow before components. Choose the simplest fitting architecture and explain trade-offs.
|
|
19
|
-
3.
|
|
20
|
-
4.
|
|
21
|
-
5.
|
|
22
|
-
|
|
23
|
-
|
|
24
|
+
3. Include exact headings `## Requirements Traceability`, `## Architecture and Data Flow`, `## Components and Interfaces`, `## Failure Handling`, and `## Verification`.
|
|
25
|
+
4. Give each decision a unique `### D-N: ...` section with same-line labels `**Covers:**`, `**Decision:**`, `**Failure behavior:**`, and `**Verification:**`. `Covers` is a comma-separated list of known requirement IDs.
|
|
26
|
+
5. Specify responsibilities, interfaces, dependencies, invariants, persistence/migration, compatibility, authorization, input boundaries, concurrency, failure behavior, rollback, and verification where relevant.
|
|
27
|
+
|
|
28
|
+
Internally submit the complete Markdown with the exact revision and artifact identity last observed. Submission, not direct file editing, is the canonical write. Present the saved path and concise validation outcome. On failed validation, keep the durable draft, load it explicitly, and revise; do not request approval.
|
|
29
|
+
|
|
30
|
+
## Human Gate
|
|
31
|
+
|
|
32
|
+
When validation passes, ask one explicit question: **“Approve this design?”** Only an unambiguous affirmative answer in this Skill flow permits internal approval of the exact reviewed revision and artifact. Never self-approve. Reread status after approval and report the persisted outcome.
|
|
24
33
|
|
|
25
34
|
## Specialist Delegation
|
|
26
35
|
|
|
27
|
-
Target renderers provide the `architect` route. When a native advisor is required, dispatch exactly one compact handoff with `specialistDepth: 1`; include only approved requirements,
|
|
36
|
+
Target renderers provide the `architect` route. When a native advisor is required, dispatch exactly one compact handoff with `specialistDepth: 1`; include only approved requirements, architecture facts, constraints, and needed decisions. The specialist must not delegate again. Keep the handoff and returned summary at or below 2,048 estimated tokens. If unavailable, record one fallback and continue in the parent without retrying or spawning a generic child.
|
|
28
37
|
|
|
29
38
|
## Output
|
|
30
39
|
|
|
31
|
-
|
|
40
|
+
Return the canonical saved path, traceable decisions, concise validation evidence, the approval question or persisted approval, and durable blockers. Do not present raw MCP operations as next steps.
|
|
32
41
|
|
|
33
42
|
## Optional Reference
|
|
34
43
|
|
|
35
|
-
Read [REFERENCE.md](REFERENCE.md) only
|
|
44
|
+
Read [REFERENCE.md](REFERENCE.md) only for the exact design shape, component template, checklist, or pattern comparison.
|
|
@@ -2,6 +2,10 @@
|
|
|
2
2
|
|
|
3
3
|
Read only when a detailed checklist is needed for the current task.
|
|
4
4
|
|
|
5
|
+
## Progress Recording Example
|
|
6
|
+
|
|
7
|
+
For a TDD-required task, persist the observed sequence: start; RED with the exact command, non-zero exit code, and failure summary; GREEN with command, zero exit code, and passing summary; final zero-exit verification plus affected project-relative artifacts. If interrupted, status supplies the persisted state and next action; never reconstruct it from conversation history.
|
|
8
|
+
|
|
5
9
|
## Design Prompts
|
|
6
10
|
|
|
7
11
|
- SRP: does each unit own one reason to change?
|
|
@@ -6,36 +6,40 @@ disable-model-invocation: true
|
|
|
6
6
|
|
|
7
7
|
# SDD Implementation
|
|
8
8
|
|
|
9
|
-
Work inline in the current turn. Do not create a serial implementation specialist. Delegate only when at least two genuinely independent slices can run concurrently.
|
|
9
|
+
Work inline in the current turn. Do not create a serial implementation specialist. Delegate only when at least two genuinely independent slices can run concurrently. Backend lifecycle calls are internal; never ask the user to operate raw MCP tools.
|
|
10
10
|
|
|
11
|
-
##
|
|
11
|
+
## Restore Durable Progress
|
|
12
12
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
13
|
+
1. Internally resolve status and load compact implementation context. Requirements, design, tasks, and any required test-case review must be approved.
|
|
14
|
+
2. If invoked too early or state is blocked, present the persisted blocker and make no workflow or source change.
|
|
15
|
+
3. Internally begin implementation when status requests it. Otherwise follow the returned next action: continue the exact active task, ask the user to select among resumable candidates, or select only a dependency-ready pending task.
|
|
16
|
+
4. Read the approved task, acceptance criteria, design interfaces, and relevant steering before editing. Never infer progress from chat or Markdown checkboxes.
|
|
16
17
|
|
|
17
|
-
|
|
18
|
+
If the runtime is unavailable because of host permission, report an actionable reload/trust or policy blocker; never substitute manual backend instructions.
|
|
18
19
|
|
|
19
|
-
|
|
20
|
+
## Governed Task Loop
|
|
20
21
|
|
|
21
|
-
|
|
22
|
-
2. **GREEN:** implement only enough production code to pass; run the focused test.
|
|
23
|
-
3. **REFACTOR:** simplify without changing behavior; rerun the focused test.
|
|
22
|
+
For each selected task, internally record `start` with the exact implementation revision. Then:
|
|
24
23
|
|
|
25
|
-
|
|
24
|
+
1. **RED:** for TDD-required work, write a focused observable test and run it to prove the expected failure. Record the observed command, non-zero exit code, and concise summary before production changes.
|
|
25
|
+
2. **GREEN:** implement only enough to pass and run the focused test. Record the observed command, zero exit code, and summary.
|
|
26
|
+
3. **REFACTOR:** simplify without changing behavior; rerun focused verification.
|
|
27
|
+
4. **COMPLETE:** run final verification. Only after a zero exit code and all acceptance/security checks, record completion with the observed affected project-relative artifacts.
|
|
28
|
+
|
|
29
|
+
For `not-applicable` TDD tasks, start, implement, verify, then complete with zero-exit verification evidence. If work cannot continue after start, internally record the blocker and reason; do not fabricate evidence. On resume, continue from persisted `in-progress`, `red-observed`, `green-observed`, or `blocked` state without replaying completed transitions. Reread status after every progress record.
|
|
26
30
|
|
|
27
31
|
## Mandatory Checks
|
|
28
32
|
|
|
29
33
|
- Preserve approved interfaces and existing conventions; update every affected caller.
|
|
34
|
+
- Test relevant boundaries, errors, invariants, transitions, and precedence—not implementation plumbing.
|
|
30
35
|
- Validate untrusted input, enforce authorization, avoid injection, protect secrets and sensitive logs, and fail safely.
|
|
31
|
-
- Consider concurrency,
|
|
32
|
-
- Run only relevant verification while iterating, then
|
|
33
|
-
- Update task status only after acceptance criteria and security checks pass. Never fabricate test, coverage, lint, or build results.
|
|
36
|
+
- Consider concurrency, cleanup, compatibility, cancellation, rollback, and error propagation where applicable.
|
|
37
|
+
- Run only relevant verification while iterating, then all affected checks. Never fabricate test, coverage, lint, or build results.
|
|
34
38
|
|
|
35
39
|
## Output
|
|
36
40
|
|
|
37
|
-
Report
|
|
41
|
+
Report persisted task numbers/states, observed affected artifacts, RED/GREEN/final verification evidence, security decisions, next action, and blockers. Do not expose backend JSON or present raw MCP operations as user steps.
|
|
38
42
|
|
|
39
43
|
## Optional Reference
|
|
40
44
|
|
|
41
|
-
Read [REFERENCE.md](REFERENCE.md) only when detailed SOLID, OWASP, anti-pattern, or completion checklists are needed.
|
|
45
|
+
Read [REFERENCE.md](REFERENCE.md) only when detailed progress examples, SOLID, OWASP, anti-pattern, or completion checklists are needed.
|
|
@@ -12,18 +12,26 @@ WHERE test-case review is enabled THE service SHALL require review before tasks
|
|
|
12
12
|
IF handoff publication fails after approval THEN the service SHALL retain the approved state and report pending regeneration.
|
|
13
13
|
```
|
|
14
14
|
|
|
15
|
-
##
|
|
15
|
+
## Exact Document Shape
|
|
16
16
|
|
|
17
17
|
```markdown
|
|
18
18
|
# Requirements: Feature
|
|
19
|
-
|
|
19
|
+
|
|
20
20
|
## Functional Requirements
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
21
|
+
|
|
22
|
+
### FR-1: Observable outcome
|
|
23
|
+
**Objective:** Why this behavior matters.
|
|
24
|
+
**EARS Specification:** WHEN an event occurs THEN the system SHALL produce an observable result.
|
|
25
|
+
**Acceptance Criteria:**
|
|
26
|
+
1. A measurable result is observed.
|
|
27
|
+
|
|
24
28
|
## Non-functional Requirements
|
|
25
|
-
|
|
26
|
-
|
|
29
|
+
|
|
30
|
+
### NFR-1: Bounded quality
|
|
31
|
+
**Objective:** The quality attribute and stakeholder value.
|
|
32
|
+
**EARS Specification:** The system SHALL satisfy a measurable bound.
|
|
33
|
+
**Acceptance Criteria:**
|
|
34
|
+
1. The bound is verified under stated conditions.
|
|
27
35
|
```
|
|
28
36
|
|
|
29
37
|
## Quality Checklist
|