@mortice/mapwright 0.8.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 +161 -0
- package/LICENSE +21 -0
- package/README.md +262 -0
- package/dist/catalogue/canonicalisation.d.ts +36 -0
- package/dist/catalogue/canonicalisation.js +262 -0
- package/dist/catalogue/config.d.ts +13 -0
- package/dist/catalogue/config.js +77 -0
- package/dist/catalogue/deterministic.d.ts +3 -0
- package/dist/catalogue/deterministic.js +25 -0
- package/dist/catalogue/diagnostics.d.ts +2 -0
- package/dist/catalogue/diagnostics.js +34 -0
- package/dist/catalogue/evidence.d.ts +1 -0
- package/dist/catalogue/evidence.js +10 -0
- package/dist/catalogue/examples.d.ts +3 -0
- package/dist/catalogue/examples.js +20 -0
- package/dist/catalogue/identity.d.ts +61 -0
- package/dist/catalogue/identity.js +114 -0
- package/dist/catalogue/ignore.d.ts +4 -0
- package/dist/catalogue/ignore.js +29 -0
- package/dist/catalogue/indexer.d.ts +20 -0
- package/dist/catalogue/indexer.js +1393 -0
- package/dist/catalogue/linkage.d.ts +16 -0
- package/dist/catalogue/linkage.js +419 -0
- package/dist/catalogue/moduleResolution.d.ts +4 -0
- package/dist/catalogue/moduleResolution.js +67 -0
- package/dist/catalogue/ordering.d.ts +13 -0
- package/dist/catalogue/ordering.js +86 -0
- package/dist/catalogue/packages.d.ts +12 -0
- package/dist/catalogue/packages.js +475 -0
- package/dist/catalogue/pythonReExports.d.ts +7 -0
- package/dist/catalogue/pythonReExports.js +113 -0
- package/dist/catalogue/resolveRefs.d.ts +40 -0
- package/dist/catalogue/resolveRefs.js +284 -0
- package/dist/catalogue/scanner.d.ts +8 -0
- package/dist/catalogue/scanner.js +99 -0
- package/dist/catalogue/schema.d.ts +289 -0
- package/dist/catalogue/schema.js +1 -0
- package/dist/catalogue/store.d.ts +41 -0
- package/dist/catalogue/store.js +209 -0
- package/dist/catalogue/templates.d.ts +18 -0
- package/dist/catalogue/templates.js +158 -0
- package/dist/catalogue/version.d.ts +12 -0
- package/dist/catalogue/version.js +30 -0
- package/dist/cli/commands/adoptionPlan.d.ts +8 -0
- package/dist/cli/commands/adoptionPlan.js +24 -0
- package/dist/cli/commands/auditDocs.d.ts +8 -0
- package/dist/cli/commands/auditDocs.js +24 -0
- package/dist/cli/commands/changeImpact.d.ts +10 -0
- package/dist/cli/commands/changeImpact.js +36 -0
- package/dist/cli/commands/changes.d.ts +12 -0
- package/dist/cli/commands/changes.js +31 -0
- package/dist/cli/commands/check.d.ts +9 -0
- package/dist/cli/commands/check.js +4 -0
- package/dist/cli/commands/compatibility.d.ts +10 -0
- package/dist/cli/commands/compatibility.js +43 -0
- package/dist/cli/commands/diff.d.ts +31 -0
- package/dist/cli/commands/diff.js +118 -0
- package/dist/cli/commands/dogfood.d.ts +8 -0
- package/dist/cli/commands/dogfood.js +24 -0
- package/dist/cli/commands/drift.d.ts +8 -0
- package/dist/cli/commands/drift.js +13 -0
- package/dist/cli/commands/index.d.ts +9 -0
- package/dist/cli/commands/index.js +9 -0
- package/dist/cli/commands/indexWorkspace.d.ts +8 -0
- package/dist/cli/commands/indexWorkspace.js +23 -0
- package/dist/cli/commands/recommendConfig.d.ts +7 -0
- package/dist/cli/commands/recommendConfig.js +20 -0
- package/dist/cli/commands/schema.d.ts +1 -0
- package/dist/cli/commands/schema.js +37 -0
- package/dist/cli/commands/template.d.ts +5 -0
- package/dist/cli/commands/template.js +44 -0
- package/dist/cli/commands/validate.d.ts +9 -0
- package/dist/cli/commands/validate.js +85 -0
- package/dist/cli/index.d.ts +2 -0
- package/dist/cli/index.js +211 -0
- package/dist/comparison/artefactValidate.d.ts +19 -0
- package/dist/comparison/artefactValidate.js +334 -0
- package/dist/comparison/candidates.d.ts +12 -0
- package/dist/comparison/candidates.js +391 -0
- package/dist/comparison/compare.d.ts +15 -0
- package/dist/comparison/compare.js +240 -0
- package/dist/comparison/compatibility.d.ts +26 -0
- package/dist/comparison/compatibility.js +316 -0
- package/dist/comparison/drift.d.ts +34 -0
- package/dist/comparison/drift.js +71 -0
- package/dist/comparison/identity.d.ts +30 -0
- package/dist/comparison/identity.js +73 -0
- package/dist/comparison/impact.d.ts +14 -0
- package/dist/comparison/impact.js +291 -0
- package/dist/comparison/index.d.ts +6 -0
- package/dist/comparison/index.js +6 -0
- package/dist/comparison/integrity.d.ts +12 -0
- package/dist/comparison/integrity.js +199 -0
- package/dist/comparison/ordering.d.ts +4 -0
- package/dist/comparison/ordering.js +69 -0
- package/dist/comparison/projections.d.ts +19 -0
- package/dist/comparison/projections.js +185 -0
- package/dist/comparison/relationshipPolicy.d.ts +19 -0
- package/dist/comparison/relationshipPolicy.js +98 -0
- package/dist/comparison/schema.d.ts +178 -0
- package/dist/comparison/schema.js +16 -0
- package/dist/comparison/store.d.ts +58 -0
- package/dist/comparison/store.js +462 -0
- package/dist/comparison/validate.d.ts +23 -0
- package/dist/comparison/validate.js +137 -0
- package/dist/comparison/version.d.ts +9 -0
- package/dist/comparison/version.js +11 -0
- package/dist/extractors/docTags.d.ts +9 -0
- package/dist/extractors/docTags.js +106 -0
- package/dist/extractors/generic.d.ts +5 -0
- package/dist/extractors/generic.js +3 -0
- package/dist/extractors/javascript.d.ts +3 -0
- package/dist/extractors/javascript.js +4 -0
- package/dist/extractors/markdown.d.ts +7 -0
- package/dist/extractors/markdown.js +269 -0
- package/dist/extractors/python.d.ts +7 -0
- package/dist/extractors/python.js +314 -0
- package/dist/extractors/typescript.d.ts +7 -0
- package/dist/extractors/typescript.js +387 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +2 -0
- package/dist/mcp/resources.d.ts +18 -0
- package/dist/mcp/resources.js +57 -0
- package/dist/mcp/server.d.ts +2 -0
- package/dist/mcp/server.js +95 -0
- package/dist/mcp/tools.d.ts +29 -0
- package/dist/mcp/tools.js +902 -0
- package/dist/queries/adoption.d.ts +62 -0
- package/dist/queries/adoption.js +366 -0
- package/dist/queries/capabilities.d.ts +45 -0
- package/dist/queries/capabilities.js +124 -0
- package/dist/queries/changes.d.ts +33 -0
- package/dist/queries/changes.js +53 -0
- package/dist/queries/dependencies.d.ts +17 -0
- package/dist/queries/dependencies.js +94 -0
- package/dist/queries/dogfood.d.ts +50 -0
- package/dist/queries/dogfood.js +116 -0
- package/dist/queries/editingContext.d.ts +84 -0
- package/dist/queries/editingContext.js +240 -0
- package/dist/queries/examples.d.ts +8 -0
- package/dist/queries/examples.js +16 -0
- package/dist/queries/files.d.ts +8 -0
- package/dist/queries/files.js +14 -0
- package/dist/queries/lists.d.ts +94 -0
- package/dist/queries/lists.js +184 -0
- package/dist/queries/overview.d.ts +2 -0
- package/dist/queries/overview.js +8 -0
- package/dist/queries/publicApis.d.ts +60 -0
- package/dist/queries/publicApis.js +120 -0
- package/dist/queries/ranking.d.ts +67 -0
- package/dist/queries/ranking.js +387 -0
- package/dist/queries/recommendConfig.d.ts +47 -0
- package/dist/queries/recommendConfig.js +123 -0
- package/dist/queries/relationships.d.ts +5 -0
- package/dist/queries/relationships.js +15 -0
- package/dist/queries/reuseCandidates.d.ts +34 -0
- package/dist/queries/reuseCandidates.js +181 -0
- package/dist/queries/symbols.d.ts +40 -0
- package/dist/queries/symbols.js +41 -0
- package/dist/security/pathPolicy.d.ts +12 -0
- package/dist/security/pathPolicy.js +46 -0
- package/dist/security/secretPatterns.d.ts +1 -0
- package/dist/security/secretPatterns.js +4 -0
- package/dist/security/sourceAccess.d.ts +12 -0
- package/dist/security/sourceAccess.js +35 -0
- package/package.json +60 -0
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import type { CatalogueSnapshot } from "./schema.js";
|
|
2
|
+
export declare const OUTPUT_FILES: {
|
|
3
|
+
readonly catalogue: "catalogue.json";
|
|
4
|
+
readonly files: "files.json";
|
|
5
|
+
readonly packages: "packages.json";
|
|
6
|
+
readonly capabilities: "capabilities.json";
|
|
7
|
+
readonly publicApis: "public-apis.json";
|
|
8
|
+
readonly examples: "examples.json";
|
|
9
|
+
readonly symbols: "symbols.json";
|
|
10
|
+
readonly relationships: "relationships.json";
|
|
11
|
+
readonly tests: "tests.json";
|
|
12
|
+
readonly diagnostics: "diagnostics.json";
|
|
13
|
+
readonly lock: "catalogue.lock.json";
|
|
14
|
+
};
|
|
15
|
+
/** Schema versions this generator can load without migration. Schema 1 is rejected with upgrade_required. */
|
|
16
|
+
export declare const SUPPORTED_SCHEMA_VERSIONS: readonly [2];
|
|
17
|
+
export declare const CURRENT_SCHEMA_VERSION = 2;
|
|
18
|
+
export declare const SUPPORTED_IDENTITY_SCHEMES: readonly ["stable-sha256-v1"];
|
|
19
|
+
export type CommittedCatalogueErrorCode = "committed_catalogue_not_found" | "committed_catalogue_invalid" | "catalogue_schema_unsupported" | "catalogue_lock_mismatch" | "catalogue_upgrade_required" | "catalogue_identity_scheme_unsupported";
|
|
20
|
+
export interface CommittedCatalogueError {
|
|
21
|
+
code: CommittedCatalogueErrorCode;
|
|
22
|
+
message: string;
|
|
23
|
+
}
|
|
24
|
+
export type LoadCommittedCatalogueResult = {
|
|
25
|
+
ok: true;
|
|
26
|
+
snapshot: CatalogueSnapshot;
|
|
27
|
+
warnings: string[];
|
|
28
|
+
} | {
|
|
29
|
+
ok: false;
|
|
30
|
+
error: CommittedCatalogueError;
|
|
31
|
+
};
|
|
32
|
+
export declare function writeSnapshot(workspaceRoot: string, catalogueDir: string, snapshot: CatalogueSnapshot, pretty?: boolean): void;
|
|
33
|
+
/**
|
|
34
|
+
* Load a committed catalogue without indexing source.
|
|
35
|
+
* Fails clearly for missing, corrupt, unsupported, or mismatched snapshots.
|
|
36
|
+
* Schema 1 → catalogue_upgrade_required. Unknown identityScheme → catalogue_identity_scheme_unsupported.
|
|
37
|
+
*/
|
|
38
|
+
export declare function loadCommittedCatalogue(workspaceRoot: string, catalogueDir: string): LoadCommittedCatalogueResult;
|
|
39
|
+
/** @deprecated Prefer loadCommittedCatalogue for explicit error handling. */
|
|
40
|
+
export declare function readCommittedSnapshot(workspaceRoot: string, catalogueDir: string): CatalogueSnapshot | undefined;
|
|
41
|
+
export declare function computeCatalogueId(snapshot: Omit<CatalogueSnapshot, "catalogueId">): string;
|
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
import { mkdirSync, writeFileSync, existsSync, readFileSync } from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { stableStringify, hashContent } from "./deterministic.js";
|
|
4
|
+
import { MAPWRIGHT_GENERATOR_NAME, MAPWRIGHT_GENERATOR_VERSION } from "./version.js";
|
|
5
|
+
import { IDENTITY_SCHEME } from "./identity.js";
|
|
6
|
+
export const OUTPUT_FILES = {
|
|
7
|
+
catalogue: "catalogue.json",
|
|
8
|
+
files: "files.json",
|
|
9
|
+
packages: "packages.json",
|
|
10
|
+
capabilities: "capabilities.json",
|
|
11
|
+
publicApis: "public-apis.json",
|
|
12
|
+
examples: "examples.json",
|
|
13
|
+
symbols: "symbols.json",
|
|
14
|
+
relationships: "relationships.json",
|
|
15
|
+
tests: "tests.json",
|
|
16
|
+
diagnostics: "diagnostics.json",
|
|
17
|
+
lock: "catalogue.lock.json"
|
|
18
|
+
};
|
|
19
|
+
/** Schema versions this generator can load without migration. Schema 1 is rejected with upgrade_required. */
|
|
20
|
+
export const SUPPORTED_SCHEMA_VERSIONS = [2];
|
|
21
|
+
export const CURRENT_SCHEMA_VERSION = 2;
|
|
22
|
+
export const SUPPORTED_IDENTITY_SCHEMES = [IDENTITY_SCHEME];
|
|
23
|
+
export function writeSnapshot(workspaceRoot, catalogueDir, snapshot, pretty = true) {
|
|
24
|
+
const root = path.resolve(workspaceRoot, catalogueDir);
|
|
25
|
+
mkdirSync(root, { recursive: true });
|
|
26
|
+
writeJson(path.join(root, OUTPUT_FILES.catalogue), snapshot, pretty);
|
|
27
|
+
writeJson(path.join(root, OUTPUT_FILES.files), { schemaVersion: CURRENT_SCHEMA_VERSION, items: snapshot.files }, pretty);
|
|
28
|
+
writeJson(path.join(root, OUTPUT_FILES.packages), { schemaVersion: CURRENT_SCHEMA_VERSION, items: snapshot.packages }, pretty);
|
|
29
|
+
writeJson(path.join(root, OUTPUT_FILES.capabilities), { schemaVersion: CURRENT_SCHEMA_VERSION, items: snapshot.capabilities }, pretty);
|
|
30
|
+
writeJson(path.join(root, OUTPUT_FILES.publicApis), { schemaVersion: CURRENT_SCHEMA_VERSION, items: snapshot.publicApis }, pretty);
|
|
31
|
+
writeJson(path.join(root, OUTPUT_FILES.examples), { schemaVersion: CURRENT_SCHEMA_VERSION, items: snapshot.examples }, pretty);
|
|
32
|
+
writeJson(path.join(root, OUTPUT_FILES.symbols), { schemaVersion: CURRENT_SCHEMA_VERSION, items: snapshot.symbols }, pretty);
|
|
33
|
+
writeJson(path.join(root, OUTPUT_FILES.relationships), { schemaVersion: CURRENT_SCHEMA_VERSION, items: snapshot.relationships }, pretty);
|
|
34
|
+
writeJson(path.join(root, OUTPUT_FILES.tests), { schemaVersion: CURRENT_SCHEMA_VERSION, items: snapshot.tests }, pretty);
|
|
35
|
+
writeJson(path.join(root, OUTPUT_FILES.diagnostics), { schemaVersion: CURRENT_SCHEMA_VERSION, items: snapshot.diagnostics }, pretty);
|
|
36
|
+
writeJson(path.join(root, OUTPUT_FILES.lock), { schemaVersion: CURRENT_SCHEMA_VERSION, catalogueId: snapshot.catalogueId }, pretty);
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Load a committed catalogue without indexing source.
|
|
40
|
+
* Fails clearly for missing, corrupt, unsupported, or mismatched snapshots.
|
|
41
|
+
* Schema 1 → catalogue_upgrade_required. Unknown identityScheme → catalogue_identity_scheme_unsupported.
|
|
42
|
+
*/
|
|
43
|
+
export function loadCommittedCatalogue(workspaceRoot, catalogueDir) {
|
|
44
|
+
const root = path.resolve(workspaceRoot, catalogueDir);
|
|
45
|
+
const cataloguePath = path.join(root, OUTPUT_FILES.catalogue);
|
|
46
|
+
const lockPath = path.join(root, OUTPUT_FILES.lock);
|
|
47
|
+
if (!existsSync(cataloguePath)) {
|
|
48
|
+
return {
|
|
49
|
+
ok: false,
|
|
50
|
+
error: {
|
|
51
|
+
code: "committed_catalogue_not_found",
|
|
52
|
+
message: `No committed catalogue found in ${catalogueDir}.`
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
let parsed;
|
|
57
|
+
try {
|
|
58
|
+
parsed = JSON.parse(readFileSync(cataloguePath, "utf8"));
|
|
59
|
+
}
|
|
60
|
+
catch (error) {
|
|
61
|
+
return {
|
|
62
|
+
ok: false,
|
|
63
|
+
error: {
|
|
64
|
+
code: "committed_catalogue_invalid",
|
|
65
|
+
message: `Committed catalogue exists but cannot be parsed: ${String(error)}`
|
|
66
|
+
}
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
70
|
+
return {
|
|
71
|
+
ok: false,
|
|
72
|
+
error: {
|
|
73
|
+
code: "committed_catalogue_invalid",
|
|
74
|
+
message: "Committed catalogue JSON must be an object."
|
|
75
|
+
}
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
const record = parsed;
|
|
79
|
+
const schemaVersion = record.schemaVersion;
|
|
80
|
+
if (schemaVersion === undefined || schemaVersion === null) {
|
|
81
|
+
return {
|
|
82
|
+
ok: false,
|
|
83
|
+
error: {
|
|
84
|
+
code: "catalogue_upgrade_required",
|
|
85
|
+
message: `Committed catalogue is missing schemaVersion. Regenerate with Mapwright ${MAPWRIGHT_GENERATOR_VERSION} (supported schema versions: ${SUPPORTED_SCHEMA_VERSIONS.join(", ")}).`
|
|
86
|
+
}
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
if (typeof schemaVersion !== "number" || !Number.isFinite(schemaVersion)) {
|
|
90
|
+
return {
|
|
91
|
+
ok: false,
|
|
92
|
+
error: {
|
|
93
|
+
code: "committed_catalogue_invalid",
|
|
94
|
+
message: "Committed catalogue schemaVersion must be a number."
|
|
95
|
+
}
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
if (schemaVersion === 1) {
|
|
99
|
+
return {
|
|
100
|
+
ok: false,
|
|
101
|
+
error: {
|
|
102
|
+
code: "catalogue_upgrade_required",
|
|
103
|
+
message: `Committed catalogue schemaVersion 1 is no longer supported. Regenerate the catalogue with Mapwright ${MAPWRIGHT_GENERATOR_VERSION} (schema ${CURRENT_SCHEMA_VERSION}, identityScheme ${IDENTITY_SCHEME}).`
|
|
104
|
+
}
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
if (schemaVersion > CURRENT_SCHEMA_VERSION) {
|
|
108
|
+
return {
|
|
109
|
+
ok: false,
|
|
110
|
+
error: {
|
|
111
|
+
code: "catalogue_schema_unsupported",
|
|
112
|
+
message: `Committed catalogue schemaVersion ${schemaVersion} is newer than supported versions (${SUPPORTED_SCHEMA_VERSIONS.join(", ")}). Upgrade Mapwright or regenerate with a compatible generator.`
|
|
113
|
+
}
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
if (!SUPPORTED_SCHEMA_VERSIONS.includes(schemaVersion)) {
|
|
117
|
+
return {
|
|
118
|
+
ok: false,
|
|
119
|
+
error: {
|
|
120
|
+
code: "catalogue_upgrade_required",
|
|
121
|
+
message: `Committed catalogue schemaVersion ${schemaVersion} is no longer supported. Regenerate with Mapwright ${MAPWRIGHT_GENERATOR_VERSION}.`
|
|
122
|
+
}
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
const identityScheme = record.identityScheme;
|
|
126
|
+
if (identityScheme === undefined || identityScheme === null || identityScheme === "") {
|
|
127
|
+
return {
|
|
128
|
+
ok: false,
|
|
129
|
+
error: {
|
|
130
|
+
code: "catalogue_identity_scheme_unsupported",
|
|
131
|
+
message: `Committed catalogue is missing identityScheme. Supported schemes: ${SUPPORTED_IDENTITY_SCHEMES.join(", ")}. Regenerate with Mapwright ${MAPWRIGHT_GENERATOR_VERSION}.`
|
|
132
|
+
}
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
if (typeof identityScheme !== "string" || !SUPPORTED_IDENTITY_SCHEMES.includes(identityScheme)) {
|
|
136
|
+
return {
|
|
137
|
+
ok: false,
|
|
138
|
+
error: {
|
|
139
|
+
code: "catalogue_identity_scheme_unsupported",
|
|
140
|
+
message: `Committed catalogue identityScheme "${String(identityScheme)}" is not supported. Supported schemes: ${SUPPORTED_IDENTITY_SCHEMES.join(", ")}.`
|
|
141
|
+
}
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
if (typeof record.catalogueId !== "string" || !record.catalogueId) {
|
|
145
|
+
return {
|
|
146
|
+
ok: false,
|
|
147
|
+
error: {
|
|
148
|
+
code: "committed_catalogue_invalid",
|
|
149
|
+
message: "Committed catalogue is missing catalogueId."
|
|
150
|
+
}
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
const warnings = [];
|
|
154
|
+
const generator = record.generator;
|
|
155
|
+
if (generator && typeof generator === "object" && !Array.isArray(generator)) {
|
|
156
|
+
const generatorRecord = generator;
|
|
157
|
+
const name = generatorRecord.name;
|
|
158
|
+
const version = generatorRecord.version;
|
|
159
|
+
if (typeof name === "string" && name !== MAPWRIGHT_GENERATOR_NAME) {
|
|
160
|
+
warnings.push(`Catalogue generator name "${name}" differs from current "${MAPWRIGHT_GENERATOR_NAME}".`);
|
|
161
|
+
}
|
|
162
|
+
if (typeof version === "string" && version !== MAPWRIGHT_GENERATOR_VERSION) {
|
|
163
|
+
warnings.push(`Catalogue generator version "${version}" differs from current "${MAPWRIGHT_GENERATOR_VERSION}". Reload remains allowed for schemaVersion ${schemaVersion}; regenerate if query results look stale.`);
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
else {
|
|
167
|
+
warnings.push("Catalogue is missing generator metadata.");
|
|
168
|
+
}
|
|
169
|
+
if (existsSync(lockPath)) {
|
|
170
|
+
try {
|
|
171
|
+
const lock = JSON.parse(readFileSync(lockPath, "utf8"));
|
|
172
|
+
if (typeof lock.catalogueId === "string" && lock.catalogueId !== record.catalogueId) {
|
|
173
|
+
return {
|
|
174
|
+
ok: false,
|
|
175
|
+
error: {
|
|
176
|
+
code: "catalogue_lock_mismatch",
|
|
177
|
+
message: `catalogue.lock.json catalogueId ${lock.catalogueId} does not match catalogue.json ${record.catalogueId}.`
|
|
178
|
+
}
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
catch (error) {
|
|
183
|
+
return {
|
|
184
|
+
ok: false,
|
|
185
|
+
error: {
|
|
186
|
+
code: "committed_catalogue_invalid",
|
|
187
|
+
message: `catalogue.lock.json exists but cannot be parsed: ${String(error)}`
|
|
188
|
+
}
|
|
189
|
+
};
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
return {
|
|
193
|
+
ok: true,
|
|
194
|
+
snapshot: parsed,
|
|
195
|
+
warnings
|
|
196
|
+
};
|
|
197
|
+
}
|
|
198
|
+
/** @deprecated Prefer loadCommittedCatalogue for explicit error handling. */
|
|
199
|
+
export function readCommittedSnapshot(workspaceRoot, catalogueDir) {
|
|
200
|
+
const result = loadCommittedCatalogue(workspaceRoot, catalogueDir);
|
|
201
|
+
return result.ok ? result.snapshot : undefined;
|
|
202
|
+
}
|
|
203
|
+
export function computeCatalogueId(snapshot) {
|
|
204
|
+
const payload = stableStringify(snapshot, false);
|
|
205
|
+
return hashContent(payload);
|
|
206
|
+
}
|
|
207
|
+
function writeJson(filePath, payload, pretty) {
|
|
208
|
+
writeFileSync(filePath, stableStringify(payload, pretty), "utf8");
|
|
209
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { DocumentationTemplateId } from "../queries/adoption.js";
|
|
2
|
+
export type TemplateSurface = "markdown" | "typescript" | "python" | "test" | "generic";
|
|
3
|
+
export interface TemplateMetadata {
|
|
4
|
+
templateId: DocumentationTemplateId;
|
|
5
|
+
title: string;
|
|
6
|
+
description: string;
|
|
7
|
+
surface: TemplateSurface;
|
|
8
|
+
}
|
|
9
|
+
export interface TemplateResult {
|
|
10
|
+
templateId: DocumentationTemplateId;
|
|
11
|
+
title: string;
|
|
12
|
+
description: string;
|
|
13
|
+
surface: TemplateSurface;
|
|
14
|
+
content: string;
|
|
15
|
+
}
|
|
16
|
+
export declare function getDocumentationTemplate(templateId: DocumentationTemplateId): TemplateResult;
|
|
17
|
+
export declare function listDocumentationTemplateIds(): DocumentationTemplateId[];
|
|
18
|
+
export declare function listDocumentationTemplates(): TemplateMetadata[];
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
const TEMPLATE_CATALOGUE = {
|
|
2
|
+
"package-catalogue": {
|
|
3
|
+
templateId: "package-catalogue",
|
|
4
|
+
title: "Package CATALOGUE scaffold",
|
|
5
|
+
description: "Markdown scaffold for package metadata and one initial capability section.",
|
|
6
|
+
surface: "markdown",
|
|
7
|
+
content: [
|
|
8
|
+
"# Catalogue",
|
|
9
|
+
"",
|
|
10
|
+
"## Package",
|
|
11
|
+
"",
|
|
12
|
+
"Name: <package-name>",
|
|
13
|
+
"Purpose: TODO: Describe the package purpose.",
|
|
14
|
+
"Stability: unknown",
|
|
15
|
+
"",
|
|
16
|
+
"## Capability: TODO.capability-id",
|
|
17
|
+
"",
|
|
18
|
+
"Name: TODO capability name",
|
|
19
|
+
"Summary: TODO: Describe what this capability provides.",
|
|
20
|
+
"Stability: unknown",
|
|
21
|
+
"Intended use: TODO",
|
|
22
|
+
"",
|
|
23
|
+
"Public APIs:",
|
|
24
|
+
"- TODO",
|
|
25
|
+
"",
|
|
26
|
+
"Examples:",
|
|
27
|
+
"- TODO",
|
|
28
|
+
"",
|
|
29
|
+
"Tests:",
|
|
30
|
+
"- TODO",
|
|
31
|
+
"",
|
|
32
|
+
"Contracts:",
|
|
33
|
+
"- TODO",
|
|
34
|
+
"",
|
|
35
|
+
"Limitations:",
|
|
36
|
+
"- TODO",
|
|
37
|
+
""
|
|
38
|
+
].join("\n")
|
|
39
|
+
},
|
|
40
|
+
"capability-section": {
|
|
41
|
+
templateId: "capability-section",
|
|
42
|
+
title: "Capability section scaffold",
|
|
43
|
+
description: "Markdown capability section with conservative TODO placeholders.",
|
|
44
|
+
surface: "markdown",
|
|
45
|
+
content: [
|
|
46
|
+
"## Capability: TODO.capability-id",
|
|
47
|
+
"",
|
|
48
|
+
"Name: TODO capability name",
|
|
49
|
+
"Summary: TODO: Describe what this capability provides.",
|
|
50
|
+
"Stability: unknown",
|
|
51
|
+
"Intended use: TODO",
|
|
52
|
+
"",
|
|
53
|
+
"Public APIs:",
|
|
54
|
+
"- TODO",
|
|
55
|
+
"",
|
|
56
|
+
"Examples:",
|
|
57
|
+
"- TODO",
|
|
58
|
+
"",
|
|
59
|
+
"Tests:",
|
|
60
|
+
"- TODO",
|
|
61
|
+
"",
|
|
62
|
+
"Contracts:",
|
|
63
|
+
"- TODO",
|
|
64
|
+
"",
|
|
65
|
+
"Limitations:",
|
|
66
|
+
"- TODO",
|
|
67
|
+
""
|
|
68
|
+
].join("\n")
|
|
69
|
+
},
|
|
70
|
+
"typescript-public-api-jsdoc": {
|
|
71
|
+
templateId: "typescript-public-api-jsdoc",
|
|
72
|
+
title: "TypeScript public API JSDoc",
|
|
73
|
+
description: "JSDoc template for agent-facing public APIs in TypeScript or JavaScript.",
|
|
74
|
+
surface: "typescript",
|
|
75
|
+
content: [
|
|
76
|
+
"/**",
|
|
77
|
+
" * TODO: Describe what this public API does.",
|
|
78
|
+
" *",
|
|
79
|
+
" * @catalogue public-api",
|
|
80
|
+
" * @capability TODO.capability-id",
|
|
81
|
+
" * @stability unknown",
|
|
82
|
+
" * @intendedUse TODO",
|
|
83
|
+
" * @inputs TODO",
|
|
84
|
+
" * @returns TODO",
|
|
85
|
+
" * @contract TODO",
|
|
86
|
+
" * @example TODO",
|
|
87
|
+
" * @tests TODO",
|
|
88
|
+
" */",
|
|
89
|
+
""
|
|
90
|
+
].join("\n")
|
|
91
|
+
},
|
|
92
|
+
"python-public-api-docstring": {
|
|
93
|
+
templateId: "python-public-api-docstring",
|
|
94
|
+
title: "Python public API docstring",
|
|
95
|
+
description: "Docstring template for agent-facing public APIs in Python.",
|
|
96
|
+
surface: "python",
|
|
97
|
+
content: [
|
|
98
|
+
'"""',
|
|
99
|
+
"TODO: Describe what this public API does.",
|
|
100
|
+
"",
|
|
101
|
+
"@catalogue public-api",
|
|
102
|
+
"@capability TODO.capability-id",
|
|
103
|
+
"@stability unknown",
|
|
104
|
+
"@intendedUse TODO",
|
|
105
|
+
"@inputs TODO",
|
|
106
|
+
"@returns TODO",
|
|
107
|
+
"@contract TODO",
|
|
108
|
+
"@example TODO",
|
|
109
|
+
"@tests TODO",
|
|
110
|
+
'"""',
|
|
111
|
+
""
|
|
112
|
+
].join("\n")
|
|
113
|
+
},
|
|
114
|
+
"test-coverage-doc": {
|
|
115
|
+
templateId: "test-coverage-doc",
|
|
116
|
+
title: "Test coverage tags",
|
|
117
|
+
description: "Template comment for linking tests to capabilities and symbols.",
|
|
118
|
+
surface: "test",
|
|
119
|
+
content: [
|
|
120
|
+
"/**",
|
|
121
|
+
" * @catalogue test",
|
|
122
|
+
" * @coversCapability TODO.capability-id",
|
|
123
|
+
" * @coversSymbol TODO.symbol-name",
|
|
124
|
+
" * @contract TODO: Describe what behavior this test proves.",
|
|
125
|
+
" */",
|
|
126
|
+
""
|
|
127
|
+
].join("\n")
|
|
128
|
+
},
|
|
129
|
+
"example-reference": {
|
|
130
|
+
templateId: "example-reference",
|
|
131
|
+
title: "Example reference list",
|
|
132
|
+
description: "Metadata-only example references for capability or public API docs.",
|
|
133
|
+
surface: "generic",
|
|
134
|
+
content: [
|
|
135
|
+
"Examples:",
|
|
136
|
+
"- path/to/example.ts#anchor",
|
|
137
|
+
"- public-api:PublicApiName|path/to/example.md#anchor",
|
|
138
|
+
""
|
|
139
|
+
].join("\n")
|
|
140
|
+
}
|
|
141
|
+
};
|
|
142
|
+
export function getDocumentationTemplate(templateId) {
|
|
143
|
+
return TEMPLATE_CATALOGUE[templateId];
|
|
144
|
+
}
|
|
145
|
+
export function listDocumentationTemplateIds() {
|
|
146
|
+
return Object.keys(TEMPLATE_CATALOGUE).sort();
|
|
147
|
+
}
|
|
148
|
+
export function listDocumentationTemplates() {
|
|
149
|
+
return listDocumentationTemplateIds().map((templateId) => {
|
|
150
|
+
const template = TEMPLATE_CATALOGUE[templateId];
|
|
151
|
+
return {
|
|
152
|
+
templateId: template.templateId,
|
|
153
|
+
title: template.title,
|
|
154
|
+
description: template.description,
|
|
155
|
+
surface: template.surface
|
|
156
|
+
};
|
|
157
|
+
});
|
|
158
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/** Product display name. */
|
|
2
|
+
export declare const MAPWRIGHT_PRODUCT_NAME = "Mortice Mapwright";
|
|
3
|
+
/** Short product name. */
|
|
4
|
+
export declare const MAPWRIGHT_NAME = "Mapwright";
|
|
5
|
+
/**
|
|
6
|
+
* Generator name written into new catalogues: "mapwright".
|
|
7
|
+
* Compatible Schema 2 catalogues previously emitted generator.name "code-atlas" instead of "mapwright"; loaders accept both.
|
|
8
|
+
*/
|
|
9
|
+
export declare const MAPWRIGHT_GENERATOR_NAME = "mapwright";
|
|
10
|
+
export declare const MAPWRIGHT_GENERATOR_VERSION: string;
|
|
11
|
+
/** Generator names accepted when loading catalogues: current "mapwright" plus pre-release Code Atlas "code-atlas". */
|
|
12
|
+
export declare const SUPPORTED_GENERATOR_NAMES: readonly ["mapwright", "code-atlas"];
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { readFileSync } from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { fileURLToPath } from "node:url";
|
|
4
|
+
/** Product display name. */
|
|
5
|
+
export const MAPWRIGHT_PRODUCT_NAME = "Mortice Mapwright";
|
|
6
|
+
/** Short product name. */
|
|
7
|
+
export const MAPWRIGHT_NAME = "Mapwright";
|
|
8
|
+
/**
|
|
9
|
+
* Generator name written into new catalogues: "mapwright".
|
|
10
|
+
* Compatible Schema 2 catalogues previously emitted generator.name "code-atlas" instead of "mapwright"; loaders accept both.
|
|
11
|
+
*/
|
|
12
|
+
export const MAPWRIGHT_GENERATOR_NAME = "mapwright";
|
|
13
|
+
const FALLBACK_GENERATOR_VERSION = "0.0.0";
|
|
14
|
+
export const MAPWRIGHT_GENERATOR_VERSION = resolveGeneratorVersion();
|
|
15
|
+
/** Generator names accepted when loading catalogues: current "mapwright" plus pre-release Code Atlas "code-atlas". */
|
|
16
|
+
export const SUPPORTED_GENERATOR_NAMES = ["mapwright", "code-atlas"];
|
|
17
|
+
function resolveGeneratorVersion() {
|
|
18
|
+
try {
|
|
19
|
+
const currentDir = path.dirname(fileURLToPath(import.meta.url));
|
|
20
|
+
const packageJsonPath = path.resolve(currentDir, "../../package.json");
|
|
21
|
+
const parsed = JSON.parse(readFileSync(packageJsonPath, "utf8"));
|
|
22
|
+
if (typeof parsed.version === "string" && parsed.version.trim()) {
|
|
23
|
+
return parsed.version.trim();
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
catch {
|
|
27
|
+
// Keep a stable fallback instead of throwing during indexing or server startup.
|
|
28
|
+
}
|
|
29
|
+
return FALLBACK_GENERATOR_VERSION;
|
|
30
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export interface AdoptionPlanCommandOptions {
|
|
2
|
+
workspace: string;
|
|
3
|
+
config?: string;
|
|
4
|
+
includeInfo?: boolean;
|
|
5
|
+
includeGenerated?: boolean;
|
|
6
|
+
maxGaps?: number;
|
|
7
|
+
}
|
|
8
|
+
export declare function runAdoptionPlanCommand(options: AdoptionPlanCommandOptions): Record<string, unknown>;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
import { indexWorkspace } from "../../catalogue/indexer.js";
|
|
3
|
+
import { getAdoptionPlan } from "../../queries/adoption.js";
|
|
4
|
+
export function runAdoptionPlanCommand(options) {
|
|
5
|
+
const workspaceRoot = path.resolve(options.workspace);
|
|
6
|
+
const { snapshot } = indexWorkspace({
|
|
7
|
+
workspaceRoot,
|
|
8
|
+
configPath: options.config,
|
|
9
|
+
mode: "memory",
|
|
10
|
+
write: false
|
|
11
|
+
});
|
|
12
|
+
return {
|
|
13
|
+
ok: true,
|
|
14
|
+
data: getAdoptionPlan(snapshot, {
|
|
15
|
+
includeInfo: options.includeInfo,
|
|
16
|
+
includeGenerated: options.includeGenerated,
|
|
17
|
+
maxGaps: options.maxGaps
|
|
18
|
+
}),
|
|
19
|
+
warnings: [],
|
|
20
|
+
provenance: {
|
|
21
|
+
source: "mapwright"
|
|
22
|
+
}
|
|
23
|
+
};
|
|
24
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export interface AuditDocsCommandOptions {
|
|
2
|
+
workspace: string;
|
|
3
|
+
config?: string;
|
|
4
|
+
includeInfo?: boolean;
|
|
5
|
+
includeGenerated?: boolean;
|
|
6
|
+
maxGaps?: number;
|
|
7
|
+
}
|
|
8
|
+
export declare function runAuditDocsCommand(options: AuditDocsCommandOptions): Record<string, unknown>;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
import { indexWorkspace } from "../../catalogue/indexer.js";
|
|
3
|
+
import { getAdoptionAudit } from "../../queries/adoption.js";
|
|
4
|
+
export function runAuditDocsCommand(options) {
|
|
5
|
+
const workspaceRoot = path.resolve(options.workspace);
|
|
6
|
+
const { snapshot } = indexWorkspace({
|
|
7
|
+
workspaceRoot,
|
|
8
|
+
configPath: options.config,
|
|
9
|
+
mode: "memory",
|
|
10
|
+
write: false
|
|
11
|
+
});
|
|
12
|
+
return {
|
|
13
|
+
ok: true,
|
|
14
|
+
data: getAdoptionAudit(snapshot, {
|
|
15
|
+
includeInfo: options.includeInfo,
|
|
16
|
+
includeGenerated: options.includeGenerated,
|
|
17
|
+
maxGaps: options.maxGaps
|
|
18
|
+
}),
|
|
19
|
+
warnings: [],
|
|
20
|
+
provenance: {
|
|
21
|
+
source: "mapwright"
|
|
22
|
+
}
|
|
23
|
+
};
|
|
24
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
import { loadComparisonArtefact } from "../../comparison/store.js";
|
|
3
|
+
import { getChangeImpact } from "../../queries/changes.js";
|
|
4
|
+
export function runChangeImpactCommand(options) {
|
|
5
|
+
if (!options.comparisonDir) {
|
|
6
|
+
return {
|
|
7
|
+
output: { ok: false, error: { code: "usage_error", message: "--comparison-dir is required" } },
|
|
8
|
+
exitCode: 2
|
|
9
|
+
};
|
|
10
|
+
}
|
|
11
|
+
if (!options.changeId) {
|
|
12
|
+
return {
|
|
13
|
+
output: { ok: false, error: { code: "usage_error", message: "--change-id is required" } },
|
|
14
|
+
exitCode: 2
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
const loaded = loadComparisonArtefact(path.resolve(options.comparisonDir));
|
|
18
|
+
if (!loaded.ok) {
|
|
19
|
+
return {
|
|
20
|
+
output: { ok: false, error: loaded.error },
|
|
21
|
+
exitCode: loaded.error.code === "comparison_path_rejected" ? 4 : 3
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
const impact = getChangeImpact(loaded.comparison, options.changeId, {
|
|
25
|
+
maxDepth: options.maxDepth,
|
|
26
|
+
offset: options.offset,
|
|
27
|
+
limit: options.limit
|
|
28
|
+
});
|
|
29
|
+
if (!impact) {
|
|
30
|
+
return {
|
|
31
|
+
output: { ok: false, error: { code: "change_not_found", message: `Unknown changeId ${options.changeId}` } },
|
|
32
|
+
exitCode: 3
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
return { output: { ok: true, data: impact }, exitCode: 0 };
|
|
36
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { FailOn } from "./diff.js";
|
|
2
|
+
export declare function runChangesCommand(options: {
|
|
3
|
+
comparisonDir: string;
|
|
4
|
+
domain?: string;
|
|
5
|
+
status?: string;
|
|
6
|
+
offset?: number;
|
|
7
|
+
limit?: number;
|
|
8
|
+
failOn?: FailOn;
|
|
9
|
+
}): {
|
|
10
|
+
output: Record<string, unknown>;
|
|
11
|
+
exitCode: number;
|
|
12
|
+
};
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
import { loadComparisonArtefact } from "../../comparison/store.js";
|
|
3
|
+
import { listChanges } from "../../queries/changes.js";
|
|
4
|
+
export function runChangesCommand(options) {
|
|
5
|
+
if (!options.comparisonDir) {
|
|
6
|
+
return {
|
|
7
|
+
output: { ok: false, error: { code: "usage_error", message: "--comparison-dir is required" } },
|
|
8
|
+
exitCode: 2
|
|
9
|
+
};
|
|
10
|
+
}
|
|
11
|
+
const loaded = loadComparisonArtefact(path.resolve(options.comparisonDir));
|
|
12
|
+
if (!loaded.ok) {
|
|
13
|
+
return { output: { ok: false, error: loaded.error }, exitCode: 3 };
|
|
14
|
+
}
|
|
15
|
+
const page = listChanges(loaded.comparison, {
|
|
16
|
+
domain: options.domain,
|
|
17
|
+
status: options.status,
|
|
18
|
+
offset: options.offset,
|
|
19
|
+
limit: options.limit
|
|
20
|
+
});
|
|
21
|
+
const failOn = options.failOn ?? "never";
|
|
22
|
+
const counts = loaded.comparison.manifest.counts;
|
|
23
|
+
const total = counts.added + counts.removed + counts.modified;
|
|
24
|
+
let exitCode = 0;
|
|
25
|
+
if (failOn === "any-change" && total > 0)
|
|
26
|
+
exitCode = 1;
|
|
27
|
+
if (failOn === "any-public-change" && loaded.comparison.changes.some((c) => c.domain === "publicApis" && c.status !== "unchanged")) {
|
|
28
|
+
exitCode = 1;
|
|
29
|
+
}
|
|
30
|
+
return { output: { ok: true, data: page }, exitCode };
|
|
31
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export interface CheckCommandOptions {
|
|
2
|
+
workspace: string;
|
|
3
|
+
config?: string;
|
|
4
|
+
failOn?: "info" | "warning" | "error" | "never";
|
|
5
|
+
}
|
|
6
|
+
export declare function runCheckCommand(options: CheckCommandOptions): {
|
|
7
|
+
output: Record<string, unknown>;
|
|
8
|
+
exitCode: number;
|
|
9
|
+
};
|