@sdd-method/sdd-cli 0.19.0 → 0.22.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 +30 -10
- package/dist/index.js +3 -3
- package/dist/index.js.map +1 -1
- package/dist/lib/agent-harness.d.ts +20 -0
- package/dist/lib/agent-harness.d.ts.map +1 -0
- package/dist/lib/agent-harness.js +28 -0
- package/dist/lib/agent-harness.js.map +1 -0
- package/dist/lib/briefing/index.d.ts +15 -0
- package/dist/lib/briefing/index.d.ts.map +1 -0
- package/dist/lib/briefing/index.js +13 -0
- package/dist/lib/briefing/index.js.map +1 -0
- package/dist/lib/briefing/render.d.ts +57 -0
- package/dist/lib/briefing/render.d.ts.map +1 -0
- package/dist/lib/briefing/render.js +112 -0
- package/dist/lib/briefing/render.js.map +1 -0
- package/dist/lib/briefing/variables.d.ts +49 -0
- package/dist/lib/briefing/variables.d.ts.map +1 -0
- package/dist/lib/briefing/variables.js +92 -0
- package/dist/lib/briefing/variables.js.map +1 -0
- package/dist/lib/catalogue/aggregate.d.ts +19 -0
- package/dist/lib/catalogue/aggregate.d.ts.map +1 -1
- package/dist/lib/catalogue/aggregate.js +88 -0
- package/dist/lib/catalogue/aggregate.js.map +1 -1
- package/dist/lib/catalogue/build.d.ts.map +1 -1
- package/dist/lib/catalogue/build.js +78 -4
- package/dist/lib/catalogue/build.js.map +1 -1
- package/dist/lib/catalogue/builders/c4-containers.d.ts.map +1 -1
- package/dist/lib/catalogue/builders/c4-containers.js +15 -0
- package/dist/lib/catalogue/builders/c4-containers.js.map +1 -1
- package/dist/lib/catalogue/builders/capabilities.d.ts.map +1 -1
- package/dist/lib/catalogue/builders/capabilities.js +18 -4
- package/dist/lib/catalogue/builders/capabilities.js.map +1 -1
- package/dist/lib/catalogue/builders/capability-spec-walker.d.ts +55 -0
- package/dist/lib/catalogue/builders/capability-spec-walker.d.ts.map +1 -0
- package/dist/lib/catalogue/builders/capability-spec-walker.js +99 -0
- package/dist/lib/catalogue/builders/capability-spec-walker.js.map +1 -0
- package/dist/lib/catalogue/builders/capability-spec.d.ts +51 -0
- package/dist/lib/catalogue/builders/capability-spec.d.ts.map +1 -0
- package/dist/lib/catalogue/builders/capability-spec.js +276 -0
- package/dist/lib/catalogue/builders/capability-spec.js.map +1 -0
- package/dist/lib/catalogue/builders/contracts.d.ts.map +1 -1
- package/dist/lib/catalogue/builders/contracts.js +88 -41
- package/dist/lib/catalogue/builders/contracts.js.map +1 -1
- package/dist/lib/catalogue/builders/feature-subscription-channels.d.ts +12 -0
- package/dist/lib/catalogue/builders/feature-subscription-channels.d.ts.map +1 -0
- package/dist/lib/catalogue/builders/feature-subscription-channels.js +197 -0
- package/dist/lib/catalogue/builders/feature-subscription-channels.js.map +1 -0
- package/dist/lib/catalogue/builders/index.d.ts +8 -0
- package/dist/lib/catalogue/builders/index.d.ts.map +1 -1
- package/dist/lib/catalogue/builders/index.js +4 -0
- package/dist/lib/catalogue/builders/index.js.map +1 -1
- package/dist/lib/catalogue/builders/product-platform-dependencies.d.ts +10 -0
- package/dist/lib/catalogue/builders/product-platform-dependencies.d.ts.map +1 -0
- package/dist/lib/catalogue/builders/product-platform-dependencies.js +155 -0
- package/dist/lib/catalogue/builders/product-platform-dependencies.js.map +1 -0
- package/dist/lib/catalogue/builders/service-contract-consumes.d.ts +24 -0
- package/dist/lib/catalogue/builders/service-contract-consumes.d.ts.map +1 -0
- package/dist/lib/catalogue/builders/service-contract-consumes.js +173 -0
- package/dist/lib/catalogue/builders/service-contract-consumes.js.map +1 -0
- package/dist/lib/catalogue/canonical-schema.yaml +100 -5
- package/dist/lib/catalogue/service-contract-aliases-loader.d.ts +60 -0
- package/dist/lib/catalogue/service-contract-aliases-loader.d.ts.map +1 -0
- package/dist/lib/catalogue/service-contract-aliases-loader.js +109 -0
- package/dist/lib/catalogue/service-contract-aliases-loader.js.map +1 -0
- package/dist/lib/catalogue/traceability-loader.d.ts +17 -0
- package/dist/lib/catalogue/traceability-loader.d.ts.map +1 -1
- package/dist/lib/catalogue/traceability-loader.js +6 -0
- package/dist/lib/catalogue/traceability-loader.js.map +1 -1
- package/dist/lib/generate-briefing/index.d.ts +22 -0
- package/dist/lib/generate-briefing/index.d.ts.map +1 -0
- package/dist/lib/generate-briefing/index.js +77 -0
- package/dist/lib/generate-briefing/index.js.map +1 -0
- package/dist/lib/hooks-seed/copilot.d.ts +93 -0
- package/dist/lib/hooks-seed/copilot.d.ts.map +1 -0
- package/dist/lib/hooks-seed/copilot.js +167 -0
- package/dist/lib/hooks-seed/copilot.js.map +1 -0
- package/dist/lib/hooks-seed/index.d.ts +4 -0
- package/dist/lib/hooks-seed/index.d.ts.map +1 -1
- package/dist/lib/hooks-seed/index.js +2 -0
- package/dist/lib/hooks-seed/index.js.map +1 -1
- package/dist/lib/hooks-seed/lifecycle-mapping.d.ts +12 -0
- package/dist/lib/hooks-seed/lifecycle-mapping.d.ts.map +1 -0
- package/dist/lib/hooks-seed/lifecycle-mapping.js +28 -0
- package/dist/lib/hooks-seed/lifecycle-mapping.js.map +1 -0
- package/dist/lib/init/index.d.ts +6 -4
- package/dist/lib/init/index.d.ts.map +1 -1
- package/dist/lib/init/index.js +5 -26
- package/dist/lib/init/index.js.map +1 -1
- package/dist/lib/init/platform.d.ts +9 -0
- package/dist/lib/init/platform.d.ts.map +1 -1
- package/dist/lib/init/platform.js +8 -2
- package/dist/lib/init/platform.js.map +1 -1
- package/dist/lib/sync/briefing-merge.d.ts +34 -0
- package/dist/lib/sync/briefing-merge.d.ts.map +1 -0
- package/dist/lib/sync/briefing-merge.js +82 -0
- package/dist/lib/sync/briefing-merge.js.map +1 -0
- package/dist/lib/sync/copilot-hooks-merge.d.ts +30 -0
- package/dist/lib/sync/copilot-hooks-merge.d.ts.map +1 -0
- package/dist/lib/sync/copilot-hooks-merge.js +96 -0
- package/dist/lib/sync/copilot-hooks-merge.js.map +1 -0
- package/dist/lib/sync/index.d.ts +8 -3
- package/dist/lib/sync/index.d.ts.map +1 -1
- package/dist/lib/sync/index.js +63 -23
- package/dist/lib/sync/index.js.map +1 -1
- package/dist/verbs/generate-briefing.d.ts +3 -0
- package/dist/verbs/generate-briefing.d.ts.map +1 -0
- package/dist/verbs/generate-briefing.js +28 -0
- package/dist/verbs/generate-briefing.js.map +1 -0
- package/dist/verbs/init.d.ts.map +1 -1
- package/dist/verbs/init.js +11 -8
- package/dist/verbs/init.js.map +1 -1
- package/dist/verbs/sync.d.ts.map +1 -1
- package/dist/verbs/sync.js +11 -4
- package/dist/verbs/sync.js.map +1 -1
- package/package.json +2 -2
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Walker for capability spec markdown files per ADR 0145 (schema 2.7.0).
|
|
3
|
+
*
|
|
4
|
+
* Reads `## Feature Grounding (code-path trace)` markdown tables of the
|
|
5
|
+
* canonical shape:
|
|
6
|
+
*
|
|
7
|
+
* | Feature | Implementation | Grounding Doc |
|
|
8
|
+
* |---|---|---|
|
|
9
|
+
* | `alerts-module` | `alerts` Vuex module + `src/components/alerts` | docs/.../feature-grounding.md |
|
|
10
|
+
*
|
|
11
|
+
* Path convention (per ADR 0145 §4.3):
|
|
12
|
+
* - platform-profile: `docs/domains/<dom>/product/<capability>.md`
|
|
13
|
+
*
|
|
14
|
+
* Capability id resolves from the filename stem. Tolerant of column
|
|
15
|
+
* re-ordering and missing optional columns. Reuses the table-parsing
|
|
16
|
+
* logic from `feature-grounding-walker.ts` (any markdown table whose
|
|
17
|
+
* first header normalises to `feature` is parsed).
|
|
18
|
+
*
|
|
19
|
+
* Recovery is row-local — a malformed row emits a finding and the
|
|
20
|
+
* walker continues with the next row.
|
|
21
|
+
*/
|
|
22
|
+
import { readdir } from "node:fs/promises";
|
|
23
|
+
import { basename, join, relative, sep } from "node:path";
|
|
24
|
+
import { parseGroundingTable, } from "./feature-grounding-walker.js";
|
|
25
|
+
const DOMAINS_DIR_REL = join("docs", "domains");
|
|
26
|
+
const PRODUCT_DIR_NAME = "product";
|
|
27
|
+
/**
|
|
28
|
+
* Find all `docs/domains/<dom>/product/<capability>.md` files under the
|
|
29
|
+
* SDD root. Excludes `.traceability.yaml` sidecars. Sorted for
|
|
30
|
+
* deterministic output.
|
|
31
|
+
*/
|
|
32
|
+
export async function findCapabilitySpecFiles(sddPath) {
|
|
33
|
+
const out = [];
|
|
34
|
+
const domainsDir = join(sddPath, DOMAINS_DIR_REL);
|
|
35
|
+
let domains;
|
|
36
|
+
try {
|
|
37
|
+
domains = await readdir(domainsDir, { withFileTypes: true });
|
|
38
|
+
}
|
|
39
|
+
catch {
|
|
40
|
+
return out;
|
|
41
|
+
}
|
|
42
|
+
for (const d of domains) {
|
|
43
|
+
if (!d.isDirectory())
|
|
44
|
+
continue;
|
|
45
|
+
const productDir = join(domainsDir, d.name, PRODUCT_DIR_NAME);
|
|
46
|
+
let files;
|
|
47
|
+
try {
|
|
48
|
+
files = await readdir(productDir, { withFileTypes: true });
|
|
49
|
+
}
|
|
50
|
+
catch {
|
|
51
|
+
continue;
|
|
52
|
+
}
|
|
53
|
+
for (const f of files) {
|
|
54
|
+
if (!f.isFile())
|
|
55
|
+
continue;
|
|
56
|
+
if (!f.name.endsWith(".md"))
|
|
57
|
+
continue;
|
|
58
|
+
// Skip the README that lives in some product/ dirs.
|
|
59
|
+
if (f.name === "README.md")
|
|
60
|
+
continue;
|
|
61
|
+
out.push(join(productDir, f.name));
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
return out.sort();
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Resolve the capability id from a capability spec file's absolute
|
|
68
|
+
* path. Returns the filename stem (`.md` stripped).
|
|
69
|
+
*
|
|
70
|
+
* docs/domains/applications/product/alerts-and-notifications.md
|
|
71
|
+
* → "alerts-and-notifications"
|
|
72
|
+
*/
|
|
73
|
+
export function capabilityIdFromSpecPath(absPath, sddPath) {
|
|
74
|
+
const rel = relative(sddPath, absPath);
|
|
75
|
+
const parts = rel.split(sep);
|
|
76
|
+
// Expected: ["docs", "domains", "<dom>", "product", "<file>.md"]
|
|
77
|
+
if (parts.length < 5)
|
|
78
|
+
return "";
|
|
79
|
+
const file = parts[parts.length - 1] ?? "";
|
|
80
|
+
if (!file.endsWith(".md"))
|
|
81
|
+
return "";
|
|
82
|
+
return file.slice(0, -3);
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Parse the markdown content of a capability spec file and return the
|
|
86
|
+
* rows from its `## Feature Grounding (code-path trace)` table.
|
|
87
|
+
*
|
|
88
|
+
* Implementation detail: we delegate to `parseGroundingTable`, which
|
|
89
|
+
* picks the first table whose first column normalises to `feature`.
|
|
90
|
+
* Capability specs typically have one such table under
|
|
91
|
+
* `## Feature Grounding (code-path trace)`; the parser tolerates
|
|
92
|
+
* variations in the heading text.
|
|
93
|
+
*/
|
|
94
|
+
export function parseCapabilitySpecTable(text) {
|
|
95
|
+
return parseGroundingTable(text);
|
|
96
|
+
}
|
|
97
|
+
/** Re-export basename for convenience in tests. */
|
|
98
|
+
export { basename };
|
|
99
|
+
//# sourceMappingURL=capability-spec-walker.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"capability-spec-walker.js","sourceRoot":"","sources":["../../../../src/lib/catalogue/builders/capability-spec-walker.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,EAAE,OAAO,EAAY,MAAM,kBAAkB,CAAC;AACrD,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,QAAQ,EAAE,GAAG,EAAE,MAAM,WAAW,CAAC;AAC1D,OAAO,EACL,mBAAmB,GAEpB,MAAM,+BAA+B,CAAC;AAEvC,MAAM,eAAe,GAAG,IAAI,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;AAChD,MAAM,gBAAgB,GAAG,SAAS,CAAC;AAEnC;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,uBAAuB,CAC3C,OAAe;IAEf,MAAM,GAAG,GAAa,EAAE,CAAC;IACzB,MAAM,UAAU,GAAG,IAAI,CAAC,OAAO,EAAE,eAAe,CAAC,CAAC;IAClD,IAAI,OAAO,CAAC;IACZ,IAAI,CAAC;QACH,OAAO,GAAG,MAAM,OAAO,CAAC,UAAU,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;IAC/D,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,GAAG,CAAC;IACb,CAAC;IACD,KAAK,MAAM,CAAC,IAAI,OAAO,EAAE,CAAC;QACxB,IAAI,CAAC,CAAC,CAAC,WAAW,EAAE;YAAE,SAAS;QAC/B,MAAM,UAAU,GAAG,IAAI,CAAC,UAAU,EAAE,CAAC,CAAC,IAAI,EAAE,gBAAgB,CAAC,CAAC;QAC9D,IAAI,KAAK,CAAC;QACV,IAAI,CAAC;YACH,KAAK,GAAG,MAAM,OAAO,CAAC,UAAU,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;QAC7D,CAAC;QAAC,MAAM,CAAC;YACP,SAAS;QACX,CAAC;QACD,KAAK,MAAM,CAAC,IAAI,KAAK,EAAE,CAAC;YACtB,IAAI,CAAC,CAAC,CAAC,MAAM,EAAE;gBAAE,SAAS;YAC1B,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC;gBAAE,SAAS;YACtC,oDAAoD;YACpD,IAAI,CAAC,CAAC,IAAI,KAAK,WAAW;gBAAE,SAAS;YACrC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;QACrC,CAAC;IACH,CAAC;IACD,OAAO,GAAG,CAAC,IAAI,EAAE,CAAC;AACpB,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,wBAAwB,CACtC,OAAe,EACf,OAAe;IAEf,MAAM,GAAG,GAAG,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IACvC,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC7B,iEAAiE;IACjE,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC;QAAE,OAAO,EAAE,CAAC;IAChC,MAAM,IAAI,GAAG,KAAK,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;IAC3C,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC;IACrC,OAAO,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;AAC3B,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,wBAAwB,CAAC,IAAY;IACnD,OAAO,mBAAmB,CAAC,IAAI,CAAC,CAAC;AACnC,CAAC;AAOD,mDAAmD;AACnD,OAAO,EAAE,QAAQ,EAAE,CAAC"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Capability-spec feature extractor per ADR 0145 (schema 2.7.0).
|
|
3
|
+
*
|
|
4
|
+
* Walks `docs/domains/<dom>/product/<capability>.md` (platform-profile),
|
|
5
|
+
* parses the `## Feature Grounding (code-path trace)` markdown table,
|
|
6
|
+
* and emits four catalogue contributions:
|
|
7
|
+
*
|
|
8
|
+
* - `features.csv` rows with `source: capability-spec`.
|
|
9
|
+
* - `capability_feature.csv` rows (1:1 with each feature row).
|
|
10
|
+
* - `feature_repo.csv` rows derived from file-path references in
|
|
11
|
+
* the Implementation column.
|
|
12
|
+
* - `feature_service.csv` rows derived from class names / file
|
|
13
|
+
* basenames / route fragments in the Implementation column,
|
|
14
|
+
* resolved via `services.csv` + the optional per-SDD alias map
|
|
15
|
+
* introduced by ADR 0143.
|
|
16
|
+
*
|
|
17
|
+
* Resolution failures (unresolved capability, service, repo) emit
|
|
18
|
+
* findings but never break FK validation — only confidently-resolved
|
|
19
|
+
* rows are emitted.
|
|
20
|
+
*
|
|
21
|
+
* Precedence per ADR 0145 §4.7: feature-tree, feature-spec, and
|
|
22
|
+
* feature-grounding rows win on id collision (they are more specific
|
|
23
|
+
* sources); capability-spec rows are skipped with a divergence finding
|
|
24
|
+
* when their id is already taken.
|
|
25
|
+
*/
|
|
26
|
+
import type { CatalogueRow } from "../csv-writer.js";
|
|
27
|
+
import type { FindingsLog } from "../findings.js";
|
|
28
|
+
import type { LoadedAliases } from "../feature-grounding-aliases-loader.js";
|
|
29
|
+
export interface CapabilitySpecInputs {
|
|
30
|
+
readonly sddPath: string;
|
|
31
|
+
readonly findings: FindingsLog;
|
|
32
|
+
readonly profile: string;
|
|
33
|
+
/** Set of capability ids known from capabilities.csv (for path resolution). */
|
|
34
|
+
readonly knownCapabilityIds: ReadonlySet<string>;
|
|
35
|
+
/** Set of service ids known from services.csv (for service-edge resolution). */
|
|
36
|
+
readonly knownServiceIds: ReadonlySet<string>;
|
|
37
|
+
/** Set of canonical_repo_keys known from repositories.csv. */
|
|
38
|
+
readonly knownRepoKeys: ReadonlySet<string>;
|
|
39
|
+
/** Already-emitted feature ids from earlier sources — capability-spec rows lose on collision. */
|
|
40
|
+
readonly existingFeatureIds: ReadonlySet<string>;
|
|
41
|
+
/** Optional alias map for display-name → canonical-id translation. */
|
|
42
|
+
readonly aliases: LoadedAliases | null;
|
|
43
|
+
}
|
|
44
|
+
export interface CapabilitySpecResult {
|
|
45
|
+
readonly featureRows: CatalogueRow[];
|
|
46
|
+
readonly capabilityFeatureRows: CatalogueRow[];
|
|
47
|
+
readonly featureRepoRows: CatalogueRow[];
|
|
48
|
+
readonly featureServiceRows: CatalogueRow[];
|
|
49
|
+
}
|
|
50
|
+
export declare function buildCapabilitySpec(inputs: CapabilitySpecInputs): Promise<CapabilitySpecResult>;
|
|
51
|
+
//# sourceMappingURL=capability-spec.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"capability-spec.d.ts","sourceRoot":"","sources":["../../../../src/lib/catalogue/builders/capability-spec.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAIH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAClD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,wCAAwC,CAAC;AAgB5E,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,QAAQ,EAAE,WAAW,CAAC;IAC/B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,+EAA+E;IAC/E,QAAQ,CAAC,kBAAkB,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IACjD,gFAAgF;IAChF,QAAQ,CAAC,eAAe,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IAC9C,8DAA8D;IAC9D,QAAQ,CAAC,aAAa,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IAC5C,iGAAiG;IACjG,QAAQ,CAAC,kBAAkB,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IACjD,sEAAsE;IACtE,QAAQ,CAAC,OAAO,EAAE,aAAa,GAAG,IAAI,CAAC;CACxC;AAED,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,WAAW,EAAE,YAAY,EAAE,CAAC;IACrC,QAAQ,CAAC,qBAAqB,EAAE,YAAY,EAAE,CAAC;IAC/C,QAAQ,CAAC,eAAe,EAAE,YAAY,EAAE,CAAC;IACzC,QAAQ,CAAC,kBAAkB,EAAE,YAAY,EAAE,CAAC;CAC7C;AAED,wBAAsB,mBAAmB,CACvC,MAAM,EAAE,oBAAoB,GAC3B,OAAO,CAAC,oBAAoB,CAAC,CA+H/B"}
|
|
@@ -0,0 +1,276 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Capability-spec feature extractor per ADR 0145 (schema 2.7.0).
|
|
3
|
+
*
|
|
4
|
+
* Walks `docs/domains/<dom>/product/<capability>.md` (platform-profile),
|
|
5
|
+
* parses the `## Feature Grounding (code-path trace)` markdown table,
|
|
6
|
+
* and emits four catalogue contributions:
|
|
7
|
+
*
|
|
8
|
+
* - `features.csv` rows with `source: capability-spec`.
|
|
9
|
+
* - `capability_feature.csv` rows (1:1 with each feature row).
|
|
10
|
+
* - `feature_repo.csv` rows derived from file-path references in
|
|
11
|
+
* the Implementation column.
|
|
12
|
+
* - `feature_service.csv` rows derived from class names / file
|
|
13
|
+
* basenames / route fragments in the Implementation column,
|
|
14
|
+
* resolved via `services.csv` + the optional per-SDD alias map
|
|
15
|
+
* introduced by ADR 0143.
|
|
16
|
+
*
|
|
17
|
+
* Resolution failures (unresolved capability, service, repo) emit
|
|
18
|
+
* findings but never break FK validation — only confidently-resolved
|
|
19
|
+
* rows are emitted.
|
|
20
|
+
*
|
|
21
|
+
* Precedence per ADR 0145 §4.7: feature-tree, feature-spec, and
|
|
22
|
+
* feature-grounding rows win on id collision (they are more specific
|
|
23
|
+
* sources); capability-spec rows are skipped with a divergence finding
|
|
24
|
+
* when their id is already taken.
|
|
25
|
+
*/
|
|
26
|
+
import { readFile } from "node:fs/promises";
|
|
27
|
+
import { relative } from "node:path";
|
|
28
|
+
import { capabilityIdFromSpecPath, findCapabilitySpecFiles, parseCapabilitySpecTable, } from "./capability-spec-walker.js";
|
|
29
|
+
const DESCRIPTION_MAX = 500;
|
|
30
|
+
/** Columns the service-name resolver scans for class names / route fragments. */
|
|
31
|
+
const SERVICE_RESOLUTION_COLUMNS = ["implementation"];
|
|
32
|
+
/** Columns the repo-name resolver scans for file-path references. */
|
|
33
|
+
const REPO_RESOLUTION_COLUMNS = ["implementation", "grounding_doc"];
|
|
34
|
+
export async function buildCapabilitySpec(inputs) {
|
|
35
|
+
const featureRows = [];
|
|
36
|
+
const capabilityFeatureRows = [];
|
|
37
|
+
const featureRepoRows = [];
|
|
38
|
+
const featureServiceRows = [];
|
|
39
|
+
const seenFeatureRepo = new Set();
|
|
40
|
+
const seenFeatureService = new Set();
|
|
41
|
+
const seenFeatures = new Set(inputs.existingFeatureIds);
|
|
42
|
+
if (inputs.profile !== "platform-profile") {
|
|
43
|
+
return {
|
|
44
|
+
featureRows,
|
|
45
|
+
capabilityFeatureRows,
|
|
46
|
+
featureRepoRows,
|
|
47
|
+
featureServiceRows,
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
const files = await findCapabilitySpecFiles(inputs.sddPath);
|
|
51
|
+
for (const absPath of files) {
|
|
52
|
+
const capabilityId = capabilityIdFromSpecPath(absPath, inputs.sddPath);
|
|
53
|
+
const relPath = relative(inputs.sddPath, absPath);
|
|
54
|
+
if (capabilityId === "") {
|
|
55
|
+
inputs.findings.add("convention", `${relPath}: capability id could not be resolved from file path`);
|
|
56
|
+
continue;
|
|
57
|
+
}
|
|
58
|
+
if (!inputs.knownCapabilityIds.has(capabilityId)) {
|
|
59
|
+
// Common for product README-style files that aren't capability specs.
|
|
60
|
+
// Treat as orphan, not convention — silently skip.
|
|
61
|
+
inputs.findings.add("orphan", `${relPath}: filename stem "${capabilityId}" does not match any capability id in capabilities.csv — skipping`);
|
|
62
|
+
continue;
|
|
63
|
+
}
|
|
64
|
+
const text = await readFile(absPath, "utf-8");
|
|
65
|
+
const rows = parseCapabilitySpecTable(text);
|
|
66
|
+
if (rows.length === 0) {
|
|
67
|
+
inputs.findings.add("coverage", `${relPath}: capability spec found but no "## Feature Grounding (code-path trace)" table recognised`);
|
|
68
|
+
continue;
|
|
69
|
+
}
|
|
70
|
+
const slugsInThisFile = new Set();
|
|
71
|
+
for (const row of rows) {
|
|
72
|
+
if (slugsInThisFile.has(row.slug)) {
|
|
73
|
+
inputs.findings.add("divergence", `${relPath}:${row.lineNumber}: duplicate feature slug "${row.slug}" in same file (first occurrence wins)`);
|
|
74
|
+
continue;
|
|
75
|
+
}
|
|
76
|
+
slugsInThisFile.add(row.slug);
|
|
77
|
+
const featureId = `${capabilityId}-${row.slug}`;
|
|
78
|
+
if (seenFeatures.has(featureId)) {
|
|
79
|
+
inputs.findings.add("divergence", `${relPath}:${row.lineNumber}: feature id "${featureId}" already emitted by an earlier source (feature-tree / feature-spec / feature-grounding wins)`);
|
|
80
|
+
continue;
|
|
81
|
+
}
|
|
82
|
+
seenFeatures.add(featureId);
|
|
83
|
+
featureRows.push({
|
|
84
|
+
id: featureId,
|
|
85
|
+
name: row.slug,
|
|
86
|
+
product_id: "",
|
|
87
|
+
capability_id: capabilityId,
|
|
88
|
+
parent_group_id: "",
|
|
89
|
+
parent_feature_id: "",
|
|
90
|
+
description: deriveDescription(row),
|
|
91
|
+
maturity: "",
|
|
92
|
+
status: "active",
|
|
93
|
+
source: "capability-spec",
|
|
94
|
+
runway: "",
|
|
95
|
+
source_sdd_id: "",
|
|
96
|
+
});
|
|
97
|
+
const cfId = `${capabilityId}__${featureId}`;
|
|
98
|
+
capabilityFeatureRows.push({
|
|
99
|
+
id: cfId,
|
|
100
|
+
capability_id: capabilityId,
|
|
101
|
+
feature_id: featureId,
|
|
102
|
+
});
|
|
103
|
+
// feature_service edges
|
|
104
|
+
const services = resolveServices(row, inputs);
|
|
105
|
+
for (const serviceId of services) {
|
|
106
|
+
const edgeId = `${featureId}__${serviceId}`;
|
|
107
|
+
if (seenFeatureService.has(edgeId))
|
|
108
|
+
continue;
|
|
109
|
+
seenFeatureService.add(edgeId);
|
|
110
|
+
featureServiceRows.push({
|
|
111
|
+
id: edgeId,
|
|
112
|
+
feature_id: featureId,
|
|
113
|
+
service_id: serviceId,
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
// feature_repo edges
|
|
117
|
+
const repos = resolveRepos(row, inputs);
|
|
118
|
+
for (const repoKey of repos) {
|
|
119
|
+
const edgeId = `${featureId}__${repoKey}`;
|
|
120
|
+
if (seenFeatureRepo.has(edgeId))
|
|
121
|
+
continue;
|
|
122
|
+
seenFeatureRepo.add(edgeId);
|
|
123
|
+
featureRepoRows.push({
|
|
124
|
+
id: edgeId,
|
|
125
|
+
feature_id: featureId,
|
|
126
|
+
repo_id: repoKey,
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
return {
|
|
132
|
+
featureRows,
|
|
133
|
+
capabilityFeatureRows,
|
|
134
|
+
featureRepoRows,
|
|
135
|
+
featureServiceRows,
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Build the description column by joining non-feature cells, capped at
|
|
140
|
+
* 500 chars to match the feature-grounding convention.
|
|
141
|
+
*/
|
|
142
|
+
function deriveDescription(row) {
|
|
143
|
+
const parts = [];
|
|
144
|
+
for (const [key, value] of row.cells) {
|
|
145
|
+
if (value === "")
|
|
146
|
+
continue;
|
|
147
|
+
parts.push(`${prettyHeader(key)}: ${value}`);
|
|
148
|
+
}
|
|
149
|
+
const joined = parts.join(" • ");
|
|
150
|
+
return joined.length > DESCRIPTION_MAX
|
|
151
|
+
? joined.slice(0, DESCRIPTION_MAX)
|
|
152
|
+
: joined;
|
|
153
|
+
}
|
|
154
|
+
function prettyHeader(key) {
|
|
155
|
+
return key
|
|
156
|
+
.split("_")
|
|
157
|
+
.map((p) => (p.length === 0 ? p : p[0].toUpperCase() + p.slice(1)))
|
|
158
|
+
.join(" ");
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* Resolve service ids referenced in a row's Implementation cell.
|
|
162
|
+
* Same strategy as feature-grounding: tokenize, alias-lookup, normalise,
|
|
163
|
+
* known-id lookup.
|
|
164
|
+
*/
|
|
165
|
+
function resolveServices(row, inputs) {
|
|
166
|
+
const out = new Set();
|
|
167
|
+
for (const col of SERVICE_RESOLUTION_COLUMNS) {
|
|
168
|
+
const cell = row.cells.get(col) ?? "";
|
|
169
|
+
if (cell === "")
|
|
170
|
+
continue;
|
|
171
|
+
for (const token of tokenize(cell)) {
|
|
172
|
+
const resolved = resolveServiceToken(token, inputs);
|
|
173
|
+
if (resolved !== null)
|
|
174
|
+
out.add(resolved);
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
return [...out].sort();
|
|
178
|
+
}
|
|
179
|
+
function resolveServiceToken(rawToken, inputs) {
|
|
180
|
+
if (inputs.aliases !== null) {
|
|
181
|
+
const aliased = inputs.aliases.serviceAliases.get(rawToken);
|
|
182
|
+
if (aliased !== undefined && inputs.knownServiceIds.has(aliased)) {
|
|
183
|
+
return aliased;
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
const normalised = normaliseToken(rawToken);
|
|
187
|
+
if (normalised === "")
|
|
188
|
+
return null;
|
|
189
|
+
if (inputs.knownServiceIds.has(normalised))
|
|
190
|
+
return normalised;
|
|
191
|
+
if (inputs.aliases !== null) {
|
|
192
|
+
const aliased = inputs.aliases.serviceAliases.get(normalised);
|
|
193
|
+
if (aliased !== undefined && inputs.knownServiceIds.has(aliased)) {
|
|
194
|
+
return aliased;
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
return null;
|
|
198
|
+
}
|
|
199
|
+
function resolveRepos(row, inputs) {
|
|
200
|
+
const out = new Set();
|
|
201
|
+
for (const col of REPO_RESOLUTION_COLUMNS) {
|
|
202
|
+
const cell = row.cells.get(col) ?? "";
|
|
203
|
+
if (cell === "")
|
|
204
|
+
continue;
|
|
205
|
+
for (const token of tokenize(cell)) {
|
|
206
|
+
const resolved = resolveRepoToken(token, inputs);
|
|
207
|
+
if (resolved !== null)
|
|
208
|
+
out.add(resolved);
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
return [...out].sort();
|
|
212
|
+
}
|
|
213
|
+
function resolveRepoToken(rawToken, inputs) {
|
|
214
|
+
if (inputs.aliases !== null) {
|
|
215
|
+
const aliased = inputs.aliases.repoAliases.get(rawToken);
|
|
216
|
+
if (aliased !== undefined && inputs.knownRepoKeys.has(aliased)) {
|
|
217
|
+
return aliased;
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
if (inputs.knownRepoKeys.has(rawToken))
|
|
221
|
+
return rawToken;
|
|
222
|
+
for (const segment of rawToken.split("/")) {
|
|
223
|
+
const stripped = segment
|
|
224
|
+
.replace(/-master@.*$/, "")
|
|
225
|
+
.replace(/@[^/]+$/, "");
|
|
226
|
+
if (stripped !== "" && inputs.knownRepoKeys.has(stripped)) {
|
|
227
|
+
return stripped;
|
|
228
|
+
}
|
|
229
|
+
const trailingMaster = stripped.replace(/-master$/, "");
|
|
230
|
+
if (trailingMaster !== stripped &&
|
|
231
|
+
inputs.knownRepoKeys.has(trailingMaster)) {
|
|
232
|
+
return trailingMaster;
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
return null;
|
|
236
|
+
}
|
|
237
|
+
/**
|
|
238
|
+
* Tokenize a markdown cell — mirrors the feature-grounding tokenizer.
|
|
239
|
+
* Matches backticked spans, bare CamelCase / kebab-case identifiers,
|
|
240
|
+
* and path-like tokens. Strips method call parens and array indexers.
|
|
241
|
+
*/
|
|
242
|
+
function tokenize(cell) {
|
|
243
|
+
const out = new Set();
|
|
244
|
+
for (const match of cell.matchAll(/`([^`]+)`/g)) {
|
|
245
|
+
const inner = match[1] ?? "";
|
|
246
|
+
addCandidatesFromToken(inner, out);
|
|
247
|
+
}
|
|
248
|
+
const stripped = cell.replace(/`[^`]+`/g, " ");
|
|
249
|
+
for (const match of stripped.matchAll(/[A-Za-z][A-Za-z0-9._@/-]*[A-Za-z0-9]/g)) {
|
|
250
|
+
addCandidatesFromToken(match[0], out);
|
|
251
|
+
}
|
|
252
|
+
return [...out];
|
|
253
|
+
}
|
|
254
|
+
function addCandidatesFromToken(token, out) {
|
|
255
|
+
if (token === "")
|
|
256
|
+
return;
|
|
257
|
+
if (token.includes("/")) {
|
|
258
|
+
out.add(token);
|
|
259
|
+
const first = token.split("/")[0] ?? "";
|
|
260
|
+
if (first !== "" && first !== token)
|
|
261
|
+
out.add(first);
|
|
262
|
+
return;
|
|
263
|
+
}
|
|
264
|
+
const head = token.split(/[(.[]/)[0] ?? "";
|
|
265
|
+
if (head !== "")
|
|
266
|
+
out.add(head);
|
|
267
|
+
out.add(token);
|
|
268
|
+
}
|
|
269
|
+
function normaliseToken(token) {
|
|
270
|
+
return token
|
|
271
|
+
.toLowerCase()
|
|
272
|
+
.replace(/\.(ts|tsx|js|jsx|java|kt|kts|py|go|rs|yaml|yml|json|md)$/i, "")
|
|
273
|
+
.replace(/\(\)$/, "")
|
|
274
|
+
.trim();
|
|
275
|
+
}
|
|
276
|
+
//# sourceMappingURL=capability-spec.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"capability-spec.js","sourceRoot":"","sources":["../../../../src/lib/catalogue/builders/capability-spec.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"contracts.d.ts","sourceRoot":"","sources":["../../../../src/lib/catalogue/builders/contracts.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"contracts.d.ts","sourceRoot":"","sources":["../../../../src/lib/catalogue/builders/contracts.ts"],"names":[],"mappings":"AAqBA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAElD,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,QAAQ,EAAE,WAAW,CAAC;IAC/B,yEAAyE;IACzE,QAAQ,CAAC,kBAAkB,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;CAClD;AAED,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,IAAI,EAAE,YAAY,EAAE,CAAC;IAC9B,4FAA4F;IAC5F,QAAQ,CAAC,QAAQ,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAChD;AAwBD,wBAAsB,cAAc,CAClC,MAAM,EAAE,oBAAoB,GAC3B,OAAO,CAAC,oBAAoB,CAAC,CA6F/B"}
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
// Contracts discoverer — emits `contracts.csv` rows from
|
|
2
|
-
// `contracts/{openapi,proto,avro}/<domain>/<name>.<ext
|
|
2
|
+
// `contracts/{openapi,proto,avro}/<domain>/<name>.<ext>` (canonical) and
|
|
3
|
+
// `docs/domains/<domain>/contracts/{openapi,proto,avro}/<name>.<ext>`
|
|
4
|
+
// (platform-profile per reverse/workflows/contract.md).
|
|
3
5
|
//
|
|
4
6
|
// Per the canonical schema (catalogue-schema.yaml):
|
|
5
7
|
// - kind enum: rest | graphql | rpc | event
|
|
@@ -17,6 +19,7 @@ import { readdir, readFile } from "node:fs/promises";
|
|
|
17
19
|
import { extname, join, relative, sep } from "node:path";
|
|
18
20
|
import { parse as parseYaml } from "yaml";
|
|
19
21
|
const CONTRACTS_DIR_REL = "contracts";
|
|
22
|
+
const DOCS_DOMAINS_DIR_REL = join("docs", "domains");
|
|
20
23
|
const KIND_SPECS = [
|
|
21
24
|
{ subdir: "openapi", extensions: [".yaml", ".yml"], kind: "rest" },
|
|
22
25
|
{ subdir: "proto", extensions: [".proto"], kind: "rpc" },
|
|
@@ -26,54 +29,98 @@ export async function buildContracts(inputs) {
|
|
|
26
29
|
const rows = [];
|
|
27
30
|
const idByPath = new Map();
|
|
28
31
|
const seen = new Set();
|
|
32
|
+
const discovered = [];
|
|
33
|
+
// Layout 1: canonical SDD-root layout — contracts/<subdir>/<domain>/<file>.<ext>.
|
|
29
34
|
for (const spec of KIND_SPECS) {
|
|
30
35
|
const dir = join(inputs.sddPath, CONTRACTS_DIR_REL, spec.subdir);
|
|
31
36
|
const files = await collectFiles(dir, spec.extensions);
|
|
32
|
-
for (const path of files
|
|
33
|
-
const filename = basenameOf(path);
|
|
34
|
-
// Skip schema/config files at any depth.
|
|
35
|
-
if (filename === "schema.yaml" || filename === "schema.yml")
|
|
36
|
-
continue;
|
|
37
|
+
for (const path of files) {
|
|
37
38
|
const rel = relative(inputs.sddPath, path);
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
: slugify(stem);
|
|
43
|
-
if (seen.has(slug)) {
|
|
44
|
-
inputs.findings.add("divergence", `${rel}: contract id "${slug}" already emitted by an earlier file`);
|
|
45
|
-
continue;
|
|
46
|
-
}
|
|
47
|
-
seen.add(slug);
|
|
48
|
-
let description = "";
|
|
49
|
-
let version = "";
|
|
50
|
-
let sourceRepoId = "";
|
|
51
|
-
if (spec.kind === "rest") {
|
|
52
|
-
const meta = await tryReadOpenapiInfo(path);
|
|
53
|
-
description = meta.description;
|
|
54
|
-
version = meta.version;
|
|
55
|
-
if (meta.xSourceRepo !== "" && inputs.knownRepositoryIds.has(meta.xSourceRepo)) {
|
|
56
|
-
sourceRepoId = meta.xSourceRepo;
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
rows.push({
|
|
60
|
-
id: slug,
|
|
61
|
-
name: stem,
|
|
62
|
-
service_id: "",
|
|
63
|
-
source_repo_id: sourceRepoId,
|
|
39
|
+
discovered.push({
|
|
40
|
+
absPath: path,
|
|
41
|
+
relPath: rel,
|
|
42
|
+
domain: domainSegmentCanonical(rel),
|
|
64
43
|
kind: spec.kind,
|
|
65
|
-
version,
|
|
66
|
-
status: "active",
|
|
67
|
-
spec_path: rel,
|
|
68
|
-
visibility: "internal",
|
|
69
|
-
description,
|
|
70
|
-
source_sdd_id: "",
|
|
71
44
|
});
|
|
72
|
-
idByPath.set(rel, slug);
|
|
73
45
|
}
|
|
74
46
|
}
|
|
47
|
+
// Layout 2: platform-profile layout — docs/domains/<domain>/contracts/<subdir>/<file>.<ext>.
|
|
48
|
+
// Canonical for platform-profile SDDs per reverse/workflows/contract.md and
|
|
49
|
+
// reverse/workflow.md §3 ("docs/domains/{domain}/contracts/openapi/*.yaml ←
|
|
50
|
+
// refresh API surfaces"). Federated SDDs without docs/domains/ harmlessly
|
|
51
|
+
// contribute zero rows.
|
|
52
|
+
const domainsRoot = join(inputs.sddPath, DOCS_DOMAINS_DIR_REL);
|
|
53
|
+
const domainDirs = await listDirs(domainsRoot);
|
|
54
|
+
for (const domainName of domainDirs) {
|
|
55
|
+
for (const spec of KIND_SPECS) {
|
|
56
|
+
const dir = join(domainsRoot, domainName, CONTRACTS_DIR_REL, spec.subdir);
|
|
57
|
+
const files = await collectFiles(dir, spec.extensions);
|
|
58
|
+
for (const path of files) {
|
|
59
|
+
const rel = relative(inputs.sddPath, path);
|
|
60
|
+
discovered.push({
|
|
61
|
+
absPath: path,
|
|
62
|
+
relPath: rel,
|
|
63
|
+
domain: domainName,
|
|
64
|
+
kind: spec.kind,
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
discovered.sort((a, b) => a.relPath.localeCompare(b.relPath));
|
|
70
|
+
for (const entry of discovered) {
|
|
71
|
+
const filename = basenameOf(entry.absPath);
|
|
72
|
+
// Skip schema/config files at any depth.
|
|
73
|
+
if (filename === "schema.yaml" || filename === "schema.yml")
|
|
74
|
+
continue;
|
|
75
|
+
const stem = stemOf(filename);
|
|
76
|
+
const slug = entry.domain !== ""
|
|
77
|
+
? slugify(`${entry.domain}-${stem}`)
|
|
78
|
+
: slugify(stem);
|
|
79
|
+
if (seen.has(slug)) {
|
|
80
|
+
inputs.findings.add("divergence", `${entry.relPath}: contract id "${slug}" already emitted by an earlier file`);
|
|
81
|
+
continue;
|
|
82
|
+
}
|
|
83
|
+
seen.add(slug);
|
|
84
|
+
let description = "";
|
|
85
|
+
let version = "";
|
|
86
|
+
let sourceRepoId = "";
|
|
87
|
+
if (entry.kind === "rest") {
|
|
88
|
+
const meta = await tryReadOpenapiInfo(entry.absPath);
|
|
89
|
+
description = meta.description;
|
|
90
|
+
version = meta.version;
|
|
91
|
+
if (meta.xSourceRepo !== "" && inputs.knownRepositoryIds.has(meta.xSourceRepo)) {
|
|
92
|
+
sourceRepoId = meta.xSourceRepo;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
rows.push({
|
|
96
|
+
id: slug,
|
|
97
|
+
name: stem,
|
|
98
|
+
service_id: "",
|
|
99
|
+
source_repo_id: sourceRepoId,
|
|
100
|
+
kind: entry.kind,
|
|
101
|
+
version,
|
|
102
|
+
status: "active",
|
|
103
|
+
spec_path: entry.relPath,
|
|
104
|
+
visibility: "internal",
|
|
105
|
+
description,
|
|
106
|
+
source_sdd_id: "",
|
|
107
|
+
});
|
|
108
|
+
idByPath.set(entry.relPath, slug);
|
|
109
|
+
}
|
|
75
110
|
return { rows, idByPath };
|
|
76
111
|
}
|
|
112
|
+
async function listDirs(parent) {
|
|
113
|
+
try {
|
|
114
|
+
const entries = await readdir(parent, { withFileTypes: true });
|
|
115
|
+
return entries.filter((e) => e.isDirectory()).map((e) => e.name);
|
|
116
|
+
}
|
|
117
|
+
catch (err) {
|
|
118
|
+
const code = err.code;
|
|
119
|
+
if (code === "ENOENT")
|
|
120
|
+
return [];
|
|
121
|
+
throw err;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
77
124
|
async function tryReadOpenapiInfo(path) {
|
|
78
125
|
try {
|
|
79
126
|
const text = await readFile(path, "utf-8");
|
|
@@ -135,8 +182,8 @@ function basenameOf(absPath) {
|
|
|
135
182
|
function stemOf(filename) {
|
|
136
183
|
return filename.replace(/\.[^.]+$/, "");
|
|
137
184
|
}
|
|
138
|
-
function
|
|
139
|
-
//
|
|
185
|
+
function domainSegmentCanonical(relPath) {
|
|
186
|
+
// Canonical layout: contracts/<subdir>/<domain>/<file>.<ext>
|
|
140
187
|
// → parts = ["contracts", subdir, domain, file]
|
|
141
188
|
const parts = relPath.split(sep);
|
|
142
189
|
if (parts.length < 4)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"contracts.js","sourceRoot":"","sources":["../../../../src/lib/catalogue/builders/contracts.ts"],"names":[],"mappings":"AAAA,yDAAyD;AACzD,
|
|
1
|
+
{"version":3,"file":"contracts.js","sourceRoot":"","sources":["../../../../src/lib/catalogue/builders/contracts.ts"],"names":[],"mappings":"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"}
|