@intentset/core 0.1.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/artifact.d.ts +28 -0
- package/dist/artifact.d.ts.map +1 -0
- package/dist/artifact.js +621 -0
- package/dist/artifact.js.map +1 -0
- package/dist/carrier.d.ts +21 -0
- package/dist/carrier.d.ts.map +1 -0
- package/dist/carrier.js +70 -0
- package/dist/carrier.js.map +1 -0
- package/dist/config.d.ts +17 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +74 -0
- package/dist/config.js.map +1 -0
- package/dist/context.d.ts +28 -0
- package/dist/context.d.ts.map +1 -0
- package/dist/context.js +223 -0
- package/dist/context.js.map +1 -0
- package/dist/diagnostics.d.ts +37 -0
- package/dist/diagnostics.d.ts.map +1 -0
- package/dist/diagnostics.js +22 -0
- package/dist/diagnostics.js.map +1 -0
- package/dist/export.d.ts +23 -0
- package/dist/export.d.ts.map +1 -0
- package/dist/export.js +144 -0
- package/dist/export.js.map +1 -0
- package/dist/graph.d.ts +17 -0
- package/dist/graph.d.ts.map +1 -0
- package/dist/graph.js +51 -0
- package/dist/graph.js.map +1 -0
- package/dist/hash.d.ts +16 -0
- package/dist/hash.d.ts.map +1 -0
- package/dist/hash.js +55 -0
- package/dist/hash.js.map +1 -0
- package/dist/impact.d.ts +6 -0
- package/dist/impact.d.ts.map +1 -0
- package/dist/impact.js +89 -0
- package/dist/impact.js.map +1 -0
- package/dist/index.d.ts +15 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +15 -0
- package/dist/index.js.map +1 -0
- package/dist/registries.d.ts +19 -0
- package/dist/registries.d.ts.map +1 -0
- package/dist/registries.js +137 -0
- package/dist/registries.js.map +1 -0
- package/dist/report.d.ts +34 -0
- package/dist/report.d.ts.map +1 -0
- package/dist/report.js +58 -0
- package/dist/report.js.map +1 -0
- package/dist/types.d.ts +266 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +90 -0
- package/dist/types.js.map +1 -0
- package/dist/validate.d.ts +6 -0
- package/dist/validate.d.ts.map +1 -0
- package/dist/validate.js +573 -0
- package/dist/validate.js.map +1 -0
- package/dist/yaml.d.ts +48 -0
- package/dist/yaml.d.ts.map +1 -0
- package/dist/yaml.js +413 -0
- package/dist/yaml.js.map +1 -0
- package/package.json +36 -0
- package/src/artifact.ts +835 -0
- package/src/carrier.ts +81 -0
- package/src/config.ts +96 -0
- package/src/context.ts +240 -0
- package/src/diagnostics.ts +60 -0
- package/src/export.ts +173 -0
- package/src/graph.ts +49 -0
- package/src/hash.ts +53 -0
- package/src/impact.ts +90 -0
- package/src/index.ts +14 -0
- package/src/registries.ts +171 -0
- package/src/report.ts +84 -0
- package/src/types.ts +357 -0
- package/src/validate.ts +655 -0
- package/src/yaml.ts +406 -0
package/dist/export.d.ts
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { type ExportEnvelope, type Level, type Registries, type ValidationResult } from "./types.ts";
|
|
2
|
+
/** What the caller knows and the validation result does not: identity, commit, scope, level, release. */
|
|
3
|
+
export interface ExportMeta {
|
|
4
|
+
/** Stable identity of the repository, from config. */
|
|
5
|
+
repository: string;
|
|
6
|
+
/** The commit the export describes, or null with `commitUnavailable` saying why (a default reason is written when none is given). */
|
|
7
|
+
commit: string | null;
|
|
8
|
+
commitUnavailable?: string;
|
|
9
|
+
/** The scope globs validated; defaults to every Markdown file. */
|
|
10
|
+
scope?: string[];
|
|
11
|
+
/** The level the validation ran at; defaults to L1. */
|
|
12
|
+
level?: Level;
|
|
13
|
+
release?: {
|
|
14
|
+
product: string;
|
|
15
|
+
label: string;
|
|
16
|
+
} | null;
|
|
17
|
+
/** ISO 8601; defaults to now. Fix it to make two exports comparable byte for byte. */
|
|
18
|
+
generatedAt?: string;
|
|
19
|
+
includeBodies?: boolean;
|
|
20
|
+
}
|
|
21
|
+
/** Core §12 and the integration contract: the `intentset/export/0.1` envelope over a validation result. */
|
|
22
|
+
export declare function exportGraph(result: ValidationResult, registries: Registries, meta: ExportMeta): ExportEnvelope;
|
|
23
|
+
//# sourceMappingURL=export.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"export.d.ts","sourceRoot":"","sources":["../src/export.ts"],"names":[],"mappings":"AAQA,OAAO,EAIL,KAAK,cAAc,EAEnB,KAAK,KAAK,EAEV,KAAK,UAAU,EAGf,KAAK,gBAAgB,EACtB,MAAM,YAAY,CAAC;AAEpB,yGAAyG;AACzG,MAAM,WAAW,UAAU;IACzB,sDAAsD;IACtD,UAAU,EAAE,MAAM,CAAC;IACnB,qIAAqI;IACrI,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,kEAAkE;IAClE,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB,uDAAuD;IACvD,KAAK,CAAC,EAAE,KAAK,CAAC;IACd,OAAO,CAAC,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;IACpD,sFAAsF;IACtF,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB;AAED,2GAA2G;AAC3G,wBAAgB,WAAW,CAAC,MAAM,EAAE,gBAAgB,EAAE,UAAU,EAAE,UAAU,EAAE,IAAI,EAAE,UAAU,GAAG,cAAc,CA6B9G"}
|
package/dist/export.js
ADDED
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The export envelope (Core §12; the integration contract; spec/export.schema.json).
|
|
3
|
+
* Artifacts are sorted by ID and every list inside is sorted, so the same
|
|
4
|
+
* validation result with the same `generatedAt` is the same bytes. Bodies
|
|
5
|
+
* are included only when asked for.
|
|
6
|
+
*/
|
|
7
|
+
import { graphHash, sortKeysDeep } from "./hash.js";
|
|
8
|
+
import { compareStrings } from "./report.js";
|
|
9
|
+
import { EXPORT_CONTRACT, LINK_KINDS, SPEC_VERSION, } from "./types.js";
|
|
10
|
+
/** Core §12 and the integration contract: the `intentset/export/0.1` envelope over a validation result. */
|
|
11
|
+
export function exportGraph(result, registries, meta) {
|
|
12
|
+
const { graph } = result;
|
|
13
|
+
const ids = [...graph.artifacts.keys()].sort(compareStrings);
|
|
14
|
+
const errors = result.diagnostics.filter((d) => d.severity === "error").length;
|
|
15
|
+
const warnings = result.diagnostics.length - errors;
|
|
16
|
+
const source = { commit: meta.commit };
|
|
17
|
+
if (meta.commit === null)
|
|
18
|
+
source.commitUnavailable = meta.commitUnavailable ?? "No commit was supplied to the export.";
|
|
19
|
+
return {
|
|
20
|
+
contract: EXPORT_CONTRACT,
|
|
21
|
+
spec: SPEC_VERSION,
|
|
22
|
+
generatedAt: meta.generatedAt ?? new Date().toISOString(),
|
|
23
|
+
repository: meta.repository,
|
|
24
|
+
products: ids.filter((id) => graph.artifacts.get(id)?.meta.type === "product"),
|
|
25
|
+
source,
|
|
26
|
+
graphHash: graphHash(graph),
|
|
27
|
+
release: meta.release ?? null,
|
|
28
|
+
validation: {
|
|
29
|
+
level: meta.level ?? "L1",
|
|
30
|
+
scope: [...(meta.scope ?? ["**/*.md"])],
|
|
31
|
+
status: result.ok ? "pass" : "fail",
|
|
32
|
+
errors,
|
|
33
|
+
warnings,
|
|
34
|
+
diagnostics: [...result.diagnostics],
|
|
35
|
+
},
|
|
36
|
+
registries: exportRegistries(registries),
|
|
37
|
+
artifacts: ids.map((id) => exportArtifact(result, id, meta.includeBodies === true)),
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
function exportArtifact(result, id, includeBody) {
|
|
41
|
+
const { graph } = result;
|
|
42
|
+
const artifact = graph.artifacts.get(id);
|
|
43
|
+
if (artifact === undefined)
|
|
44
|
+
throw new Error(`graph has no artifact ${id}`);
|
|
45
|
+
const { meta } = artifact;
|
|
46
|
+
const links = {};
|
|
47
|
+
for (const kind of LINK_KINDS) {
|
|
48
|
+
if (kind === "parent")
|
|
49
|
+
continue;
|
|
50
|
+
const list = meta.links[kind];
|
|
51
|
+
if (list !== undefined)
|
|
52
|
+
links[kind] = [...list].sort(compareStrings);
|
|
53
|
+
}
|
|
54
|
+
const derived = {};
|
|
55
|
+
const byKind = new Map();
|
|
56
|
+
for (const edge of graph.in.get(id) ?? []) {
|
|
57
|
+
const list = byKind.get(edge.kind);
|
|
58
|
+
if (list === undefined)
|
|
59
|
+
byKind.set(edge.kind, [edge.from]);
|
|
60
|
+
else
|
|
61
|
+
list.push(edge.from);
|
|
62
|
+
}
|
|
63
|
+
for (const kind of LINK_KINDS) {
|
|
64
|
+
const list = byKind.get(kind);
|
|
65
|
+
if (list !== undefined)
|
|
66
|
+
derived[kind] = [...new Set(list)].sort(compareStrings);
|
|
67
|
+
}
|
|
68
|
+
const exported = {
|
|
69
|
+
id,
|
|
70
|
+
type: meta.type,
|
|
71
|
+
title: meta.title,
|
|
72
|
+
status: meta.status,
|
|
73
|
+
owner: meta.owner,
|
|
74
|
+
visibility: meta.visibility,
|
|
75
|
+
audiences: [...meta.audiences].sort(compareStrings),
|
|
76
|
+
profile: meta.profile,
|
|
77
|
+
revision: meta.revision ?? null,
|
|
78
|
+
path: artifact.path,
|
|
79
|
+
sourceHash: artifact.sourceHash,
|
|
80
|
+
parent: meta.parent ?? null,
|
|
81
|
+
links,
|
|
82
|
+
derived,
|
|
83
|
+
availability: meta.availability === undefined ? null : sortedAvailability(meta.availability),
|
|
84
|
+
slice: meta.slice === undefined ? null : sortedSlice(meta.slice),
|
|
85
|
+
verification: meta.verification === undefined
|
|
86
|
+
? null
|
|
87
|
+
: {
|
|
88
|
+
method: meta.verification.method,
|
|
89
|
+
locator: meta.verification.locator,
|
|
90
|
+
selector: meta.verification.selector,
|
|
91
|
+
},
|
|
92
|
+
extensions: meta.extensions === undefined ? null : sortKeysDeep(meta.extensions),
|
|
93
|
+
};
|
|
94
|
+
if (includeBody)
|
|
95
|
+
exported.body = artifact.body;
|
|
96
|
+
return exported;
|
|
97
|
+
}
|
|
98
|
+
function sortedAvailability(availability) {
|
|
99
|
+
return {
|
|
100
|
+
products: [...availability.products].sort(compareStrings),
|
|
101
|
+
releases: [...availability.releases].sort(compareStrings),
|
|
102
|
+
roles: [...availability.roles].sort(compareStrings),
|
|
103
|
+
editions: [...availability.editions].sort(compareStrings),
|
|
104
|
+
flags: [...availability.flags].sort(compareStrings),
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
function sortedSlice(slice) {
|
|
108
|
+
const layers = {};
|
|
109
|
+
for (const layer of Object.keys(slice.layers).sort(compareStrings)) {
|
|
110
|
+
layers[layer] = [...slice.layers[layer]].sort(compareStrings);
|
|
111
|
+
}
|
|
112
|
+
const out = {
|
|
113
|
+
kind: slice.kind,
|
|
114
|
+
domain: slice.domain,
|
|
115
|
+
entrypoints: [...slice.entrypoints].sort(compareStrings),
|
|
116
|
+
layers,
|
|
117
|
+
claims: [...slice.claims]
|
|
118
|
+
.map((claim) => ({ kind: claim.kind, path: claim.path }))
|
|
119
|
+
.sort((a, b) => compareStrings(a.kind, b.kind) || compareStrings(a.path, b.path)),
|
|
120
|
+
usesResources: [...slice.usesResources].sort(compareStrings),
|
|
121
|
+
};
|
|
122
|
+
if (slice.rationale !== undefined)
|
|
123
|
+
out.rationale = slice.rationale;
|
|
124
|
+
return out;
|
|
125
|
+
}
|
|
126
|
+
function exportRegistries(registries) {
|
|
127
|
+
return {
|
|
128
|
+
owners: [...registries.owners].sort(compareStrings),
|
|
129
|
+
audiences: [...registries.audiences].sort(compareStrings),
|
|
130
|
+
releases: [...registries.releases].sort(compareStrings),
|
|
131
|
+
roles: [...registries.roles].sort(compareStrings),
|
|
132
|
+
editions: [...registries.editions].sort(compareStrings),
|
|
133
|
+
flags: [...registries.flags].sort(compareStrings),
|
|
134
|
+
resources: [...registries.resources]
|
|
135
|
+
.map((resource) => ({
|
|
136
|
+
id: resource.id,
|
|
137
|
+
path: resource.path,
|
|
138
|
+
owner: resource.owner,
|
|
139
|
+
consumers: [...resource.consumers].sort(compareStrings),
|
|
140
|
+
}))
|
|
141
|
+
.sort((a, b) => compareStrings(a.id, b.id)),
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
//# sourceMappingURL=export.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"export.js","sourceRoot":"","sources":["../src/export.ts"],"names":[],"mappings":"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"}
|
package/dist/graph.d.ts
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The typed graph (Core §5, §12): authored edges in the direction they are
|
|
3
|
+
* written, and one derived inverse per authored edge, marked derived.
|
|
4
|
+
*/
|
|
5
|
+
import { type Artifact, type Edge, type Graph } from "./types.ts";
|
|
6
|
+
/**
|
|
7
|
+
* Core §5 and §12: build the graph from artifacts whose IDs are already
|
|
8
|
+
* unique. Edges follow document order (the order given) then field order
|
|
9
|
+
* (`parent`, then the Core §5 table). Edges to IDs that are not in the graph
|
|
10
|
+
* are kept as authored; the validator reports them.
|
|
11
|
+
*/
|
|
12
|
+
export declare function buildGraph(artifacts: readonly Artifact[]): Graph;
|
|
13
|
+
/** Core §5: authored edges of one kind leaving an artifact. */
|
|
14
|
+
export declare function outgoing(graph: Graph, id: string, kind: Edge["kind"]): Edge[];
|
|
15
|
+
/** Core §5: authored edges of one kind arriving at an artifact, the authored side of a derived inverse. */
|
|
16
|
+
export declare function incomingEdges(graph: Graph, id: string, kind: Edge["kind"]): Edge[];
|
|
17
|
+
//# sourceMappingURL=graph.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"graph.d.ts","sourceRoot":"","sources":["../src/graph.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EAAE,KAAK,QAAQ,EAAE,KAAK,IAAI,EAAE,KAAK,KAAK,EAAc,MAAM,YAAY,CAAC;AAE9E;;;;;GAKG;AACH,wBAAgB,UAAU,CAAC,SAAS,EAAE,SAAS,QAAQ,EAAE,GAAG,KAAK,CAoBhE;AAQD,+DAA+D;AAC/D,wBAAgB,QAAQ,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,MAAM,CAAC,GAAG,IAAI,EAAE,CAE7E;AAED,2GAA2G;AAC3G,wBAAgB,aAAa,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,MAAM,CAAC,GAAG,IAAI,EAAE,CAElF"}
|
package/dist/graph.js
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The typed graph (Core §5, §12): authored edges in the direction they are
|
|
3
|
+
* written, and one derived inverse per authored edge, marked derived.
|
|
4
|
+
*/
|
|
5
|
+
import { LINK_KINDS } from "./types.js";
|
|
6
|
+
/**
|
|
7
|
+
* Core §5 and §12: build the graph from artifacts whose IDs are already
|
|
8
|
+
* unique. Edges follow document order (the order given) then field order
|
|
9
|
+
* (`parent`, then the Core §5 table). Edges to IDs that are not in the graph
|
|
10
|
+
* are kept as authored; the validator reports them.
|
|
11
|
+
*/
|
|
12
|
+
export function buildGraph(artifacts) {
|
|
13
|
+
const map = new Map();
|
|
14
|
+
const edges = [];
|
|
15
|
+
for (const artifact of artifacts) {
|
|
16
|
+
const { meta } = artifact;
|
|
17
|
+
map.set(meta.id, artifact);
|
|
18
|
+
if (meta.parent !== undefined)
|
|
19
|
+
edges.push({ kind: "parent", from: meta.id, to: meta.parent, derived: false });
|
|
20
|
+
for (const kind of LINK_KINDS) {
|
|
21
|
+
if (kind === "parent")
|
|
22
|
+
continue;
|
|
23
|
+
for (const to of meta.links[kind] ?? [])
|
|
24
|
+
edges.push({ kind, from: meta.id, to, derived: false });
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
const derived = edges.map((edge) => ({ kind: edge.kind, from: edge.to, to: edge.from, derived: true }));
|
|
28
|
+
const out = new Map();
|
|
29
|
+
const incoming = new Map();
|
|
30
|
+
for (const edge of edges) {
|
|
31
|
+
push(out, edge.from, edge);
|
|
32
|
+
push(incoming, edge.to, edge);
|
|
33
|
+
}
|
|
34
|
+
return { artifacts: map, edges, derived, out, in: incoming };
|
|
35
|
+
}
|
|
36
|
+
function push(map, key, edge) {
|
|
37
|
+
const list = map.get(key);
|
|
38
|
+
if (list === undefined)
|
|
39
|
+
map.set(key, [edge]);
|
|
40
|
+
else
|
|
41
|
+
list.push(edge);
|
|
42
|
+
}
|
|
43
|
+
/** Core §5: authored edges of one kind leaving an artifact. */
|
|
44
|
+
export function outgoing(graph, id, kind) {
|
|
45
|
+
return (graph.out.get(id) ?? []).filter((edge) => edge.kind === kind);
|
|
46
|
+
}
|
|
47
|
+
/** Core §5: authored edges of one kind arriving at an artifact, the authored side of a derived inverse. */
|
|
48
|
+
export function incomingEdges(graph, id, kind) {
|
|
49
|
+
return (graph.in.get(id) ?? []).filter((edge) => edge.kind === kind);
|
|
50
|
+
}
|
|
51
|
+
//# sourceMappingURL=graph.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"graph.js","sourceRoot":"","sources":["../src/graph.ts"],"names":[],"mappings":"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"}
|
package/dist/hash.d.ts
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { Graph } from "./types.ts";
|
|
2
|
+
/** ADR 0005: JSON with keys sorted recursively and no whitespace. `undefined` members are omitted, as JSON.stringify omits them. */
|
|
3
|
+
export declare function canonicalJson(value: unknown): string;
|
|
4
|
+
/** ADR 0005: the same value with every object's keys in sorted order, arrays untouched. */
|
|
5
|
+
export declare function sortKeysDeep(value: unknown): unknown;
|
|
6
|
+
/** ADR 0005: lowercase hex SHA-256 of a string's UTF-8 bytes or of raw bytes. */
|
|
7
|
+
export declare function sha256Hex(input: string | Uint8Array): string;
|
|
8
|
+
/**
|
|
9
|
+
* ADR 0005: SHA-256 of the canonical JSON of the sorted list of
|
|
10
|
+
* `{ id, type, sourceHash, links }`, where `links` holds the artifact's
|
|
11
|
+
* authored edges by kind (`parent` included) with each target list sorted.
|
|
12
|
+
* Timestamps and commits stay outside, so the same files at two commits hash
|
|
13
|
+
* the same.
|
|
14
|
+
*/
|
|
15
|
+
export declare function graphHash(graph: Graph): string;
|
|
16
|
+
//# sourceMappingURL=hash.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hash.d.ts","sourceRoot":"","sources":["../src/hash.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,KAAK,EAAY,MAAM,YAAY,CAAC;AAElD,oIAAoI;AACpI,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAEpD;AAED,2FAA2F;AAC3F,wBAAgB,YAAY,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAWpD;AAED,iFAAiF;AACjF,wBAAgB,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,UAAU,GAAG,MAAM,CAE5D;AAED;;;;;;GAMG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,KAAK,GAAG,MAAM,CAc9C"}
|
package/dist/hash.js
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Canonical JSON and SHA-256 (ADR 0005). Everything hashed goes through
|
|
3
|
+
* `canonicalJson`, so the same value is the same bytes on every machine.
|
|
4
|
+
*/
|
|
5
|
+
import { createHash } from "node:crypto";
|
|
6
|
+
/** ADR 0005: JSON with keys sorted recursively and no whitespace. `undefined` members are omitted, as JSON.stringify omits them. */
|
|
7
|
+
export function canonicalJson(value) {
|
|
8
|
+
return JSON.stringify(sortKeysDeep(value));
|
|
9
|
+
}
|
|
10
|
+
/** ADR 0005: the same value with every object's keys in sorted order, arrays untouched. */
|
|
11
|
+
export function sortKeysDeep(value) {
|
|
12
|
+
if (Array.isArray(value))
|
|
13
|
+
return value.map(sortKeysDeep);
|
|
14
|
+
if (typeof value === "object" && value !== null) {
|
|
15
|
+
const record = value;
|
|
16
|
+
const out = {};
|
|
17
|
+
for (const key of Object.keys(record).sort()) {
|
|
18
|
+
if (record[key] !== undefined)
|
|
19
|
+
out[key] = sortKeysDeep(record[key]);
|
|
20
|
+
}
|
|
21
|
+
return out;
|
|
22
|
+
}
|
|
23
|
+
return value;
|
|
24
|
+
}
|
|
25
|
+
/** ADR 0005: lowercase hex SHA-256 of a string's UTF-8 bytes or of raw bytes. */
|
|
26
|
+
export function sha256Hex(input) {
|
|
27
|
+
return createHash("sha256").update(input).digest("hex");
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* ADR 0005: SHA-256 of the canonical JSON of the sorted list of
|
|
31
|
+
* `{ id, type, sourceHash, links }`, where `links` holds the artifact's
|
|
32
|
+
* authored edges by kind (`parent` included) with each target list sorted.
|
|
33
|
+
* Timestamps and commits stay outside, so the same files at two commits hash
|
|
34
|
+
* the same.
|
|
35
|
+
*/
|
|
36
|
+
export function graphHash(graph) {
|
|
37
|
+
const entries = [...graph.artifacts.keys()].sort().map((id) => {
|
|
38
|
+
const artifact = graph.artifacts.get(id);
|
|
39
|
+
if (artifact === undefined)
|
|
40
|
+
throw new Error(`graph has no artifact ${id}`);
|
|
41
|
+
const links = {};
|
|
42
|
+
for (const edge of graph.out.get(id) ?? []) {
|
|
43
|
+
const list = links[edge.kind];
|
|
44
|
+
if (list === undefined)
|
|
45
|
+
links[edge.kind] = [edge.to];
|
|
46
|
+
else
|
|
47
|
+
list.push(edge.to);
|
|
48
|
+
}
|
|
49
|
+
for (const kind of Object.keys(links))
|
|
50
|
+
links[kind]?.sort();
|
|
51
|
+
return { id, type: artifact.meta.type, sourceHash: artifact.sourceHash, links };
|
|
52
|
+
});
|
|
53
|
+
return sha256Hex(canonicalJson(entries));
|
|
54
|
+
}
|
|
55
|
+
//# sourceMappingURL=hash.js.map
|
package/dist/hash.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hash.js","sourceRoot":"","sources":["../src/hash.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAGzC,oIAAoI;AACpI,MAAM,UAAU,aAAa,CAAC,KAAc;IAC1C,OAAO,IAAI,CAAC,SAAS,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC,CAAC;AAC7C,CAAC;AAED,2FAA2F;AAC3F,MAAM,UAAU,YAAY,CAAC,KAAc;IACzC,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;IACzD,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;QAChD,MAAM,MAAM,GAAG,KAAgC,CAAC;QAChD,MAAM,GAAG,GAA4B,EAAE,CAAC;QACxC,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC;YAC7C,IAAI,MAAM,CAAC,GAAG,CAAC,KAAK,SAAS;gBAAE,GAAG,CAAC,GAAG,CAAC,GAAG,YAAY,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;QACtE,CAAC;QACD,OAAO,GAAG,CAAC;IACb,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,iFAAiF;AACjF,MAAM,UAAU,SAAS,CAAC,KAA0B;IAClD,OAAO,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AAC1D,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,SAAS,CAAC,KAAY;IACpC,MAAM,OAAO,GAAG,CAAC,GAAG,KAAK,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE;QAC5D,MAAM,QAAQ,GAAG,KAAK,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACzC,IAAI,QAAQ,KAAK,SAAS;YAAE,MAAM,IAAI,KAAK,CAAC,yBAAyB,EAAE,EAAE,CAAC,CAAC;QAC3E,MAAM,KAAK,GAAwC,EAAE,CAAC;QACtD,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC;YAC3C,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAC9B,IAAI,IAAI,KAAK,SAAS;gBAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;;gBAChD,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAC1B,CAAC;QACD,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,IAAI,CAAC,KAAK,CAAe;YAAE,KAAK,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,CAAC;QACzE,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,QAAQ,CAAC,IAAI,CAAC,IAAI,EAAE,UAAU,EAAE,QAAQ,CAAC,UAAU,EAAE,KAAK,EAAE,CAAC;IAClF,CAAC,CAAC,CAAC;IACH,OAAO,SAAS,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC,CAAC;AAC3C,CAAC"}
|
package/dist/impact.d.ts
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { Edge, Graph, ImpactReport } from "./types.ts";
|
|
2
|
+
/** Core §10: the reason recorded for one step, a sentence read from the authored edge's source. */
|
|
3
|
+
export declare function reasonFor(edge: Edge): string;
|
|
4
|
+
/** Core §10: the impact report for an artifact. An ID not in the graph yields an empty report. */
|
|
5
|
+
export declare function impact(graph: Graph, id: string): ImpactReport;
|
|
6
|
+
//# sourceMappingURL=impact.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"impact.d.ts","sourceRoot":"","sources":["../src/impact.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,IAAI,EAAE,KAAK,EAAa,YAAY,EAAwB,MAAM,YAAY,CAAC;AAoB7F,mGAAmG;AACnG,wBAAgB,SAAS,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,CAE5C;AAED,kGAAkG;AAClG,wBAAgB,MAAM,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE,EAAE,MAAM,GAAG,YAAY,CA+C7D"}
|
package/dist/impact.js
ADDED
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Impact traversal (Core §10). From a starting ID, the artifacts one
|
|
3
|
+
* derived edge away are direct; everything reachable beyond them by further
|
|
4
|
+
* reverse traversal, with a visited set, is a candidate; the start's own
|
|
5
|
+
* rules, contracts and decisions are review context; navigation ancestors
|
|
6
|
+
* come through `parent`. Each hit carries the path that reached it, with a
|
|
7
|
+
* reason sentence per step. Reachability is recorded, never asserted as
|
|
8
|
+
* proof that runtime behavior changed.
|
|
9
|
+
*/
|
|
10
|
+
import { compareStrings } from "./report.js";
|
|
11
|
+
const PHRASES = {
|
|
12
|
+
parent: "has {to} as its navigation parent",
|
|
13
|
+
governedBy: "is governed by {to}",
|
|
14
|
+
illustrates: "illustrates {to}",
|
|
15
|
+
implements: "implements {to}",
|
|
16
|
+
dependsOn: "depends on {to}",
|
|
17
|
+
exposes: "exposes {to}",
|
|
18
|
+
consumes: "consumes {to}",
|
|
19
|
+
verifies: "verifies {to}",
|
|
20
|
+
explains: "explains {to}",
|
|
21
|
+
informedBy: "is informed by {to}",
|
|
22
|
+
requires: "requires {to}",
|
|
23
|
+
supports: "supports {to}",
|
|
24
|
+
replacedBy: "is replaced by {to}",
|
|
25
|
+
};
|
|
26
|
+
const CONTEXT_KINDS = ["governedBy", "exposes", "consumes", "informedBy"];
|
|
27
|
+
/** Core §10: the reason recorded for one step, a sentence read from the authored edge's source. */
|
|
28
|
+
export function reasonFor(edge) {
|
|
29
|
+
return `${edge.from} ${PHRASES[edge.kind].replace("{to}", edge.to)}.`;
|
|
30
|
+
}
|
|
31
|
+
/** Core §10: the impact report for an artifact. An ID not in the graph yields an empty report. */
|
|
32
|
+
export function impact(graph, id) {
|
|
33
|
+
const report = { start: id, direct: [], candidates: [], context: [], ancestors: [] };
|
|
34
|
+
if (!graph.artifacts.has(id))
|
|
35
|
+
return report;
|
|
36
|
+
const paths = new Map();
|
|
37
|
+
const queue = [id];
|
|
38
|
+
paths.set(id, []);
|
|
39
|
+
while (queue.length > 0) {
|
|
40
|
+
const current = queue.shift();
|
|
41
|
+
const sofar = paths.get(current);
|
|
42
|
+
const arriving = [...(graph.in.get(current) ?? [])].sort((a, b) => compareStrings(a.from, b.from) || compareStrings(a.kind, b.kind));
|
|
43
|
+
for (const edge of arriving) {
|
|
44
|
+
if (paths.has(edge.from))
|
|
45
|
+
continue;
|
|
46
|
+
paths.set(edge.from, [...sofar, { id: edge.from, via: `${edge.kind}←`, reason: reasonFor(edge) }]);
|
|
47
|
+
queue.push(edge.from);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
for (const hitId of [...paths.keys()].sort(compareStrings)) {
|
|
51
|
+
if (hitId === id)
|
|
52
|
+
continue;
|
|
53
|
+
const path = paths.get(hitId);
|
|
54
|
+
const hit = toHit(graph, hitId, path);
|
|
55
|
+
if (hit === null)
|
|
56
|
+
continue;
|
|
57
|
+
if (path.length === 1)
|
|
58
|
+
report.direct.push(hit);
|
|
59
|
+
else
|
|
60
|
+
report.candidates.push(hit);
|
|
61
|
+
}
|
|
62
|
+
const contextEdges = (graph.out.get(id) ?? [])
|
|
63
|
+
.filter((edge) => CONTEXT_KINDS.includes(edge.kind) && graph.artifacts.has(edge.to))
|
|
64
|
+
.sort((a, b) => compareStrings(a.to, b.to) || compareStrings(a.kind, b.kind));
|
|
65
|
+
const seenContext = new Set();
|
|
66
|
+
for (const edge of contextEdges) {
|
|
67
|
+
if (seenContext.has(edge.to))
|
|
68
|
+
continue;
|
|
69
|
+
seenContext.add(edge.to);
|
|
70
|
+
const hit = toHit(graph, edge.to, [{ id: edge.to, via: `${edge.kind}→`, reason: reasonFor(edge) }]);
|
|
71
|
+
if (hit !== null)
|
|
72
|
+
report.context.push(hit);
|
|
73
|
+
}
|
|
74
|
+
const visited = new Set([id]);
|
|
75
|
+
let cursor = graph.artifacts.get(id)?.meta.parent;
|
|
76
|
+
while (cursor !== undefined && !visited.has(cursor) && graph.artifacts.has(cursor)) {
|
|
77
|
+
visited.add(cursor);
|
|
78
|
+
report.ancestors.push(cursor);
|
|
79
|
+
cursor = graph.artifacts.get(cursor)?.meta.parent;
|
|
80
|
+
}
|
|
81
|
+
return report;
|
|
82
|
+
}
|
|
83
|
+
function toHit(graph, id, path) {
|
|
84
|
+
const artifact = graph.artifacts.get(id);
|
|
85
|
+
if (artifact === undefined)
|
|
86
|
+
return null;
|
|
87
|
+
return { id, type: artifact.meta.type, title: artifact.meta.title, path };
|
|
88
|
+
}
|
|
89
|
+
//# sourceMappingURL=impact.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"impact.js","sourceRoot":"","sources":["../src/impact.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export * from "./artifact.ts";
|
|
2
|
+
export * from "./carrier.ts";
|
|
3
|
+
export * from "./config.ts";
|
|
4
|
+
export * from "./context.ts";
|
|
5
|
+
export * from "./diagnostics.ts";
|
|
6
|
+
export * from "./export.ts";
|
|
7
|
+
export * from "./graph.ts";
|
|
8
|
+
export * from "./hash.ts";
|
|
9
|
+
export * from "./impact.ts";
|
|
10
|
+
export * from "./registries.ts";
|
|
11
|
+
export * from "./types.ts";
|
|
12
|
+
export * from "./validate.ts";
|
|
13
|
+
export * from "./yaml.ts";
|
|
14
|
+
export { compareStrings } from "./report.ts";
|
|
15
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,eAAe,CAAC;AAC9B,cAAc,cAAc,CAAC;AAC7B,cAAc,aAAa,CAAC;AAC5B,cAAc,cAAc,CAAC;AAC7B,cAAc,kBAAkB,CAAC;AACjC,cAAc,aAAa,CAAC;AAC5B,cAAc,YAAY,CAAC;AAC3B,cAAc,WAAW,CAAC;AAC1B,cAAc,aAAa,CAAC;AAC5B,cAAc,iBAAiB,CAAC;AAChC,cAAc,YAAY,CAAC;AAC3B,cAAc,eAAe,CAAC;AAC9B,cAAc,WAAW,CAAC;AAC1B,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export * from "./artifact.js";
|
|
2
|
+
export * from "./carrier.js";
|
|
3
|
+
export * from "./config.js";
|
|
4
|
+
export * from "./context.js";
|
|
5
|
+
export * from "./diagnostics.js";
|
|
6
|
+
export * from "./export.js";
|
|
7
|
+
export * from "./graph.js";
|
|
8
|
+
export * from "./hash.js";
|
|
9
|
+
export * from "./impact.js";
|
|
10
|
+
export * from "./registries.js";
|
|
11
|
+
export * from "./types.js";
|
|
12
|
+
export * from "./validate.js";
|
|
13
|
+
export * from "./yaml.js";
|
|
14
|
+
export { compareStrings } from "./report.js";
|
|
15
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,eAAe,CAAC;AAC9B,cAAc,cAAc,CAAC;AAC7B,cAAc,aAAa,CAAC;AAC5B,cAAc,cAAc,CAAC;AAC7B,cAAc,kBAAkB,CAAC;AACjC,cAAc,aAAa,CAAC;AAC5B,cAAc,YAAY,CAAC;AAC3B,cAAc,WAAW,CAAC;AAC1B,cAAc,aAAa,CAAC;AAC5B,cAAc,iBAAiB,CAAC;AAChC,cAAc,YAAY,CAAC;AAC3B,cAAc,eAAe,CAAC;AAC9B,cAAc,WAAW,CAAC;AAC1B,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The repository registries (Core §4, §7; VSA §3): owners, audiences, the
|
|
3
|
+
* four release dimensions, and the shared-resource inventory. The file is
|
|
4
|
+
* `registries.yaml` in the shape of examples/scheduling/registries.yaml.
|
|
5
|
+
* A missing or empty file is empty registries, which the validator reads as
|
|
6
|
+
* "not declared" rather than "nothing allowed".
|
|
7
|
+
*/
|
|
8
|
+
import type { Diagnostic } from "./diagnostics.ts";
|
|
9
|
+
import { type Registries } from "./types.ts";
|
|
10
|
+
/**
|
|
11
|
+
* Core §4 and §7, VSA §3: read registries.yaml. Shape problems are CFG002
|
|
12
|
+
* (origin "profile"); a YAML rejection is CFG002, also with origin "profile" (origin "syntax" is Markset's alone). Every
|
|
13
|
+
* list comes back sorted. `null` text means the file is absent.
|
|
14
|
+
*/
|
|
15
|
+
export declare function readRegistries(text: string | null, path: string): {
|
|
16
|
+
registries: Registries;
|
|
17
|
+
diagnostics: Diagnostic[];
|
|
18
|
+
};
|
|
19
|
+
//# sourceMappingURL=registries.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registries.d.ts","sourceRoot":"","sources":["../src/registries.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAEnD,OAAO,EAAgC,KAAK,UAAU,EAAiB,MAAM,YAAY,CAAC;AAM1F;;;;GAIG;AACH,wBAAgB,cAAc,CAC5B,IAAI,EAAE,MAAM,GAAG,IAAI,EACnB,IAAI,EAAE,MAAM,GACX;IAAE,UAAU,EAAE,UAAU,CAAC;IAAC,WAAW,EAAE,UAAU,EAAE,CAAA;CAAE,CAwEvD"}
|