requ-mcp 0.2.0 → 0.5.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 +64 -3
- package/dist/coverage.d.ts +28 -4
- package/dist/coverage.js +48 -6
- package/dist/coverage.js.map +1 -1
- package/dist/export-import.d.ts +10 -0
- package/dist/export-import.js +127 -0
- package/dist/export-import.js.map +1 -0
- package/dist/index.js +663 -58
- package/dist/index.js.map +1 -1
- package/dist/public/app.js +914 -0
- package/dist/public/index.html +1418 -0
- package/dist/public/style.css +458 -0
- package/dist/schema.d.ts +666 -28
- package/dist/schema.js +90 -29
- package/dist/schema.js.map +1 -1
- package/dist/sqlite-store.d.ts +43 -0
- package/dist/sqlite-store.js +210 -0
- package/dist/sqlite-store.js.map +1 -0
- package/dist/storage.d.ts +16 -4
- package/dist/storage.js +53 -19
- package/dist/storage.js.map +1 -1
- package/dist/web-api.d.ts +9 -0
- package/dist/web-api.js +789 -0
- package/dist/web-api.js.map +1 -0
- package/package.json +9 -5
package/README.md
CHANGED
|
@@ -20,7 +20,8 @@ Phase (v1.0, v1.1, …) → Execution (a scenario result for a run)
|
|
|
20
20
|
At the end of a working session — or for any release — you ask the server one
|
|
21
21
|
question — *"what's our coverage?"* — and get a precise, always-current answer
|
|
22
22
|
instead of a stale spreadsheet, plus the **trend** of how coverage changed
|
|
23
|
-
release over release.
|
|
23
|
+
release over release. The server also ships a **web dashboard** (in HTTP mode)
|
|
24
|
+
that visualizes coverage and requirements in 6 interactive tabs.
|
|
24
25
|
|
|
25
26
|
## Quickstart
|
|
26
27
|
|
|
@@ -72,7 +73,50 @@ npm run smoke # optional: end-to-end self-test
|
|
|
72
73
|
```
|
|
73
74
|
</details>
|
|
74
75
|
|
|
75
|
-
|
|
76
|
+
## Web Dashboard
|
|
77
|
+
|
|
78
|
+
The server ships an optional **HTTP transport mode** that serves a professional web dashboard alongside the MCP endpoint. Launch with the `REQU_TRANSPORT=http` environment variable:
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
REQU_TRANSPORT=http npx requ-mcp
|
|
82
|
+
# → Dashboard: http://localhost:8788/
|
|
83
|
+
# → MCP endpoint: http://localhost:8788/mcp
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
Or in your MCP client config:
|
|
87
|
+
|
|
88
|
+
```json
|
|
89
|
+
{
|
|
90
|
+
"mcpServers": {
|
|
91
|
+
"requ": {
|
|
92
|
+
"command": "npx",
|
|
93
|
+
"args": ["-y", "requ-mcp"],
|
|
94
|
+
"env": { "REQU_TRANSPORT": "http" }
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
**Default port:** `8788`. Override it with `REQU_PORT=9000 REQU_TRANSPORT=http npx requ-mcp`.
|
|
101
|
+
|
|
102
|
+
### Dashboard tabs
|
|
103
|
+
|
|
104
|
+
| Tab | Content |
|
|
105
|
+
|-----|---------|
|
|
106
|
+
| **Overview** | KPI cards (requirements, stories, scenario pass rate, verified %) + coverage trend chart + component breakdown + gaps summary + phases strip |
|
|
107
|
+
| **Requirements** | Sortable/filterable table of all requirements with inline expansion showing linked story IDs and tags |
|
|
108
|
+
| **Stories** | User stories with status, acceptance criteria count, and coverage badge; expand to see acceptance criteria and linked scenarios with pass/fail/pending icons |
|
|
109
|
+
| **Coverage** | Phase + mode selector (Cumulative / Strict), summary stats, per-component breakdown, and gaps (reqs without story / stories without scenarios / stories not covered) |
|
|
110
|
+
| **Components** | Card grid of components showing description, domain tags, requirement count, and verified percentage |
|
|
111
|
+
| **VCS** | Table of VCS refs (branches and MRs) linked to stories and requirements, with state badges and external links |
|
|
112
|
+
|
|
113
|
+
**Live updates:** The dashboard polls for KPI count changes every 5 seconds via Server-Sent Events (SSE) — no page refresh needed.
|
|
114
|
+
|
|
115
|
+
**Before init:** If the project hasn't been initialized with `init_project` yet, all API endpoints and the dashboard show a "Project not initialized" message rather than crashing.
|
|
116
|
+
|
|
117
|
+
## Usage
|
|
118
|
+
|
|
119
|
+
A typical flow, all driven through the agent:
|
|
76
120
|
|
|
77
121
|
0. `check_conductor` *(optional)* — confirm the Conductor folder exists and see its detected name before initializing.
|
|
78
122
|
1. `init_project` — points at your Conductor project (`conductorPath`); it **verifies the folder exists and is a real Conductor project** (has `features/` or a cucumber config) and reports its name before creating `.requ/`. Pass `force:true` to override.
|
|
@@ -106,6 +150,22 @@ two modes:
|
|
|
106
150
|
|
|
107
151
|
`coverage_trend` returns the summary at each phase in order — the evolution view.
|
|
108
152
|
|
|
153
|
+
### Phase planning & scope
|
|
154
|
+
|
|
155
|
+
Requirements and user stories can be **assigned a target phase** — the release
|
|
156
|
+
they're planned for — via the optional `phase` field on `create_requirement` /
|
|
157
|
+
`create_user_story` (defaults to the active phase; pass `phase: ""` to leave
|
|
158
|
+
unassigned) and `update_requirement` / `update_user_story`. This is *planning*
|
|
159
|
+
("what's in scope for v1.1?"), distinct from *execution* ("what was tested").
|
|
160
|
+
|
|
161
|
+
Phase reports are then scoped to the items planned for that phase, mirroring the
|
|
162
|
+
coverage modes:
|
|
163
|
+
|
|
164
|
+
- **cumulative** — items assigned to the target phase **or any earlier phase**.
|
|
165
|
+
- **strict** — only items assigned to **that** phase.
|
|
166
|
+
- items with **no** phase assigned are **always in scope** (so existing,
|
|
167
|
+
un-phased data behaves exactly as before until you start assigning phases).
|
|
168
|
+
|
|
109
169
|
### Components
|
|
110
170
|
|
|
111
171
|
Requirements carry a `components` array, so coverage can be sliced per
|
|
@@ -182,7 +242,8 @@ doesn't exist.
|
|
|
182
242
|
npm install
|
|
183
243
|
npm run build # tsc -> dist/
|
|
184
244
|
npm run smoke # end-to-end test against the built server over stdio
|
|
185
|
-
npm run dev # run from source with tsx
|
|
245
|
+
npm run dev # run from source with tsx (stdio mode)
|
|
246
|
+
npm run start:http # run from source in HTTP mode with dashboard
|
|
186
247
|
```
|
|
187
248
|
|
|
188
249
|
## How it finds the project
|
package/dist/coverage.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type CoverageMode, type Execution, type Phase, type Requirement, type TestStatus, type UserStory } from "./schema.js";
|
|
1
|
+
import { type CoverageMode, type Execution, type Phase, type Requirement, type TestStatus, type UserStory, type VcsRef } from "./schema.js";
|
|
2
2
|
import type { ConductorScenario } from "./conductor.js";
|
|
3
3
|
/**
|
|
4
4
|
* Phase-aware, story-level coverage rollup.
|
|
@@ -19,6 +19,16 @@ import type { ConductorScenario } from "./conductor.js";
|
|
|
19
19
|
*/
|
|
20
20
|
export type StatusMap = Map<string, TestStatus>;
|
|
21
21
|
export type ScenariosByStory = Map<string, ConductorScenario[]>;
|
|
22
|
+
/**
|
|
23
|
+
* Whether a requirement/story is in scope for a phase report.
|
|
24
|
+
*
|
|
25
|
+
* Mirrors the execution cumulative/strict model:
|
|
26
|
+
* - unassigned (no phase) → always in scope (backward-compatible),
|
|
27
|
+
* - strict → only items assigned to the target phase,
|
|
28
|
+
* - cumulative → items assigned to the target phase or any earlier phase.
|
|
29
|
+
* An item whose phase id is unknown (not in `phases`) is treated as unassigned.
|
|
30
|
+
*/
|
|
31
|
+
export declare function inScope(itemPhase: string | undefined, targetPhaseId: string | null, phases: Phase[], mode: CoverageMode): boolean;
|
|
22
32
|
export declare function resolveStatuses(executionsByPhase: Map<string, Execution[]>, phases: Phase[], targetPhaseId: string | null, mode: CoverageMode): StatusMap;
|
|
23
33
|
export interface ScenarioCoverage {
|
|
24
34
|
feature: string;
|
|
@@ -38,6 +48,16 @@ export interface StoryCoverage {
|
|
|
38
48
|
tested: boolean;
|
|
39
49
|
/** Covered = tested AND every tagged scenario passes. */
|
|
40
50
|
covered: boolean;
|
|
51
|
+
/**
|
|
52
|
+
* Merged-MR is a SEPARATE dimension from `covered` (it does not affect it):
|
|
53
|
+
* the merge-request VcsRef (kind="mr") referencing this story, preferring a
|
|
54
|
+
* state="merged" ref. Optional / backward-compatible.
|
|
55
|
+
*/
|
|
56
|
+
mergedMr?: {
|
|
57
|
+
ref: string;
|
|
58
|
+
state: string;
|
|
59
|
+
url: string;
|
|
60
|
+
};
|
|
41
61
|
}
|
|
42
62
|
export interface RequirementCoverage {
|
|
43
63
|
id: string;
|
|
@@ -77,8 +97,12 @@ export interface CoverageReport {
|
|
|
77
97
|
byComponent: ComponentCoverage[];
|
|
78
98
|
summary: CoverageSummary;
|
|
79
99
|
}
|
|
80
|
-
export declare function computeStoryCoverage(story: UserStory, scenariosByStory: ScenariosByStory, status: StatusMap
|
|
81
|
-
|
|
100
|
+
export declare function computeStoryCoverage(story: UserStory, scenariosByStory: ScenariosByStory, status: StatusMap, mergedMr?: {
|
|
101
|
+
ref: string;
|
|
102
|
+
state: string;
|
|
103
|
+
url: string;
|
|
104
|
+
}): StoryCoverage;
|
|
105
|
+
export declare function buildReport(requirements: Requirement[], stories: UserStory[], scenariosByStory: ScenariosByStory, status: StatusMap, phaseId: string | null, mode: CoverageMode, vcsRefs?: VcsRef[], phases?: Phase[]): CoverageReport;
|
|
82
106
|
export interface TrendPoint {
|
|
83
107
|
phase: string;
|
|
84
108
|
phaseName: string;
|
|
@@ -106,4 +130,4 @@ export interface Gaps {
|
|
|
106
130
|
pending: string[];
|
|
107
131
|
}[];
|
|
108
132
|
}
|
|
109
|
-
export declare function findGaps(requirements: Requirement[], stories: UserStory[], scenariosByStory: ScenariosByStory, status: StatusMap, phaseId: string | null, mode: CoverageMode): Gaps;
|
|
133
|
+
export declare function findGaps(requirements: Requirement[], stories: UserStory[], scenariosByStory: ScenariosByStory, status: StatusMap, phaseId: string | null, mode: CoverageMode, phases?: Phase[]): Gaps;
|
package/dist/coverage.js
CHANGED
|
@@ -1,4 +1,26 @@
|
|
|
1
1
|
import { testKey, } from "./schema.js";
|
|
2
|
+
/**
|
|
3
|
+
* Whether a requirement/story is in scope for a phase report.
|
|
4
|
+
*
|
|
5
|
+
* Mirrors the execution cumulative/strict model:
|
|
6
|
+
* - unassigned (no phase) → always in scope (backward-compatible),
|
|
7
|
+
* - strict → only items assigned to the target phase,
|
|
8
|
+
* - cumulative → items assigned to the target phase or any earlier phase.
|
|
9
|
+
* An item whose phase id is unknown (not in `phases`) is treated as unassigned.
|
|
10
|
+
*/
|
|
11
|
+
export function inScope(itemPhase, targetPhaseId, phases, mode) {
|
|
12
|
+
if (!itemPhase)
|
|
13
|
+
return true;
|
|
14
|
+
if (!targetPhaseId)
|
|
15
|
+
return true;
|
|
16
|
+
if (mode === "strict")
|
|
17
|
+
return itemPhase === targetPhaseId;
|
|
18
|
+
const itemOrder = phases.find((p) => p.id === itemPhase)?.order;
|
|
19
|
+
const targetOrder = phases.find((p) => p.id === targetPhaseId)?.order;
|
|
20
|
+
if (itemOrder === undefined || targetOrder === undefined)
|
|
21
|
+
return true;
|
|
22
|
+
return itemOrder <= targetOrder;
|
|
23
|
+
}
|
|
2
24
|
export function resolveStatuses(executionsByPhase, phases, targetPhaseId, mode) {
|
|
3
25
|
const out = new Map();
|
|
4
26
|
if (!targetPhaseId)
|
|
@@ -16,10 +38,25 @@ export function resolveStatuses(executionsByPhase, phases, targetPhaseId, mode)
|
|
|
16
38
|
}
|
|
17
39
|
return out;
|
|
18
40
|
}
|
|
41
|
+
/** Build a story-id → best MR reference map (prefers a merged MR). */
|
|
42
|
+
function mergedMrByStory(vcsRefs) {
|
|
43
|
+
const out = new Map();
|
|
44
|
+
const mrs = vcsRefs.filter((r) => r.kind === "mr");
|
|
45
|
+
for (const mr of mrs) {
|
|
46
|
+
for (const storyId of mr.storyIds) {
|
|
47
|
+
const current = out.get(storyId);
|
|
48
|
+
// Prefer a merged ref; otherwise keep the first seen.
|
|
49
|
+
if (!current || (current.state !== "merged" && mr.state === "merged")) {
|
|
50
|
+
out.set(storyId, { ref: mr.ref, state: mr.state, url: mr.url });
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
return out;
|
|
55
|
+
}
|
|
19
56
|
function pct(num, den) {
|
|
20
57
|
return den === 0 ? 0 : Math.round((num / den) * 1000) / 10;
|
|
21
58
|
}
|
|
22
|
-
export function computeStoryCoverage(story, scenariosByStory, status) {
|
|
59
|
+
export function computeStoryCoverage(story, scenariosByStory, status, mergedMr) {
|
|
23
60
|
const scs = scenariosByStory.get(story.id) ?? [];
|
|
24
61
|
let passing = 0;
|
|
25
62
|
let failing = 0;
|
|
@@ -45,10 +82,15 @@ export function computeStoryCoverage(story, scenariosByStory, status) {
|
|
|
45
82
|
pending,
|
|
46
83
|
tested: scs.length > 0,
|
|
47
84
|
covered: scs.length > 0 && passing === scs.length,
|
|
85
|
+
...(mergedMr ? { mergedMr } : {}),
|
|
48
86
|
};
|
|
49
87
|
}
|
|
50
|
-
export function buildReport(requirements, stories, scenariosByStory, status, phaseId, mode) {
|
|
51
|
-
|
|
88
|
+
export function buildReport(requirements, stories, scenariosByStory, status, phaseId, mode, vcsRefs = [], phases = []) {
|
|
89
|
+
// Scope to the items planned for this phase (unassigned items always count).
|
|
90
|
+
requirements = requirements.filter((r) => inScope(r.phase, phaseId, phases, mode));
|
|
91
|
+
stories = stories.filter((s) => inScope(s.phase, phaseId, phases, mode));
|
|
92
|
+
const mrByStory = mergedMrByStory(vcsRefs);
|
|
93
|
+
const storyCov = stories.map((s) => computeStoryCoverage(s, scenariosByStory, status, mrByStory.get(s.id)));
|
|
52
94
|
const storyById = new Map(storyCov.map((s) => [s.id, s]));
|
|
53
95
|
const storiesByReq = new Map();
|
|
54
96
|
for (const s of stories) {
|
|
@@ -127,12 +169,12 @@ export function buildTrend(requirements, stories, scenariosByStory, executionsBy
|
|
|
127
169
|
.sort((a, b) => a.order - b.order)
|
|
128
170
|
.map((p) => {
|
|
129
171
|
const status = resolveStatuses(executionsByPhase, phases, p.id, mode);
|
|
130
|
-
const report = buildReport(requirements, stories, scenariosByStory, status, p.id, mode);
|
|
172
|
+
const report = buildReport(requirements, stories, scenariosByStory, status, p.id, mode, [], phases);
|
|
131
173
|
return { phase: p.id, phaseName: p.name, order: p.order, summary: report.summary };
|
|
132
174
|
});
|
|
133
175
|
}
|
|
134
|
-
export function findGaps(requirements, stories, scenariosByStory, status, phaseId, mode) {
|
|
135
|
-
const report = buildReport(requirements, stories, scenariosByStory, status, phaseId, mode);
|
|
176
|
+
export function findGaps(requirements, stories, scenariosByStory, status, phaseId, mode, phases = []) {
|
|
177
|
+
const report = buildReport(requirements, stories, scenariosByStory, status, phaseId, mode, [], phases);
|
|
136
178
|
const requirementsWithoutStory = report.requirements
|
|
137
179
|
.filter((r) => r.status === "active" && !r.hasStory)
|
|
138
180
|
.map((r) => ({ id: r.id, title: r.title, priority: r.priority, components: r.components }));
|
package/dist/coverage.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"coverage.js","sourceRoot":"","sources":["../src/coverage.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,OAAO,
|
|
1
|
+
{"version":3,"file":"coverage.js","sourceRoot":"","sources":["../src/coverage.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared export/import logic — used by both MCP tools and REST routes.
|
|
3
|
+
*/
|
|
4
|
+
import type { Store } from "./storage.js";
|
|
5
|
+
import type { SqliteStore } from "./sqlite-store.js";
|
|
6
|
+
import type { ExportPayload, ImportReport } from "./schema.js";
|
|
7
|
+
type AnyStore = Store | SqliteStore;
|
|
8
|
+
export declare function buildExport(store: AnyStore): Promise<ExportPayload>;
|
|
9
|
+
export declare function applyImport(store: AnyStore, payload: ExportPayload): Promise<ImportReport>;
|
|
10
|
+
export {};
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
export async function buildExport(store) {
|
|
2
|
+
const [config, components, requirements, stories, phases, vcsRefs, executionsByPhase] = await Promise.all([
|
|
3
|
+
store.readConfig().catch(() => null),
|
|
4
|
+
store.listComponents(),
|
|
5
|
+
store.listRequirements(),
|
|
6
|
+
store.listStories(),
|
|
7
|
+
store.listPhases(),
|
|
8
|
+
store.listVcsRefs(),
|
|
9
|
+
store.readAllExecutions(),
|
|
10
|
+
]);
|
|
11
|
+
// Convert Map<phaseId, Execution[]> to plain object
|
|
12
|
+
const executions = {};
|
|
13
|
+
for (const [phaseId, runs] of executionsByPhase.entries()) {
|
|
14
|
+
executions[phaseId] = runs;
|
|
15
|
+
}
|
|
16
|
+
return {
|
|
17
|
+
version: "1",
|
|
18
|
+
exportedAt: new Date().toISOString(),
|
|
19
|
+
source: config ? { name: config.name } : undefined,
|
|
20
|
+
data: { components, requirements, stories, phases, executions, vcsRefs },
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
export async function applyImport(store, payload) {
|
|
24
|
+
const report = {
|
|
25
|
+
imported: {},
|
|
26
|
+
skipped: {},
|
|
27
|
+
errors: [],
|
|
28
|
+
};
|
|
29
|
+
const inc = (key) => { report.imported[key] = (report.imported[key] ?? 0) + 1; };
|
|
30
|
+
const skip = (key, id) => {
|
|
31
|
+
(report.skipped[key] ??= []).push(id);
|
|
32
|
+
};
|
|
33
|
+
// Fetch existing IDs for all entity types in parallel
|
|
34
|
+
const [existingComponents, existingRequirements, existingStories, existingPhases, existingVcsRefs, existingExecutionsByPhase,] = await Promise.all([
|
|
35
|
+
store.listComponents(),
|
|
36
|
+
store.listRequirements(),
|
|
37
|
+
store.listStories(),
|
|
38
|
+
store.listPhases(),
|
|
39
|
+
store.listVcsRefs(),
|
|
40
|
+
store.readAllExecutions(),
|
|
41
|
+
]);
|
|
42
|
+
const existingComponentIds = new Set(existingComponents.map(x => x.id));
|
|
43
|
+
const existingRequirementIds = new Set(existingRequirements.map(x => x.id));
|
|
44
|
+
const existingStoryIds = new Set(existingStories.map(x => x.id));
|
|
45
|
+
const existingPhaseIds = new Set(existingPhases.map(x => x.id));
|
|
46
|
+
const existingVcsRefIds = new Set(existingVcsRefs.map(x => x.id));
|
|
47
|
+
const { data } = payload;
|
|
48
|
+
// --- Components ---
|
|
49
|
+
for (const comp of data.components) {
|
|
50
|
+
if (existingComponentIds.has(comp.id)) {
|
|
51
|
+
skip("components", comp.id);
|
|
52
|
+
continue;
|
|
53
|
+
}
|
|
54
|
+
await store.writeComponent(comp);
|
|
55
|
+
existingComponentIds.add(comp.id);
|
|
56
|
+
inc("components");
|
|
57
|
+
}
|
|
58
|
+
// --- Requirements ---
|
|
59
|
+
for (const req of data.requirements) {
|
|
60
|
+
if (existingRequirementIds.has(req.id)) {
|
|
61
|
+
skip("requirements", req.id);
|
|
62
|
+
continue;
|
|
63
|
+
}
|
|
64
|
+
await store.writeRequirement(req);
|
|
65
|
+
existingRequirementIds.add(req.id);
|
|
66
|
+
inc("requirements");
|
|
67
|
+
}
|
|
68
|
+
// --- Stories ---
|
|
69
|
+
for (const story of data.stories) {
|
|
70
|
+
if (existingStoryIds.has(story.id)) {
|
|
71
|
+
skip("stories", story.id);
|
|
72
|
+
continue;
|
|
73
|
+
}
|
|
74
|
+
// FK check: all referenced requirements must exist (in DB or just imported)
|
|
75
|
+
const missingReqs = story.requirements.filter(rid => !existingRequirementIds.has(rid));
|
|
76
|
+
if (missingReqs.length > 0) {
|
|
77
|
+
report.errors.push(`Story ${story.id} references unknown requirement(s): ${missingReqs.join(", ")}`);
|
|
78
|
+
continue;
|
|
79
|
+
}
|
|
80
|
+
await store.writeStory(story);
|
|
81
|
+
existingStoryIds.add(story.id);
|
|
82
|
+
inc("stories");
|
|
83
|
+
}
|
|
84
|
+
// --- Phases ---
|
|
85
|
+
for (const phase of data.phases) {
|
|
86
|
+
if (existingPhaseIds.has(phase.id)) {
|
|
87
|
+
skip("phases", phase.id);
|
|
88
|
+
continue;
|
|
89
|
+
}
|
|
90
|
+
await store.writePhase(phase);
|
|
91
|
+
existingPhaseIds.add(phase.id);
|
|
92
|
+
inc("phases");
|
|
93
|
+
}
|
|
94
|
+
// --- Executions (keyed by phaseId) ---
|
|
95
|
+
for (const [phaseId, runs] of Object.entries(data.executions)) {
|
|
96
|
+
if (!existingPhaseIds.has(phaseId)) {
|
|
97
|
+
report.errors.push(`Executions reference unknown phase "${phaseId}" — skipped ${runs.length} execution(s)`);
|
|
98
|
+
continue;
|
|
99
|
+
}
|
|
100
|
+
// Build a set of existing execution keys for this phase to avoid duplicates
|
|
101
|
+
const existingForPhase = existingExecutionsByPhase.get(phaseId) ?? [];
|
|
102
|
+
const existingKeys = new Set(existingForPhase.map(e => `${e.feature}::${e.name}`));
|
|
103
|
+
const newRuns = runs.filter(e => !existingKeys.has(`${e.feature}::${e.name}`));
|
|
104
|
+
const skippedCount = runs.length - newRuns.length;
|
|
105
|
+
if (skippedCount > 0) {
|
|
106
|
+
(report.skipped["executions"] ??= []).push(...runs
|
|
107
|
+
.filter(e => existingKeys.has(`${e.feature}::${e.name}`))
|
|
108
|
+
.map(e => `${phaseId}::${e.feature}::${e.name}`));
|
|
109
|
+
}
|
|
110
|
+
if (newRuns.length > 0) {
|
|
111
|
+
await store.appendExecutions(phaseId, newRuns);
|
|
112
|
+
report.imported["executions"] = (report.imported["executions"] ?? 0) + newRuns.length;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
// --- VCS Refs ---
|
|
116
|
+
for (const ref of data.vcsRefs) {
|
|
117
|
+
if (existingVcsRefIds.has(ref.id)) {
|
|
118
|
+
skip("vcsRefs", ref.id);
|
|
119
|
+
continue;
|
|
120
|
+
}
|
|
121
|
+
await store.writeVcsRef(ref);
|
|
122
|
+
existingVcsRefIds.add(ref.id);
|
|
123
|
+
inc("vcsRefs");
|
|
124
|
+
}
|
|
125
|
+
return report;
|
|
126
|
+
}
|
|
127
|
+
//# sourceMappingURL=export-import.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"export-import.js","sourceRoot":"","sources":["../src/export-import.ts"],"names":[],"mappings":"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"}
|