@sdd-method/maintain-cli 0.13.0 → 0.13.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -14,7 +14,10 @@
|
|
|
14
14
|
// ## Trigger
|
|
15
15
|
// ...
|
|
16
16
|
//
|
|
17
|
-
//
|
|
17
|
+
// Any SDD catalogues the journeys it owns: an application its own, and a platform root a journey that no single
|
|
18
|
+
// application owns (a cross-application journey, M-ADR 0146, or one that runs through platform services only), whose
|
|
19
|
+
// journey feature names it with @journey:<id> (M-ADR 0229 §4.2, option B). **App:** is omitted where no app owns it.
|
|
20
|
+
// Only an application is expected to have journeys/, so only there is its absence a coverage finding.
|
|
18
21
|
// id = `{product_id}-{slug}`, slug from filename stem.
|
|
19
22
|
import { readdir, readFile } from "node:fs/promises";
|
|
20
23
|
import { basename, join, relative } from "node:path";
|
|
@@ -26,17 +29,6 @@ export async function buildUserJourneys(inputs) {
|
|
|
26
29
|
const relatedFeatureSlugsById = new Map();
|
|
27
30
|
const primaryPersonaById = new Map();
|
|
28
31
|
const supportingPersonasById = new Map();
|
|
29
|
-
if (inputs.profile !== "application-product") {
|
|
30
|
-
return {
|
|
31
|
-
rows: [],
|
|
32
|
-
idByPath,
|
|
33
|
-
idBySlug,
|
|
34
|
-
featurePathsById,
|
|
35
|
-
relatedFeatureSlugsById,
|
|
36
|
-
primaryPersonaById,
|
|
37
|
-
supportingPersonasById,
|
|
38
|
-
};
|
|
39
|
-
}
|
|
40
32
|
const dir = join(inputs.sddPath, JOURNEYS_DIR_REL);
|
|
41
33
|
let entries;
|
|
42
34
|
try {
|
|
@@ -45,7 +37,10 @@ export async function buildUserJourneys(inputs) {
|
|
|
45
37
|
catch (err) {
|
|
46
38
|
if (err.code !== "ENOENT")
|
|
47
39
|
throw err;
|
|
48
|
-
|
|
40
|
+
// An application is expected to describe its journeys; another SDD holds journeys only where it owns one.
|
|
41
|
+
if (inputs.profile === "application-product") {
|
|
42
|
+
inputs.findings.add("coverage", `${JOURNEYS_DIR_REL}/ not found — emitting empty user_journeys.csv`);
|
|
43
|
+
}
|
|
49
44
|
return {
|
|
50
45
|
rows: [],
|
|
51
46
|
idByPath,
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
// never the proposal's.
|
|
10
10
|
// unnamed a listed journey the proposal's `## Affected Journeys` section does not name.
|
|
11
11
|
// unshown a journey named `altered` with nothing to show it: no delta in the change to a feature of kind journey
|
|
12
|
-
// whose
|
|
12
|
+
// whose delta or living spec tags it @journey:<journey-id> (option B), and no task naming it (option A).
|
|
13
13
|
// A proposal line is `- <journey-id>: altered ...` or `- <journey-id>: unaffected, <reason>`; an unaffected line
|
|
14
14
|
// with no reason is reported too.
|
|
15
15
|
//
|
|
@@ -52,6 +52,10 @@ async function csv(repo, name, dir = "catalogues") {
|
|
|
52
52
|
return text === null ? null : parseCatalogueCsv(text).rows;
|
|
53
53
|
}
|
|
54
54
|
/** The `## Affected Journeys` section: journey id -> what the proposal says of it. */
|
|
55
|
+
/** The journey ids a spec tags with @journey:<id>. */
|
|
56
|
+
export function journeyTags(text) {
|
|
57
|
+
return new Set([...text.matchAll(/@journey:([a-z0-9][a-z0-9-]*)/g)].map((m) => m[1]));
|
|
58
|
+
}
|
|
55
59
|
export function parseAffectedJourneys(proposal) {
|
|
56
60
|
const out = new Map();
|
|
57
61
|
let inSection = false;
|
|
@@ -178,7 +182,18 @@ export async function checkJourneyImpact(repo) {
|
|
|
178
182
|
if (n.verdict === "unaffected" && n.rest === "")
|
|
179
183
|
warnings.push(`${CHANGES_DIR}/${change}/proposal.md: journey ${j} is named unaffected without a reason`);
|
|
180
184
|
if (n.verdict === "altered") {
|
|
181
|
-
|
|
185
|
+
// Option B: a delta to a feature of kind journey that names this journey with its @journey tag, in the delta
|
|
186
|
+
// or in the living spec it changes (M-ADR 0229 §4.2). The tag, not the feature's id, binds the two.
|
|
187
|
+
let journeyDelta = false;
|
|
188
|
+
for (const f of deltaFeatures) {
|
|
189
|
+
if (featureKinds.get(f) !== "journey")
|
|
190
|
+
continue;
|
|
191
|
+
const text = `${(await readText(join(dir, "specs", f, "spec.md"))) ?? ""}\n${(await readText(join(repo, "openspec", "specs", f, "spec.md"))) ?? ""}`;
|
|
192
|
+
if (journeyTags(text).has(j)) {
|
|
193
|
+
journeyDelta = true;
|
|
194
|
+
break;
|
|
195
|
+
}
|
|
196
|
+
}
|
|
182
197
|
const shown = journeyDelta || tasks.includes(j);
|
|
183
198
|
if (!shown)
|
|
184
199
|
warnings.push(`${CHANGES_DIR}/${change}/proposal.md: journey ${j} is named altered, and the change shows nothing for it: no delta to its journey feature and no task naming it`);
|
package/dist/verify-version.json
CHANGED
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sdd-method/maintain-cli",
|
|
3
|
-
"version": "0.13.
|
|
4
|
-
"sddCliVersion": "4.0.
|
|
3
|
+
"version": "0.13.1",
|
|
4
|
+
"sddCliVersion": "4.0.1",
|
|
5
5
|
"description": "Bring an SDD repository current and rebuild its derived model — sync, briefing, catalogue build and aggregate, pack build, context pull — plus every read-only verify verb. Ships only the code those verbs reach; it cannot author specification content. Authoring is in @sdd-method/sdd-cli.",
|
|
6
6
|
"license": "UNLICENSED",
|
|
7
7
|
"type": "module",
|