@sdd-method/sdd-cli 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/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -1
- package/dist/index.js.map +1 -1
- package/dist/lib/catalogue/aggregate.d.ts +39 -0
- package/dist/lib/catalogue/aggregate.d.ts.map +1 -0
- package/dist/lib/catalogue/aggregate.js +344 -0
- package/dist/lib/catalogue/aggregate.js.map +1 -0
- package/dist/lib/catalogue/aggregation-manifest-loader.d.ts +25 -0
- package/dist/lib/catalogue/aggregation-manifest-loader.d.ts.map +1 -0
- package/dist/lib/catalogue/aggregation-manifest-loader.js +111 -0
- package/dist/lib/catalogue/aggregation-manifest-loader.js.map +1 -0
- package/dist/lib/catalogue/build.d.ts +42 -0
- package/dist/lib/catalogue/build.d.ts.map +1 -0
- package/dist/lib/catalogue/build.js +373 -0
- package/dist/lib/catalogue/build.js.map +1 -0
- package/dist/lib/catalogue/builders/adr-supersedes.d.ts +14 -0
- package/dist/lib/catalogue/builders/adr-supersedes.d.ts.map +1 -0
- package/dist/lib/catalogue/builders/adr-supersedes.js +62 -0
- package/dist/lib/catalogue/builders/adr-supersedes.js.map +1 -0
- package/dist/lib/catalogue/builders/adrs.d.ts +27 -0
- package/dist/lib/catalogue/builders/adrs.d.ts.map +1 -0
- package/dist/lib/catalogue/builders/adrs.js +191 -0
- package/dist/lib/catalogue/builders/adrs.js.map +1 -0
- package/dist/lib/catalogue/builders/c4-containers.d.ts +16 -0
- package/dist/lib/catalogue/builders/c4-containers.d.ts.map +1 -0
- package/dist/lib/catalogue/builders/c4-containers.js +169 -0
- package/dist/lib/catalogue/builders/c4-containers.js.map +1 -0
- package/dist/lib/catalogue/builders/c4-systems.d.ts +10 -0
- package/dist/lib/catalogue/builders/c4-systems.d.ts.map +1 -0
- package/dist/lib/catalogue/builders/c4-systems.js +99 -0
- package/dist/lib/catalogue/builders/c4-systems.js.map +1 -0
- package/dist/lib/catalogue/builders/capabilities.d.ts +11 -0
- package/dist/lib/catalogue/builders/capabilities.d.ts.map +1 -0
- package/dist/lib/catalogue/builders/capabilities.js +173 -0
- package/dist/lib/catalogue/builders/capabilities.js.map +1 -0
- package/dist/lib/catalogue/builders/capability-edges.d.ts +27 -0
- package/dist/lib/catalogue/builders/capability-edges.d.ts.map +1 -0
- package/dist/lib/catalogue/builders/capability-edges.js +166 -0
- package/dist/lib/catalogue/builders/capability-edges.js.map +1 -0
- package/dist/lib/catalogue/builders/contracts.d.ts +15 -0
- package/dist/lib/catalogue/builders/contracts.d.ts.map +1 -0
- package/dist/lib/catalogue/builders/contracts.js +153 -0
- package/dist/lib/catalogue/builders/contracts.js.map +1 -0
- package/dist/lib/catalogue/builders/domains.d.ts +10 -0
- package/dist/lib/catalogue/builders/domains.d.ts.map +1 -0
- package/dist/lib/catalogue/builders/domains.js +93 -0
- package/dist/lib/catalogue/builders/domains.js.map +1 -0
- package/dist/lib/catalogue/builders/event-edges.d.ts +20 -0
- package/dist/lib/catalogue/builders/event-edges.d.ts.map +1 -0
- package/dist/lib/catalogue/builders/event-edges.js +112 -0
- package/dist/lib/catalogue/builders/event-edges.js.map +1 -0
- package/dist/lib/catalogue/builders/events.d.ts +26 -0
- package/dist/lib/catalogue/builders/events.d.ts.map +1 -0
- package/dist/lib/catalogue/builders/events.js +99 -0
- package/dist/lib/catalogue/builders/events.js.map +1 -0
- package/dist/lib/catalogue/builders/feature-groups.d.ts +10 -0
- package/dist/lib/catalogue/builders/feature-groups.d.ts.map +1 -0
- package/dist/lib/catalogue/builders/feature-groups.js +118 -0
- package/dist/lib/catalogue/builders/feature-groups.js.map +1 -0
- package/dist/lib/catalogue/builders/features.d.ts +35 -0
- package/dist/lib/catalogue/builders/features.d.ts.map +1 -0
- package/dist/lib/catalogue/builders/features.js +206 -0
- package/dist/lib/catalogue/builders/features.js.map +1 -0
- package/dist/lib/catalogue/builders/glossary-xref.d.ts +11 -0
- package/dist/lib/catalogue/builders/glossary-xref.d.ts.map +1 -0
- package/dist/lib/catalogue/builders/glossary-xref.js +107 -0
- package/dist/lib/catalogue/builders/glossary-xref.js.map +1 -0
- package/dist/lib/catalogue/builders/glossary.d.ts +14 -0
- package/dist/lib/catalogue/builders/glossary.d.ts.map +1 -0
- package/dist/lib/catalogue/builders/glossary.js +150 -0
- package/dist/lib/catalogue/builders/glossary.js.map +1 -0
- package/dist/lib/catalogue/builders/index.d.ts +57 -0
- package/dist/lib/catalogue/builders/index.d.ts.map +1 -0
- package/dist/lib/catalogue/builders/index.js +33 -0
- package/dist/lib/catalogue/builders/index.js.map +1 -0
- package/dist/lib/catalogue/builders/integrations.d.ts +12 -0
- package/dist/lib/catalogue/builders/integrations.d.ts.map +1 -0
- package/dist/lib/catalogue/builders/integrations.js +85 -0
- package/dist/lib/catalogue/builders/integrations.js.map +1 -0
- package/dist/lib/catalogue/builders/persona-journey-edges.d.ts +26 -0
- package/dist/lib/catalogue/builders/persona-journey-edges.d.ts.map +1 -0
- package/dist/lib/catalogue/builders/persona-journey-edges.js +133 -0
- package/dist/lib/catalogue/builders/persona-journey-edges.js.map +1 -0
- package/dist/lib/catalogue/builders/personas.d.ts +22 -0
- package/dist/lib/catalogue/builders/personas.d.ts.map +1 -0
- package/dist/lib/catalogue/builders/personas.js +150 -0
- package/dist/lib/catalogue/builders/personas.js.map +1 -0
- package/dist/lib/catalogue/builders/product-edges.d.ts +15 -0
- package/dist/lib/catalogue/builders/product-edges.d.ts.map +1 -0
- package/dist/lib/catalogue/builders/product-edges.js +97 -0
- package/dist/lib/catalogue/builders/product-edges.js.map +1 -0
- package/dist/lib/catalogue/builders/products.d.ts +26 -0
- package/dist/lib/catalogue/builders/products.d.ts.map +1 -0
- package/dist/lib/catalogue/builders/products.js +57 -0
- package/dist/lib/catalogue/builders/products.js.map +1 -0
- package/dist/lib/catalogue/builders/repo-edges.d.ts +18 -0
- package/dist/lib/catalogue/builders/repo-edges.d.ts.map +1 -0
- package/dist/lib/catalogue/builders/repo-edges.js +113 -0
- package/dist/lib/catalogue/builders/repo-edges.js.map +1 -0
- package/dist/lib/catalogue/builders/repositories.d.ts +78 -0
- package/dist/lib/catalogue/builders/repositories.d.ts.map +1 -0
- package/dist/lib/catalogue/builders/repositories.js +204 -0
- package/dist/lib/catalogue/builders/repositories.js.map +1 -0
- package/dist/lib/catalogue/builders/service-contract.d.ts +11 -0
- package/dist/lib/catalogue/builders/service-contract.d.ts.map +1 -0
- package/dist/lib/catalogue/builders/service-contract.js +53 -0
- package/dist/lib/catalogue/builders/service-contract.js.map +1 -0
- package/dist/lib/catalogue/builders/services.d.ts +15 -0
- package/dist/lib/catalogue/builders/services.d.ts.map +1 -0
- package/dist/lib/catalogue/builders/services.js +40 -0
- package/dist/lib/catalogue/builders/services.js.map +1 -0
- package/dist/lib/catalogue/builders/user-journeys.d.ts +24 -0
- package/dist/lib/catalogue/builders/user-journeys.d.ts.map +1 -0
- package/dist/lib/catalogue/builders/user-journeys.js +253 -0
- package/dist/lib/catalogue/builders/user-journeys.js.map +1 -0
- package/dist/lib/catalogue/canonical-schema.yaml +624 -0
- package/dist/lib/catalogue/cli-version.d.ts +10 -0
- package/dist/lib/catalogue/cli-version.d.ts.map +1 -0
- package/dist/lib/catalogue/cli-version.js +10 -0
- package/dist/lib/catalogue/cli-version.js.map +1 -0
- package/dist/lib/catalogue/csv-reader.d.ts +7 -0
- package/dist/lib/catalogue/csv-reader.d.ts.map +1 -0
- package/dist/lib/catalogue/csv-reader.js +97 -0
- package/dist/lib/catalogue/csv-reader.js.map +1 -0
- package/dist/lib/catalogue/csv-writer.d.ts +29 -0
- package/dist/lib/catalogue/csv-writer.d.ts.map +1 -0
- package/dist/lib/catalogue/csv-writer.js +55 -0
- package/dist/lib/catalogue/csv-writer.js.map +1 -0
- package/dist/lib/catalogue/findings.d.ts +27 -0
- package/dist/lib/catalogue/findings.d.ts.map +1 -0
- package/dist/lib/catalogue/findings.js +34 -0
- package/dist/lib/catalogue/findings.js.map +1 -0
- package/dist/lib/catalogue/fk-validator.d.ts +44 -0
- package/dist/lib/catalogue/fk-validator.d.ts.map +1 -0
- package/dist/lib/catalogue/fk-validator.js +90 -0
- package/dist/lib/catalogue/fk-validator.js.map +1 -0
- package/dist/lib/catalogue/index.d.ts +27 -0
- package/dist/lib/catalogue/index.d.ts.map +1 -0
- package/dist/lib/catalogue/index.js +18 -0
- package/dist/lib/catalogue/index.js.map +1 -0
- package/dist/lib/catalogue/manifest-loader.d.ts +47 -0
- package/dist/lib/catalogue/manifest-loader.d.ts.map +1 -0
- package/dist/lib/catalogue/manifest-loader.js +161 -0
- package/dist/lib/catalogue/manifest-loader.js.map +1 -0
- package/dist/lib/catalogue/schema-compat.d.ts +47 -0
- package/dist/lib/catalogue/schema-compat.d.ts.map +1 -0
- package/dist/lib/catalogue/schema-compat.js +52 -0
- package/dist/lib/catalogue/schema-compat.js.map +1 -0
- package/dist/lib/catalogue/schema-loader.d.ts +58 -0
- package/dist/lib/catalogue/schema-loader.d.ts.map +1 -0
- package/dist/lib/catalogue/schema-loader.js +86 -0
- package/dist/lib/catalogue/schema-loader.js.map +1 -0
- package/dist/lib/catalogue/traceability-loader.d.ts +56 -0
- package/dist/lib/catalogue/traceability-loader.d.ts.map +1 -0
- package/dist/lib/catalogue/traceability-loader.js +217 -0
- package/dist/lib/catalogue/traceability-loader.js.map +1 -0
- package/dist/lib/catalogue/validate.d.ts +16 -0
- package/dist/lib/catalogue/validate.d.ts.map +1 -0
- package/dist/lib/catalogue/validate.js +137 -0
- package/dist/lib/catalogue/validate.js.map +1 -0
- package/dist/lib/catalogue/version.d.ts +3 -0
- package/dist/lib/catalogue/version.d.ts.map +1 -0
- package/dist/lib/catalogue/version.js +18 -0
- package/dist/lib/catalogue/version.js.map +1 -0
- package/dist/lib/init/index.d.ts.map +1 -1
- package/dist/lib/init/index.js +6 -0
- package/dist/lib/init/index.js.map +1 -1
- package/dist/lib/mcp/build-info.d.ts +1 -1
- package/dist/lib/mcp/build-info.d.ts.map +1 -1
- package/dist/lib/mcp/build-info.js +1 -1
- package/dist/lib/mcp/build-info.js.map +1 -1
- package/dist/lib/repo-kind.d.ts +3 -3
- package/dist/lib/repo-kind.d.ts.map +1 -1
- package/dist/lib/repo-kind.js +4 -0
- package/dist/lib/repo-kind.js.map +1 -1
- package/dist/verbs/catalogue.d.ts +3 -0
- package/dist/verbs/catalogue.d.ts.map +1 -0
- package/dist/verbs/catalogue.js +60 -0
- package/dist/verbs/catalogue.js.map +1 -0
- package/package.json +3 -3
- package/scripts/copy-yaml-assets.mjs +38 -0
- package/scripts/sync-canonical-schema.sh +39 -0
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
// Domain discoverer — emits `domains.csv` rows from `docs/domains/<slug>/`.
|
|
2
|
+
//
|
|
3
|
+
// Per ADR 0134 and catalogue-builder-specification.md:
|
|
4
|
+
// - Domains are method-defined: each subdirectory under docs/domains/
|
|
5
|
+
// is one domain, named by its slug.
|
|
6
|
+
// - method_profile reflects the SDD's profile (the domain belongs to
|
|
7
|
+
// this SDD's method profile).
|
|
8
|
+
// - repo_count is computed by the build orchestrator after repositories
|
|
9
|
+
// are discovered, since this builder runs first.
|
|
10
|
+
import { readdir, readFile, stat } from "node:fs/promises";
|
|
11
|
+
import { join } from "node:path";
|
|
12
|
+
const DOMAINS_DIR_REL = join("docs", "domains");
|
|
13
|
+
export async function buildDomains(inputs) {
|
|
14
|
+
const domainsDir = join(inputs.sddPath, DOMAINS_DIR_REL);
|
|
15
|
+
let entries;
|
|
16
|
+
try {
|
|
17
|
+
entries = (await readdir(domainsDir, { withFileTypes: true }))
|
|
18
|
+
.filter((e) => e.isDirectory())
|
|
19
|
+
.map((e) => ({ name: e.name }));
|
|
20
|
+
}
|
|
21
|
+
catch (err) {
|
|
22
|
+
const code = err.code;
|
|
23
|
+
if (code === "ENOENT") {
|
|
24
|
+
inputs.findings.add("coverage", `${DOMAINS_DIR_REL}/ not found - emitting empty domains.csv`);
|
|
25
|
+
return [];
|
|
26
|
+
}
|
|
27
|
+
throw err;
|
|
28
|
+
}
|
|
29
|
+
const rows = [];
|
|
30
|
+
for (const entry of entries.sort((a, b) => a.name.localeCompare(b.name))) {
|
|
31
|
+
const slug = entry.name;
|
|
32
|
+
const description = await readDomainDescription(join(domainsDir, slug), inputs.findings, slug);
|
|
33
|
+
rows.push({
|
|
34
|
+
id: slug,
|
|
35
|
+
name: titleCase(slug),
|
|
36
|
+
description,
|
|
37
|
+
method_profile: inputs.manifest.profile,
|
|
38
|
+
reference_architecture_equivalent: "",
|
|
39
|
+
status: "active",
|
|
40
|
+
repo_count: 0, // populated by orchestrator after repositories build
|
|
41
|
+
source_sdd_id: "",
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
return rows;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Look for a one-line description in a domain README. Falls back to
|
|
48
|
+
* empty when no README or no usable first paragraph is present.
|
|
49
|
+
*/
|
|
50
|
+
async function readDomainDescription(domainDir, findings, slug) {
|
|
51
|
+
const candidates = ["README.md", "README.markdown"];
|
|
52
|
+
for (const name of candidates) {
|
|
53
|
+
const path = join(domainDir, name);
|
|
54
|
+
try {
|
|
55
|
+
const s = await stat(path);
|
|
56
|
+
if (!s.isFile())
|
|
57
|
+
continue;
|
|
58
|
+
const text = await readFile(path, "utf-8");
|
|
59
|
+
const firstPara = extractFirstParagraph(text);
|
|
60
|
+
if (firstPara)
|
|
61
|
+
return firstPara.slice(0, 500);
|
|
62
|
+
}
|
|
63
|
+
catch (err) {
|
|
64
|
+
const code = err.code;
|
|
65
|
+
if (code !== "ENOENT")
|
|
66
|
+
throw err;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
findings.add("coverage", `domain ${slug} has no README.md — description left empty`);
|
|
70
|
+
return "";
|
|
71
|
+
}
|
|
72
|
+
function extractFirstParagraph(markdown) {
|
|
73
|
+
// Strip an optional H1, then return the first non-empty paragraph
|
|
74
|
+
// (text up to the first blank line).
|
|
75
|
+
const lines = markdown.split(/\r?\n/);
|
|
76
|
+
let i = 0;
|
|
77
|
+
while (i < lines.length && (lines[i] === undefined || lines[i].trim() === "" || lines[i].startsWith("#"))) {
|
|
78
|
+
i++;
|
|
79
|
+
}
|
|
80
|
+
const para = [];
|
|
81
|
+
while (i < lines.length && lines[i].trim() !== "") {
|
|
82
|
+
para.push(lines[i].trim());
|
|
83
|
+
i++;
|
|
84
|
+
}
|
|
85
|
+
return para.join(" ").trim();
|
|
86
|
+
}
|
|
87
|
+
function titleCase(slug) {
|
|
88
|
+
return slug
|
|
89
|
+
.split("-")
|
|
90
|
+
.map((p) => (p.length === 0 ? p : p[0].toUpperCase() + p.slice(1)))
|
|
91
|
+
.join(" ");
|
|
92
|
+
}
|
|
93
|
+
//# sourceMappingURL=domains.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"domains.js","sourceRoot":"","sources":["../../../../src/lib/catalogue/builders/domains.ts"],"names":[],"mappings":"AAAA,4EAA4E;AAC5E,EAAE;AACF,uDAAuD;AACvD,wEAAwE;AACxE,wCAAwC;AACxC,uEAAuE;AACvE,kCAAkC;AAClC,0EAA0E;AAC1E,qDAAqD;AAErD,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAC3D,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAWjC,MAAM,eAAe,GAAG,IAAI,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;AAEhD,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,MAA0B;IAE1B,MAAM,UAAU,GAAG,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,eAAe,CAAC,CAAC;IACzD,IAAI,OAAgC,CAAC;IACrC,IAAI,CAAC;QACH,OAAO,GAAG,CAAC,MAAM,OAAO,CAAC,UAAU,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;aAC3D,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC;aAC9B,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;IACpC,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,IAAI,GAAI,GAA6B,CAAC,IAAI,CAAC;QACjD,IAAI,IAAI,KAAK,QAAQ,EAAE,CAAC;YACtB,MAAM,CAAC,QAAQ,CAAC,GAAG,CACjB,UAAU,EACV,GAAG,eAAe,0CAA0C,CAC7D,CAAC;YACF,OAAO,EAAE,CAAC;QACZ,CAAC;QACD,MAAM,GAAG,CAAC;IACZ,CAAC;IAED,MAAM,IAAI,GAAmB,EAAE,CAAC;IAChC,KAAK,MAAM,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC;QACzE,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC;QACxB,MAAM,WAAW,GAAG,MAAM,qBAAqB,CAC7C,IAAI,CAAC,UAAU,EAAE,IAAI,CAAC,EACtB,MAAM,CAAC,QAAQ,EACf,IAAI,CACL,CAAC;QACF,IAAI,CAAC,IAAI,CAAC;YACR,EAAE,EAAE,IAAI;YACR,IAAI,EAAE,SAAS,CAAC,IAAI,CAAC;YACrB,WAAW;YACX,cAAc,EAAE,MAAM,CAAC,QAAQ,CAAC,OAAO;YACvC,iCAAiC,EAAE,EAAE;YACrC,MAAM,EAAE,QAAQ;YAChB,UAAU,EAAE,CAAC,EAAE,qDAAqD;YACpE,aAAa,EAAE,EAAE;SAClB,CAAC,CAAC;IACL,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;GAGG;AACH,KAAK,UAAU,qBAAqB,CAClC,SAAiB,EACjB,QAAqB,EACrB,IAAY;IAEZ,MAAM,UAAU,GAAG,CAAC,WAAW,EAAE,iBAAiB,CAAC,CAAC;IACpD,KAAK,MAAM,IAAI,IAAI,UAAU,EAAE,CAAC;QAC9B,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;QACnC,IAAI,CAAC;YACH,MAAM,CAAC,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,CAAC;YAC3B,IAAI,CAAC,CAAC,CAAC,MAAM,EAAE;gBAAE,SAAS;YAC1B,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;YAC3C,MAAM,SAAS,GAAG,qBAAqB,CAAC,IAAI,CAAC,CAAC;YAC9C,IAAI,SAAS;gBAAE,OAAO,SAAS,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;QAChD,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,IAAI,GAAI,GAA6B,CAAC,IAAI,CAAC;YACjD,IAAI,IAAI,KAAK,QAAQ;gBAAE,MAAM,GAAG,CAAC;QACnC,CAAC;IACH,CAAC;IACD,QAAQ,CAAC,GAAG,CACV,UAAU,EACV,UAAU,IAAI,4CAA4C,CAC3D,CAAC;IACF,OAAO,EAAE,CAAC;AACZ,CAAC;AAED,SAAS,qBAAqB,CAAC,QAAgB;IAC7C,kEAAkE;IAClE,qCAAqC;IACrC,MAAM,KAAK,GAAG,QAAQ,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IACtC,IAAI,CAAC,GAAG,CAAC,CAAC;IACV,OAAO,CAAC,GAAG,KAAK,CAAC,MAAM,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,SAAS,IAAI,KAAK,CAAC,CAAC,CAAE,CAAC,IAAI,EAAE,KAAK,EAAE,IAAI,KAAK,CAAC,CAAC,CAAE,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC;QAC5G,CAAC,EAAE,CAAC;IACN,CAAC;IACD,MAAM,IAAI,GAAa,EAAE,CAAC;IAC1B,OAAO,CAAC,GAAG,KAAK,CAAC,MAAM,IAAI,KAAK,CAAC,CAAC,CAAE,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC;QACnD,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAE,CAAC,IAAI,EAAE,CAAC,CAAC;QAC5B,CAAC,EAAE,CAAC;IACN,CAAC;IACD,OAAO,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;AAC/B,CAAC;AAED,SAAS,SAAS,CAAC,IAAY;IAC7B,OAAO,IAAI;SACR,KAAK,CAAC,GAAG,CAAC;SACV,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAE,CAAC,WAAW,EAAE,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;SACnE,IAAI,CAAC,GAAG,CAAC,CAAC;AACf,CAAC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { CatalogueRow } from "../csv-writer.js";
|
|
2
|
+
import type { FindingsLog } from "../findings.js";
|
|
3
|
+
import type { ParsedRepoConfig } from "./repositories.js";
|
|
4
|
+
import type { TraceabilityManifest } from "../traceability-loader.js";
|
|
5
|
+
export interface ServiceEventInputs {
|
|
6
|
+
readonly findings: FindingsLog;
|
|
7
|
+
readonly configs: readonly ParsedRepoConfig[];
|
|
8
|
+
readonly contractIdByPath: ReadonlyMap<string, string>;
|
|
9
|
+
readonly knownServiceIds: ReadonlySet<string>;
|
|
10
|
+
readonly knownEventIds: ReadonlySet<string>;
|
|
11
|
+
}
|
|
12
|
+
export interface CapabilityEventInputs {
|
|
13
|
+
readonly findings: FindingsLog;
|
|
14
|
+
readonly manifests: readonly TraceabilityManifest[];
|
|
15
|
+
readonly knownCapabilityIds: ReadonlySet<string>;
|
|
16
|
+
readonly knownEventIds: ReadonlySet<string>;
|
|
17
|
+
}
|
|
18
|
+
export declare function buildServiceEvent(inputs: ServiceEventInputs): CatalogueRow[];
|
|
19
|
+
export declare function buildCapabilityEvent(inputs: CapabilityEventInputs): CatalogueRow[];
|
|
20
|
+
//# sourceMappingURL=event-edges.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"event-edges.d.ts","sourceRoot":"","sources":["../../../../src/lib/catalogue/builders/event-edges.ts"],"names":[],"mappings":"AAiBA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAClD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAC1D,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AAEtE,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,QAAQ,EAAE,WAAW,CAAC;IAC/B,QAAQ,CAAC,OAAO,EAAE,SAAS,gBAAgB,EAAE,CAAC;IAC9C,QAAQ,CAAC,gBAAgB,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACvD,QAAQ,CAAC,eAAe,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IAC9C,QAAQ,CAAC,aAAa,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;CAC7C;AAED,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,QAAQ,EAAE,WAAW,CAAC;IAC/B,QAAQ,CAAC,SAAS,EAAE,SAAS,oBAAoB,EAAE,CAAC;IACpD,QAAQ,CAAC,kBAAkB,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IACjD,QAAQ,CAAC,aAAa,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;CAC7C;AAED,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,kBAAkB,GAAG,YAAY,EAAE,CAiC5E;AAED,wBAAgB,oBAAoB,CAClC,MAAM,EAAE,qBAAqB,GAC5B,YAAY,EAAE,CAuChB"}
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
// service_event + capability_event edge builders.
|
|
2
|
+
//
|
|
3
|
+
// service_event:
|
|
4
|
+
// - From repo-config `events.produces[].schema` (role=publishes)
|
|
5
|
+
// and `events.consumes[].schema` (role=consumes). Each schema is
|
|
6
|
+
// resolved against the contracts.avro index → event id.
|
|
7
|
+
// - `contracts.avro` is NOT a fallback for publishes — it's a
|
|
8
|
+
// build-time list (for code-gen / validation) that consumers
|
|
9
|
+
// commonly declare too. Only the events block is authoritative.
|
|
10
|
+
//
|
|
11
|
+
// capability_event:
|
|
12
|
+
// - From traceability `traceability.events[]` when present (forward
|
|
13
|
+
// method extension; not yet adopted in contextua-platform per the
|
|
14
|
+
// metamodel's "populated where specs adopt `## Related Events`" note).
|
|
15
|
+
// - Empty until adopters declare events under their traceability.
|
|
16
|
+
import { sep } from "node:path";
|
|
17
|
+
export function buildServiceEvent(inputs) {
|
|
18
|
+
const rows = [];
|
|
19
|
+
const seen = new Set();
|
|
20
|
+
const emit = (serviceId, eventId, role) => {
|
|
21
|
+
if (!inputs.knownServiceIds.has(serviceId))
|
|
22
|
+
return;
|
|
23
|
+
if (!inputs.knownEventIds.has(eventId))
|
|
24
|
+
return;
|
|
25
|
+
const id = `${serviceId}__${eventId}__${role}`;
|
|
26
|
+
if (seen.has(id))
|
|
27
|
+
return;
|
|
28
|
+
seen.add(id);
|
|
29
|
+
rows.push({ id, service_id: serviceId, event_id: eventId, role });
|
|
30
|
+
};
|
|
31
|
+
for (const cfg of inputs.configs) {
|
|
32
|
+
const events = cfg.data.events;
|
|
33
|
+
if (!events)
|
|
34
|
+
continue;
|
|
35
|
+
for (const entry of events.produces ?? []) {
|
|
36
|
+
if (!entry.schema)
|
|
37
|
+
continue;
|
|
38
|
+
const eid = resolveAvroPath(entry.schema, inputs.contractIdByPath);
|
|
39
|
+
if (eid !== undefined)
|
|
40
|
+
emit(cfg.repoId, eid, "publishes");
|
|
41
|
+
}
|
|
42
|
+
for (const entry of events.consumes ?? []) {
|
|
43
|
+
if (!entry.schema)
|
|
44
|
+
continue;
|
|
45
|
+
const eid = resolveAvroPath(entry.schema, inputs.contractIdByPath);
|
|
46
|
+
if (eid !== undefined)
|
|
47
|
+
emit(cfg.repoId, eid, "consumes");
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
return rows;
|
|
51
|
+
}
|
|
52
|
+
export function buildCapabilityEvent(inputs) {
|
|
53
|
+
const rows = [];
|
|
54
|
+
const seen = new Set();
|
|
55
|
+
for (const m of inputs.manifests) {
|
|
56
|
+
const capId = m.capability.id;
|
|
57
|
+
if (!inputs.knownCapabilityIds.has(capId))
|
|
58
|
+
continue;
|
|
59
|
+
// The traceability.events block is an aspirational forward extension;
|
|
60
|
+
// not all manifests declare it. When absent, this manifest contributes
|
|
61
|
+
// nothing to the edge.
|
|
62
|
+
const events = m.data
|
|
63
|
+
?.traceability?.events;
|
|
64
|
+
if (!Array.isArray(events))
|
|
65
|
+
continue;
|
|
66
|
+
for (const entry of events) {
|
|
67
|
+
if (!entry || typeof entry !== "object")
|
|
68
|
+
continue;
|
|
69
|
+
const o = entry;
|
|
70
|
+
const eid = String(o["id"] ?? "").trim();
|
|
71
|
+
const role = String(o["role"] ?? "").trim();
|
|
72
|
+
if (eid === "" || (role !== "publishes" && role !== "consumes"))
|
|
73
|
+
continue;
|
|
74
|
+
if (!inputs.knownEventIds.has(eid)) {
|
|
75
|
+
inputs.findings.add("orphan", `${m.relPath}: capability_event references "${eid}" but no such event exists`);
|
|
76
|
+
continue;
|
|
77
|
+
}
|
|
78
|
+
const edgeId = `${capId}__${eid}__${role}`;
|
|
79
|
+
if (seen.has(edgeId))
|
|
80
|
+
continue;
|
|
81
|
+
seen.add(edgeId);
|
|
82
|
+
rows.push({
|
|
83
|
+
id: edgeId,
|
|
84
|
+
capability_id: capId,
|
|
85
|
+
event_id: eid,
|
|
86
|
+
role,
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
return rows;
|
|
91
|
+
}
|
|
92
|
+
function resolveAvroPath(schema, index) {
|
|
93
|
+
const cleaned = schema.replace(/^\/+/, "");
|
|
94
|
+
const full = `contracts/avro/${cleaned}`;
|
|
95
|
+
if (index.has(full))
|
|
96
|
+
return index.get(full);
|
|
97
|
+
if (index.has(cleaned))
|
|
98
|
+
return index.get(cleaned);
|
|
99
|
+
for (const [path, id] of index) {
|
|
100
|
+
const parts = path.split(sep);
|
|
101
|
+
if (parts.length >= 2 && parts.slice(-2).join("/") === cleaned)
|
|
102
|
+
return id;
|
|
103
|
+
}
|
|
104
|
+
const base = cleaned.split("/").slice(-1)[0] ?? cleaned;
|
|
105
|
+
for (const [path, id] of index) {
|
|
106
|
+
const parts = path.split(sep);
|
|
107
|
+
if ((parts[parts.length - 1] ?? "") === base)
|
|
108
|
+
return id;
|
|
109
|
+
}
|
|
110
|
+
return undefined;
|
|
111
|
+
}
|
|
112
|
+
//# sourceMappingURL=event-edges.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"event-edges.js","sourceRoot":"","sources":["../../../../src/lib/catalogue/builders/event-edges.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { CatalogueRow } from "../csv-writer.js";
|
|
2
|
+
import type { FindingsLog } from "../findings.js";
|
|
3
|
+
import type { ParsedRepoConfig } from "./repositories.js";
|
|
4
|
+
export interface EventsBuildInputs {
|
|
5
|
+
readonly findings: FindingsLog;
|
|
6
|
+
/** Contract rows where kind=event (avro). */
|
|
7
|
+
readonly avroContracts: readonly CatalogueRow[];
|
|
8
|
+
/** Map of contract spec_path → contract id, for repo-config schema-path resolution. */
|
|
9
|
+
readonly contractIdByPath: ReadonlyMap<string, string>;
|
|
10
|
+
/** Repo-config configs from the repositories builder. */
|
|
11
|
+
readonly configs: readonly ParsedRepoConfig[];
|
|
12
|
+
/** Service ids known to this build (so publisher_service_id only resolves to runtime services). */
|
|
13
|
+
readonly knownServiceIds: ReadonlySet<string>;
|
|
14
|
+
/** Domain ids known to this build (for domain_id fallback). */
|
|
15
|
+
readonly knownDomainIds: ReadonlySet<string>;
|
|
16
|
+
}
|
|
17
|
+
export interface PublisherIndex {
|
|
18
|
+
/** Map of contract id → repo (== service) id that publishes it, when one is declared. */
|
|
19
|
+
readonly publisherByContractId: ReadonlyMap<string, string>;
|
|
20
|
+
}
|
|
21
|
+
export interface EventsBuildResult {
|
|
22
|
+
readonly rows: CatalogueRow[];
|
|
23
|
+
readonly publisherIndex: PublisherIndex;
|
|
24
|
+
}
|
|
25
|
+
export declare function buildEvents(inputs: EventsBuildInputs): EventsBuildResult;
|
|
26
|
+
//# sourceMappingURL=events.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"events.d.ts","sourceRoot":"","sources":["../../../../src/lib/catalogue/builders/events.ts"],"names":[],"mappings":"AAkBA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAClD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAE1D,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,QAAQ,EAAE,WAAW,CAAC;IAC/B,6CAA6C;IAC7C,QAAQ,CAAC,aAAa,EAAE,SAAS,YAAY,EAAE,CAAC;IAChD,uFAAuF;IACvF,QAAQ,CAAC,gBAAgB,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACvD,yDAAyD;IACzD,QAAQ,CAAC,OAAO,EAAE,SAAS,gBAAgB,EAAE,CAAC;IAC9C,mGAAmG;IACnG,QAAQ,CAAC,eAAe,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IAC9C,+DAA+D;IAC/D,QAAQ,CAAC,cAAc,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;CAC9C;AAED,MAAM,WAAW,cAAc;IAC7B,yFAAyF;IACzF,QAAQ,CAAC,qBAAqB,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC7D;AAED,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,IAAI,EAAE,YAAY,EAAE,CAAC;IAC9B,QAAQ,CAAC,cAAc,EAAE,cAAc,CAAC;CACzC;AAED,wBAAgB,WAAW,CAAC,MAAM,EAAE,iBAAiB,GAAG,iBAAiB,CAkDxE"}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
// Events discoverer — emits `events.csv` from avro contracts (kind=event).
|
|
2
|
+
//
|
|
3
|
+
// In the forward method, every avro `*.avsc` schema declares one event;
|
|
4
|
+
// the canonical builder treats events as 1:1 with avro contracts and
|
|
5
|
+
// reuses the contract's id as the event id.
|
|
6
|
+
//
|
|
7
|
+
// publisher_service_id derivation: ONLY events.produces is authoritative.
|
|
8
|
+
// `contracts.avro` is a build-time list (for code-gen / validation) and
|
|
9
|
+
// MUST NOT be inferred as a publish declaration — services that consume
|
|
10
|
+
// avro schemas commonly list them under contracts.avro too. If no
|
|
11
|
+
// service declares events.produces for a given schema, the event row
|
|
12
|
+
// emits with empty publisher_service_id.
|
|
13
|
+
//
|
|
14
|
+
// transport defaults to `nats` per ADR 0068 (Scaleway MnQ NATS for
|
|
15
|
+
// platform messaging). The schema's enum doesn't include "nats" today;
|
|
16
|
+
// the column is nullable string so any value is accepted.
|
|
17
|
+
import { sep } from "node:path";
|
|
18
|
+
export function buildEvents(inputs) {
|
|
19
|
+
// Build the publisher index from repo-config events.produces only.
|
|
20
|
+
// Earlier-encountered service wins on ties (deterministic per sorted
|
|
21
|
+
// config order from the repositories builder).
|
|
22
|
+
const publisherByContractId = new Map();
|
|
23
|
+
for (const cfg of inputs.configs) {
|
|
24
|
+
if (!inputs.knownServiceIds.has(cfg.repoId))
|
|
25
|
+
continue;
|
|
26
|
+
const events = cfg.data.events;
|
|
27
|
+
const produces = events?.produces ?? [];
|
|
28
|
+
for (const entry of produces) {
|
|
29
|
+
const schema = entry.schema;
|
|
30
|
+
if (!schema)
|
|
31
|
+
continue;
|
|
32
|
+
const id = resolveContractByPath(schema, "avro", inputs.contractIdByPath);
|
|
33
|
+
if (id === undefined)
|
|
34
|
+
continue;
|
|
35
|
+
if (!publisherByContractId.has(id)) {
|
|
36
|
+
publisherByContractId.set(id, cfg.repoId);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
const rows = [];
|
|
41
|
+
for (const c of inputs.avroContracts) {
|
|
42
|
+
const id = String(c["id"]);
|
|
43
|
+
const specPath = String(c["spec_path"] ?? "");
|
|
44
|
+
const rawDomain = inferDomainFromAvroPath(specPath);
|
|
45
|
+
let domain = rawDomain;
|
|
46
|
+
if (rawDomain.startsWith("_")) {
|
|
47
|
+
// `_common`, `_shared`, etc. — cross-domain envelope schemas.
|
|
48
|
+
// Emit empty domain_id (events.domain_id is nullable per schema 1.4.0).
|
|
49
|
+
domain = "";
|
|
50
|
+
}
|
|
51
|
+
else if (rawDomain !== "" && !inputs.knownDomainIds.has(rawDomain)) {
|
|
52
|
+
inputs.findings.add("orphan", `event ${id}: schema is at ${specPath} but no docs/domains/${rawDomain}/ exists — emitting with empty domain_id`);
|
|
53
|
+
domain = "";
|
|
54
|
+
}
|
|
55
|
+
rows.push({
|
|
56
|
+
id,
|
|
57
|
+
name: String(c["name"] ?? id),
|
|
58
|
+
publisher_service_id: publisherByContractId.get(id) ?? "",
|
|
59
|
+
domain_id: domain,
|
|
60
|
+
transport: "nats",
|
|
61
|
+
schema_path: specPath,
|
|
62
|
+
version: String(c["version"] ?? ""),
|
|
63
|
+
source_sdd_id: "",
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
return { rows, publisherIndex: { publisherByContractId } };
|
|
67
|
+
}
|
|
68
|
+
function inferDomainFromAvroPath(relPath) {
|
|
69
|
+
// Layout: contracts/avro/<domain>/<file>.avsc
|
|
70
|
+
const parts = relPath.split(sep);
|
|
71
|
+
if (parts.length < 4)
|
|
72
|
+
return "";
|
|
73
|
+
return parts[2] ?? "";
|
|
74
|
+
}
|
|
75
|
+
function resolveContractByPath(schema, kind, index) {
|
|
76
|
+
const cleaned = schema.replace(/^\/+/, "");
|
|
77
|
+
// Repo-config event paths are relative to contracts/<kind>/.
|
|
78
|
+
const fullCandidate = `contracts/${kind}/${cleaned}`;
|
|
79
|
+
if (index.has(fullCandidate))
|
|
80
|
+
return index.get(fullCandidate);
|
|
81
|
+
if (index.has(cleaned))
|
|
82
|
+
return index.get(cleaned);
|
|
83
|
+
// Suffix fallback (last two segments).
|
|
84
|
+
for (const [path, id] of index) {
|
|
85
|
+
const parts = path.split(sep);
|
|
86
|
+
const last2 = parts.length >= 2 ? parts.slice(-2).join("/") : "";
|
|
87
|
+
if (last2 === cleaned)
|
|
88
|
+
return id;
|
|
89
|
+
}
|
|
90
|
+
// Basename fallback.
|
|
91
|
+
const base = cleaned.split("/").slice(-1)[0] ?? cleaned;
|
|
92
|
+
for (const [path, id] of index) {
|
|
93
|
+
const parts = path.split(sep);
|
|
94
|
+
if ((parts[parts.length - 1] ?? "") === base)
|
|
95
|
+
return id;
|
|
96
|
+
}
|
|
97
|
+
return undefined;
|
|
98
|
+
}
|
|
99
|
+
//# sourceMappingURL=events.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"events.js","sourceRoot":"","sources":["../../../../src/lib/catalogue/builders/events.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { CatalogueRow } from "../csv-writer.js";
|
|
2
|
+
import type { FindingsLog } from "../findings.js";
|
|
3
|
+
export interface FeatureGroupsBuildInputs {
|
|
4
|
+
readonly sddPath: string;
|
|
5
|
+
readonly findings: FindingsLog;
|
|
6
|
+
/** Used to scope group ids when product-bound (typically the SDD's own product id). */
|
|
7
|
+
readonly productId: string;
|
|
8
|
+
}
|
|
9
|
+
export declare function buildFeatureGroups(inputs: FeatureGroupsBuildInputs): Promise<CatalogueRow[]>;
|
|
10
|
+
//# sourceMappingURL=feature-groups.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"feature-groups.d.ts","sourceRoot":"","sources":["../../../../src/lib/catalogue/builders/feature-groups.ts"],"names":[],"mappings":"AAoBA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAElD,MAAM,WAAW,wBAAwB;IACvC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,QAAQ,EAAE,WAAW,CAAC;IAC/B,uFAAuF;IACvF,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;CAC5B;AAOD,wBAAsB,kBAAkB,CACtC,MAAM,EAAE,wBAAwB,GAC/B,OAAO,CAAC,YAAY,EAAE,CAAC,CAkDzB"}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
// FeatureGroups discoverer — emits `feature_groups.csv` rows from
|
|
2
|
+
// hierarchical `feature-tree.md` files.
|
|
3
|
+
//
|
|
4
|
+
// Per Q7.2 resolution (adopt-canonical-catalogue-builder.md §7.2),
|
|
5
|
+
// FeatureGroups are first-class entities. This builder parses pure
|
|
6
|
+
// markdown H2/H3 headings as the hierarchical structure:
|
|
7
|
+
// - H2 heading → top-level FeatureGroup (parent_group_id = "")
|
|
8
|
+
// - H3 heading → child FeatureGroup (parent_group_id = enclosing H2's id)
|
|
9
|
+
//
|
|
10
|
+
// ASCII-tree representations inside fenced code blocks are NOT parsed
|
|
11
|
+
// — those are an adopter authoring style that doesn't map cleanly to
|
|
12
|
+
// catalogue entities. Adopters wanting first-class groups format their
|
|
13
|
+
// feature trees with proper H2/H3 headings.
|
|
14
|
+
//
|
|
15
|
+
// Source paths checked (in order, first match wins):
|
|
16
|
+
// - <sddRoot>/feature-tree.md (typical for app-product SDDs)
|
|
17
|
+
// - <sddRoot>/docs/platform/feature-tree.md (typical for platform SDDs)
|
|
18
|
+
import { readFile } from "node:fs/promises";
|
|
19
|
+
import { join, relative } from "node:path";
|
|
20
|
+
const CANDIDATE_PATHS_REL = [
|
|
21
|
+
"feature-tree.md",
|
|
22
|
+
join("docs", "platform", "feature-tree.md"),
|
|
23
|
+
];
|
|
24
|
+
export async function buildFeatureGroups(inputs) {
|
|
25
|
+
const featureTreePath = await firstExisting(inputs.sddPath, CANDIDATE_PATHS_REL);
|
|
26
|
+
if (!featureTreePath) {
|
|
27
|
+
return [];
|
|
28
|
+
}
|
|
29
|
+
const text = await readFile(featureTreePath, "utf-8");
|
|
30
|
+
const headings = extractHeadingsOutsideCodeFences(text);
|
|
31
|
+
const rows = [];
|
|
32
|
+
let currentH2Id = "";
|
|
33
|
+
for (const h of headings) {
|
|
34
|
+
if (h.level === 2) {
|
|
35
|
+
const id = `${inputs.productId}-group-${slugify(h.text)}`;
|
|
36
|
+
currentH2Id = id;
|
|
37
|
+
rows.push({
|
|
38
|
+
id,
|
|
39
|
+
name: h.text,
|
|
40
|
+
product_id: inputs.productId,
|
|
41
|
+
capability_id: "",
|
|
42
|
+
parent_group_id: "",
|
|
43
|
+
description: "",
|
|
44
|
+
source: "feature-tree-h2",
|
|
45
|
+
source_sdd_id: "",
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
else if (h.level === 3) {
|
|
49
|
+
if (currentH2Id === "") {
|
|
50
|
+
// H3 with no enclosing H2 — orphan; surface as finding but emit anyway.
|
|
51
|
+
inputs.findings.add("convention", `${relative(inputs.sddPath, featureTreePath)}: H3 "${h.text}" has no enclosing H2`);
|
|
52
|
+
}
|
|
53
|
+
const id = currentH2Id !== ""
|
|
54
|
+
? `${currentH2Id}-${slugify(h.text)}`
|
|
55
|
+
: `${inputs.productId}-group-${slugify(h.text)}`;
|
|
56
|
+
rows.push({
|
|
57
|
+
id,
|
|
58
|
+
name: h.text,
|
|
59
|
+
product_id: inputs.productId,
|
|
60
|
+
capability_id: "",
|
|
61
|
+
parent_group_id: currentH2Id,
|
|
62
|
+
description: "",
|
|
63
|
+
source: "feature-tree-h3",
|
|
64
|
+
source_sdd_id: "",
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
return rows;
|
|
69
|
+
}
|
|
70
|
+
function extractHeadingsOutsideCodeFences(text) {
|
|
71
|
+
const out = [];
|
|
72
|
+
let inFence = false;
|
|
73
|
+
for (const rawLine of text.split(/\r?\n/)) {
|
|
74
|
+
const line = rawLine.trimEnd();
|
|
75
|
+
if (line.startsWith("```")) {
|
|
76
|
+
inFence = !inFence;
|
|
77
|
+
continue;
|
|
78
|
+
}
|
|
79
|
+
if (inFence)
|
|
80
|
+
continue;
|
|
81
|
+
const m = /^(#{2,3})\s+(.+?)\s*$/.exec(line);
|
|
82
|
+
if (!m || m[1] === undefined || m[2] === undefined)
|
|
83
|
+
continue;
|
|
84
|
+
const level = m[1].length === 2 ? 2 : 3;
|
|
85
|
+
const headingText = m[2]
|
|
86
|
+
.replace(/^[\d.]+\s*/, "") // strip leading "1.", "1.1", etc.
|
|
87
|
+
.replace(/\s*\[.+?\]\s*$/, "") // strip trailing "[Business]" / "[Enabler-Runway]" tags
|
|
88
|
+
.trim();
|
|
89
|
+
if (headingText === "")
|
|
90
|
+
continue;
|
|
91
|
+
out.push({ level, text: headingText });
|
|
92
|
+
}
|
|
93
|
+
return out;
|
|
94
|
+
}
|
|
95
|
+
function slugify(text) {
|
|
96
|
+
return text
|
|
97
|
+
.toLowerCase()
|
|
98
|
+
.replace(/&/g, " and ")
|
|
99
|
+
.replace(/[^a-z0-9]+/g, "-")
|
|
100
|
+
.replace(/^-+|-+$/g, "");
|
|
101
|
+
}
|
|
102
|
+
async function firstExisting(sddPath, candidates) {
|
|
103
|
+
for (const rel of candidates) {
|
|
104
|
+
const full = join(sddPath, rel);
|
|
105
|
+
try {
|
|
106
|
+
await readFile(full, "utf-8");
|
|
107
|
+
return full;
|
|
108
|
+
}
|
|
109
|
+
catch (err) {
|
|
110
|
+
const code = err.code;
|
|
111
|
+
if (code === "ENOENT")
|
|
112
|
+
continue;
|
|
113
|
+
throw err;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
return null;
|
|
117
|
+
}
|
|
118
|
+
//# sourceMappingURL=feature-groups.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"feature-groups.js","sourceRoot":"","sources":["../../../../src/lib/catalogue/builders/feature-groups.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import type { CatalogueRow } from "../csv-writer.js";
|
|
2
|
+
import type { FindingsLog } from "../findings.js";
|
|
3
|
+
import type { TraceabilityManifest } from "../traceability-loader.js";
|
|
4
|
+
export interface FeaturesBuildInputs {
|
|
5
|
+
readonly sddPath: string;
|
|
6
|
+
readonly findings: FindingsLog;
|
|
7
|
+
readonly manifests: readonly TraceabilityManifest[];
|
|
8
|
+
readonly knownCapabilityIds: ReadonlySet<string>;
|
|
9
|
+
/**
|
|
10
|
+
* SDD profile, used to opt in to app-product feature discovery at
|
|
11
|
+
* `features/<group>/<file>.md` (alongside the platform/domain
|
|
12
|
+
* convention). Per Step 4 of the canonical-builder Phase 2 plan.
|
|
13
|
+
*/
|
|
14
|
+
readonly profile: string;
|
|
15
|
+
/**
|
|
16
|
+
* Product id for the SDD itself — used as the feature id prefix and
|
|
17
|
+
* `product_id` value when reading app-product features. Ignored for
|
|
18
|
+
* platform-profile SDDs.
|
|
19
|
+
*/
|
|
20
|
+
readonly productId: string;
|
|
21
|
+
}
|
|
22
|
+
export interface FeaturesBuildResult {
|
|
23
|
+
readonly rows: CatalogueRow[];
|
|
24
|
+
/** Map of feature spec relative path → feature id (for capability_feature edge resolution). */
|
|
25
|
+
readonly idByPath: ReadonlyMap<string, string>;
|
|
26
|
+
/**
|
|
27
|
+
* Map of feature slug (filename stem) → feature id, for resolving
|
|
28
|
+
* bare-slug references in personas/journeys content. First-seen wins
|
|
29
|
+
* when the same slug appears under multiple capabilities; the orphan
|
|
30
|
+
* finding from the consumer side surfaces the (rare) collision.
|
|
31
|
+
*/
|
|
32
|
+
readonly idBySlug: ReadonlyMap<string, string>;
|
|
33
|
+
}
|
|
34
|
+
export declare function buildFeatures(inputs: FeaturesBuildInputs): Promise<FeaturesBuildResult>;
|
|
35
|
+
//# sourceMappingURL=features.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"features.d.ts","sourceRoot":"","sources":["../../../../src/lib/catalogue/builders/features.ts"],"names":[],"mappings":"AAkBA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAClD,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AAEtE,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,QAAQ,EAAE,WAAW,CAAC;IAC/B,QAAQ,CAAC,SAAS,EAAE,SAAS,oBAAoB,EAAE,CAAC;IACpD,QAAQ,CAAC,kBAAkB,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IACjD;;;;OAIG;IACH,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB;;;;OAIG;IACH,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;CAC5B;AAED,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,IAAI,EAAE,YAAY,EAAE,CAAC;IAC9B,+FAA+F;IAC/F,QAAQ,CAAC,QAAQ,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC/C;;;;;OAKG;IACH,QAAQ,CAAC,QAAQ,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAChD;AAID,wBAAsB,aAAa,CACjC,MAAM,EAAE,mBAAmB,GAC1B,OAAO,CAAC,mBAAmB,CAAC,CAkG9B"}
|