@intentset/cli 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/commands/architecture.d.ts +6 -0
- package/dist/commands/architecture.d.ts.map +1 -0
- package/dist/commands/architecture.js +65 -0
- package/dist/commands/architecture.js.map +1 -0
- package/dist/commands/context.d.ts +4 -0
- package/dist/commands/context.d.ts.map +1 -0
- package/dist/commands/context.js +124 -0
- package/dist/commands/context.js.map +1 -0
- package/dist/commands/evidence.d.ts +29 -0
- package/dist/commands/evidence.d.ts.map +1 -0
- package/dist/commands/evidence.js +157 -0
- package/dist/commands/evidence.js.map +1 -0
- package/dist/commands/graph.d.ts +18 -0
- package/dist/commands/graph.d.ts.map +1 -0
- package/dist/commands/graph.js +77 -0
- package/dist/commands/graph.js.map +1 -0
- package/dist/commands/impact.d.ts +20 -0
- package/dist/commands/impact.d.ts.map +1 -0
- package/dist/commands/impact.js +92 -0
- package/dist/commands/impact.js.map +1 -0
- package/dist/commands/init.d.ts +18 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +122 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/mcp.d.ts +24 -0
- package/dist/commands/mcp.d.ts.map +1 -0
- package/dist/commands/mcp.js +122 -0
- package/dist/commands/mcp.js.map +1 -0
- package/dist/commands/publish.d.ts +19 -0
- package/dist/commands/publish.d.ts.map +1 -0
- package/dist/commands/publish.js +98 -0
- package/dist/commands/publish.js.map +1 -0
- package/dist/commands/review.d.ts +29 -0
- package/dist/commands/review.d.ts.map +1 -0
- package/dist/commands/review.js +147 -0
- package/dist/commands/review.js.map +1 -0
- package/dist/commands/serve.d.ts +14 -0
- package/dist/commands/serve.d.ts.map +1 -0
- package/dist/commands/serve.js +246 -0
- package/dist/commands/serve.js.map +1 -0
- package/dist/commands/shared.d.ts +19 -0
- package/dist/commands/shared.d.ts.map +1 -0
- package/dist/commands/shared.js +43 -0
- package/dist/commands/shared.js.map +1 -0
- package/dist/commands/validate.d.ts +11 -0
- package/dist/commands/validate.d.ts.map +1 -0
- package/dist/commands/validate.js +38 -0
- package/dist/commands/validate.js.map +1 -0
- package/dist/git.d.ts +25 -0
- package/dist/git.d.ts.map +1 -0
- package/dist/git.js +63 -0
- package/dist/git.js.map +1 -0
- package/dist/glob.d.ts +16 -0
- package/dist/glob.d.ts.map +1 -0
- package/dist/glob.js +60 -0
- package/dist/glob.js.map +1 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +8 -0
- package/dist/index.js.map +1 -0
- package/dist/intentset.d.ts +3 -0
- package/dist/intentset.d.ts.map +1 -0
- package/dist/intentset.js +15 -0
- package/dist/intentset.js.map +1 -0
- package/dist/main.d.ts +5 -0
- package/dist/main.d.ts.map +1 -0
- package/dist/main.js +406 -0
- package/dist/main.js.map +1 -0
- package/dist/output.d.ts +38 -0
- package/dist/output.d.ts.map +1 -0
- package/dist/output.js +53 -0
- package/dist/output.js.map +1 -0
- package/dist/outputs.d.ts +17 -0
- package/dist/outputs.d.ts.map +1 -0
- package/dist/outputs.js +70 -0
- package/dist/outputs.js.map +1 -0
- package/dist/reports.d.ts +16 -0
- package/dist/reports.d.ts.map +1 -0
- package/dist/reports.js +89 -0
- package/dist/reports.js.map +1 -0
- package/dist/repository.d.ts +56 -0
- package/dist/repository.d.ts.map +1 -0
- package/dist/repository.js +191 -0
- package/dist/repository.js.map +1 -0
- package/dist/session.d.ts +61 -0
- package/dist/session.d.ts.map +1 -0
- package/dist/session.js +202 -0
- package/dist/session.js.map +1 -0
- package/dist/tree.d.ts +15 -0
- package/dist/tree.d.ts.map +1 -0
- package/dist/tree.js +56 -0
- package/dist/tree.js.map +1 -0
- package/package.json +46 -0
- package/src/commands/architecture.ts +77 -0
- package/src/commands/context.ts +142 -0
- package/src/commands/evidence.ts +180 -0
- package/src/commands/graph.ts +89 -0
- package/src/commands/impact.ts +97 -0
- package/src/commands/init.ts +138 -0
- package/src/commands/mcp.ts +143 -0
- package/src/commands/publish.ts +119 -0
- package/src/commands/review.ts +155 -0
- package/src/commands/serve.ts +261 -0
- package/src/commands/shared.ts +46 -0
- package/src/commands/validate.ts +39 -0
- package/src/git.ts +81 -0
- package/src/glob.ts +58 -0
- package/src/index.ts +8 -0
- package/src/intentset.ts +15 -0
- package/src/main.ts +408 -0
- package/src/output.ts +78 -0
- package/src/outputs.ts +65 -0
- package/src/reports.ts +103 -0
- package/src/repository.ts +220 -0
- package/src/session.ts +276 -0
- package/src/tree.ts +64 -0
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { type ArchitectureResult, type Mode } from "@intentset/architecture";
|
|
2
|
+
import { type Diagnostic, type Graph, type Level, type ValidationResult } from "@intentset/core";
|
|
3
|
+
import { type EvidenceCheck, type EvidenceSnapshot, type RunScope } from "@intentset/verification";
|
|
4
|
+
import { type Io, type Snapshot } from "./output.ts";
|
|
5
|
+
import { type CarrierName, type Repository } from "./repository.ts";
|
|
6
|
+
import { type Tree } from "./tree.ts";
|
|
7
|
+
/** Where run records are read from when no --evidence is given. Local output: not to be committed. */
|
|
8
|
+
export declare const EVIDENCE_DIR = ".intentset/evidence";
|
|
9
|
+
export interface SessionOptions {
|
|
10
|
+
root?: string;
|
|
11
|
+
carrier: CarrierName;
|
|
12
|
+
level: Level;
|
|
13
|
+
/** L2 and above: architecture mode and baseline. */
|
|
14
|
+
mode?: Mode;
|
|
15
|
+
baseline?: string;
|
|
16
|
+
/** L3 and above: evidence files as given (relative to cwd); undefined reads EVIDENCE_DIR. */
|
|
17
|
+
evidence?: string[];
|
|
18
|
+
/** L3 and above: the exact product and release evidence is assessed for; null considers every scope. */
|
|
19
|
+
scope?: RunScope | null;
|
|
20
|
+
/** The day exceptions expire against; default today, UTC. */
|
|
21
|
+
today?: string;
|
|
22
|
+
}
|
|
23
|
+
export interface EvidenceRun {
|
|
24
|
+
/** The files read, as repository-relative paths where they lie inside the root. */
|
|
25
|
+
files: string[];
|
|
26
|
+
records: number;
|
|
27
|
+
check: EvidenceCheck;
|
|
28
|
+
snapshot: EvidenceSnapshot;
|
|
29
|
+
}
|
|
30
|
+
export interface Session {
|
|
31
|
+
repo: Repository;
|
|
32
|
+
level: Level;
|
|
33
|
+
/** Core's result with every level's diagnostics folded in, so `ok` and the export carry them all. */
|
|
34
|
+
result: ValidationResult;
|
|
35
|
+
diagnostics: Diagnostic[];
|
|
36
|
+
errors: number;
|
|
37
|
+
warnings: number;
|
|
38
|
+
snapshot: Snapshot;
|
|
39
|
+
tree?: Tree;
|
|
40
|
+
architecture?: ArchitectureResult;
|
|
41
|
+
evidence?: EvidenceRun;
|
|
42
|
+
/** L4: the active knowledge artifacts checked for publication readiness, by ID. */
|
|
43
|
+
publication?: {
|
|
44
|
+
checked: string[];
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
/** Load and check at the level, or return the exit code (2) after reporting why the repository could not be read. */
|
|
48
|
+
export declare function openSession(command: string, options: SessionOptions, io: Io): Session | number;
|
|
49
|
+
/** The evidence files to read: those given, else every `*.json` in EVIDENCE_DIR, sorted. Absolute paths. */
|
|
50
|
+
export declare function evidenceFiles(root: string, cwd: string, given: string[] | undefined): string[];
|
|
51
|
+
/**
|
|
52
|
+
* Core §9 and §11 at L4: every knowledge artifact that is neither draft nor
|
|
53
|
+
* retired is current against the sources it was reviewed against, and says
|
|
54
|
+
* where it applies. Anything else is CORE008, because it could not be
|
|
55
|
+
* published as current.
|
|
56
|
+
*/
|
|
57
|
+
export declare function publicationReadiness(graph: Graph): {
|
|
58
|
+
checked: string[];
|
|
59
|
+
diagnostics: Diagnostic[];
|
|
60
|
+
};
|
|
61
|
+
//# sourceMappingURL=session.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../src/session.ts"],"names":[],"mappings":"AAgBA,OAAO,EACL,KAAK,kBAAkB,EAGvB,KAAK,IAAI,EAEV,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAGL,KAAK,UAAU,EACf,KAAK,KAAK,EAIV,KAAK,KAAK,EAEV,KAAK,gBAAgB,EAEtB,MAAM,iBAAiB,CAAC;AAEzB,OAAO,EAEL,KAAK,aAAa,EAClB,KAAK,gBAAgB,EAErB,KAAK,QAAQ,EAEd,MAAM,yBAAyB,CAAC;AAEjC,OAAO,EAAoB,KAAK,EAAE,EAAE,KAAK,QAAQ,EAAE,MAAM,aAAa,CAAC;AACvE,OAAO,EAAE,KAAK,WAAW,EAAyC,KAAK,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC3G,OAAO,EAAY,KAAK,IAAI,EAAE,MAAM,WAAW,CAAC;AAEhD,sGAAsG;AACtG,eAAO,MAAM,YAAY,wBAAwB,CAAC;AAElD,MAAM,WAAW,cAAc;IAC7B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,WAAW,CAAC;IACrB,KAAK,EAAE,KAAK,CAAC;IACb,oDAAoD;IACpD,IAAI,CAAC,EAAE,IAAI,CAAC;IACZ,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,6FAA6F;IAC7F,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,wGAAwG;IACxG,KAAK,CAAC,EAAE,QAAQ,GAAG,IAAI,CAAC;IACxB,6DAA6D;IAC7D,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,WAAW;IAC1B,mFAAmF;IACnF,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,aAAa,CAAC;IACrB,QAAQ,EAAE,gBAAgB,CAAC;CAC5B;AAED,MAAM,WAAW,OAAO;IACtB,IAAI,EAAE,UAAU,CAAC;IACjB,KAAK,EAAE,KAAK,CAAC;IACb,qGAAqG;IACrG,MAAM,EAAE,gBAAgB,CAAC;IACzB,WAAW,EAAE,UAAU,EAAE,CAAC;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,QAAQ,CAAC;IACnB,IAAI,CAAC,EAAE,IAAI,CAAC;IACZ,YAAY,CAAC,EAAE,kBAAkB,CAAC;IAClC,QAAQ,CAAC,EAAE,WAAW,CAAC;IACvB,mFAAmF;IACnF,WAAW,CAAC,EAAE;QAAE,OAAO,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC;CACrC;AAID,qHAAqH;AACrH,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,cAAc,EAAE,EAAE,EAAE,EAAE,GAAG,OAAO,GAAG,MAAM,CAsG9F;AAiBD,4GAA4G;AAC5G,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,SAAS,GAAG,MAAM,EAAE,CAQ9F;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,KAAK,GAAG;IAAE,OAAO,EAAE,MAAM,EAAE,CAAC;IAAC,WAAW,EAAE,UAAU,EAAE,CAAA;CAAE,CA4CnG"}
|
package/dist/session.js
ADDED
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The shared front half of every reading command: find the root, load the
|
|
3
|
+
* repository, and run every check the requested level asks for, each level
|
|
4
|
+
* including the ones below it (Core §11):
|
|
5
|
+
*
|
|
6
|
+
* L1 core: parse, identity, fields, typed links, hierarchy, lifecycle, narrative
|
|
7
|
+
* L2 + ownership (core) and the architecture check over the repository tree
|
|
8
|
+
* L3 + run records classified against this snapshot, and current-pass coverage
|
|
9
|
+
* L4 + publication readiness: active knowledge is review-current and carries availability
|
|
10
|
+
* L5 is a claim about continuous CI, which one run cannot check; main refuses it
|
|
11
|
+
*
|
|
12
|
+
* Returns an exit code instead when the command cannot proceed, having said
|
|
13
|
+
* why. Nothing here writes.
|
|
14
|
+
*/
|
|
15
|
+
import { existsSync, readdirSync, readFileSync } from "node:fs";
|
|
16
|
+
import { join, resolve } from "node:path";
|
|
17
|
+
import { checkArchitecture, parseBaseline, } from "@intentset/architecture";
|
|
18
|
+
import { compareStrings, graphHash, hasErrors, LEVELS, sortDiagnostics, validate, } from "@intentset/core";
|
|
19
|
+
import { reviewStatus } from "@intentset/publisher";
|
|
20
|
+
import { checkEvidence, readRunRecords, } from "@intentset/verification";
|
|
21
|
+
import { insideRoot } from "./outputs.js";
|
|
22
|
+
import { formatDiagnostic } from "./output.js";
|
|
23
|
+
import { CONFIG_PATH, findRoot, loadRepository } from "./repository.js";
|
|
24
|
+
import { readTree } from "./tree.js";
|
|
25
|
+
/** Where run records are read from when no --evidence is given. Local output: not to be committed. */
|
|
26
|
+
export const EVIDENCE_DIR = ".intentset/evidence";
|
|
27
|
+
const at = (level, floor) => LEVELS.indexOf(level) >= LEVELS.indexOf(floor);
|
|
28
|
+
/** Load and check at the level, or return the exit code (2) after reporting why the repository could not be read. */
|
|
29
|
+
export function openSession(command, options, io) {
|
|
30
|
+
const root = findRoot(io.cwd, options.root);
|
|
31
|
+
if (root === null) {
|
|
32
|
+
const where = options.root === undefined ? "this directory or any above it" : options.root;
|
|
33
|
+
io.stderr(`intentset ${command}: no ${CONFIG_PATH} in ${where}.\n` +
|
|
34
|
+
"Run `intentset init` at the repository root to create one, or pass --root <dir>.\n");
|
|
35
|
+
return 2;
|
|
36
|
+
}
|
|
37
|
+
const repo = loadRepository(root, options.carrier);
|
|
38
|
+
if (!repo.configOk) {
|
|
39
|
+
io.stderr(`intentset ${command}: the configuration has errors, so the scope is unknown.\n`);
|
|
40
|
+
for (const d of sortDiagnostics(repo.diagnostics))
|
|
41
|
+
io.stderr(formatDiagnostic(d));
|
|
42
|
+
return 2;
|
|
43
|
+
}
|
|
44
|
+
const level = options.level;
|
|
45
|
+
const validated = validate(repo.inputs, repo.registries, { level });
|
|
46
|
+
const graph = validated.graph;
|
|
47
|
+
const snapshot = { commit: repo.commit, graphHash: graphHash(graph) };
|
|
48
|
+
if (repo.commitUnavailable !== undefined)
|
|
49
|
+
snapshot.commitUnavailable = repo.commitUnavailable;
|
|
50
|
+
if (repo.uncommitted === true)
|
|
51
|
+
snapshot.uncommitted = true;
|
|
52
|
+
const all = [...validated.diagnostics, ...repo.diagnostics];
|
|
53
|
+
const session = { repo, level, snapshot };
|
|
54
|
+
if (at(level, "L2")) {
|
|
55
|
+
let baseline = [];
|
|
56
|
+
if (options.baseline !== undefined) {
|
|
57
|
+
const read = readBaseline(resolve(io.cwd, options.baseline));
|
|
58
|
+
if (typeof read === "string") {
|
|
59
|
+
io.stderr(`intentset ${command}: --baseline ${options.baseline}: ${read}\n`);
|
|
60
|
+
return 2;
|
|
61
|
+
}
|
|
62
|
+
baseline = read;
|
|
63
|
+
}
|
|
64
|
+
const tree = readTree(root, repo.config);
|
|
65
|
+
const architecture = checkArchitecture(graph, repo.registries, { files: tree.files }, {
|
|
66
|
+
level,
|
|
67
|
+
mode: options.mode ?? "migration",
|
|
68
|
+
baseline,
|
|
69
|
+
today: options.today ?? new Date().toISOString().slice(0, 10),
|
|
70
|
+
...(repo.config.registries === null ? {} : { registriesPath: repo.config.registries }),
|
|
71
|
+
});
|
|
72
|
+
session.tree = tree;
|
|
73
|
+
session.architecture = architecture;
|
|
74
|
+
all.push(...architecture.diagnostics);
|
|
75
|
+
}
|
|
76
|
+
if (at(level, "L3")) {
|
|
77
|
+
const files = evidenceFiles(root, io.cwd, options.evidence);
|
|
78
|
+
const records = [];
|
|
79
|
+
const seen = new Set();
|
|
80
|
+
const shown = [];
|
|
81
|
+
for (const file of files) {
|
|
82
|
+
const path = insideRoot(root, file) ?? file;
|
|
83
|
+
let json;
|
|
84
|
+
try {
|
|
85
|
+
json = JSON.parse(readFileSync(file, "utf8"));
|
|
86
|
+
}
|
|
87
|
+
catch (error) {
|
|
88
|
+
io.stderr(`intentset ${command}: evidence ${path} is not readable JSON: ${error.message}\n`);
|
|
89
|
+
return 2;
|
|
90
|
+
}
|
|
91
|
+
const read = readRunRecords(json, path);
|
|
92
|
+
all.push(...read.diagnostics);
|
|
93
|
+
// The same record imported into two files is one run, not two.
|
|
94
|
+
for (const record of read.records) {
|
|
95
|
+
const key = JSON.stringify(record);
|
|
96
|
+
if (seen.has(key))
|
|
97
|
+
continue;
|
|
98
|
+
seen.add(key);
|
|
99
|
+
records.push(record);
|
|
100
|
+
}
|
|
101
|
+
shown.push(path);
|
|
102
|
+
}
|
|
103
|
+
const evidenceSnapshot = {
|
|
104
|
+
commit: snapshot.commit,
|
|
105
|
+
graphHash: snapshot.graphHash,
|
|
106
|
+
scope: options.scope ?? null,
|
|
107
|
+
};
|
|
108
|
+
const check = checkEvidence(graph, records, evidenceSnapshot, {
|
|
109
|
+
level,
|
|
110
|
+
files: session.tree?.paths,
|
|
111
|
+
evidencePath: shown.length === 1 ? shown[0] : null,
|
|
112
|
+
});
|
|
113
|
+
session.evidence = { files: shown, records: records.length, check, snapshot: evidenceSnapshot };
|
|
114
|
+
all.push(...check.diagnostics);
|
|
115
|
+
}
|
|
116
|
+
if (at(level, "L4")) {
|
|
117
|
+
const readiness = publicationReadiness(graph);
|
|
118
|
+
session.publication = { checked: readiness.checked };
|
|
119
|
+
all.push(...readiness.diagnostics);
|
|
120
|
+
}
|
|
121
|
+
const diagnostics = sortDiagnostics(all);
|
|
122
|
+
const errors = diagnostics.filter((d) => d.severity === "error").length;
|
|
123
|
+
const result = { graph, diagnostics, ok: !hasErrors(diagnostics) };
|
|
124
|
+
return { ...session, result, diagnostics, errors, warnings: diagnostics.length - errors };
|
|
125
|
+
}
|
|
126
|
+
/** A baseline file's entries, or why it could not be read. */
|
|
127
|
+
function readBaseline(file) {
|
|
128
|
+
let text;
|
|
129
|
+
try {
|
|
130
|
+
text = readFileSync(file, "utf8");
|
|
131
|
+
}
|
|
132
|
+
catch (error) {
|
|
133
|
+
return `could not be read: ${error.message}`;
|
|
134
|
+
}
|
|
135
|
+
try {
|
|
136
|
+
return parseBaseline(text);
|
|
137
|
+
}
|
|
138
|
+
catch (error) {
|
|
139
|
+
return error.message;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
/** The evidence files to read: those given, else every `*.json` in EVIDENCE_DIR, sorted. Absolute paths. */
|
|
143
|
+
export function evidenceFiles(root, cwd, given) {
|
|
144
|
+
if (given !== undefined && given.length > 0)
|
|
145
|
+
return given.map((file) => resolve(cwd, file));
|
|
146
|
+
const dir = join(root, EVIDENCE_DIR);
|
|
147
|
+
if (!existsSync(dir))
|
|
148
|
+
return [];
|
|
149
|
+
return readdirSync(dir)
|
|
150
|
+
.filter((name) => name.endsWith(".json"))
|
|
151
|
+
.sort(compareStrings)
|
|
152
|
+
.map((name) => join(dir, name));
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* Core §9 and §11 at L4: every knowledge artifact that is neither draft nor
|
|
156
|
+
* retired is current against the sources it was reviewed against, and says
|
|
157
|
+
* where it applies. Anything else is CORE008, because it could not be
|
|
158
|
+
* published as current.
|
|
159
|
+
*/
|
|
160
|
+
export function publicationReadiness(graph) {
|
|
161
|
+
const checked = [];
|
|
162
|
+
const diagnostics = [];
|
|
163
|
+
for (const id of [...graph.artifacts.keys()].sort(compareStrings)) {
|
|
164
|
+
const artifact = graph.artifacts.get(id);
|
|
165
|
+
const { meta } = artifact;
|
|
166
|
+
if (meta.type !== "knowledge" || meta.status === "draft" || meta.status === "retired")
|
|
167
|
+
continue;
|
|
168
|
+
checked.push(id);
|
|
169
|
+
const report = (field, message, remediation) => diagnostics.push({
|
|
170
|
+
code: "CORE008",
|
|
171
|
+
severity: "error",
|
|
172
|
+
origin: "publication",
|
|
173
|
+
artifact: id,
|
|
174
|
+
path: artifact.path,
|
|
175
|
+
field,
|
|
176
|
+
message,
|
|
177
|
+
remediation,
|
|
178
|
+
});
|
|
179
|
+
if (meta.availability === undefined) {
|
|
180
|
+
report("/intentset/availability", `${meta.status} knowledge ${id} has no availability, so no release could publish it (Core §7: missing access information fails closed).`, "Add availability with the products, releases, roles, editions and flags the guidance applies to.");
|
|
181
|
+
}
|
|
182
|
+
const review = reviewStatus(graph, artifact);
|
|
183
|
+
if (review.status === "current")
|
|
184
|
+
continue;
|
|
185
|
+
const reasons = [];
|
|
186
|
+
if (review.changed.length > 0)
|
|
187
|
+
reasons.push(`${review.changed.join(", ")} changed since review`);
|
|
188
|
+
if (review.missing.length > 0)
|
|
189
|
+
reasons.push(`no review pin for ${review.missing.join(", ")}`);
|
|
190
|
+
if (review.reviewer === null)
|
|
191
|
+
reasons.push("it names no reviewer");
|
|
192
|
+
if (review.reviewedAt === null)
|
|
193
|
+
reasons.push("it gives no review date");
|
|
194
|
+
report(review.reviewer === null
|
|
195
|
+
? "/intentset/reviewedBy"
|
|
196
|
+
: review.reviewedAt === null
|
|
197
|
+
? "/intentset/reviewedAt"
|
|
198
|
+
: "/intentset/extensions/intentset.org~1review", `${meta.status} knowledge ${id} needs review: ${reasons.join("; ")} (Core §9).`, "Review the knowledge against its current sources, then update reviewedBy, reviewedAt and the intentset.org/review pins (Core §9).");
|
|
199
|
+
}
|
|
200
|
+
return { checked, diagnostics };
|
|
201
|
+
}
|
|
202
|
+
//# sourceMappingURL=session.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session.js","sourceRoot":"","sources":["../src/session.ts"],"names":[],"mappings":"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"}
|
package/dist/tree.d.ts
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { Config } from "@intentset/core";
|
|
2
|
+
/** Extensions read as text: code the import graph needs, and the JSON, Markdown and YAML it and the claims name. */
|
|
3
|
+
export declare const TEXT_EXTENSIONS: string[];
|
|
4
|
+
/** The largest file read into the tree; Core §3 bounds what a tool reads, and a record has the same limit. */
|
|
5
|
+
export declare const TREE_MAX_BYTES: number;
|
|
6
|
+
export interface Tree {
|
|
7
|
+
/** Every path in the tree, with its text for code and configuration and "" for anything else. */
|
|
8
|
+
files: Map<string, string>;
|
|
9
|
+
/** Every path in the tree, for checks that only ask whether a file exists. */
|
|
10
|
+
paths: Set<string>;
|
|
11
|
+
/** Files with a text extension that were over the limit and not read, sorted. */
|
|
12
|
+
skipped: string[];
|
|
13
|
+
}
|
|
14
|
+
export declare function readTree(root: string, config: Pick<Config, "ignore">): Tree;
|
|
15
|
+
//# sourceMappingURL=tree.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tree.d.ts","sourceRoot":"","sources":["../src/tree.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AAG9C,oHAAoH;AACpH,eAAO,MAAM,eAAe,UAa3B,CAAC;AAEF,8GAA8G;AAC9G,eAAO,MAAM,cAAc,QAAc,CAAC;AAE1C,MAAM,WAAW,IAAI;IACnB,iGAAiG;IACjG,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC3B,8EAA8E;IAC9E,KAAK,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IACnB,iFAAiF;IACjF,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB;AAED,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,QAAQ,CAAC,GAAG,IAAI,CAoB3E"}
|
package/dist/tree.js
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The repository as the architecture and evidence checks see it: every file
|
|
3
|
+
* `listFiles` returns that neither `.intentset/config.yaml` nor
|
|
4
|
+
* `.intentset/architecture.yaml` ignores. Code and configuration carry their
|
|
5
|
+
* text; every other file (a stylesheet, an image, a font) is present with an
|
|
6
|
+
* empty text, so an import of it resolves to a file rather than to nothing.
|
|
7
|
+
* A text file over 1 MiB is present but not read, and the report lists it,
|
|
8
|
+
* rather than a check quietly seeing less than the tree holds.
|
|
9
|
+
*/
|
|
10
|
+
import { readFileSync, statSync } from "node:fs";
|
|
11
|
+
import { join } from "node:path";
|
|
12
|
+
import { ARCHITECTURE_CONFIG_PATH, readArchitectureConfig, resolveConfig } from "@intentset/architecture";
|
|
13
|
+
import { listFiles } from "./repository.js";
|
|
14
|
+
/** Extensions read as text: code the import graph needs, and the JSON, Markdown and YAML it and the claims name. */
|
|
15
|
+
export const TEXT_EXTENSIONS = [
|
|
16
|
+
".ts",
|
|
17
|
+
".tsx",
|
|
18
|
+
".mts",
|
|
19
|
+
".cts",
|
|
20
|
+
".js",
|
|
21
|
+
".jsx",
|
|
22
|
+
".mjs",
|
|
23
|
+
".cjs",
|
|
24
|
+
".json",
|
|
25
|
+
".md",
|
|
26
|
+
".yaml",
|
|
27
|
+
".yml",
|
|
28
|
+
];
|
|
29
|
+
/** The largest file read into the tree; Core §3 bounds what a tool reads, and a record has the same limit. */
|
|
30
|
+
export const TREE_MAX_BYTES = 1024 * 1024;
|
|
31
|
+
export function readTree(root, config) {
|
|
32
|
+
let ignore = resolveConfig().ignore;
|
|
33
|
+
try {
|
|
34
|
+
const text = readFileSync(join(root, ARCHITECTURE_CONFIG_PATH), "utf8");
|
|
35
|
+
ignore = resolveConfig(readArchitectureConfig(text).config).ignore;
|
|
36
|
+
}
|
|
37
|
+
catch {
|
|
38
|
+
// No architecture configuration: its default ignore list stands.
|
|
39
|
+
}
|
|
40
|
+
const files = new Map();
|
|
41
|
+
const skipped = [];
|
|
42
|
+
const paths = listFiles(root, [...config.ignore, ...ignore]);
|
|
43
|
+
for (const path of paths) {
|
|
44
|
+
const file = join(root, path);
|
|
45
|
+
if (!TEXT_EXTENSIONS.some((extension) => path.endsWith(extension)))
|
|
46
|
+
files.set(path, "");
|
|
47
|
+
else if (statSync(file).size > TREE_MAX_BYTES) {
|
|
48
|
+
skipped.push(path);
|
|
49
|
+
files.set(path, "");
|
|
50
|
+
}
|
|
51
|
+
else
|
|
52
|
+
files.set(path, readFileSync(file, "utf8"));
|
|
53
|
+
}
|
|
54
|
+
return { files, paths: new Set(paths), skipped };
|
|
55
|
+
}
|
|
56
|
+
//# sourceMappingURL=tree.js.map
|
package/dist/tree.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tree.js","sourceRoot":"","sources":["../src/tree.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AACjD,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,wBAAwB,EAAE,sBAAsB,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AAE1G,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAE5C,oHAAoH;AACpH,MAAM,CAAC,MAAM,eAAe,GAAG;IAC7B,KAAK;IACL,MAAM;IACN,MAAM;IACN,MAAM;IACN,KAAK;IACL,MAAM;IACN,MAAM;IACN,MAAM;IACN,OAAO;IACP,KAAK;IACL,OAAO;IACP,MAAM;CACP,CAAC;AAEF,8GAA8G;AAC9G,MAAM,CAAC,MAAM,cAAc,GAAG,IAAI,GAAG,IAAI,CAAC;AAW1C,MAAM,UAAU,QAAQ,CAAC,IAAY,EAAE,MAA8B;IACnE,IAAI,MAAM,GAAG,aAAa,EAAE,CAAC,MAAM,CAAC;IACpC,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,YAAY,CAAC,IAAI,CAAC,IAAI,EAAE,wBAAwB,CAAC,EAAE,MAAM,CAAC,CAAC;QACxE,MAAM,GAAG,aAAa,CAAC,sBAAsB,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC;IACrE,CAAC;IAAC,MAAM,CAAC;QACP,iEAAiE;IACnE,CAAC;IACD,MAAM,KAAK,GAAG,IAAI,GAAG,EAAkB,CAAC;IACxC,MAAM,OAAO,GAAa,EAAE,CAAC;IAC7B,MAAM,KAAK,GAAG,SAAS,CAAC,IAAI,EAAE,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,MAAM,CAAC,CAAC,CAAC;IAC7D,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;QAC9B,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC;YAAE,KAAK,CAAC,GAAG,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;aACnF,IAAI,QAAQ,CAAC,IAAI,CAAC,CAAC,IAAI,GAAG,cAAc,EAAE,CAAC;YAC9C,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACnB,KAAK,CAAC,GAAG,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;QACtB,CAAC;;YAAM,KAAK,CAAC,GAAG,CAAC,IAAI,EAAE,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC;IACrD,CAAC;IACD,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,GAAG,CAAC,KAAK,CAAC,EAAE,OAAO,EAAE,CAAC;AACnD,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@intentset/cli",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "The intentset command: validate, graph, architecture check, evidence, impact, review, publish, serve, context, mcp.",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"engines": {
|
|
8
|
+
"node": ">=22.18"
|
|
9
|
+
},
|
|
10
|
+
"repository": {
|
|
11
|
+
"type": "git",
|
|
12
|
+
"url": "git+https://github.com/intentset/intentset.git",
|
|
13
|
+
"directory": "packages/cli"
|
|
14
|
+
},
|
|
15
|
+
"homepage": "https://intentset.org/",
|
|
16
|
+
"publishConfig": {
|
|
17
|
+
"access": "public"
|
|
18
|
+
},
|
|
19
|
+
"files": [
|
|
20
|
+
"dist",
|
|
21
|
+
"src"
|
|
22
|
+
],
|
|
23
|
+
"exports": {
|
|
24
|
+
".": {
|
|
25
|
+
"intentset-source": "./src/index.ts",
|
|
26
|
+
"types": "./dist/index.d.ts",
|
|
27
|
+
"default": "./dist/index.js"
|
|
28
|
+
}
|
|
29
|
+
},
|
|
30
|
+
"bin": {
|
|
31
|
+
"intentset": "./dist/intentset.js"
|
|
32
|
+
},
|
|
33
|
+
"dependencies": {
|
|
34
|
+
"@intentset/core": "^0.1.0",
|
|
35
|
+
"@intentset/markset-adapter": "^0.1.0",
|
|
36
|
+
"@intentset/architecture": "^0.1.0",
|
|
37
|
+
"@intentset/verification": "^0.1.0",
|
|
38
|
+
"@intentset/publisher": "^0.1.0",
|
|
39
|
+
"@intentset/atlas": "^0.1.0",
|
|
40
|
+
"@intentset/mcp": "^0.1.0",
|
|
41
|
+
"@intentset/conformance-suite": "^0.1.0"
|
|
42
|
+
},
|
|
43
|
+
"devDependencies": {
|
|
44
|
+
"@modelcontextprotocol/sdk": "^1.32.0"
|
|
45
|
+
}
|
|
46
|
+
}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `intentset architecture check` (VSA §2, the profile's boundaries): claims,
|
|
3
|
+
* ownership, the import graph, layers, regions, resources, exceptions and,
|
|
4
|
+
* in migration mode, the baseline, over every file the configuration does
|
|
5
|
+
* not ignore. Diagnostics like validate's, then the summary with what was not
|
|
6
|
+
* checked and what is left to review. `--write-baseline` writes the one file
|
|
7
|
+
* it names. Nothing else is written.
|
|
8
|
+
*/
|
|
9
|
+
import { writeFileSync } from "node:fs";
|
|
10
|
+
import { resolve } from "node:path";
|
|
11
|
+
import { writeBaseline } from "@intentset/architecture";
|
|
12
|
+
import { count, formatDiagnostic, type Io, json, TOOL } from "../output.ts";
|
|
13
|
+
import { outputProblem } from "../outputs.ts";
|
|
14
|
+
import { architectureLines } from "../reports.ts";
|
|
15
|
+
import type { Session } from "../session.ts";
|
|
16
|
+
|
|
17
|
+
export function architectureCommand(
|
|
18
|
+
session: Session,
|
|
19
|
+
options: { writeBaseline?: string },
|
|
20
|
+
asJson: boolean,
|
|
21
|
+
io: Io,
|
|
22
|
+
): number {
|
|
23
|
+
const architecture = session.architecture;
|
|
24
|
+
if (architecture === undefined) throw new Error("architecture check opened a session below L2");
|
|
25
|
+
const diagnostics = architecture.diagnostics;
|
|
26
|
+
const errors = diagnostics.filter((d) => d.severity === "error").length;
|
|
27
|
+
const warnings = diagnostics.length - errors;
|
|
28
|
+
const outside = session.errors - errors;
|
|
29
|
+
|
|
30
|
+
if (options.writeBaseline !== undefined) {
|
|
31
|
+
const target = resolve(io.cwd, options.writeBaseline);
|
|
32
|
+
const problem = outputProblem(session.repo, target);
|
|
33
|
+
if (problem !== null) {
|
|
34
|
+
io.stderr(`intentset architecture check: --write-baseline ${options.writeBaseline} ${problem}; not written.\n`);
|
|
35
|
+
return 2;
|
|
36
|
+
}
|
|
37
|
+
const entries = writeBaseline(diagnostics);
|
|
38
|
+
try {
|
|
39
|
+
writeFileSync(target, `${JSON.stringify(entries, null, 2)}\n`);
|
|
40
|
+
} catch (error) {
|
|
41
|
+
io.stderr(
|
|
42
|
+
`intentset architecture check: could not write ${options.writeBaseline}: ${(error as Error).message}\n`,
|
|
43
|
+
);
|
|
44
|
+
return 2;
|
|
45
|
+
}
|
|
46
|
+
io.stderr(
|
|
47
|
+
`intentset architecture check: wrote ${count(entries.length, "baseline entry", "baseline entries")} to ${options.writeBaseline}\n`,
|
|
48
|
+
);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
if (asJson) {
|
|
52
|
+
io.stdout(
|
|
53
|
+
json({
|
|
54
|
+
tool: TOOL,
|
|
55
|
+
level: session.level,
|
|
56
|
+
snapshot: session.snapshot,
|
|
57
|
+
summary: architecture.summary,
|
|
58
|
+
skipped: session.tree?.skipped ?? [],
|
|
59
|
+
errors,
|
|
60
|
+
warnings,
|
|
61
|
+
diagnostics,
|
|
62
|
+
validation: { errorsOutsideArchitecture: outside },
|
|
63
|
+
}),
|
|
64
|
+
);
|
|
65
|
+
} else {
|
|
66
|
+
for (const d of diagnostics) io.stdout(formatDiagnostic(d));
|
|
67
|
+
const lines = [`${count(errors, "error")}, ${count(warnings, "warning")} from the architecture check`];
|
|
68
|
+
if (outside > 0) {
|
|
69
|
+
lines.push(
|
|
70
|
+
`Validation has ${count(outside, "other error")}, so the graph this checked may be incomplete; run \`intentset validate --level ${session.level}\`.`,
|
|
71
|
+
);
|
|
72
|
+
}
|
|
73
|
+
lines.push(...architectureLines(architecture, session.tree?.skipped ?? []));
|
|
74
|
+
io.stdout(`${lines.join("\n")}\n`);
|
|
75
|
+
}
|
|
76
|
+
return session.errors > 0 ? 1 : 0;
|
|
77
|
+
}
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `intentset context <ID>` (Core §10): the bounded context an engineer or an
|
|
3
|
+
* agent loads before changing implementation, from core's `contextFor`: for
|
|
4
|
+
* a behavior, its owning slice, rules, scenarios, verifications, the slice's
|
|
5
|
+
* contracts, the decisions, the knowledge explaining it and its navigation
|
|
6
|
+
* parents; for a rule, capability or slice the bundles of the behaviors it
|
|
7
|
+
* reaches; for anything else its direct neighbours. Each artifact comes with
|
|
8
|
+
* its source path and body, and the whole names its snapshot.
|
|
9
|
+
*
|
|
10
|
+
* `restricted` artifacts are withheld unless asked for, and the report says
|
|
11
|
+
* how many, so a short context never reads as a complete one. Never writes.
|
|
12
|
+
*/
|
|
13
|
+
import {
|
|
14
|
+
type Artifact,
|
|
15
|
+
type ContextArtifact,
|
|
16
|
+
type ContextRole,
|
|
17
|
+
compareStrings,
|
|
18
|
+
contextFor,
|
|
19
|
+
type Graph,
|
|
20
|
+
type LinkKind,
|
|
21
|
+
} from "@intentset/core";
|
|
22
|
+
import { count, formatDiagnostic, type Io, json, snapshotLine, TOOL } from "../output.ts";
|
|
23
|
+
import type { Session } from "../session.ts";
|
|
24
|
+
import { unresolved, validationLine, validationSummary } from "./shared.ts";
|
|
25
|
+
|
|
26
|
+
const HEADINGS: Record<ContextRole, string> = {
|
|
27
|
+
start: "Start",
|
|
28
|
+
owner: "Owning slice",
|
|
29
|
+
behavior: "Behaviors",
|
|
30
|
+
rule: "Rules",
|
|
31
|
+
scenario: "Scenarios",
|
|
32
|
+
verification: "Verification definitions",
|
|
33
|
+
contract: "Contracts",
|
|
34
|
+
decision: "Decisions",
|
|
35
|
+
knowledge: "Knowledge",
|
|
36
|
+
ancestor: "Navigation ancestors",
|
|
37
|
+
neighbour: "Neighbours",
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
export function contextCommand(
|
|
41
|
+
session: Session,
|
|
42
|
+
id: string,
|
|
43
|
+
includeRestricted: boolean,
|
|
44
|
+
asJson: boolean,
|
|
45
|
+
io: Io,
|
|
46
|
+
): number {
|
|
47
|
+
const { graph } = session.result;
|
|
48
|
+
const bundle = contextFor(graph, id, { includeRestricted });
|
|
49
|
+
if (bundle === null) {
|
|
50
|
+
const diagnostic = unresolved(id, session);
|
|
51
|
+
if (asJson) {
|
|
52
|
+
io.stdout(
|
|
53
|
+
json({
|
|
54
|
+
tool: TOOL,
|
|
55
|
+
snapshot: session.snapshot,
|
|
56
|
+
validation: validationSummary(session, session.level),
|
|
57
|
+
start: null,
|
|
58
|
+
diagnostics: [diagnostic],
|
|
59
|
+
}),
|
|
60
|
+
);
|
|
61
|
+
} else {
|
|
62
|
+
io.stderr(formatDiagnostic(diagnostic));
|
|
63
|
+
}
|
|
64
|
+
return 1;
|
|
65
|
+
}
|
|
66
|
+
const visible = new Set(bundle.artifacts.map((a) => a.id));
|
|
67
|
+
const full = (a: ContextArtifact) => graph.artifacts.get(a.id) as Artifact;
|
|
68
|
+
|
|
69
|
+
if (asJson) {
|
|
70
|
+
io.stdout(
|
|
71
|
+
json({
|
|
72
|
+
tool: TOOL,
|
|
73
|
+
snapshot: session.snapshot,
|
|
74
|
+
validation: validationSummary(session, session.level),
|
|
75
|
+
start: id,
|
|
76
|
+
included: bundle.artifacts.length,
|
|
77
|
+
withheld: bundle.withheld,
|
|
78
|
+
restrictedIncluded: includeRestricted,
|
|
79
|
+
artifacts: bundle.artifacts.map((a) => ({
|
|
80
|
+
...a,
|
|
81
|
+
sourceHash: full(a).sourceHash,
|
|
82
|
+
links: links(graph, full(a), visible),
|
|
83
|
+
body: full(a).body,
|
|
84
|
+
})),
|
|
85
|
+
diagnostics: [],
|
|
86
|
+
}),
|
|
87
|
+
);
|
|
88
|
+
return session.result.ok ? 0 : 1;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
const start = graph.artifacts.get(id) as Artifact;
|
|
92
|
+
const out: string[] = [
|
|
93
|
+
`# Context for ${id}`,
|
|
94
|
+
"",
|
|
95
|
+
`Bounded engineering context (Core §10) for ${start.meta.type} ${id}, "${start.meta.title}".`,
|
|
96
|
+
"",
|
|
97
|
+
`- ${snapshotLine(session.snapshot)}`,
|
|
98
|
+
`- ${validationLine(session, session.level)}`,
|
|
99
|
+
`- Included: ${count(bundle.artifacts.length, "artifact")}. ` +
|
|
100
|
+
(includeRestricted
|
|
101
|
+
? "Restricted artifacts are included, as asked."
|
|
102
|
+
: `Withheld: ${bundle.withheld} restricted${bundle.withheld === 0 ? "" : "; pass --include-restricted to include them"}.`),
|
|
103
|
+
"- Paths are relative to the repository root. The files are authoritative; this is a derived view of them.",
|
|
104
|
+
"",
|
|
105
|
+
];
|
|
106
|
+
let role: ContextRole | null = null;
|
|
107
|
+
for (const a of bundle.artifacts) {
|
|
108
|
+
if (a.role !== role) {
|
|
109
|
+
role = a.role;
|
|
110
|
+
out.push(`## ${HEADINGS[role]}`, "");
|
|
111
|
+
}
|
|
112
|
+
out.push(`### ${a.id}: ${a.title}`, "");
|
|
113
|
+
out.push(`- ID: ${a.id}`, `- Type: ${a.type}`, `- Status: ${a.status}`, `- Path: ${a.path}`);
|
|
114
|
+
const linked = links(graph, full(a), visible);
|
|
115
|
+
const kinds = (Object.keys(linked) as LinkKind[]).sort(compareStrings);
|
|
116
|
+
if (kinds.length > 0) out.push(`- Links: ${kinds.map((k) => `${k} ${linked[k]?.join(", ")}`).join("; ")}`);
|
|
117
|
+
out.push("", ...fenced(full(a).body), "");
|
|
118
|
+
}
|
|
119
|
+
io.stdout(`${out.join("\n").trimEnd()}\n`);
|
|
120
|
+
return session.result.ok ? 0 : 1;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/** Authored links from `artifact` to artifacts in the context, so nothing withheld is named. */
|
|
124
|
+
function links(graph: Graph, artifact: Artifact, visible: Set<string>): Partial<Record<LinkKind, string[]>> {
|
|
125
|
+
const out: Partial<Record<LinkKind, string[]>> = {};
|
|
126
|
+
for (const edge of graph.out.get(artifact.meta.id) ?? []) {
|
|
127
|
+
if (!visible.has(edge.to)) continue;
|
|
128
|
+
const list = out[edge.kind];
|
|
129
|
+
if (list === undefined) out[edge.kind] = [edge.to];
|
|
130
|
+
else if (!list.includes(edge.to)) list.push(edge.to);
|
|
131
|
+
}
|
|
132
|
+
for (const list of Object.values(out)) list?.sort(compareStrings);
|
|
133
|
+
return out;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/** The body verbatim, in a tilde fence longer than any tilde run inside it, so nothing in it can close the fence. */
|
|
137
|
+
function fenced(body: string): string[] {
|
|
138
|
+
const text = body.replace(/^\s*\n/, "").trimEnd();
|
|
139
|
+
const longest = Math.max(0, ...[...text.matchAll(/~+/g)].map((m) => m[0].length));
|
|
140
|
+
const fence = "~".repeat(Math.max(4, longest + 1));
|
|
141
|
+
return [`${fence}markdown`, text, fence];
|
|
142
|
+
}
|