@rsaglobaltech/specgate 0.9.0 → 0.11.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/CHANGELOG.md +162 -0
- package/README.md +10 -18
- package/bin/specgate.ts +10 -3
- package/dist/bin/specgate.js +8 -3
- package/dist/bin/specgate.js.map +1 -1
- package/dist/packages/core/src/domain/DerivedMatrix.js +348 -0
- package/dist/packages/core/src/domain/DerivedMatrix.js.map +1 -0
- package/dist/packages/core/src/domain/DoneVerification.js +22 -1
- package/dist/packages/core/src/domain/DoneVerification.js.map +1 -1
- package/dist/packages/core/src/domain/GherkinQuality.js +19 -3
- package/dist/packages/core/src/domain/GherkinQuality.js.map +1 -1
- package/dist/packages/core/src/domain/NewRequirement.js +46 -0
- package/dist/packages/core/src/domain/NewRequirement.js.map +1 -0
- package/dist/packages/core/src/domain/RequirementPlan.js +1 -0
- package/dist/packages/core/src/domain/RequirementPlan.js.map +1 -1
- package/dist/packages/core/src/domain/RequirementReadiness.js +2 -2
- package/dist/packages/core/src/domain/RequirementReadiness.js.map +1 -1
- package/dist/packages/core/src/domain/TraceabilityFormat.js +8 -1
- package/dist/packages/core/src/domain/TraceabilityFormat.js.map +1 -1
- package/dist/packages/core/src/infrastructure/DerivedMatrixSources.js +157 -0
- package/dist/packages/core/src/infrastructure/DerivedMatrixSources.js.map +1 -0
- package/dist/packages/core/test/unit/derived-matrix.test.js +196 -0
- package/dist/packages/core/test/unit/derived-matrix.test.js.map +1 -0
- package/dist/packages/core/test/unit/done-verification.test.js +7 -6
- package/dist/packages/core/test/unit/done-verification.test.js.map +1 -1
- package/dist/packages/core/test/unit/gherkin-quality.test.js +28 -0
- package/dist/packages/core/test/unit/gherkin-quality.test.js.map +1 -1
- package/dist/packages/core/test/unit/new-requirement.test.js +67 -0
- package/dist/packages/core/test/unit/new-requirement.test.js.map +1 -0
- package/dist/scripts/agents/init.js +58 -14
- package/dist/scripts/agents/init.js.map +1 -1
- package/dist/scripts/check.js +10 -0
- package/dist/scripts/check.js.map +1 -0
- package/dist/scripts/cli/commands/change/ChangeCommand.js +4 -0
- package/dist/scripts/cli/commands/change/ChangeCommand.js.map +1 -1
- package/dist/scripts/cli/commands/harness/RunCommand.js +17 -5
- package/dist/scripts/cli/commands/harness/RunCommand.js.map +1 -1
- package/dist/scripts/cli/commands/pack/ExpandDomainPackCommand.js +9 -0
- package/dist/scripts/cli/commands/pack/ExpandDomainPackCommand.js.map +1 -1
- package/dist/scripts/cli/commands/project/AdoptCommand.js +17 -7
- package/dist/scripts/cli/commands/project/AdoptCommand.js.map +1 -1
- package/dist/scripts/cli/commands/project/InitProjectCommand.js +51 -1
- package/dist/scripts/cli/commands/project/InitProjectCommand.js.map +1 -1
- package/dist/scripts/cli/commands/project/UpdateCommand.js +118 -8
- package/dist/scripts/cli/commands/project/UpdateCommand.js.map +1 -1
- package/dist/scripts/cli/commands/quality/CheckCommand.js +192 -0
- package/dist/scripts/cli/commands/quality/CheckCommand.js.map +1 -0
- package/dist/scripts/cli/commands/quality/FixCommand.js +20 -0
- package/dist/scripts/cli/commands/quality/FixCommand.js.map +1 -1
- package/dist/scripts/cli/commands/quality/ValidateSpecsCommand.js +83 -6
- package/dist/scripts/cli/commands/quality/ValidateSpecsCommand.js.map +1 -1
- package/dist/scripts/cli/commands/spec/DoneCommand.js +23 -5
- package/dist/scripts/cli/commands/spec/DoneCommand.js.map +1 -1
- package/dist/scripts/cli/commands/spec/MatrixCommand.js +305 -0
- package/dist/scripts/cli/commands/spec/MatrixCommand.js.map +1 -0
- package/dist/scripts/cli/commands/spec/NewCommand.js +183 -0
- package/dist/scripts/cli/commands/spec/NewCommand.js.map +1 -0
- package/dist/scripts/cli/commands/spec/PlanCommand.js +6 -1
- package/dist/scripts/cli/commands/spec/PlanCommand.js.map +1 -1
- package/dist/scripts/cli/commands/spec/ReqCommand.js +39 -8
- package/dist/scripts/cli/commands/spec/ReqCommand.js.map +1 -1
- package/dist/scripts/cli/commands/spec/StatusCommand.js +94 -33
- package/dist/scripts/cli/commands/spec/StatusCommand.js.map +1 -1
- package/dist/scripts/lib/derived-writes.js +91 -0
- package/dist/scripts/lib/derived-writes.js.map +1 -0
- package/dist/scripts/lib/surface.js +67 -37
- package/dist/scripts/lib/surface.js.map +1 -1
- package/dist/scripts/matrix.js +11 -0
- package/dist/scripts/matrix.js.map +1 -0
- package/dist/scripts/new.js +10 -0
- package/dist/scripts/new.js.map +1 -0
- package/dist/scripts/plugin/gate-hook.js +2 -2
- package/dist/scripts/plugin/gate-hook.js.map +1 -1
- package/package.json +2 -1
- package/templates/harness/harness.config.yaml.tpl +3 -3
|
@@ -0,0 +1,348 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* The traceability matrix as a projection, not a document (phase 3 of
|
|
4
|
+
* mejoras/plan-simplificacion-equipo.md).
|
|
5
|
+
*
|
|
6
|
+
* ## Why
|
|
7
|
+
*
|
|
8
|
+
* The team found the tool hard to absorb, and the matrix was the heaviest part
|
|
9
|
+
* of it: ten columns kept in step by `req add`, `req link`, `done` and a
|
|
10
|
+
* custom merge driver, so that every behaviour change was also a table edit.
|
|
11
|
+
* Everything in a row is already said somewhere else — the requirement in
|
|
12
|
+
* `spec.md`, its scenario by an `@REQ-NNN @SCN-NNN` tag, its test by naming the
|
|
13
|
+
* requirement. This module computes the rows from those sources.
|
|
14
|
+
*
|
|
15
|
+
* ## Where each column comes from
|
|
16
|
+
*
|
|
17
|
+
* | Column | Source |
|
|
18
|
+
* |---|---|
|
|
19
|
+
* | Requirement, Use Case | the `## REQ-NNN — title` section in `spec.md` |
|
|
20
|
+
* | Scenario ID, Feature file | scenarios tagged `@REQ-NNN` (their `@SCN-…`), one row each |
|
|
21
|
+
* | Test artifact | test files that mention `REQ-NNN` |
|
|
22
|
+
* | Technical artifact | other source files that mention `REQ-NNN` |
|
|
23
|
+
* | Status | `status=` in the section's `csda:trace` comment — the one owner |
|
|
24
|
+
* | anything | an explicit key in that comment wins over what is derived |
|
|
25
|
+
*
|
|
26
|
+
* The comment is the grammar capability specs already use
|
|
27
|
+
* (`<!-- csda:trace status=Implemented test=test/totals.test.js -->`), so
|
|
28
|
+
* `TraceabilityMatrix.traceRow` turns it into a row exactly as it does there.
|
|
29
|
+
*
|
|
30
|
+
* ## Why the file is still written
|
|
31
|
+
*
|
|
32
|
+
* Twenty readers open `docs/specs/traceability.md` directly. Keeping it on disk
|
|
33
|
+
* as generated output leaves every one of them working, and keeps the table a
|
|
34
|
+
* reviewer reads in a pull request. What changes is ownership: nobody edits it,
|
|
35
|
+
* and `validate` fails when it no longer matches its sources.
|
|
36
|
+
*/
|
|
37
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
38
|
+
exports.DERIVED_MARKER = void 0;
|
|
39
|
+
exports.isDerivedMatrix = isDerivedMatrix;
|
|
40
|
+
exports.requirementsIn = requirementsIn;
|
|
41
|
+
exports.deriveRows = deriveRows;
|
|
42
|
+
exports.renderDerivedMatrix = renderDerivedMatrix;
|
|
43
|
+
exports.setTraceFields = setTraceFields;
|
|
44
|
+
exports.rowKey = rowKey;
|
|
45
|
+
exports.diffRows = diffRows;
|
|
46
|
+
exports.rowsOf = rowsOf;
|
|
47
|
+
exports.traceValueWritable = traceValueWritable;
|
|
48
|
+
exports.fieldsToReproduce = fieldsToReproduce;
|
|
49
|
+
const TraceabilityMatrix_1 = require("./TraceabilityMatrix");
|
|
50
|
+
const TraceabilityFormat_1 = require("./TraceabilityFormat");
|
|
51
|
+
const SpecParser_1 = require("./SpecParser");
|
|
52
|
+
const GherkinTags_1 = require("./GherkinTags");
|
|
53
|
+
/** First line of a derived matrix. Its presence is what makes a project derived. */
|
|
54
|
+
exports.DERIVED_MARKER = "<!-- specgate:derived — generated from spec.md, features/ and tests. " +
|
|
55
|
+
"Do not edit by hand: run `specgate matrix`. -->";
|
|
56
|
+
function isDerivedMatrix(content) {
|
|
57
|
+
return String(content || "").includes("<!-- specgate:derived");
|
|
58
|
+
}
|
|
59
|
+
const SECTION_HEADING = /^(#{2,4})\s+(REQ-[A-Za-z0-9.]+)\b\s*[—–:-]?\s*(.*)$/;
|
|
60
|
+
const TRACE_LINE = /^\s*<!--\s*csda:trace\b/;
|
|
61
|
+
/** Every `## REQ-NNN — title` section in `spec.md`, in document order. */
|
|
62
|
+
function requirementsIn(spec) {
|
|
63
|
+
const lines = String(spec || "")
|
|
64
|
+
.replace(/\r\n/g, "\n")
|
|
65
|
+
.split("\n");
|
|
66
|
+
const found = [];
|
|
67
|
+
for (let i = 0; i < lines.length; i += 1) {
|
|
68
|
+
const m = SECTION_HEADING.exec(lines[i].trim());
|
|
69
|
+
if (!m || found.some((r) => r.id === m[2]))
|
|
70
|
+
continue;
|
|
71
|
+
const level = m[1].length;
|
|
72
|
+
let trace = {};
|
|
73
|
+
for (let j = i + 1; j < lines.length; j += 1) {
|
|
74
|
+
if (new RegExp(`^#{1,${level}}\\s+\\S`).test(lines[j]))
|
|
75
|
+
break;
|
|
76
|
+
if (TRACE_LINE.test(lines[j])) {
|
|
77
|
+
trace = (0, SpecParser_1.parseTraceComment)(lines[j]);
|
|
78
|
+
break;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
found.push({ id: m[2], title: m[3].trim(), trace });
|
|
82
|
+
}
|
|
83
|
+
return found;
|
|
84
|
+
}
|
|
85
|
+
/** `REQ-002` as a whole token: not `REQ-0021`, not `XREQ-002`. */
|
|
86
|
+
function mentions(source, id) {
|
|
87
|
+
const escaped = id.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
88
|
+
return new RegExp(`(^|[^A-Za-z0-9])${escaped}(?![A-Za-z0-9])`).test(source);
|
|
89
|
+
}
|
|
90
|
+
/** The scenarios tagged with a requirement: `[{ scn, feature }]`, in file order. */
|
|
91
|
+
function taggedScenarios(features, id) {
|
|
92
|
+
const out = [];
|
|
93
|
+
for (const f of [...features].sort((a, b) => a.path.localeCompare(b.path))) {
|
|
94
|
+
for (const tags of Object.values((0, GherkinTags_1.csdaTagsByScenario)(f.source))) {
|
|
95
|
+
if (!tags.includes(`@${id}`))
|
|
96
|
+
continue;
|
|
97
|
+
const scn = tags.find((t) => t.startsWith("@SCN-"));
|
|
98
|
+
out.push({ scn: scn ? scn.slice(1) : "-", feature: f.path });
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
return out;
|
|
102
|
+
}
|
|
103
|
+
/** The matrix rows the sources imply. */
|
|
104
|
+
function deriveRows(sources) {
|
|
105
|
+
const rows = [];
|
|
106
|
+
for (const req of requirementsIn(sources.spec)) {
|
|
107
|
+
const trace = { ...req.trace };
|
|
108
|
+
if (!trace.uc && req.title)
|
|
109
|
+
trace.uc = req.title;
|
|
110
|
+
if (!trace.test) {
|
|
111
|
+
const tests = sources.tests
|
|
112
|
+
.filter((t) => mentions(t.source, req.id))
|
|
113
|
+
.map((t) => t.path)
|
|
114
|
+
.sort();
|
|
115
|
+
if (tests.length > 0)
|
|
116
|
+
trace.test = tests.join(", ");
|
|
117
|
+
}
|
|
118
|
+
if (!trace.artifact) {
|
|
119
|
+
const code = (sources.code || [])
|
|
120
|
+
.filter((t) => mentions(t.source, req.id))
|
|
121
|
+
.map((t) => t.path)
|
|
122
|
+
.sort();
|
|
123
|
+
if (code.length > 0)
|
|
124
|
+
trace.artifact = code.join(", ");
|
|
125
|
+
}
|
|
126
|
+
const scenarios = trace.scn || trace.feature ? [] : taggedScenarios(sources.features, req.id);
|
|
127
|
+
const variants = scenarios.length > 0
|
|
128
|
+
? scenarios.map((s) => ({ ...trace, scn: s.scn, feature: s.feature }))
|
|
129
|
+
: [trace];
|
|
130
|
+
for (const t of variants) {
|
|
131
|
+
const row = TraceabilityMatrix_1.TraceabilityMatrix.traceRow({ id: req.id, trace: t });
|
|
132
|
+
if (t.depends)
|
|
133
|
+
row.dependsOn = String(t.depends).split(",").filter(Boolean);
|
|
134
|
+
if (t.context)
|
|
135
|
+
row.context = t.context;
|
|
136
|
+
rows.push(row);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
const fromSpec = new Set(rows.map((r) => r.requirement));
|
|
140
|
+
for (const cap of [...(sources.capabilities || [])].sort((a, b) => a.path.localeCompare(b.path))) {
|
|
141
|
+
let parsed;
|
|
142
|
+
try {
|
|
143
|
+
parsed = (0, SpecParser_1.parseSpec)(cap.source);
|
|
144
|
+
}
|
|
145
|
+
catch {
|
|
146
|
+
continue;
|
|
147
|
+
}
|
|
148
|
+
for (const req of parsed.requirements || []) {
|
|
149
|
+
if (!req.id || fromSpec.has(req.id))
|
|
150
|
+
continue;
|
|
151
|
+
const row = TraceabilityMatrix_1.TraceabilityMatrix.traceRow(req);
|
|
152
|
+
const trace = req.trace || {};
|
|
153
|
+
if (trace.depends)
|
|
154
|
+
row.dependsOn = String(trace.depends).split(",").filter(Boolean);
|
|
155
|
+
if (trace.context)
|
|
156
|
+
row.context = trace.context;
|
|
157
|
+
rows.push(row);
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
return rows;
|
|
161
|
+
}
|
|
162
|
+
/** The generated `traceability.md`. */
|
|
163
|
+
function renderDerivedMatrix(rows, projectName) {
|
|
164
|
+
const body = (0, TraceabilityFormat_1.buildTraceabilityMarkdown)(rows, "rich").replace("# Traceability Matrix", `# Traceability Matrix${projectName ? ` — ${projectName}` : ""}`);
|
|
165
|
+
return `${exports.DERIVED_MARKER}\n${body}`;
|
|
166
|
+
}
|
|
167
|
+
// ── Writing the one owner ────────────────────────────────────────────────────
|
|
168
|
+
/**
|
|
169
|
+
* `spec.md` with `fields` set in `reqId`'s `csda:trace` comment.
|
|
170
|
+
*
|
|
171
|
+
* The comment is created right under the heading when the section has none.
|
|
172
|
+
* A value of `""` removes the key. Returns `null` when the section is absent.
|
|
173
|
+
*/
|
|
174
|
+
function setTraceFields(spec, reqId, fields) {
|
|
175
|
+
const lines = String(spec || "")
|
|
176
|
+
.replace(/\r\n/g, "\n")
|
|
177
|
+
.split("\n");
|
|
178
|
+
let heading = -1;
|
|
179
|
+
let level = 2;
|
|
180
|
+
for (let i = 0; i < lines.length; i += 1) {
|
|
181
|
+
const m = SECTION_HEADING.exec(lines[i].trim());
|
|
182
|
+
if (m && m[2] === reqId) {
|
|
183
|
+
heading = i;
|
|
184
|
+
level = m[1].length;
|
|
185
|
+
break;
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
if (heading === -1)
|
|
189
|
+
return null;
|
|
190
|
+
let at = -1;
|
|
191
|
+
for (let j = heading + 1; j < lines.length; j += 1) {
|
|
192
|
+
if (new RegExp(`^#{1,${level}}\\s+\\S`).test(lines[j]))
|
|
193
|
+
break;
|
|
194
|
+
if (TRACE_LINE.test(lines[j])) {
|
|
195
|
+
at = j;
|
|
196
|
+
break;
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
const current = at === -1 ? {} : (0, SpecParser_1.parseTraceComment)(lines[at]);
|
|
200
|
+
const merged = { ...current };
|
|
201
|
+
for (const [k, v] of Object.entries(fields)) {
|
|
202
|
+
if (v === "")
|
|
203
|
+
delete merged[k];
|
|
204
|
+
else
|
|
205
|
+
merged[k] = v;
|
|
206
|
+
}
|
|
207
|
+
const rendered = renderTraceComment(merged);
|
|
208
|
+
if (at !== -1) {
|
|
209
|
+
if (rendered === null)
|
|
210
|
+
lines.splice(at, 1);
|
|
211
|
+
else
|
|
212
|
+
lines[at] = rendered;
|
|
213
|
+
}
|
|
214
|
+
else if (rendered !== null) {
|
|
215
|
+
lines.splice(heading + 1, 0, "", rendered);
|
|
216
|
+
}
|
|
217
|
+
return lines.join("\n");
|
|
218
|
+
}
|
|
219
|
+
/** Keys in a stable order, so a status change is a one-line diff. */
|
|
220
|
+
const KEY_ORDER = [
|
|
221
|
+
"status",
|
|
222
|
+
"scn",
|
|
223
|
+
"feature",
|
|
224
|
+
"test",
|
|
225
|
+
"artifact",
|
|
226
|
+
"uc",
|
|
227
|
+
"cmd",
|
|
228
|
+
"qry",
|
|
229
|
+
"agg",
|
|
230
|
+
"evt",
|
|
231
|
+
];
|
|
232
|
+
function renderTraceComment(trace) {
|
|
233
|
+
const keys = Object.keys(trace).sort((a, b) => {
|
|
234
|
+
const ia = KEY_ORDER.indexOf(a);
|
|
235
|
+
const ib = KEY_ORDER.indexOf(b);
|
|
236
|
+
return (ia === -1 ? 99 : ia) - (ib === -1 ? 99 : ib) || a.localeCompare(b);
|
|
237
|
+
});
|
|
238
|
+
if (keys.length === 0)
|
|
239
|
+
return null;
|
|
240
|
+
const parts = keys.map((k) => {
|
|
241
|
+
// The grammar has quotes and no escapes: a value with spaces is wrapped in
|
|
242
|
+
// whichever quote it does not contain. One with both cannot be written,
|
|
243
|
+
// and `traceValueWritable` keeps migration from trying.
|
|
244
|
+
const v = String(trace[k]);
|
|
245
|
+
if (!/[\s"']/.test(v))
|
|
246
|
+
return `${k}=${v}`;
|
|
247
|
+
return v.includes("'") ? `${k}="${v}"` : `${k}='${v}'`;
|
|
248
|
+
});
|
|
249
|
+
return `<!-- csda:trace ${parts.join(" ")} -->`;
|
|
250
|
+
}
|
|
251
|
+
// ── Comparing, for --check and for migration ─────────────────────────────────
|
|
252
|
+
const COLUMNS = [
|
|
253
|
+
"requirement",
|
|
254
|
+
"scenarioId",
|
|
255
|
+
"featureFile",
|
|
256
|
+
"useCase",
|
|
257
|
+
"commandOrQuery",
|
|
258
|
+
"aggregate",
|
|
259
|
+
"event",
|
|
260
|
+
"technicalArtifact",
|
|
261
|
+
"testArtifact",
|
|
262
|
+
"status",
|
|
263
|
+
];
|
|
264
|
+
function norm(v) {
|
|
265
|
+
const s = String(v ?? "-")
|
|
266
|
+
.replace(/`/g, "")
|
|
267
|
+
.replace(/\s*,\s*/g, ", ")
|
|
268
|
+
.trim() || "-";
|
|
269
|
+
// `-` and `TBD` both mean "no test declared"; the gate reads them alike.
|
|
270
|
+
return s.toUpperCase() === "TBD" ? "-" : s;
|
|
271
|
+
}
|
|
272
|
+
/** A row as a comparable key, backticks and spacing ignored. */
|
|
273
|
+
function rowKey(row) {
|
|
274
|
+
return COLUMNS.map((c) => norm(row[c])).join(" | ");
|
|
275
|
+
}
|
|
276
|
+
/** Rows present on one side and not the other. Empty both ways means equal. */
|
|
277
|
+
function diffRows(expected, actual) {
|
|
278
|
+
const a = expected.map(rowKey);
|
|
279
|
+
const b = actual.map(rowKey);
|
|
280
|
+
const missing = a.filter((k) => !b.includes(k));
|
|
281
|
+
const extra = b.filter((k) => !a.includes(k));
|
|
282
|
+
return { missing, extra };
|
|
283
|
+
}
|
|
284
|
+
/** The rows a matrix file holds, in the shape `deriveRows` returns. */
|
|
285
|
+
function rowsOf(matrixContent) {
|
|
286
|
+
const parsed = (0, TraceabilityFormat_1.parseTraceabilityRows)(matrixContent);
|
|
287
|
+
return parsed.mode === "rich" ? parsed.rows : [];
|
|
288
|
+
}
|
|
289
|
+
/**
|
|
290
|
+
* The `csda:trace` fields a requirement needs so that derivation reproduces
|
|
291
|
+
* `rows` — or the reason it cannot.
|
|
292
|
+
*
|
|
293
|
+
* Only what derivation would get wrong is written: a matrix whose tags and
|
|
294
|
+
* test names already carry the links migrates to nothing but status lines.
|
|
295
|
+
*/
|
|
296
|
+
/** Can this value be stored in a `csda:trace` comment and read back intact? */
|
|
297
|
+
function traceValueWritable(v) {
|
|
298
|
+
return !(v.includes("'") && v.includes('"')) && !v.includes("-->");
|
|
299
|
+
}
|
|
300
|
+
function fieldsToReproduce(req, rows, sources) {
|
|
301
|
+
const derived = deriveRows({
|
|
302
|
+
...sources,
|
|
303
|
+
spec: `## ${req.id} — ${req.title}\n`,
|
|
304
|
+
});
|
|
305
|
+
if (rows.length > 1) {
|
|
306
|
+
// Several rows for one requirement: only tags can say which scenario is
|
|
307
|
+
// which, and every other column has to agree across them.
|
|
308
|
+
const shared = COLUMNS.filter((c) => !["scenarioId", "featureFile"].includes(c));
|
|
309
|
+
const disagree = shared.filter((c) => new Set(rows.map((r) => norm(r[c]))).size > 1);
|
|
310
|
+
if (disagree.length > 0) {
|
|
311
|
+
return {
|
|
312
|
+
reason: `${rows.length} rows that differ in ${disagree.join(", ")} — one requirement, one value per column`,
|
|
313
|
+
};
|
|
314
|
+
}
|
|
315
|
+
const wanted = rows.map((r) => `${norm(r.scenarioId)}@${norm(r.featureFile)}`).sort();
|
|
316
|
+
const got = derived.map((r) => `${norm(r.scenarioId)}@${norm(r.featureFile)}`).sort();
|
|
317
|
+
if (wanted.join() !== got.join()) {
|
|
318
|
+
return {
|
|
319
|
+
reason: `${rows.length} scenarios that are not tagged @${req.id} @SCN-… in their feature files`,
|
|
320
|
+
};
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
const row = rows[0];
|
|
324
|
+
const first = derived[0] || {};
|
|
325
|
+
const fields = {};
|
|
326
|
+
const set = (key, column, value) => {
|
|
327
|
+
if (norm(row[column]) !== norm(first[column]))
|
|
328
|
+
fields[key] = value ?? norm(row[column]);
|
|
329
|
+
};
|
|
330
|
+
if (rows.length === 1) {
|
|
331
|
+
set("scn", "scenarioId");
|
|
332
|
+
set("feature", "featureFile");
|
|
333
|
+
}
|
|
334
|
+
set("uc", "useCase");
|
|
335
|
+
set("cmd", "commandOrQuery");
|
|
336
|
+
set("agg", "aggregate");
|
|
337
|
+
set("evt", "event");
|
|
338
|
+
set("artifact", "technicalArtifact");
|
|
339
|
+
set("test", "testArtifact");
|
|
340
|
+
if (norm(row.status) !== "Draft")
|
|
341
|
+
fields.status = norm(row.status);
|
|
342
|
+
const unwritable = Object.entries(fields).find(([, v]) => !traceValueWritable(v));
|
|
343
|
+
if (unwritable) {
|
|
344
|
+
return { reason: `its ${unwritable[0]} cell mixes both quote characters: ${unwritable[1]}` };
|
|
345
|
+
}
|
|
346
|
+
return { fields };
|
|
347
|
+
}
|
|
348
|
+
//# sourceMappingURL=DerivedMatrix.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DerivedMatrix.js","sourceRoot":"","sources":["../../../../../packages/core/src/domain/DerivedMatrix.ts"],"names":[],"mappings":"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"}
|
|
@@ -33,6 +33,7 @@
|
|
|
33
33
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
34
34
|
exports.NO_TEST_COMMAND_WARNING = void 0;
|
|
35
35
|
exports.planDoneVerification = planDoneVerification;
|
|
36
|
+
exports.planGateCheck = planGateCheck;
|
|
36
37
|
/**
|
|
37
38
|
* The checks `done` should run, in the order they should run.
|
|
38
39
|
*
|
|
@@ -48,14 +49,34 @@ function planDoneVerification(projectDir, opts) {
|
|
|
48
49
|
// `--strict` means "the gate this project can actually give me". Anything
|
|
49
50
|
// weaker recreates the defect a cold evaluator named: following the
|
|
50
51
|
// documentation leaves you with a weaker gate than the tool supports.
|
|
51
|
-
|
|
52
|
+
// The whole gate, not a subset: a subset let a scenario of unfilled
|
|
53
|
+
// `<placeholder>` steps close as Implemented (--strict-scenarios was not
|
|
54
|
+
// in it), and "one gate, one name" is the rule since #174.
|
|
55
|
+
validateArgs.push("--strict");
|
|
52
56
|
}
|
|
57
|
+
if (opts.reqId)
|
|
58
|
+
validateArgs.push("--delivering", opts.reqId);
|
|
53
59
|
const steps = [{ stage: "validate", argv: validateArgs }];
|
|
54
60
|
const testCmd = (opts.testCmd || "").trim();
|
|
55
61
|
if (testCmd !== "")
|
|
56
62
|
steps.push({ stage: "tests", argv: [testCmd] });
|
|
57
63
|
return { steps, testsUnverified: testCmd === "" };
|
|
58
64
|
}
|
|
65
|
+
/**
|
|
66
|
+
* The checks `specgate check` runs: the gate, then the suite.
|
|
67
|
+
*
|
|
68
|
+
* `check` is the one command a team needs in CI and before a PR. It is
|
|
69
|
+
* `validate --strict` — not a subset, because a subset is how ten pages ended
|
|
70
|
+
* up recommending a gate that passed a requirement whose test file was gone —
|
|
71
|
+
* followed by the project's tests when a command is configured.
|
|
72
|
+
*/
|
|
73
|
+
function planGateCheck(projectDir, testCmd) {
|
|
74
|
+
const steps = [{ stage: "validate", argv: [projectDir, "--strict"] }];
|
|
75
|
+
const cmd = (testCmd || "").trim();
|
|
76
|
+
if (cmd !== "")
|
|
77
|
+
steps.push({ stage: "tests", argv: [cmd] });
|
|
78
|
+
return { steps, testsUnverified: cmd === "" };
|
|
79
|
+
}
|
|
59
80
|
/** The line `done` prints when nothing ran the project's tests. */
|
|
60
81
|
exports.NO_TEST_COMMAND_WARNING = Object.freeze({
|
|
61
82
|
message: "No test command configured — this checked the specification, not the code.",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DoneVerification.js","sourceRoot":"","sources":["../../../../../packages/core/src/domain/DoneVerification.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;;;
|
|
1
|
+
{"version":3,"file":"DoneVerification.js","sourceRoot":"","sources":["../../../../../packages/core/src/domain/DoneVerification.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;;;AAyCH,oDAwBC;AAUD,sCAKC;AA9CD;;;;;;GAMG;AACH,SAAgB,oBAAoB,CAClC,UAAkB,EAClB,IAAsB;IAEtB,IAAI,CAAC,IAAI,CAAC,KAAK,IAAI,CAAC,IAAI,CAAC,MAAM;QAAE,OAAO,EAAE,KAAK,EAAE,EAAE,EAAE,eAAe,EAAE,KAAK,EAAE,CAAC;IAE9E,MAAM,YAAY,GAAG,CAAC,UAAU,CAAC,CAAC;IAClC,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;QAChB,0EAA0E;QAC1E,oEAAoE;QACpE,sEAAsE;QACtE,oEAAoE;QACpE,yEAAyE;QACzE,2DAA2D;QAC3D,YAAY,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IAChC,CAAC;IACD,IAAI,IAAI,CAAC,KAAK;QAAE,YAAY,CAAC,IAAI,CAAC,cAAc,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC;IAE9D,MAAM,KAAK,GAAuB,CAAC,EAAE,KAAK,EAAE,UAAU,EAAE,IAAI,EAAE,YAAY,EAAE,CAAC,CAAC;IAE9E,MAAM,OAAO,GAAG,CAAC,IAAI,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;IAC5C,IAAI,OAAO,KAAK,EAAE;QAAE,KAAK,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IAEpE,OAAO,EAAE,KAAK,EAAE,eAAe,EAAE,OAAO,KAAK,EAAE,EAAE,CAAC;AACpD,CAAC;AAED;;;;;;;GAOG;AACH,SAAgB,aAAa,CAAC,UAAkB,EAAE,OAAgB;IAChE,MAAM,KAAK,GAAuB,CAAC,EAAE,KAAK,EAAE,UAAU,EAAE,IAAI,EAAE,CAAC,UAAU,EAAE,UAAU,CAAC,EAAE,CAAC,CAAC;IAC1F,MAAM,GAAG,GAAG,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;IACnC,IAAI,GAAG,KAAK,EAAE;QAAE,KAAK,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAC5D,OAAO,EAAE,KAAK,EAAE,eAAe,EAAE,GAAG,KAAK,EAAE,EAAE,CAAC;AAChD,CAAC;AAED,mEAAmE;AACtD,QAAA,uBAAuB,GAAG,MAAM,CAAC,MAAM,CAAC;IACnD,OAAO,EAAE,4EAA4E;IACrF,GAAG,EAAE;QACH,yEAAyE;QACzE,4EAA4E;QAC5E,0CAA0C;KAC3C;CACF,CAAC,CAAC"}
|
|
@@ -30,8 +30,9 @@
|
|
|
30
30
|
*
|
|
31
31
|
* ## Severity is not a matter of taste
|
|
32
32
|
*
|
|
33
|
-
*
|
|
34
|
-
*
|
|
33
|
+
* Three rules are errors and can never be demoted to style: `scenario_has_no_steps`,
|
|
34
|
+
* `keyword_case_invalid` and `scenario_placeholder_step` — a template nobody
|
|
35
|
+
* filled in describes no behaviour. Cucumber reports an empty scenario as
|
|
35
36
|
* `1 scenario (1 passed) · 0 steps · exit 0` — a test that proves nothing and
|
|
36
37
|
* says it passed. 27 shipped scenarios were in that state while `--strict`
|
|
37
38
|
* called them fine (H14). The rest are warnings: a two-step scenario is weak,
|
|
@@ -62,7 +63,18 @@ exports.QUALITY_CODES = Object.freeze({
|
|
|
62
63
|
OUTLINE_WITHOUT_EXAMPLES: "scenario_outline_without_examples",
|
|
63
64
|
VAGUE_STEP: "vague_step",
|
|
64
65
|
KEYWORD_CASE: "keyword_case_invalid",
|
|
66
|
+
PLACEHOLDER_STEP: "scenario_placeholder_step",
|
|
65
67
|
});
|
|
68
|
+
/**
|
|
69
|
+
* An unfilled `<placeholder>` in a plain Scenario.
|
|
70
|
+
*
|
|
71
|
+
* In an Outline, `<x>` is a parameter the Examples table fills. In a plain
|
|
72
|
+
* Scenario nothing fills it: `Given <the starting state>` is a template a
|
|
73
|
+
* person was meant to rewrite. Measured 2026-10-06: a scenario made of three
|
|
74
|
+
* such steps passed `validate --strict` and `done --strict` with its
|
|
75
|
+
* requirement Implemented — three steps, a real title, no vague word.
|
|
76
|
+
*/
|
|
77
|
+
const PLACEHOLDER_RE = /<[^<>]+>/;
|
|
66
78
|
/**
|
|
67
79
|
* A title that names nothing: `Test`, `Scenario 1`, or fewer than three words.
|
|
68
80
|
*
|
|
@@ -76,7 +88,7 @@ function isGenericTitle(title) {
|
|
|
76
88
|
return title.split(/\s+/).filter(Boolean).length < 3;
|
|
77
89
|
}
|
|
78
90
|
/**
|
|
79
|
-
* The
|
|
91
|
+
* The nine rules, applied to one scenario.
|
|
80
92
|
*
|
|
81
93
|
* `target` is what the caller wants the reader to look at — a pack scenario id,
|
|
82
94
|
* a file path, whatever locates it. The domain does not invent it because the
|
|
@@ -113,6 +125,10 @@ function analyseScenario(scenario, target, file) {
|
|
|
113
125
|
found.push((0, Diagnostic_1.error)(exports.QUALITY_CODES.OUTLINE_WITHOUT_EXAMPLES, "Scenario Outline has no Examples table.", at({ fix: "Add an `Examples:` table, or make it a plain `Scenario`." })));
|
|
114
126
|
}
|
|
115
127
|
for (const step of scenario.steps) {
|
|
128
|
+
if (!scenario.outline && PLACEHOLDER_RE.test(step.text)) {
|
|
129
|
+
found.push((0, Diagnostic_1.error)(exports.QUALITY_CODES.PLACEHOLDER_STEP, `unfilled placeholder in "${step.keyword} ${step.text}" — nothing fills it outside an Outline.`, at({ fix: "Replace the <placeholder> with the concrete state, action or outcome." })));
|
|
130
|
+
continue;
|
|
131
|
+
}
|
|
116
132
|
if (VAGUE_STEP_RE.test(step.text)) {
|
|
117
133
|
found.push((0, Diagnostic_1.warning)(exports.QUALITY_CODES.VAGUE_STEP, `vague step "${step.keyword} ${step.text}" — make it concrete and falsifiable.`, at({ fix: "State a checkable fact: a value, a state, an emitted event." })));
|
|
118
134
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"GherkinQuality.js","sourceRoot":"","sources":["../../../../../packages/core/src/domain/GherkinQuality.ts"],"names":[],"mappings":";AAAA
|
|
1
|
+
{"version":3,"file":"GherkinQuality.js","sourceRoot":"","sources":["../../../../../packages/core/src/domain/GherkinQuality.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;;;AA6DH,wCAIC;AASD,0CAiGC;AAsBD,gDASC;AAED,oDAqBC;AA9ND,6CAA8C;AAC9C,uCAAgE;AAmBhE;;;;;GAKG;AACH,MAAM,aAAa,GACjB,6HAA6H,CAAC;AAEhI,gFAAgF;AACnE,QAAA,aAAa,GAAG,MAAM,CAAC,MAAM,CAAC;IACzC,aAAa,EAAE,wBAAwB;IACvC,QAAQ,EAAE,uBAAuB;IACjC,aAAa,EAAE,wBAAwB;IACvC,OAAO,EAAE,uBAAuB;IAChC,OAAO,EAAE,uBAAuB;IAChC,wBAAwB,EAAE,mCAAmC;IAC7D,UAAU,EAAE,YAAY;IACxB,YAAY,EAAE,sBAAsB;IACpC,gBAAgB,EAAE,2BAA2B;CAC9C,CAAC,CAAC;AAEH;;;;;;;;GAQG;AACH,MAAM,cAAc,GAAG,UAAU,CAAC;AAElC;;;;GAIG;AACH,SAAgB,cAAc,CAAC,KAAa;IAC1C,IAAI,CAAC,KAAK;QAAE,OAAO,IAAI,CAAC;IACxB,IAAI,sCAAsC,CAAC,IAAI,CAAC,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IACpE,OAAO,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC;AACvD,CAAC;AAED;;;;;;GAMG;AACH,SAAgB,eAAe,CAC7B,QAA8B,EAC9B,MAAc,EACd,IAAa;IAEb,MAAM,KAAK,GAAiB,EAAE,CAAC;IAC/B,MAAM,EAAE,GAAG,CAAC,QAAiC,EAAE,EAAE,EAAE,CAAC,CAAC;QACnD,MAAM;QACN,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACzB,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACjD,GAAG,KAAK;KACT,CAAC,CAAC;IACH,MAAM,KAAK,GAAG,IAAI,GAAG,CAAC,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC;IAE5D,IAAI,cAAc,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;QAClC,KAAK,CAAC,IAAI,CACR,IAAA,oBAAO,EACL,qBAAa,CAAC,aAAa,EAC3B,4DAA4D,EAC5D,EAAE,CAAC,EAAE,GAAG,EAAE,yEAAyE,EAAE,CAAC,CACvF,CACF,CAAC;IACJ,CAAC;IAED,IAAI,QAAQ,CAAC,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAChC,uEAAuE;QACvE,KAAK,CAAC,IAAI,CACR,IAAA,kBAAK,EACH,qBAAa,CAAC,QAAQ,EACtB,wEAAwE;YACtE,0EAA0E;YAC1E,kDAAkD,EACpD,EAAE,CAAC,EAAE,GAAG,EAAE,0DAA0D,EAAE,CAAC,CACxE,CACF,CAAC;IACJ,CAAC;SAAM,IAAI,QAAQ,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACrC,KAAK,CAAC,IAAI,CACR,IAAA,oBAAO,EACL,qBAAa,CAAC,aAAa,EAC3B,QAAQ,QAAQ,CAAC,KAAK,CAAC,MAAM,mDAAmD,EAChF,EAAE,CAAC,EAAE,GAAG,EAAE,+CAA+C,EAAE,CAAC,CAC7D,CACF,CAAC;IACJ,CAAC;IAED,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC;QACvB,KAAK,CAAC,IAAI,CACR,IAAA,oBAAO,EACL,qBAAa,CAAC,OAAO,EACrB,kDAAkD,EAClD,EAAE,CAAC,EAAE,GAAG,EAAE,iDAAiD,EAAE,CAAC,CAC/D,CACF,CAAC;IACJ,CAAC;IACD,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC;QACvB,KAAK,CAAC,IAAI,CACR,IAAA,oBAAO,EACL,qBAAa,CAAC,OAAO,EACrB,8CAA8C,EAC9C,EAAE,CAAC,EAAE,GAAG,EAAE,mDAAmD,EAAE,CAAC,CACjE,CACF,CAAC;IACJ,CAAC;IAED,IAAI,QAAQ,CAAC,OAAO,IAAI,CAAC,QAAQ,CAAC,WAAW,EAAE,CAAC;QAC9C,KAAK,CAAC,IAAI,CACR,IAAA,kBAAK,EACH,qBAAa,CAAC,wBAAwB,EACtC,yCAAyC,EACzC,EAAE,CAAC,EAAE,GAAG,EAAE,0DAA0D,EAAE,CAAC,CACxE,CACF,CAAC;IACJ,CAAC;IAED,KAAK,MAAM,IAAI,IAAI,QAAQ,CAAC,KAAK,EAAE,CAAC;QAClC,IAAI,CAAC,QAAQ,CAAC,OAAO,IAAI,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;YACxD,KAAK,CAAC,IAAI,CACR,IAAA,kBAAK,EACH,qBAAa,CAAC,gBAAgB,EAC9B,4BAA4B,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC,IAAI,0CAA0C,EAC/F,EAAE,CAAC,EAAE,GAAG,EAAE,uEAAuE,EAAE,CAAC,CACrF,CACF,CAAC;YACF,SAAS;QACX,CAAC;QACD,IAAI,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;YAClC,KAAK,CAAC,IAAI,CACR,IAAA,oBAAO,EACL,qBAAa,CAAC,UAAU,EACxB,eAAe,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC,IAAI,uCAAuC,EAC/E,EAAE,CAAC,EAAE,GAAG,EAAE,6DAA6D,EAAE,CAAC,CAC3E,CACF,CAAC;QACJ,CAAC;IACH,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;;;;GAKG;AACH;;;;;;;GAOG;AACH;;;;;GAKG;AACH,SAAgB,kBAAkB,CAAC,MAAc,EAAE,IAAY;IAC7D,OAAO,IAAA,+BAAqB,EAAC,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CACjD,IAAA,kBAAK,EACH,qBAAa,CAAC,YAAY,EAC1B,KAAK,KAAK,CAAC,KAAK,wCAAwC,KAAK,CAAC,QAAQ,MAAM;QAC1E,uDAAuD,EACzD,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,EAAE,WAAW,KAAK,CAAC,QAAQ,KAAK,EAAE,CAC9E,CACF,CAAC;AACJ,CAAC;AAED,SAAgB,oBAAoB,CAAC,MAAc,EAAE,IAAY;IAC/D,MAAM,KAAK,GAAiB,CAAC,GAAG,kBAAkB,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC,CAAC;IAElE,MAAM,GAAG,GAAG,IAAA,sBAAY,EAAC,MAAM,CAAC,CAAC;IACjC,KAAK,MAAM,QAAQ,IAAI,GAAG,CAAC,SAAS,EAAE,CAAC;QACrC,KAAK,CAAC,IAAI,CACR,GAAG,eAAe,CAChB;YACE,IAAI,EAAE,QAAQ,CAAC,IAAI;YACnB,KAAK,EAAE,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;YACxE,OAAO,EAAE,QAAQ,CAAC,OAAO;YACzB,WAAW,EAAE,QAAQ,CAAC,WAAW;YACjC,IAAI,EAAE,QAAQ,CAAC,IAAI;SACpB,EACD,GAAG,IAAI,OAAO,QAAQ,CAAC,IAAI,IAAI,YAAY,GAAG,EAC9C,IAAI,CACL,CACF,CAAC;IACJ,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* What `specgate new` writes for a requirement: a slug for its feature file
|
|
4
|
+
* and a tagged scenario of placeholders for a person to rewrite.
|
|
5
|
+
*
|
|
6
|
+
* The placeholders are deliberate. A scenario the tool invents would read as
|
|
7
|
+
* a decision nobody made; `<the observable outcome>` reads as a question. The
|
|
8
|
+
* gate leaves them alone while the requirement is Draft and refuses them once
|
|
9
|
+
* it is delivered (`scenario_placeholder_step`).
|
|
10
|
+
*/
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.slugFor = slugFor;
|
|
13
|
+
exports.scenarioBlock = scenarioBlock;
|
|
14
|
+
exports.featureWithScenario = featureWithScenario;
|
|
15
|
+
const MAX_SLUG_WORDS = 6;
|
|
16
|
+
/** `Totals are rounded half-up` → `totals-are-rounded-half-up`. */
|
|
17
|
+
function slugFor(title) {
|
|
18
|
+
const words = title
|
|
19
|
+
.normalize("NFKD")
|
|
20
|
+
.replace(/[̀-ͯ]/g, "")
|
|
21
|
+
.toLowerCase()
|
|
22
|
+
.replace(/[^a-z0-9]+/g, " ")
|
|
23
|
+
.trim()
|
|
24
|
+
.split(/\s+/)
|
|
25
|
+
.filter(Boolean)
|
|
26
|
+
.slice(0, MAX_SLUG_WORDS);
|
|
27
|
+
return words.join("-") || "requirement";
|
|
28
|
+
}
|
|
29
|
+
/** The scenario, tagged so `validate` can tie it to its matrix row. */
|
|
30
|
+
function scenarioBlock(reqId, scenarioId, title) {
|
|
31
|
+
return [
|
|
32
|
+
` @${reqId} @${scenarioId}`,
|
|
33
|
+
` Scenario: ${title}`,
|
|
34
|
+
" Given <the state before the action>",
|
|
35
|
+
" When <the action under test>",
|
|
36
|
+
" Then <the observable outcome>",
|
|
37
|
+
"",
|
|
38
|
+
].join("\n");
|
|
39
|
+
}
|
|
40
|
+
/** A new feature file, or the scenario appended to an existing one. */
|
|
41
|
+
function featureWithScenario(existing, title, block) {
|
|
42
|
+
if (existing === null)
|
|
43
|
+
return `Feature: ${title}\n\n${block}`;
|
|
44
|
+
return `${existing.replace(/\s*$/, "")}\n\n${block}`;
|
|
45
|
+
}
|
|
46
|
+
//# sourceMappingURL=NewRequirement.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"NewRequirement.js","sourceRoot":"","sources":["../../../../../packages/core/src/domain/NewRequirement.ts"],"names":[],"mappings":";AAAA;;;;;;;;GAQG;;AAKH,0BAWC;AAGD,sCASC;AAGD,kDAGC;AAhCD,MAAM,cAAc,GAAG,CAAC,CAAC;AAEzB,mEAAmE;AACnE,SAAgB,OAAO,CAAC,KAAa;IACnC,MAAM,KAAK,GAAG,KAAK;SAChB,SAAS,CAAC,MAAM,CAAC;SACjB,OAAO,CAAC,QAAQ,EAAE,EAAE,CAAC;SACrB,WAAW,EAAE;SACb,OAAO,CAAC,aAAa,EAAE,GAAG,CAAC;SAC3B,IAAI,EAAE;SACN,KAAK,CAAC,KAAK,CAAC;SACZ,MAAM,CAAC,OAAO,CAAC;SACf,KAAK,CAAC,CAAC,EAAE,cAAc,CAAC,CAAC;IAC5B,OAAO,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,aAAa,CAAC;AAC1C,CAAC;AAED,uEAAuE;AACvE,SAAgB,aAAa,CAAC,KAAa,EAAE,UAAkB,EAAE,KAAa;IAC5E,OAAO;QACL,MAAM,KAAK,KAAK,UAAU,EAAE;QAC5B,eAAe,KAAK,EAAE;QACtB,yCAAyC;QACzC,kCAAkC;QAClC,mCAAmC;QACnC,EAAE;KACH,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACf,CAAC;AAED,uEAAuE;AACvE,SAAgB,mBAAmB,CAAC,QAAuB,EAAE,KAAa,EAAE,KAAa;IACvF,IAAI,QAAQ,KAAK,IAAI;QAAE,OAAO,YAAY,KAAK,OAAO,KAAK,EAAE,CAAC;IAC9D,OAAO,GAAG,QAAQ,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,OAAO,KAAK,EAAE,CAAC;AACvD,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RequirementPlan.js","sourceRoot":"","sources":["../../../../../packages/core/src/domain/RequirementPlan.ts"],"names":[],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"RequirementPlan.js","sourceRoot":"","sources":["../../../../../packages/core/src/domain/RequirementPlan.ts"],"names":[],"mappings":";;;AAmDA,MAAa,eAAe;IACnB,MAAM,CAAU,aAAa,GAAG,IAAI,GAAG,CAAC,CAAC,aAAa,EAAE,UAAU,EAAE,UAAU,CAAC,CAAC,CAAC;IACjF,MAAM,CAAU,cAAc,GAAG,0BAA0B,CAAC;IAE5D,MAAM,CAAC,YAAY,CAAC,KAAU;QACnC,IAAI,OAAO,KAAK,KAAK,QAAQ;YAAE,OAAO,KAAK,CAAC;QAC5C,MAAM,QAAQ,GAAG,KAAK,CAAC,OAAO,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;QACpD,IAAI,CAAC,QAAQ;YAAE,OAAO,KAAK,CAAC;QAC5B,OAAO,CAAC,eAAe,CAAC,cAAc,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IACxD,CAAC;IAEM,MAAM,CAAC,WAAW,CACvB,GAAiB,EACjB,WAAyC;QAEzC,MAAM,KAAK,GAAG,GAAG,CAAC,WAAW,IAAI,EAAE,CAAC;QACpC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC;YAAE,OAAO,IAAI,CAAC;QAEzC,MAAM,aAAa,GAAG,WAAW,CAAC,GAAG,CAAC,WAAW,IAAI,EAAE,CAAC,CAAC;QACzD,MAAM,YAAY,GAAG,eAAe,CAAC,YAAY,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC;QACzE,MAAM,YAAY,GAAG,eAAe,CAAC,YAAY,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;QACpE,MAAM,UAAU,GAAG,YAAY,IAAI,WAAW,CAAC,GAAG,CAAC,iBAAiB,IAAI,EAAE,CAAC,CAAC;QAC5E,MAAM,UAAU,GAAG,YAAY,IAAI,WAAW,CAAC,GAAG,CAAC,YAAY,IAAI,EAAE,CAAC,CAAC;QACvE,MAAM,MAAM,GAAG,eAAe,CAAC,aAAa,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC;QAEnE,IAAI,QAAsB,CAAC;QAC3B,IAAI,CAAC,aAAa;YAAE,QAAQ,GAAG,eAAe,CAAC;aAC1C,IAAI,CAAC,YAAY,IAAI,CAAC,YAAY;YAAE,QAAQ,GAAG,kBAAkB,CAAC;aAClE,IAAI,YAAY,IAAI,CAAC,UAAU,IAAI,YAAY,IAAI,CAAC,UAAU;YACjE,QAAQ,GAAG,kBAAkB,CAAC;aAC3B,IAAI,YAAY,IAAI,CAAC,UAAU;YAAE,QAAQ,GAAG,YAAY,CAAC;aACzD,IAAI,YAAY,IAAI,CAAC,UAAU;YAAE,QAAQ,GAAG,sBAAsB,CAAC;aACnE,IAAI,CAAC,MAAM;YAAE,QAAQ,GAAG,qBAAqB,CAAC;;YAC9C,QAAQ,GAAG,MAAM,CAAC;QAEvB,OAAO;YACL,WAAW,EAAE,KAAK;YAClB,WAAW,EAAE,GAAG,CAAC,UAAU,IAAI,EAAE;YACjC,YAAY,EAAE,GAAG,CAAC,WAAW,IAAI,EAAE;YACnC,kBAAkB,EAAE,GAAG,CAAC,iBAAiB,IAAI,EAAE;YAC/C,aAAa,EAAE,GAAG,CAAC,YAAY,IAAI,EAAE;YACrC,MAAM,EAAE,GAAG,CAAC,MAAM,IAAI,EAAE;YACxB,cAAc,EAAE,aAAa;YAC7B,gBAAgB,EAAE,UAAU;YAC5B,WAAW,EAAE,UAAU;YACvB,QAAQ;YACR,KAAK,EAAE,GAAG,CAAC,OAAO,IAAI,EAAE;SACzB,CAAC;IACJ,CAAC;IAEM,MAAM,CAAC,YAAY,CAAC,KAAiB;QAC1C,MAAM,OAAO,GAAgB;YAC3B,KAAK,EAAE,KAAK,CAAC,MAAM;YACnB,IAAI,EAAE,CAAC;YACP,aAAa,EAAE,CAAC;YAChB,UAAU,EAAE,CAAC;YACb,oBAAoB,EAAE,CAAC;YACvB,mBAAmB,EAAE,CAAC;YACtB,gBAAgB,EAAE,CAAC;YACnB,OAAO,EAAE,CAAC;SACX,CAAC;QAEF,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,IAAI,IAAI,CAAC,QAAQ,KAAK,MAAM;gBAAE,OAAO,CAAC,IAAI,EAAE,CAAC;iBACxC,IAAI,IAAI,CAAC,QAAQ,KAAK,eAAe;gBAAE,OAAO,CAAC,aAAa,EAAE,CAAC;iBAC/D,IAAI,IAAI,CAAC,QAAQ,KAAK,YAAY;gBAAE,OAAO,CAAC,UAAU,EAAE,CAAC;iBACzD,IAAI,IAAI,CAAC,QAAQ,KAAK,sBAAsB;gBAAE,OAAO,CAAC,oBAAoB,EAAE,CAAC;iBAC7E,IAAI,IAAI,CAAC,QAAQ,KAAK,qBAAqB;gBAAE,OAAO,CAAC,mBAAmB,EAAE,CAAC;iBAC3E,IAAI,IAAI,CAAC,QAAQ,KAAK,kBAAkB;gBAAE,OAAO,CAAC,gBAAgB,EAAE,CAAC;YAE1E,IAAI,IAAI,CAAC,UAAU,IAAI,IAAI,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBAClD,OAAO,CAAC,OAAO,EAAE,CAAC;YACpB,CAAC;QACH,CAAC;QAED,OAAO,OAAO,CAAC;IACjB,CAAC;;AA5EH,0CA6EC"}
|
|
@@ -102,11 +102,11 @@ function requirementReadiness(input) {
|
|
|
102
102
|
// These are not the noise trap A2 had to avoid. `TBD` in the test column is
|
|
103
103
|
// not a false positive; it is an accurate statement about an incomplete row,
|
|
104
104
|
// and TDD says that column is what should be filled in first.
|
|
105
|
-
if (!input.testDeclared) {
|
|
105
|
+
if (!input.testDeclared && !input.derived) {
|
|
106
106
|
blockers.push((0, Diagnostic_1.warning)(exports.READINESS_CODES.NO_TEST_ARTIFACT, "the row declares no test artifact, so the agent chooses where the test " +
|
|
107
107
|
"goes and the matrix will point somewhere else.", { target, fix: `specgate req link ${target} --test <path>` }));
|
|
108
108
|
}
|
|
109
|
-
if (!input.technicalDeclared) {
|
|
109
|
+
if (!input.technicalDeclared && !input.derived) {
|
|
110
110
|
blockers.push((0, Diagnostic_1.warning)(exports.READINESS_CODES.NO_TECHNICAL_ARTIFACT, "the row declares no production artifact, so the agent chooses where the " +
|
|
111
111
|
"implementation goes and the matrix will point somewhere else.", { target, fix: `specgate req link ${target} --code <path>` }));
|
|
112
112
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RequirementReadiness.js","sourceRoot":"","sources":["../../../../../packages/core/src/domain/RequirementReadiness.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;;;
|
|
1
|
+
{"version":3,"file":"RequirementReadiness.js","sourceRoot":"","sources":["../../../../../packages/core/src/domain/RequirementReadiness.ts"],"names":[],"mappings":"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"}
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
* `ITraceabilityRepository`.
|
|
10
10
|
*/
|
|
11
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
-
exports.POST_DRAFT_STATUS = exports.ALLOWED_STATUS = exports.LEGACY_HEADER = exports.RICH_HEADER = void 0;
|
|
12
|
+
exports.DELIVERED_STATUS = exports.POST_DRAFT_STATUS = exports.ALLOWED_STATUS = exports.LEGACY_HEADER = exports.RICH_HEADER = void 0;
|
|
13
13
|
exports.parseTraceabilityRows = parseTraceabilityRows;
|
|
14
14
|
exports.parseMatrixTraceLines = parseMatrixTraceLines;
|
|
15
15
|
exports.parseMatrixDependencies = parseMatrixDependencies;
|
|
@@ -275,6 +275,13 @@ exports.ALLOWED_STATUS = new Set([
|
|
|
275
275
|
]);
|
|
276
276
|
/** The statuses that mean work has started — everything but `Draft`. */
|
|
277
277
|
exports.POST_DRAFT_STATUS = new Set([...exports.ALLOWED_STATUS].filter((s) => s !== "Draft"));
|
|
278
|
+
/**
|
|
279
|
+
* The statuses that claim the work exists. Before these, a row's declared
|
|
280
|
+
* paths are a plan — the file a requirement is going to land in — and a
|
|
281
|
+
* missing one is not drift. `Deprecated` is excluded: its files may have been
|
|
282
|
+
* removed on purpose.
|
|
283
|
+
*/
|
|
284
|
+
exports.DELIVERED_STATUS = new Set(["Implemented", "Verified", "Released"]);
|
|
278
285
|
/** Which of the two matrix shapes this file uses, or `null` if neither header is present. */
|
|
279
286
|
function detectTraceabilityMode(content) {
|
|
280
287
|
if (content.includes(exports.RICH_HEADER))
|