@qa-ai-stlc/mcp-server 0.1.2 → 0.2.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 CHANGED
@@ -7,9 +7,13 @@ that into a structured `CallToolResult` carrying a stable `code` and, when there
7
7
  `remediation`, never a raw stack trace. The server calls no model itself; it is driven by the
8
8
  agent host's own model over the MCP protocol.
9
9
 
10
- `qa-mcp-server` starts the stdio server with the built-in tools (currently `qa.ping`, a health
11
- check that does not touch `.qa/`). The engine-operation tools (doctor, explore, scope, cases,
12
- approve, validate, report) are a separate, later task.
10
+ `qa-mcp-server` starts the stdio server with the built-in tools: `qa.ping` (a health check that
11
+ does not touch `.qa/`) and one tool per engine operation `qa.doctor`, `qa.explore`, `qa.scope`,
12
+ `qa.cases_add`, `qa.approve`, `qa.validate` each calling the exact same `packages/core` or
13
+ `packages/explorer` function its CLI counterpart calls (P2-05). `qa.explore` does not support
14
+ manual pick-mode capture: opening a headed browser for a human to click through is a CLI-only
15
+ feature, not something an agent can drive over stdio. `report` has no CLI command yet, so it has
16
+ no MCP tool yet either.
13
17
 
14
18
  Part of [QA-AI-STLC](https://github.com/Klim-101/QA-AI-STLC). See the repository root for
15
19
  license, contributing and security information.
@@ -0,0 +1,8 @@
1
+ import { type EngineContext } from '@qa-ai-stlc/core';
2
+ /**
3
+ * Builds an `EngineContext` from the real Node adapters, freshly on every call rather than once
4
+ * at import time (AGENTS.md 5.3: no side effects on import), so it always reflects the process's
5
+ * current working directory and environment.
6
+ */
7
+ export declare function createNodeEngineContext(): EngineContext;
8
+ //# sourceMappingURL=engine-context.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"engine-context.d.ts","sourceRoot":"","sources":["../src/engine-context.ts"],"names":[],"mappings":"AAGA,OAAO,EAOL,KAAK,aAAa,EACnB,MAAM,kBAAkB,CAAC;AAE1B;;;;GAIG;AACH,wBAAgB,uBAAuB,IAAI,aAAa,CAWvD"}
@@ -0,0 +1,21 @@
1
+ // Copyright The QA-AI-STLC Authors
2
+ // SPDX-License-Identifier: Apache-2.0
3
+ import { fetchHttpClient, nodeFileSystem, nodeProcessRunner, noopLogger, playwrightBrowserLauncher, systemClock, } from '@qa-ai-stlc/core';
4
+ /**
5
+ * Builds an `EngineContext` from the real Node adapters, freshly on every call rather than once
6
+ * at import time (AGENTS.md 5.3: no side effects on import), so it always reflects the process's
7
+ * current working directory and environment.
8
+ */
9
+ export function createNodeEngineContext() {
10
+ return {
11
+ projectRoot: process.cwd(),
12
+ fs: nodeFileSystem,
13
+ clock: systemClock,
14
+ logger: noopLogger,
15
+ processRunner: nodeProcessRunner,
16
+ httpClient: fetchHttpClient,
17
+ browserLauncher: playwrightBrowserLauncher,
18
+ env: process.env,
19
+ };
20
+ }
21
+ //# sourceMappingURL=engine-context.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"engine-context.js","sourceRoot":"","sources":["../src/engine-context.ts"],"names":[],"mappings":"AAAA,mCAAmC;AACnC,sCAAsC;AAEtC,OAAO,EACL,eAAe,EACf,cAAc,EACd,iBAAiB,EACjB,UAAU,EACV,yBAAyB,EACzB,WAAW,GAEZ,MAAM,kBAAkB,CAAC;AAE1B;;;;GAIG;AACH,MAAM,UAAU,uBAAuB;IACrC,OAAO;QACL,WAAW,EAAE,OAAO,CAAC,GAAG,EAAE;QAC1B,EAAE,EAAE,cAAc;QAClB,KAAK,EAAE,WAAW;QAClB,MAAM,EAAE,UAAU;QAClB,aAAa,EAAE,iBAAiB;QAChC,UAAU,EAAE,eAAe;QAC3B,eAAe,EAAE,yBAAyB;QAC1C,GAAG,EAAE,OAAO,CAAC,GAAG;KACjB,CAAC;AACJ,CAAC"}
@@ -0,0 +1,42 @@
1
+ import { z } from 'zod';
2
+ import type { ToolDefinition } from '../tool.js';
3
+ declare const InputSchema: z.ZodObject<{
4
+ gate: z.ZodEnum<{
5
+ scope: "scope";
6
+ cases: "cases";
7
+ }>;
8
+ artifactPath: z.ZodString;
9
+ approvedBy: z.ZodString;
10
+ note: z.ZodOptional<z.ZodString>;
11
+ }, z.core.$strip>;
12
+ declare const OutputSchema: z.ZodObject<{
13
+ gate: z.ZodEnum<{
14
+ scope: "scope";
15
+ cases: "cases";
16
+ }>;
17
+ state: z.ZodObject<{
18
+ schemaVersion: z.ZodDefault<z.ZodLiteral<1>>;
19
+ currentPhase: z.ZodEnum<{
20
+ scope: "scope";
21
+ cases: "cases";
22
+ }>;
23
+ gates: z.ZodRecord<z.ZodEnum<{
24
+ scope: "scope";
25
+ cases: "cases";
26
+ }>, z.ZodObject<{
27
+ status: z.ZodEnum<{
28
+ open: "open";
29
+ satisfied: "satisfied";
30
+ }>;
31
+ }, z.core.$strip>>;
32
+ }, z.core.$strip>;
33
+ }, z.core.$strip>;
34
+ /**
35
+ * `qa.approve` (P2-05, ADR-003): the same `runApprove` core call `qa approve` uses — hashes the
36
+ * artifact's current content and records the approval, advancing the pipeline when `gate` is the
37
+ * current phase. Throws GATE_OUT_OF_ORDER for a later phase approved before an earlier one is
38
+ * satisfied, and GATE_ARTIFACT_MISSING when the artifact does not exist.
39
+ */
40
+ export declare const approveTool: ToolDefinition<typeof InputSchema, typeof OutputSchema>;
41
+ export {};
42
+ //# sourceMappingURL=approve.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"approve.d.ts","sourceRoot":"","sources":["../../src/tools/approve.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAEjD,QAAA,MAAM,WAAW;;;;;;;;iBAKf,CAAC;AAEH,QAAA,MAAM,YAAY;;;;;;;;;;;;;;;;;;;;;iBAGhB,CAAC;AAEH;;;;;GAKG;AACH,eAAO,MAAM,WAAW,EAAE,cAAc,CAAC,OAAO,WAAW,EAAE,OAAO,YAAY,CAe/E,CAAC"}
@@ -0,0 +1,37 @@
1
+ // Copyright The QA-AI-STLC Authors
2
+ // SPDX-License-Identifier: Apache-2.0
3
+ import { runApprove } from '@qa-ai-stlc/core';
4
+ import { PhaseNameSchema, PipelineStateSchema } from '@qa-ai-stlc/schemas';
5
+ import { z } from 'zod';
6
+ import { createNodeEngineContext } from '../engine-context.js';
7
+ const InputSchema = z.object({
8
+ gate: PhaseNameSchema.describe('The pipeline phase to approve.'),
9
+ artifactPath: z.string().describe('Project-relative path to the artifact this approval covers.'),
10
+ approvedBy: z.string().describe('Who or what approved the gate (an operator name or agent identity).'),
11
+ note: z.string().optional(),
12
+ });
13
+ const OutputSchema = z.object({
14
+ gate: PhaseNameSchema,
15
+ state: PipelineStateSchema,
16
+ });
17
+ /**
18
+ * `qa.approve` (P2-05, ADR-003): the same `runApprove` core call `qa approve` uses — hashes the
19
+ * artifact's current content and records the approval, advancing the pipeline when `gate` is the
20
+ * current phase. Throws GATE_OUT_OF_ORDER for a later phase approved before an earlier one is
21
+ * satisfied, and GATE_ARTIFACT_MISSING when the artifact does not exist.
22
+ */
23
+ export const approveTool = {
24
+ name: 'qa.approve',
25
+ description: 'Approves a pipeline gate (currently "scope" or "cases"), hash-binding the approval to the ' +
26
+ "artifact's exact current content (ADR-003). Editing the artifact afterwards reopens the " +
27
+ 'gate automatically; re-approve it to satisfy the gate again.',
28
+ inputSchema: InputSchema,
29
+ outputSchema: OutputSchema,
30
+ handler: (input) => runApprove(createNodeEngineContext(), {
31
+ gate: input.gate,
32
+ artifactPath: input.artifactPath,
33
+ approvedBy: input.approvedBy,
34
+ ...(input.note !== undefined ? { note: input.note } : {}),
35
+ }),
36
+ };
37
+ //# sourceMappingURL=approve.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"approve.js","sourceRoot":"","sources":["../../src/tools/approve.ts"],"names":[],"mappings":"AAAA,mCAAmC;AACnC,sCAAsC;AAEtC,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAAE,eAAe,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAC3E,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,uBAAuB,EAAE,MAAM,sBAAsB,CAAC;AAG/D,MAAM,WAAW,GAAG,CAAC,CAAC,MAAM,CAAC;IAC3B,IAAI,EAAE,eAAe,CAAC,QAAQ,CAAC,gCAAgC,CAAC;IAChE,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,6DAA6D,CAAC;IAChG,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,qEAAqE,CAAC;IACtG,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;CAC5B,CAAC,CAAC;AAEH,MAAM,YAAY,GAAG,CAAC,CAAC,MAAM,CAAC;IAC5B,IAAI,EAAE,eAAe;IACrB,KAAK,EAAE,mBAAmB;CAC3B,CAAC,CAAC;AAEH;;;;;GAKG;AACH,MAAM,CAAC,MAAM,WAAW,GAA4D;IAClF,IAAI,EAAE,YAAY;IAClB,WAAW,EACT,4FAA4F;QAC5F,0FAA0F;QAC1F,8DAA8D;IAChE,WAAW,EAAE,WAAW;IACxB,YAAY,EAAE,YAAY;IAC1B,OAAO,EAAE,CAAC,KAAK,EAAE,EAAE,CACjB,UAAU,CAAC,uBAAuB,EAAE,EAAE;QACpC,IAAI,EAAE,KAAK,CAAC,IAAI;QAChB,YAAY,EAAE,KAAK,CAAC,YAAY;QAChC,UAAU,EAAE,KAAK,CAAC,UAAU;QAC5B,GAAG,CAAC,KAAK,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KAC1D,CAAC;CACL,CAAC"}
@@ -0,0 +1,19 @@
1
+ import { z } from 'zod';
2
+ import type { ToolDefinition } from '../tool.js';
3
+ declare const InputSchema: z.ZodObject<{
4
+ path: z.ZodString;
5
+ }, z.core.$strip>;
6
+ declare const OutputSchema: z.ZodObject<{
7
+ casePath: z.ZodString;
8
+ id: z.ZodString;
9
+ requirementIds: z.ZodArray<z.ZodString>;
10
+ }, z.core.$strip>;
11
+ /**
12
+ * `qa.cases_add` (P2-05): the same `runCasesAdd` core call `qa cases add` uses — validates a test
13
+ * case a human or an agent wrote as JSON (the engine never authors test-case content itself,
14
+ * ADR-001), rejects it if any `requirementIds` entry does not resolve in `artifacts/scope.json`,
15
+ * and only then registers it under `artifacts/cases/<id>.json`.
16
+ */
17
+ export declare const casesAddTool: ToolDefinition<typeof InputSchema, typeof OutputSchema>;
18
+ export {};
19
+ //# sourceMappingURL=cases-add.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cases-add.d.ts","sourceRoot":"","sources":["../../src/tools/cases-add.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAEjD,QAAA,MAAM,WAAW;;iBAEf,CAAC;AAEH,QAAA,MAAM,YAAY;;;;iBAIhB,CAAC;AAEH;;;;;GAKG;AACH,eAAO,MAAM,YAAY,EAAE,cAAc,CAAC,OAAO,WAAW,EAAE,OAAO,YAAY,CAYhF,CAAC"}
@@ -0,0 +1,32 @@
1
+ // Copyright The QA-AI-STLC Authors
2
+ // SPDX-License-Identifier: Apache-2.0
3
+ import { runCasesAdd } from '@qa-ai-stlc/core';
4
+ import { z } from 'zod';
5
+ import { createNodeEngineContext } from '../engine-context.js';
6
+ const InputSchema = z.object({
7
+ path: z.string().describe('Project-relative path to a test case written as JSON (TestCaseSchema).'),
8
+ });
9
+ const OutputSchema = z.object({
10
+ casePath: z.string(),
11
+ id: z.string(),
12
+ requirementIds: z.array(z.string()),
13
+ });
14
+ /**
15
+ * `qa.cases_add` (P2-05): the same `runCasesAdd` core call `qa cases add` uses — validates a test
16
+ * case a human or an agent wrote as JSON (the engine never authors test-case content itself,
17
+ * ADR-001), rejects it if any `requirementIds` entry does not resolve in `artifacts/scope.json`,
18
+ * and only then registers it under `artifacts/cases/<id>.json`.
19
+ */
20
+ export const casesAddTool = {
21
+ name: 'qa.cases_add',
22
+ description: 'Validates a test case written as JSON at the given path and registers it under ' +
23
+ 'artifacts/cases/<id>.json. Fails with CASE_UNLINKED_REQUIREMENT if any requirementIds entry ' +
24
+ 'does not exist in artifacts/scope.json — run qa.scope first to register it.',
25
+ inputSchema: InputSchema,
26
+ outputSchema: OutputSchema,
27
+ async handler(input) {
28
+ const result = await runCasesAdd(createNodeEngineContext(), { path: input.path });
29
+ return { casePath: result.casePath, id: result.id, requirementIds: [...result.requirementIds] };
30
+ },
31
+ };
32
+ //# sourceMappingURL=cases-add.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cases-add.js","sourceRoot":"","sources":["../../src/tools/cases-add.ts"],"names":[],"mappings":"AAAA,mCAAmC;AACnC,sCAAsC;AAEtC,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,uBAAuB,EAAE,MAAM,sBAAsB,CAAC;AAG/D,MAAM,WAAW,GAAG,CAAC,CAAC,MAAM,CAAC;IAC3B,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,wEAAwE,CAAC;CACpG,CAAC,CAAC;AAEH,MAAM,YAAY,GAAG,CAAC,CAAC,MAAM,CAAC;IAC5B,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE;IACpB,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE;IACd,cAAc,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC;CACpC,CAAC,CAAC;AAEH;;;;;GAKG;AACH,MAAM,CAAC,MAAM,YAAY,GAA4D;IACnF,IAAI,EAAE,cAAc;IACpB,WAAW,EACT,iFAAiF;QACjF,8FAA8F;QAC9F,6EAA6E;IAC/E,WAAW,EAAE,WAAW;IACxB,YAAY,EAAE,YAAY;IAC1B,KAAK,CAAC,OAAO,CAAC,KAAK;QACjB,MAAM,MAAM,GAAG,MAAM,WAAW,CAAC,uBAAuB,EAAE,EAAE,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC;QAClF,OAAO,EAAE,QAAQ,EAAE,MAAM,CAAC,QAAQ,EAAE,EAAE,EAAE,MAAM,CAAC,EAAE,EAAE,cAAc,EAAE,CAAC,GAAG,MAAM,CAAC,cAAc,CAAC,EAAE,CAAC;IAClG,CAAC;CACF,CAAC"}
@@ -0,0 +1,25 @@
1
+ import { z } from 'zod';
2
+ import type { ToolDefinition } from '../tool.js';
3
+ declare const InputSchema: z.ZodObject<{
4
+ fix: z.ZodOptional<z.ZodBoolean>;
5
+ }, z.core.$strip>;
6
+ declare const OutputSchema: z.ZodObject<{
7
+ ok: z.ZodBoolean;
8
+ checks: z.ZodArray<z.ZodObject<{
9
+ name: z.ZodString;
10
+ status: z.ZodEnum<{
11
+ pass: "pass";
12
+ fail: "fail";
13
+ }>;
14
+ message: z.ZodString;
15
+ remediation: z.ZodOptional<z.ZodString>;
16
+ }, z.core.$strip>>;
17
+ }, z.core.$strip>;
18
+ /**
19
+ * `qa.doctor` (P2-05): the same `runDoctor` core call `qa doctor` uses — Node version, browser
20
+ * binaries, and, once `config.yaml` exists, every identity's secret and environment's
21
+ * reachability (ADR-004).
22
+ */
23
+ export declare const doctorTool: ToolDefinition<typeof InputSchema, typeof OutputSchema>;
24
+ export {};
25
+ //# sourceMappingURL=doctor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"doctor.d.ts","sourceRoot":"","sources":["../../src/tools/doctor.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAEjD,QAAA,MAAM,WAAW;;iBAEf,CAAC;AASH,QAAA,MAAM,YAAY;;;;;;;;;;;iBAGhB,CAAC;AAEH;;;;GAIG;AACH,eAAO,MAAM,UAAU,EAAE,cAAc,CAAC,OAAO,WAAW,EAAE,OAAO,YAAY,CAc9E,CAAC"}
@@ -0,0 +1,38 @@
1
+ // Copyright The QA-AI-STLC Authors
2
+ // SPDX-License-Identifier: Apache-2.0
3
+ import { runDoctor } from '@qa-ai-stlc/core';
4
+ import { z } from 'zod';
5
+ import { createNodeEngineContext } from '../engine-context.js';
6
+ const InputSchema = z.object({
7
+ fix: z.boolean().optional().describe('Install missing browsers through Playwright before reporting.'),
8
+ });
9
+ const DoctorCheckSchema = z.object({
10
+ name: z.string(),
11
+ status: z.enum(['pass', 'fail']),
12
+ message: z.string(),
13
+ remediation: z.string().optional(),
14
+ });
15
+ const OutputSchema = z.object({
16
+ ok: z.boolean(),
17
+ checks: z.array(DoctorCheckSchema),
18
+ });
19
+ /**
20
+ * `qa.doctor` (P2-05): the same `runDoctor` core call `qa doctor` uses — Node version, browser
21
+ * binaries, and, once `config.yaml` exists, every identity's secret and environment's
22
+ * reachability (ADR-004).
23
+ */
24
+ export const doctorTool = {
25
+ name: 'qa.doctor',
26
+ description: 'Checks the local environment the engine needs: Node version, browser binaries, and, once ' +
27
+ 'config.yaml exists, every configured identity secret and environment URL. Use before ' +
28
+ 'qa.explore to confirm the project is set up correctly. Set fix to install missing browsers.',
29
+ inputSchema: InputSchema,
30
+ outputSchema: OutputSchema,
31
+ async handler(input) {
32
+ const report = await runDoctor(createNodeEngineContext(), {
33
+ ...(input.fix !== undefined ? { fix: input.fix } : {}),
34
+ });
35
+ return { ok: report.ok, checks: [...report.checks] };
36
+ },
37
+ };
38
+ //# sourceMappingURL=doctor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"doctor.js","sourceRoot":"","sources":["../../src/tools/doctor.ts"],"names":[],"mappings":"AAAA,mCAAmC;AACnC,sCAAsC;AAEtC,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC7C,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,uBAAuB,EAAE,MAAM,sBAAsB,CAAC;AAG/D,MAAM,WAAW,GAAG,CAAC,CAAC,MAAM,CAAC;IAC3B,GAAG,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,+DAA+D,CAAC;CACtG,CAAC,CAAC;AAEH,MAAM,iBAAiB,GAAG,CAAC,CAAC,MAAM,CAAC;IACjC,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE;IAChB,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE;IACnB,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;CACnC,CAAC,CAAC;AAEH,MAAM,YAAY,GAAG,CAAC,CAAC,MAAM,CAAC;IAC5B,EAAE,EAAE,CAAC,CAAC,OAAO,EAAE;IACf,MAAM,EAAE,CAAC,CAAC,KAAK,CAAC,iBAAiB,CAAC;CACnC,CAAC,CAAC;AAEH;;;;GAIG;AACH,MAAM,CAAC,MAAM,UAAU,GAA4D;IACjF,IAAI,EAAE,WAAW;IACjB,WAAW,EACT,2FAA2F;QAC3F,uFAAuF;QACvF,6FAA6F;IAC/F,WAAW,EAAE,WAAW;IACxB,YAAY,EAAE,YAAY;IAC1B,KAAK,CAAC,OAAO,CAAC,KAAK;QACjB,MAAM,MAAM,GAAG,MAAM,SAAS,CAAC,uBAAuB,EAAE,EAAE;YACxD,GAAG,CAAC,KAAK,CAAC,GAAG,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SACvD,CAAC,CAAC;QACH,OAAO,EAAE,EAAE,EAAE,MAAM,CAAC,EAAE,EAAE,MAAM,EAAE,CAAC,GAAG,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC;IACvD,CAAC;CACF,CAAC"}
@@ -0,0 +1,41 @@
1
+ import { z } from 'zod';
2
+ import type { ToolDefinition } from '../tool.js';
3
+ declare const InputSchema: z.ZodObject<{
4
+ environment: z.ZodOptional<z.ZodString>;
5
+ identity: z.ZodOptional<z.ZodString>;
6
+ cdpEndpointUrl: z.ZodOptional<z.ZodString>;
7
+ policy: z.ZodOptional<z.ZodEnum<{
8
+ "playwright-default": "playwright-default";
9
+ "testid-first": "testid-first";
10
+ "strict-no-css": "strict-no-css";
11
+ }>>;
12
+ static: z.ZodOptional<z.ZodBoolean>;
13
+ maxPages: z.ZodOptional<z.ZodNumber>;
14
+ verify: z.ZodOptional<z.ZodBoolean>;
15
+ }, z.core.$strip>;
16
+ declare const OutputSchema: z.ZodObject<{
17
+ mode: z.ZodEnum<{
18
+ verify: "verify";
19
+ explore: "explore";
20
+ }>;
21
+ registryPath: z.ZodString;
22
+ elementCount: z.ZodNumber;
23
+ added: z.ZodNumber;
24
+ removed: z.ZodNumber;
25
+ degraded: z.ZodArray<z.ZodObject<{
26
+ elementId: z.ZodString;
27
+ previousScore: z.ZodNumber;
28
+ currentScore: z.ZodNumber;
29
+ }, z.core.$strip>>;
30
+ missingLocatorCount: z.ZodNumber;
31
+ blockedRequestCount: z.ZodNumber;
32
+ }, z.core.$strip>;
33
+ /**
34
+ * `qa.explore` (P2-05): the same `runExplore` core call `qa explore` uses for crawling, static
35
+ * source analysis and `--verify` (development plan section 6.3). Manual pick-mode capture stays a
36
+ * CLI-only feature (`qa explore --pick <url>`): it opens a headed browser for a human to click
37
+ * through, which an agent cannot drive over MCP's stdio transport (AGENTS.md 12.4).
38
+ */
39
+ export declare const exploreTool: ToolDefinition<typeof InputSchema, typeof OutputSchema>;
40
+ export {};
41
+ //# sourceMappingURL=explore.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"explore.d.ts","sourceRoot":"","sources":["../../src/tools/explore.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAEjD,QAAA,MAAM,WAAW;;;;;;;;;;;;iBAiBf,CAAC;AAQH,QAAA,MAAM,YAAY;;;;;;;;;;;;;;;;iBAShB,CAAC;AAEH;;;;;GAKG;AACH,eAAO,MAAM,WAAW,EAAE,cAAc,CAAC,OAAO,WAAW,EAAE,OAAO,YAAY,CAqB/E,CAAC"}
@@ -0,0 +1,67 @@
1
+ // Copyright The QA-AI-STLC Authors
2
+ // SPDX-License-Identifier: Apache-2.0
3
+ import { runExplore } from '@qa-ai-stlc/explorer';
4
+ import { SelectorPolicySchema } from '@qa-ai-stlc/schemas';
5
+ import { z } from 'zod';
6
+ import { createNodeEngineContext } from '../engine-context.js';
7
+ const InputSchema = z.object({
8
+ environment: z
9
+ .string()
10
+ .optional()
11
+ .describe('Environment name from config.yaml. Required when there is more than one.'),
12
+ identity: z.string().optional().describe('Identity name from config.yaml to sign in with before crawling.'),
13
+ cdpEndpointUrl: z
14
+ .string()
15
+ .optional()
16
+ .describe('Required, and only used, when the identity uses cdp-attach.'),
17
+ policy: SelectorPolicySchema.optional().describe('Overrides config.yaml selectors.policy for this run.'),
18
+ static: z.boolean().optional().describe('Also scan config.yaml source.path for framework attributes.'),
19
+ maxPages: z.number().int().positive().optional().describe('Caps how many pages the crawl visits.'),
20
+ verify: z
21
+ .boolean()
22
+ .optional()
23
+ .describe('Re-checks the stored registry live instead of building a new one; does not crawl.'),
24
+ });
25
+ const DegradedSelectorSchema = z.object({
26
+ elementId: z.string(),
27
+ previousScore: z.number(),
28
+ currentScore: z.number(),
29
+ });
30
+ const OutputSchema = z.object({
31
+ mode: z.enum(['explore', 'verify']),
32
+ registryPath: z.string(),
33
+ elementCount: z.number(),
34
+ added: z.number(),
35
+ removed: z.number(),
36
+ degraded: z.array(DegradedSelectorSchema),
37
+ missingLocatorCount: z.number(),
38
+ blockedRequestCount: z.number(),
39
+ });
40
+ /**
41
+ * `qa.explore` (P2-05): the same `runExplore` core call `qa explore` uses for crawling, static
42
+ * source analysis and `--verify` (development plan section 6.3). Manual pick-mode capture stays a
43
+ * CLI-only feature (`qa explore --pick <url>`): it opens a headed browser for a human to click
44
+ * through, which an agent cannot drive over MCP's stdio transport (AGENTS.md 12.4).
45
+ */
46
+ export const exploreTool = {
47
+ name: 'qa.explore',
48
+ description: 'Builds the selector registry by crawling the configured environment in safe mode, merging ' +
49
+ 'in static source analysis when "static" is set. Set "verify" to instead re-check every ' +
50
+ 'stored, non-deprecated selector against the live page and report which ones degraded. Does ' +
51
+ 'not support manual pick-mode capture — that is a CLI-only, human-driven feature.',
52
+ inputSchema: InputSchema,
53
+ outputSchema: OutputSchema,
54
+ async handler(input) {
55
+ const report = await runExplore(createNodeEngineContext(), {
56
+ ...(input.environment !== undefined ? { environment: input.environment } : {}),
57
+ ...(input.identity !== undefined ? { identity: input.identity } : {}),
58
+ ...(input.cdpEndpointUrl !== undefined ? { cdpEndpointUrl: input.cdpEndpointUrl } : {}),
59
+ ...(input.policy !== undefined ? { policy: input.policy } : {}),
60
+ ...(input.static !== undefined ? { static: input.static } : {}),
61
+ ...(input.maxPages !== undefined ? { maxPages: input.maxPages } : {}),
62
+ ...(input.verify !== undefined ? { verify: input.verify } : {}),
63
+ });
64
+ return { ...report, degraded: [...report.degraded] };
65
+ },
66
+ };
67
+ //# sourceMappingURL=explore.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"explore.js","sourceRoot":"","sources":["../../src/tools/explore.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,4 @@
1
1
  import type { ToolDefinition } from '../tool.js';
2
- /** Every tool the server registers by default. P2-05 adds the real engine-operation tools here. */
2
+ /** Every tool the server registers by default (P2-05: one MCP counterpart per engine operation). */
3
3
  export declare const BUILTIN_TOOLS: readonly ToolDefinition[];
4
4
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/tools/index.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAEjD,mGAAmG;AACnG,eAAO,MAAM,aAAa,EAAE,SAAS,cAAc,EAAe,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/tools/index.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAEjD,oGAAoG;AACpG,eAAO,MAAM,aAAa,EAAE,SAAS,cAAc,EAQlD,CAAC"}
@@ -1,6 +1,20 @@
1
1
  // Copyright The QA-AI-STLC Authors
2
2
  // SPDX-License-Identifier: Apache-2.0
3
+ import { approveTool } from './approve.js';
4
+ import { casesAddTool } from './cases-add.js';
5
+ import { doctorTool } from './doctor.js';
6
+ import { exploreTool } from './explore.js';
3
7
  import { pingTool } from './ping.js';
4
- /** Every tool the server registers by default. P2-05 adds the real engine-operation tools here. */
5
- export const BUILTIN_TOOLS = [pingTool];
8
+ import { scopeTool } from './scope.js';
9
+ import { validateTool } from './validate.js';
10
+ /** Every tool the server registers by default (P2-05: one MCP counterpart per engine operation). */
11
+ export const BUILTIN_TOOLS = [
12
+ pingTool,
13
+ doctorTool,
14
+ exploreTool,
15
+ scopeTool,
16
+ casesAddTool,
17
+ approveTool,
18
+ validateTool,
19
+ ];
6
20
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/tools/index.ts"],"names":[],"mappings":"AAAA,mCAAmC;AACnC,sCAAsC;AAEtC,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAGrC,mGAAmG;AACnG,MAAM,CAAC,MAAM,aAAa,GAA8B,CAAC,QAAQ,CAAC,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/tools/index.ts"],"names":[],"mappings":"AAAA,mCAAmC;AACnC,sCAAsC;AAEtC,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAC3C,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAC3C,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AACrC,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AACvC,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAG7C,oGAAoG;AACpG,MAAM,CAAC,MAAM,aAAa,GAA8B;IACtD,QAAQ;IACR,UAAU;IACV,WAAW;IACX,SAAS;IACT,YAAY;IACZ,WAAW;IACX,YAAY;CACb,CAAC"}
@@ -6,9 +6,9 @@ declare const OutputSchema: z.ZodObject<{
6
6
  version: z.ZodString;
7
7
  }, z.core.$strip>;
8
8
  /**
9
- * A health check owned by the server itself, not an engine operation (those are P2-05's tools):
10
- * proves the process is up and the tool-call round trip works, without touching `.qa/` or the
11
- * engine at all.
9
+ * A health check owned by the server itself, not an engine operation (those are P2-05's other
10
+ * tools): proves the process is up and the tool-call round trip works, without touching `.qa/` or
11
+ * the engine at all.
12
12
  */
13
13
  export declare const pingTool: ToolDefinition<typeof InputSchema, typeof OutputSchema>;
14
14
  export {};
@@ -8,9 +8,9 @@ const OutputSchema = z.object({
8
8
  version: z.string(),
9
9
  });
10
10
  /**
11
- * A health check owned by the server itself, not an engine operation (those are P2-05's tools):
12
- * proves the process is up and the tool-call round trip works, without touching `.qa/` or the
13
- * engine at all.
11
+ * A health check owned by the server itself, not an engine operation (those are P2-05's other
12
+ * tools): proves the process is up and the tool-call round trip works, without touching `.qa/` or
13
+ * the engine at all.
14
14
  */
15
15
  export const pingTool = {
16
16
  name: 'qa.ping',
@@ -0,0 +1,26 @@
1
+ import { z } from 'zod';
2
+ import type { ToolDefinition } from '../tool.js';
3
+ declare const InputSchema: z.ZodObject<{
4
+ from: z.ZodEnum<{
5
+ text: "text";
6
+ file: "file";
7
+ }>;
8
+ path: z.ZodOptional<z.ZodString>;
9
+ content: z.ZodOptional<z.ZodString>;
10
+ label: z.ZodOptional<z.ZodString>;
11
+ }, z.core.$strip>;
12
+ declare const OutputSchema: z.ZodObject<{
13
+ scopePath: z.ZodString;
14
+ added: z.ZodNumber;
15
+ updated: z.ZodNumber;
16
+ total: z.ZodNumber;
17
+ }, z.core.$strip>;
18
+ /**
19
+ * `qa.scope` (P2-05): the same `runScope` core call `qa scope` uses — deterministically extracts
20
+ * `## Heading` requirements from a local Markdown source and upserts them into
21
+ * `artifacts/scope.json` by id (development plan section 2.4, 2.7 step 4). The framework never
22
+ * fetches requirements from a tracker (AGENTS.md 2.3).
23
+ */
24
+ export declare const scopeTool: ToolDefinition<typeof InputSchema, typeof OutputSchema>;
25
+ export {};
26
+ //# sourceMappingURL=scope.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scope.d.ts","sourceRoot":"","sources":["../../src/tools/scope.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAEjD,QAAA,MAAM,WAAW;;;;;;;;iBAQf,CAAC;AAEH,QAAA,MAAM,YAAY;;;;;iBAKhB,CAAC;AAEH;;;;;GAKG;AACH,eAAO,MAAM,SAAS,EAAE,cAAc,CAAC,OAAO,WAAW,EAAE,OAAO,YAAY,CAgB7E,CAAC"}
@@ -0,0 +1,42 @@
1
+ // Copyright The QA-AI-STLC Authors
2
+ // SPDX-License-Identifier: Apache-2.0
3
+ import { runScope } from '@qa-ai-stlc/core';
4
+ import { z } from 'zod';
5
+ import { createNodeEngineContext } from '../engine-context.js';
6
+ const InputSchema = z.object({
7
+ from: z.enum(['file', 'text']).describe('Where to read requirements from.'),
8
+ path: z
9
+ .string()
10
+ .optional()
11
+ .describe('Project-relative path to a Markdown file. Required when from is "file".'),
12
+ content: z.string().optional().describe('Literal Markdown text. Required when from is "text".'),
13
+ label: z.string().optional().describe('A short label for the text source. Required when from is "text".'),
14
+ });
15
+ const OutputSchema = z.object({
16
+ scopePath: z.string(),
17
+ added: z.number(),
18
+ updated: z.number(),
19
+ total: z.number(),
20
+ });
21
+ /**
22
+ * `qa.scope` (P2-05): the same `runScope` core call `qa scope` uses — deterministically extracts
23
+ * `## Heading` requirements from a local Markdown source and upserts them into
24
+ * `artifacts/scope.json` by id (development plan section 2.4, 2.7 step 4). The framework never
25
+ * fetches requirements from a tracker (AGENTS.md 2.3).
26
+ */
27
+ export const scopeTool = {
28
+ name: 'qa.scope',
29
+ description: 'Extracts requirements from a local Markdown file or literal text (one "## Heading" per ' +
30
+ 'requirement) and upserts them by id into artifacts/scope.json. Call again with the same ' +
31
+ 'headings to update requirements instead of duplicating them. Never fetches from an issue ' +
32
+ 'tracker or wiki.',
33
+ inputSchema: InputSchema,
34
+ outputSchema: OutputSchema,
35
+ handler: (input) => runScope(createNodeEngineContext(), {
36
+ from: input.from,
37
+ ...(input.path !== undefined ? { path: input.path } : {}),
38
+ ...(input.content !== undefined ? { content: input.content } : {}),
39
+ ...(input.label !== undefined ? { label: input.label } : {}),
40
+ }),
41
+ };
42
+ //# sourceMappingURL=scope.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scope.js","sourceRoot":"","sources":["../../src/tools/scope.ts"],"names":[],"mappings":"AAAA,mCAAmC;AACnC,sCAAsC;AAEtC,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,uBAAuB,EAAE,MAAM,sBAAsB,CAAC;AAG/D,MAAM,WAAW,GAAG,CAAC,CAAC,MAAM,CAAC;IAC3B,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,kCAAkC,CAAC;IAC3E,IAAI,EAAE,CAAC;SACJ,MAAM,EAAE;SACR,QAAQ,EAAE;SACV,QAAQ,CAAC,yEAAyE,CAAC;IACtF,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,sDAAsD,CAAC;IAC/F,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,kEAAkE,CAAC;CAC1G,CAAC,CAAC;AAEH,MAAM,YAAY,GAAG,CAAC,CAAC,MAAM,CAAC;IAC5B,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE;IACrB,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE;IACjB,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE;IACnB,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE;CAClB,CAAC,CAAC;AAEH;;;;;GAKG;AACH,MAAM,CAAC,MAAM,SAAS,GAA4D;IAChF,IAAI,EAAE,UAAU;IAChB,WAAW,EACT,yFAAyF;QACzF,0FAA0F;QAC1F,2FAA2F;QAC3F,kBAAkB;IACpB,WAAW,EAAE,WAAW;IACxB,YAAY,EAAE,YAAY;IAC1B,OAAO,EAAE,CAAC,KAAK,EAAE,EAAE,CACjB,QAAQ,CAAC,uBAAuB,EAAE,EAAE;QAClC,IAAI,EAAE,KAAK,CAAC,IAAI;QAChB,GAAG,CAAC,KAAK,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACzD,GAAG,CAAC,KAAK,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAClE,GAAG,CAAC,KAAK,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KAC7D,CAAC;CACL,CAAC"}
@@ -0,0 +1,40 @@
1
+ import { z } from 'zod';
2
+ import type { ToolDefinition } from '../tool.js';
3
+ declare const InputSchema: z.ZodObject<{}, z.core.$strip>;
4
+ declare const OutputSchema: z.ZodObject<{
5
+ state: z.ZodObject<{
6
+ schemaVersion: z.ZodDefault<z.ZodLiteral<1>>;
7
+ currentPhase: z.ZodEnum<{
8
+ scope: "scope";
9
+ cases: "cases";
10
+ }>;
11
+ gates: z.ZodRecord<z.ZodEnum<{
12
+ scope: "scope";
13
+ cases: "cases";
14
+ }>, z.ZodObject<{
15
+ status: z.ZodEnum<{
16
+ open: "open";
17
+ satisfied: "satisfied";
18
+ }>;
19
+ }, z.core.$strip>>;
20
+ }, z.core.$strip>;
21
+ reopened: z.ZodArray<z.ZodEnum<{
22
+ scope: "scope";
23
+ cases: "cases";
24
+ }>>;
25
+ unlinkedCases: z.ZodArray<z.ZodObject<{
26
+ casePath: z.ZodString;
27
+ id: z.ZodString;
28
+ unlinkedRequirementIds: z.ZodArray<z.ZodString>;
29
+ }, z.core.$strip>>;
30
+ }, z.core.$strip>;
31
+ /**
32
+ * `qa.validate` (P2-05, ADR-003; P2-03 traceability): the same `runValidate` core call `qa
33
+ * validate` uses — recomputes every gate's status against the approval ledger and the current
34
+ * artifact content, and re-checks every registered test case's requirement links against the
35
+ * current scope artifact. A non-empty `reopened` or `unlinkedCases` means the pipeline needs
36
+ * attention, not a phase simply never approved yet.
37
+ */
38
+ export declare const validateTool: ToolDefinition<typeof InputSchema, typeof OutputSchema>;
39
+ export {};
40
+ //# sourceMappingURL=validate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validate.d.ts","sourceRoot":"","sources":["../../src/tools/validate.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAEjD,QAAA,MAAM,WAAW,gCAAe,CAAC;AAQjC,QAAA,MAAM,YAAY;;;;;;;;;;;;;;;;;;;;;;;;;;iBAIhB,CAAC;AAEH;;;;;;GAMG;AACH,eAAO,MAAM,YAAY,EAAE,cAAc,CAAC,OAAO,WAAW,EAAE,OAAO,YAAY,CAoBhF,CAAC"}
@@ -0,0 +1,45 @@
1
+ // Copyright The QA-AI-STLC Authors
2
+ // SPDX-License-Identifier: Apache-2.0
3
+ import { runValidate } from '@qa-ai-stlc/core';
4
+ import { PhaseNameSchema, PipelineStateSchema } from '@qa-ai-stlc/schemas';
5
+ import { z } from 'zod';
6
+ import { createNodeEngineContext } from '../engine-context.js';
7
+ const InputSchema = z.object({});
8
+ const UnlinkedCaseSchema = z.object({
9
+ casePath: z.string(),
10
+ id: z.string(),
11
+ unlinkedRequirementIds: z.array(z.string()),
12
+ });
13
+ const OutputSchema = z.object({
14
+ state: PipelineStateSchema,
15
+ reopened: z.array(PhaseNameSchema),
16
+ unlinkedCases: z.array(UnlinkedCaseSchema),
17
+ });
18
+ /**
19
+ * `qa.validate` (P2-05, ADR-003; P2-03 traceability): the same `runValidate` core call `qa
20
+ * validate` uses — recomputes every gate's status against the approval ledger and the current
21
+ * artifact content, and re-checks every registered test case's requirement links against the
22
+ * current scope artifact. A non-empty `reopened` or `unlinkedCases` means the pipeline needs
23
+ * attention, not a phase simply never approved yet.
24
+ */
25
+ export const validateTool = {
26
+ name: 'qa.validate',
27
+ description: "Recomputes every pipeline gate's status and re-checks every registered test case's " +
28
+ 'requirement links against the current scope artifact. Call after editing an approved ' +
29
+ 'artifact or a test case to see whether a gate reopened or a link broke.',
30
+ inputSchema: InputSchema,
31
+ outputSchema: OutputSchema,
32
+ async handler() {
33
+ const report = await runValidate(createNodeEngineContext());
34
+ return {
35
+ state: report.state,
36
+ reopened: [...report.reopened],
37
+ unlinkedCases: report.unlinkedCases.map((unlinkedCase) => ({
38
+ casePath: unlinkedCase.casePath,
39
+ id: unlinkedCase.id,
40
+ unlinkedRequirementIds: [...unlinkedCase.unlinkedRequirementIds],
41
+ })),
42
+ };
43
+ },
44
+ };
45
+ //# sourceMappingURL=validate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validate.js","sourceRoot":"","sources":["../../src/tools/validate.ts"],"names":[],"mappings":"AAAA,mCAAmC;AACnC,sCAAsC;AAEtC,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EAAE,eAAe,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAC3E,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,uBAAuB,EAAE,MAAM,sBAAsB,CAAC;AAG/D,MAAM,WAAW,GAAG,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;AAEjC,MAAM,kBAAkB,GAAG,CAAC,CAAC,MAAM,CAAC;IAClC,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE;IACpB,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE;IACd,sBAAsB,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC;CAC5C,CAAC,CAAC;AAEH,MAAM,YAAY,GAAG,CAAC,CAAC,MAAM,CAAC;IAC5B,KAAK,EAAE,mBAAmB;IAC1B,QAAQ,EAAE,CAAC,CAAC,KAAK,CAAC,eAAe,CAAC;IAClC,aAAa,EAAE,CAAC,CAAC,KAAK,CAAC,kBAAkB,CAAC;CAC3C,CAAC,CAAC;AAEH;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,YAAY,GAA4D;IACnF,IAAI,EAAE,aAAa;IACnB,WAAW,EACT,qFAAqF;QACrF,uFAAuF;QACvF,yEAAyE;IAC3E,WAAW,EAAE,WAAW;IACxB,YAAY,EAAE,YAAY;IAC1B,KAAK,CAAC,OAAO;QACX,MAAM,MAAM,GAAG,MAAM,WAAW,CAAC,uBAAuB,EAAE,CAAC,CAAC;QAC5D,OAAO;YACL,KAAK,EAAE,MAAM,CAAC,KAAK;YACnB,QAAQ,EAAE,CAAC,GAAG,MAAM,CAAC,QAAQ,CAAC;YAC9B,aAAa,EAAE,MAAM,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC,YAAY,EAAE,EAAE,CAAC,CAAC;gBACzD,QAAQ,EAAE,YAAY,CAAC,QAAQ;gBAC/B,EAAE,EAAE,YAAY,CAAC,EAAE;gBACnB,sBAAsB,EAAE,CAAC,GAAG,YAAY,CAAC,sBAAsB,CAAC;aACjE,CAAC,CAAC;SACJ,CAAC;IACJ,CAAC;CACF,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@qa-ai-stlc/mcp-server",
3
- "version": "0.1.2",
3
+ "version": "0.2.0",
4
4
  "description": "Local stdio MCP server over the core engine API: a tool registry with Zod input/output schemas and coded errors. Calls no model itself.",
5
5
  "type": "module",
6
6
  "license": "Apache-2.0",
@@ -21,18 +21,19 @@
21
21
  ".": "./dist/index.js"
22
22
  },
23
23
  "scripts": {
24
- "pretypecheck": "npm run build --workspace @qa-ai-stlc/schemas --workspace @qa-ai-stlc/core --workspace @qa-ai-stlc/test-utils",
24
+ "pretypecheck": "npm run build --workspace @qa-ai-stlc/schemas --workspace @qa-ai-stlc/core --workspace @qa-ai-stlc/explorer --workspace @qa-ai-stlc/test-utils",
25
25
  "typecheck": "tsc --noEmit -p .",
26
- "pretest": "npm run build --workspace @qa-ai-stlc/schemas --workspace @qa-ai-stlc/core --workspace @qa-ai-stlc/test-utils",
26
+ "pretest": "npm run build --workspace @qa-ai-stlc/schemas --workspace @qa-ai-stlc/core --workspace @qa-ai-stlc/explorer --workspace @qa-ai-stlc/test-utils",
27
27
  "test": "vitest run",
28
- "pretest:coverage": "npm run build --workspace @qa-ai-stlc/schemas --workspace @qa-ai-stlc/core --workspace @qa-ai-stlc/test-utils",
28
+ "pretest:coverage": "npm run build --workspace @qa-ai-stlc/schemas --workspace @qa-ai-stlc/core --workspace @qa-ai-stlc/explorer --workspace @qa-ai-stlc/test-utils",
29
29
  "test:coverage": "vitest run --coverage",
30
30
  "build": "tsc -b tsconfig.build.json",
31
31
  "clean": "node ../../scripts/clean-dir.mjs dist"
32
32
  },
33
33
  "dependencies": {
34
34
  "@modelcontextprotocol/sdk": "1.30.0",
35
- "@qa-ai-stlc/core": "0.8.0",
35
+ "@qa-ai-stlc/core": "0.9.0",
36
+ "@qa-ai-stlc/explorer": "0.7.0",
36
37
  "@qa-ai-stlc/schemas": "0.8.0",
37
38
  "zod": "4.6.5"
38
39
  },