@poetics/cli 0.1.2 → 0.2.1
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/backfill.d.ts +98 -0
- package/dist/backfill.d.ts.map +1 -0
- package/dist/backfill.js +582 -0
- package/dist/backfill.js.map +1 -0
- package/dist/change.d.ts +18 -0
- package/dist/change.d.ts.map +1 -0
- package/dist/change.js +155 -0
- package/dist/change.js.map +1 -0
- package/dist/changes.d.ts +4 -0
- package/dist/changes.d.ts.map +1 -0
- package/dist/changes.js +38 -0
- package/dist/changes.js.map +1 -0
- package/dist/commands.d.ts.map +1 -1
- package/dist/commands.js +6 -2
- package/dist/commands.js.map +1 -1
- package/dist/coverage.d.ts +39 -0
- package/dist/coverage.d.ts.map +1 -0
- package/dist/coverage.js +88 -0
- package/dist/coverage.js.map +1 -0
- package/dist/declarations.d.ts +26 -0
- package/dist/declarations.d.ts.map +1 -0
- package/dist/declarations.js +34 -0
- package/dist/declarations.js.map +1 -0
- package/dist/drift.d.ts +29 -0
- package/dist/drift.d.ts.map +1 -0
- package/dist/drift.js +84 -0
- package/dist/drift.js.map +1 -0
- package/dist/frameworks.d.ts +6 -0
- package/dist/frameworks.d.ts.map +1 -0
- package/dist/frameworks.js +8 -0
- package/dist/frameworks.js.map +1 -0
- package/dist/git.d.ts +19 -0
- package/dist/git.d.ts.map +1 -0
- package/dist/git.js +40 -0
- package/dist/git.js.map +1 -0
- package/dist/history.d.ts +6 -0
- package/dist/history.d.ts.map +1 -0
- package/dist/history.js +53 -0
- package/dist/history.js.map +1 -0
- package/dist/index.d.ts +21 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +12 -0
- package/dist/index.js.map +1 -1
- package/dist/indexing.d.ts +91 -0
- package/dist/indexing.d.ts.map +1 -0
- package/dist/indexing.js +372 -0
- package/dist/indexing.js.map +1 -0
- package/dist/init.d.ts +35 -0
- package/dist/init.d.ts.map +1 -0
- package/dist/init.js +186 -0
- package/dist/init.js.map +1 -0
- package/dist/rehash.d.ts +31 -0
- package/dist/rehash.d.ts.map +1 -0
- package/dist/rehash.js +73 -0
- package/dist/rehash.js.map +1 -0
- package/dist/run.d.ts +2 -2
- package/dist/run.d.ts.map +1 -1
- package/dist/run.js +258 -2
- package/dist/run.js.map +1 -1
- package/package.json +6 -3
package/dist/change.d.ts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { Scope } from "@poetics/store";
|
|
2
|
+
export type ChangeFindingKind = "untracked" | "stale" | "orphaned" | "duplicate" | "rewritten-history" | "changed-rehash" | "deleted-unit" | "missing-lineage" | "no-links" | "unverified" | "callers-not-updated" | "repeated-rationale";
|
|
3
|
+
export interface ChangeFinding {
|
|
4
|
+
severity: "error" | "warning";
|
|
5
|
+
kind: ChangeFindingKind;
|
|
6
|
+
file: string;
|
|
7
|
+
message: string;
|
|
8
|
+
}
|
|
9
|
+
export interface ChangeReport {
|
|
10
|
+
base: string;
|
|
11
|
+
changedCodeFiles: string[];
|
|
12
|
+
changedUnits: number;
|
|
13
|
+
findings: ChangeFinding[];
|
|
14
|
+
}
|
|
15
|
+
export declare function checkChange(root: string, since: string, scope: Scope & {
|
|
16
|
+
adapters?: readonly string[];
|
|
17
|
+
}): Promise<ChangeReport>;
|
|
18
|
+
//# sourceMappingURL=change.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"change.d.ts","sourceRoot":"","sources":["../src/change.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AAQ5C,MAAM,MAAM,iBAAiB,GACzB,WAAW,GACX,OAAO,GACP,UAAU,GACV,WAAW,GACX,mBAAmB,GACnB,gBAAgB,GAChB,cAAc,GACd,iBAAiB,GACjB,UAAU,GACV,YAAY,GACZ,qBAAqB,GACrB,oBAAoB,CAAC;AAEzB,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,OAAO,GAAG,SAAS,CAAC;IAC9B,IAAI,EAAE,iBAAiB,CAAC;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,gBAAgB,EAAE,MAAM,EAAE,CAAC;IAC3B,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,aAAa,EAAE,CAAC;CAC3B;AAID,wBAAsB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,GAAG;IAAE,QAAQ,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;CAAE,GAAG,OAAO,CAAC,YAAY,CAAC,CAgJrI"}
|
package/dist/change.js
ADDED
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
// The per-change check: did this commit, branch or working tree record its
|
|
2
|
+
// code changes in .poetics/ properly? A day-one stand-in for the part of
|
|
3
|
+
// `poetics verify` and the GitHub Action that review a diff.
|
|
4
|
+
import { readFile } from "node:fs/promises";
|
|
5
|
+
import { join } from "node:path";
|
|
6
|
+
import { isDeepStrictEqual } from "node:util";
|
|
7
|
+
import { createMatcher, extendsPrehistory, parseUnit, readUnitFiles, storePaths } from "@poetics/store";
|
|
8
|
+
import { declarationsIn } from "./declarations.js";
|
|
9
|
+
import { pluginsFor } from "./frameworks.js";
|
|
10
|
+
import { DRIFT_SEVERITY, compareCodeWithStore } from "./drift.js";
|
|
11
|
+
import { changesSince, showAt } from "./git.js";
|
|
12
|
+
const PARSEABLE = /\.(ts|tsx|mts|cts)$/;
|
|
13
|
+
export async function checkChange(root, since, scope) {
|
|
14
|
+
const plugins = pluginsFor(scope);
|
|
15
|
+
const { base, changes } = changesSince(root, since);
|
|
16
|
+
const inScope = createMatcher(scope.include, scope.exclude ?? []);
|
|
17
|
+
const changedPaths = new Set(changes.flatMap((c) => (c.from ? [c.path, c.from] : [c.path])));
|
|
18
|
+
const findings = [];
|
|
19
|
+
// 1. Code that changed must match the store.
|
|
20
|
+
const codeFiles = [...changedPaths].filter((path) => inScope(path) && PARSEABLE.test(path) && !path.endsWith(".d.ts")).sort();
|
|
21
|
+
const declarations = [];
|
|
22
|
+
for (const file of codeFiles) {
|
|
23
|
+
const text = await readFile(join(root, file), "utf8").catch(() => undefined);
|
|
24
|
+
if (text !== undefined)
|
|
25
|
+
declarations.push(...declarationsIn(file, text, plugins));
|
|
26
|
+
}
|
|
27
|
+
const paths = storePaths(root);
|
|
28
|
+
const units = (await readUnitFiles(paths)).map(parseUnit);
|
|
29
|
+
const covered = new Set(codeFiles);
|
|
30
|
+
for (const finding of compareCodeWithStore(declarations, units, (file) => covered.has(file)).findings) {
|
|
31
|
+
findings.push({ severity: DRIFT_SEVERITY[finding.kind], kind: finding.kind, file: finding.file, message: finding.message });
|
|
32
|
+
}
|
|
33
|
+
// 2. Unit files that changed must only append, and say why.
|
|
34
|
+
const unitChanges = changes.filter((c) => c.path.startsWith(".poetics/units/") && c.path.endsWith(".json"));
|
|
35
|
+
const newVersions = [];
|
|
36
|
+
for (const change of unitChanges) {
|
|
37
|
+
if (change.status === "D") {
|
|
38
|
+
findings.push({
|
|
39
|
+
severity: "error",
|
|
40
|
+
kind: "deleted-unit",
|
|
41
|
+
file: change.path,
|
|
42
|
+
message: `unit files are never deleted; restore it and append a "removed" version saying why the code went (ADR 0010)`,
|
|
43
|
+
});
|
|
44
|
+
continue;
|
|
45
|
+
}
|
|
46
|
+
const head = parseUnit({ path: join(root, change.path), relativePath: change.path, raw: await readFile(join(root, change.path), "utf8") });
|
|
47
|
+
const baseRaw = change.status === "A" ? undefined : showAt(root, base, change.from ?? change.path);
|
|
48
|
+
const before = baseRaw === undefined ? undefined : JSON.parse(baseRaw);
|
|
49
|
+
if (before) {
|
|
50
|
+
const kept = head.versions.slice(0, before.versions.length);
|
|
51
|
+
if (head.versions.length < before.versions.length || !isDeepStrictEqual(kept, before.versions)) {
|
|
52
|
+
findings.push({
|
|
53
|
+
severity: "error",
|
|
54
|
+
kind: "rewritten-history",
|
|
55
|
+
file: change.path,
|
|
56
|
+
message: `${head.name}: earlier versions were edited or removed; versions are append-only`,
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
// Prehistory is write-once: a later backfill may only reach further back, so what was there stays its tail.
|
|
60
|
+
const was = before.prehistory ?? [];
|
|
61
|
+
const now = head.prehistory ?? [];
|
|
62
|
+
if (!extendsPrehistory(was, now)) {
|
|
63
|
+
findings.push({
|
|
64
|
+
severity: "error",
|
|
65
|
+
kind: "rewritten-history",
|
|
66
|
+
file: change.path,
|
|
67
|
+
message: `${head.name}: recorded prehistory was edited or removed; it may only be extended further back`,
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
const moved = before.location.file !== head.location.file || before.name !== head.name;
|
|
71
|
+
if (moved && (head.lineage?.length ?? 0) <= (before.lineage?.length ?? 0)) {
|
|
72
|
+
findings.push({
|
|
73
|
+
severity: "error",
|
|
74
|
+
kind: "missing-lineage",
|
|
75
|
+
file: change.path,
|
|
76
|
+
message: `${head.name}: name or location changed (${before.name} in ${before.location.file}) without a lineage entry`,
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
for (const version of head.versions.slice(before?.versions.length ?? 0))
|
|
81
|
+
newVersions.push({ unit: head, file: change.path, version });
|
|
82
|
+
}
|
|
83
|
+
const rationaleCounts = new Map();
|
|
84
|
+
for (const { version } of newVersions)
|
|
85
|
+
rationaleCounts.set(version.rationale, (rationaleCounts.get(version.rationale) ?? 0) + 1);
|
|
86
|
+
const dependents = (uid) => units.filter((u) => Object.hasOwn(u.versions.at(-1)?.deps ?? {}, uid));
|
|
87
|
+
const versioned = new Set(newVersions.map(({ unit }) => unit.uid));
|
|
88
|
+
// Declarations of the files new rehash versions sit in, which need not be among the changed code files.
|
|
89
|
+
const declarationCache = new Map();
|
|
90
|
+
const declarationsOf = async (file) => {
|
|
91
|
+
if (!declarationCache.has(file)) {
|
|
92
|
+
const text = await readFile(join(root, file), "utf8").catch(() => undefined);
|
|
93
|
+
declarationCache.set(file, text === undefined ? [] : declarationsIn(file, text, plugins));
|
|
94
|
+
}
|
|
95
|
+
return declarationCache.get(file);
|
|
96
|
+
};
|
|
97
|
+
for (const { unit, file, version } of newVersions) {
|
|
98
|
+
// A rehash claims the code did not change: it must sit on the code's own provisional hash (ADR 0014).
|
|
99
|
+
if (version.change === "rehash" && version === unit.versions.at(-1)) {
|
|
100
|
+
const name = unit.location.export ?? unit.name;
|
|
101
|
+
const decl = (await declarationsOf(unit.location.file)).find((d) => d.name === name && (d.kind === "type") === (unit.kind === "type"));
|
|
102
|
+
if (decl && (decl.hash !== version.parent || decl.contentHash !== version.contentHash)) {
|
|
103
|
+
findings.push({
|
|
104
|
+
severity: "error",
|
|
105
|
+
kind: "changed-rehash",
|
|
106
|
+
file,
|
|
107
|
+
message: decl.hash !== version.parent
|
|
108
|
+
? `${unit.name}: rehash recorded, but the code changed since ${version.parent ?? "its parent"}; record a behaviour, interface or cosmetic version instead`
|
|
109
|
+
: `${unit.name}: rehash contentHash ${version.contentHash} is not the code's ${decl.contentHash}`,
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
if (!version.links || version.links.length === 0) {
|
|
114
|
+
findings.push({ severity: "warning", kind: "no-links", file, message: `${unit.name}: new version cites no issue, task, decision or plan section` });
|
|
115
|
+
}
|
|
116
|
+
// Rehash rationale is the same for every unit by design.
|
|
117
|
+
if (version.change !== "rehash" && (rationaleCounts.get(version.rationale) ?? 0) >= 3) {
|
|
118
|
+
findings.push({
|
|
119
|
+
severity: "warning",
|
|
120
|
+
kind: "repeated-rationale",
|
|
121
|
+
file,
|
|
122
|
+
message: `${unit.name}: the same rationale is used for ${rationaleCounts.get(version.rationale)} units; say what changed for this one`,
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
if (version.change === "behaviour" || version.change === "interface") {
|
|
126
|
+
const tests = unit.tests ?? [];
|
|
127
|
+
if (tests.length === 0) {
|
|
128
|
+
findings.push({ severity: "warning", kind: "unverified", file, message: `${unit.name}: ${version.change} change but the unit has no linked tests` });
|
|
129
|
+
}
|
|
130
|
+
else if (!tests.some((test) => changedPaths.has(test.file))) {
|
|
131
|
+
findings.push({
|
|
132
|
+
severity: "warning",
|
|
133
|
+
kind: "unverified",
|
|
134
|
+
file,
|
|
135
|
+
message: `${unit.name}: ${version.change} change but none of its linked tests changed (${tests.map((t) => t.file).join(", ")})`,
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
// A removal breaks callers at least as surely as an interface change.
|
|
140
|
+
if (version.change === "interface" || version.change === "removed") {
|
|
141
|
+
for (const caller of dependents(unit.uid)) {
|
|
142
|
+
if (versioned.has(caller.uid))
|
|
143
|
+
continue;
|
|
144
|
+
findings.push({
|
|
145
|
+
severity: "warning",
|
|
146
|
+
kind: "callers-not-updated",
|
|
147
|
+
file,
|
|
148
|
+
message: `${unit.name}: ${version.change === "removed" ? "removed" : "interface changed"} but its dependent ${caller.name} got no version`,
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
return { base, changedCodeFiles: codeFiles, changedUnits: unitChanges.length, findings };
|
|
154
|
+
}
|
|
155
|
+
//# sourceMappingURL=change.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"change.js","sourceRoot":"","sources":["../src/change.ts"],"names":[],"mappings":"AAAA,2EAA2E;AAC3E,yEAAyE;AACzE,6DAA6D;AAC7D,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAC;AAC9C,OAAO,EAAE,aAAa,EAAE,iBAAiB,EAAE,SAAS,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAGxG,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAE7C,OAAO,EAAE,cAAc,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AAClE,OAAO,EAAE,YAAY,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AA8BhD,MAAM,SAAS,GAAG,qBAAqB,CAAC;AAExC,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,IAAY,EAAE,KAAa,EAAE,KAA+C;IAC5G,MAAM,OAAO,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC;IAClC,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,YAAY,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;IACpD,MAAM,OAAO,GAAG,aAAa,CAAC,KAAK,CAAC,OAAO,EAAE,KAAK,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC;IAClE,MAAM,YAAY,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;IAC7F,MAAM,QAAQ,GAAoB,EAAE,CAAC;IAErC,6CAA6C;IAC7C,MAAM,SAAS,GAAG,CAAC,GAAG,YAAY,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;IAC9H,MAAM,YAAY,GAAkB,EAAE,CAAC;IACvC,KAAK,MAAM,IAAI,IAAI,SAAS,EAAE,CAAC;QAC7B,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;QAC7E,IAAI,IAAI,KAAK,SAAS;YAAE,YAAY,CAAC,IAAI,CAAC,GAAG,cAAc,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC;IACpF,CAAC;IACD,MAAM,KAAK,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC;IAC/B,MAAM,KAAK,GAAG,CAAC,MAAM,aAAa,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;IAC1D,MAAM,OAAO,GAAG,IAAI,GAAG,CAAC,SAAS,CAAC,CAAC;IACnC,KAAK,MAAM,OAAO,IAAI,oBAAoB,CAAC,YAAY,EAAE,KAAK,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC;QACtG,QAAQ,CAAC,IAAI,CAAC,EAAE,QAAQ,EAAE,cAAc,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC;IAC9H,CAAC;IAED,4DAA4D;IAC5D,MAAM,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,iBAAiB,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC;IAC5G,MAAM,WAAW,GAA2E,EAAE,CAAC;IAC/F,KAAK,MAAM,MAAM,IAAI,WAAW,EAAE,CAAC;QACjC,IAAI,MAAM,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;YAC1B,QAAQ,CAAC,IAAI,CAAC;gBACZ,QAAQ,EAAE,OAAO;gBACjB,IAAI,EAAE,cAAc;gBACpB,IAAI,EAAE,MAAM,CAAC,IAAI;gBACjB,OAAO,EAAE,6GAA6G;aACvH,CAAC,CAAC;YACH,SAAS;QACX,CAAC;QACD,MAAM,IAAI,GAAG,SAAS,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,MAAM,CAAC,IAAI,CAAC,EAAE,YAAY,EAAE,MAAM,CAAC,IAAI,EAAE,GAAG,EAAE,MAAM,QAAQ,CAAC,IAAI,CAAC,IAAI,EAAE,MAAM,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC,EAAE,CAAC,CAAC;QAC3I,MAAM,OAAO,GAAG,MAAM,CAAC,MAAM,KAAK,GAAG,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,IAAI,MAAM,CAAC,IAAI,CAAC,CAAC;QACnG,MAAM,MAAM,GAAG,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAE,IAAI,CAAC,KAAK,CAAC,OAAO,CAAU,CAAC;QAEjF,IAAI,MAAM,EAAE,CAAC;YACX,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;YAC5D,IAAI,IAAI,CAAC,QAAQ,CAAC,MAAM,GAAG,MAAM,CAAC,QAAQ,CAAC,MAAM,IAAI,CAAC,iBAAiB,CAAC,IAAI,EAAE,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC;gBAC/F,QAAQ,CAAC,IAAI,CAAC;oBACZ,QAAQ,EAAE,OAAO;oBACjB,IAAI,EAAE,mBAAmB;oBACzB,IAAI,EAAE,MAAM,CAAC,IAAI;oBACjB,OAAO,EAAE,GAAG,IAAI,CAAC,IAAI,qEAAqE;iBAC3F,CAAC,CAAC;YACL,CAAC;YACD,4GAA4G;YAC5G,MAAM,GAAG,GAAG,MAAM,CAAC,UAAU,IAAI,EAAE,CAAC;YACpC,MAAM,GAAG,GAAG,IAAI,CAAC,UAAU,IAAI,EAAE,CAAC;YAClC,IAAI,CAAC,iBAAiB,CAAC,GAAG,EAAE,GAAG,CAAC,EAAE,CAAC;gBACjC,QAAQ,CAAC,IAAI,CAAC;oBACZ,QAAQ,EAAE,OAAO;oBACjB,IAAI,EAAE,mBAAmB;oBACzB,IAAI,EAAE,MAAM,CAAC,IAAI;oBACjB,OAAO,EAAE,GAAG,IAAI,CAAC,IAAI,mFAAmF;iBACzG,CAAC,CAAC;YACL,CAAC;YACD,MAAM,KAAK,GAAG,MAAM,CAAC,QAAQ,CAAC,IAAI,KAAK,IAAI,CAAC,QAAQ,CAAC,IAAI,IAAI,MAAM,CAAC,IAAI,KAAK,IAAI,CAAC,IAAI,CAAC;YACvF,IAAI,KAAK,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,IAAI,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,MAAM,IAAI,CAAC,CAAC,EAAE,CAAC;gBAC1E,QAAQ,CAAC,IAAI,CAAC;oBACZ,QAAQ,EAAE,OAAO;oBACjB,IAAI,EAAE,iBAAiB;oBACvB,IAAI,EAAE,MAAM,CAAC,IAAI;oBACjB,OAAO,EAAE,GAAG,IAAI,CAAC,IAAI,+BAA+B,MAAM,CAAC,IAAI,OAAO,MAAM,CAAC,QAAQ,CAAC,IAAI,2BAA2B;iBACtH,CAAC,CAAC;YACL,CAAC;QACH,CAAC;QACD,KAAK,MAAM,OAAO,IAAI,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,MAAM,EAAE,QAAQ,CAAC,MAAM,IAAI,CAAC,CAAC;YAAE,WAAW,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC;IACxI,CAAC;IAED,MAAM,eAAe,GAAG,IAAI,GAAG,EAAkB,CAAC;IAClD,KAAK,MAAM,EAAE,OAAO,EAAE,IAAI,WAAW;QAAE,eAAe,CAAC,GAAG,CAAC,OAAO,CAAC,SAAS,EAAE,CAAC,eAAe,CAAC,GAAG,CAAC,OAAO,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;IACjI,MAAM,UAAU,GAAG,CAAC,GAAW,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,IAAI,IAAI,EAAE,EAAE,GAAG,CAAC,CAAC,CAAC;IAC3G,MAAM,SAAS,GAAG,IAAI,GAAG,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;IAEnE,wGAAwG;IACxG,MAAM,gBAAgB,GAAG,IAAI,GAAG,EAAyB,CAAC;IAC1D,MAAM,cAAc,GAAG,KAAK,EAAE,IAAY,EAAE,EAAE;QAC5C,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;YAChC,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;YAC7E,gBAAgB,CAAC,GAAG,CAAC,IAAI,EAAE,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,cAAc,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC;QAC5F,CAAC;QACD,OAAO,gBAAgB,CAAC,GAAG,CAAC,IAAI,CAAE,CAAC;IACrC,CAAC,CAAC;IAEF,KAAK,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,WAAW,EAAE,CAAC;QAClD,sGAAsG;QACtG,IAAI,OAAO,CAAC,MAAM,KAAK,QAAQ,IAAI,OAAO,KAAK,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;YACpE,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,CAAC,MAAM,IAAI,IAAI,CAAC,IAAI,CAAC;YAC/C,MAAM,IAAI,GAAG,CAAC,MAAM,cAAc,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,IAAI,IAAI,CAAC,CAAC,CAAC,IAAI,KAAK,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC;YACvI,IAAI,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,KAAK,OAAO,CAAC,MAAM,IAAI,IAAI,CAAC,WAAW,KAAK,OAAO,CAAC,WAAW,CAAC,EAAE,CAAC;gBACvF,QAAQ,CAAC,IAAI,CAAC;oBACZ,QAAQ,EAAE,OAAO;oBACjB,IAAI,EAAE,gBAAgB;oBACtB,IAAI;oBACJ,OAAO,EACL,IAAI,CAAC,IAAI,KAAK,OAAO,CAAC,MAAM;wBAC1B,CAAC,CAAC,GAAG,IAAI,CAAC,IAAI,iDAAiD,OAAO,CAAC,MAAM,IAAI,YAAY,6DAA6D;wBAC1J,CAAC,CAAC,GAAG,IAAI,CAAC,IAAI,wBAAwB,OAAO,CAAC,WAAW,sBAAsB,IAAI,CAAC,WAAW,EAAE;iBACtG,CAAC,CAAC;YACL,CAAC;QACH,CAAC;QACD,IAAI,CAAC,OAAO,CAAC,KAAK,IAAI,OAAO,CAAC,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACjD,QAAQ,CAAC,IAAI,CAAC,EAAE,QAAQ,EAAE,SAAS,EAAE,IAAI,EAAE,UAAU,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC,IAAI,8DAA8D,EAAE,CAAC,CAAC;QACtJ,CAAC;QACD,yDAAyD;QACzD,IAAI,OAAO,CAAC,MAAM,KAAK,QAAQ,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,OAAO,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC;YACtF,QAAQ,CAAC,IAAI,CAAC;gBACZ,QAAQ,EAAE,SAAS;gBACnB,IAAI,EAAE,oBAAoB;gBAC1B,IAAI;gBACJ,OAAO,EAAE,GAAG,IAAI,CAAC,IAAI,oCAAoC,eAAe,CAAC,GAAG,CAAC,OAAO,CAAC,SAAS,CAAC,uCAAuC;aACvI,CAAC,CAAC;QACL,CAAC;QACD,IAAI,OAAO,CAAC,MAAM,KAAK,WAAW,IAAI,OAAO,CAAC,MAAM,KAAK,WAAW,EAAE,CAAC;YACrE,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,IAAI,EAAE,CAAC;YAC/B,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBACvB,QAAQ,CAAC,IAAI,CAAC,EAAE,QAAQ,EAAE,SAAS,EAAE,IAAI,EAAE,YAAY,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC,IAAI,KAAK,OAAO,CAAC,MAAM,0CAA0C,EAAE,CAAC,CAAC;YACvJ,CAAC;iBAAM,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,YAAY,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC;gBAC9D,QAAQ,CAAC,IAAI,CAAC;oBACZ,QAAQ,EAAE,SAAS;oBACnB,IAAI,EAAE,YAAY;oBAClB,IAAI;oBACJ,OAAO,EAAE,GAAG,IAAI,CAAC,IAAI,KAAK,OAAO,CAAC,MAAM,iDAAiD,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG;iBAChI,CAAC,CAAC;YACL,CAAC;QACH,CAAC;QACD,sEAAsE;QACtE,IAAI,OAAO,CAAC,MAAM,KAAK,WAAW,IAAI,OAAO,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;YACnE,KAAK,MAAM,MAAM,IAAI,UAAU,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;gBAC1C,IAAI,SAAS,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC;oBAAE,SAAS;gBACxC,QAAQ,CAAC,IAAI,CAAC;oBACZ,QAAQ,EAAE,SAAS;oBACnB,IAAI,EAAE,qBAAqB;oBAC3B,IAAI;oBACJ,OAAO,EAAE,GAAG,IAAI,CAAC,IAAI,KAAK,OAAO,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,mBAAmB,sBAAsB,MAAM,CAAC,IAAI,iBAAiB;iBAC3I,CAAC,CAAC;YACL,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO,EAAE,IAAI,EAAE,gBAAgB,EAAE,SAAS,EAAE,YAAY,EAAE,WAAW,CAAC,MAAM,EAAE,QAAQ,EAAE,CAAC;AAC3F,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"changes.d.ts","sourceRoot":"","sources":["../src/changes.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAc,MAAM,gBAAgB,CAAC;AAI5D,gGAAgG;AAChG,wBAAgB,aAAa,CAAC,GAAG,EAAE,SAAS,GAAG,MAAM,CA4BpD"}
|
package/dist/changes.js
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
const MARK = { added: "+", changed: "~", removed: "-" };
|
|
2
|
+
/** Renders a change set for a terminal: each commit's units with change class and rationale. */
|
|
3
|
+
export function formatChanges(set) {
|
|
4
|
+
const units = set.commits.reduce((n, commit) => n + commit.units.length, 0);
|
|
5
|
+
const lines = [`Changes from ${short(set.from)} to ${short(set.to)}: ${set.commits.length} commit(s), ${units} unit change(s)`];
|
|
6
|
+
for (const commit of set.commits) {
|
|
7
|
+
lines.push("", `${short(commit.commit)} ${commit.subject}`);
|
|
8
|
+
for (const unit of commit.units) {
|
|
9
|
+
const classes = unit.versions.map((v) => v.change).join(", ");
|
|
10
|
+
lines.push(` ${MARK[unit.status]} ${unit.name} (${unit.kind}, ${unit.file})${classes ? ` ${classes}` : ""}`);
|
|
11
|
+
for (const entry of unit.lineage) {
|
|
12
|
+
lines.push(` ${entry.kind}${entry.from ? ` from ${entry.from}` : ""}${entry.uids ? ` with ${entry.uids.join(", ")}` : ""}`);
|
|
13
|
+
}
|
|
14
|
+
for (const version of unit.versions) {
|
|
15
|
+
lines.push(` ${version.rationale}`);
|
|
16
|
+
const links = (version.links ?? []).map((link) => (typeof link === "string" ? link : link.url ?? link.ref));
|
|
17
|
+
if (links.length > 0)
|
|
18
|
+
lines.push(` links: ${links.join(", ")}`);
|
|
19
|
+
}
|
|
20
|
+
if (unit.status === "removed" && unit.versions.length === 0)
|
|
21
|
+
lines.push(" unit file deleted; no rationale recorded");
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
if (set.unrecorded.length > 0) {
|
|
25
|
+
lines.push("", "Commits that recorded no unit change:");
|
|
26
|
+
for (const commit of set.unrecorded)
|
|
27
|
+
lines.push(` ${short(commit.commit)} ${commit.subject}`);
|
|
28
|
+
}
|
|
29
|
+
if (set.decisions.length > 0)
|
|
30
|
+
lines.push("", `Decisions: ${set.decisions.join(", ")}`);
|
|
31
|
+
if (set.notes.length > 0)
|
|
32
|
+
lines.push("", `Notes: ${set.notes.join(", ")}`);
|
|
33
|
+
return lines.join("\n");
|
|
34
|
+
}
|
|
35
|
+
function short(ref) {
|
|
36
|
+
return /^[0-9a-f]{40}$/.test(ref) ? ref.slice(0, 7) : ref;
|
|
37
|
+
}
|
|
38
|
+
//# sourceMappingURL=changes.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"changes.js","sourceRoot":"","sources":["../src/changes.ts"],"names":[],"mappings":"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"}
|
package/dist/commands.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"commands.d.ts","sourceRoot":"","sources":["../src/commands.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,2EAA2E;AAC3E,eAAO,MAAM,QAAQ,EAAE,SAAS,WAAW,
|
|
1
|
+
{"version":3,"file":"commands.d.ts","sourceRoot":"","sources":["../src/commands.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,2EAA2E;AAC3E,eAAO,MAAM,QAAQ,EAAE,SAAS,WAAW,EAc1C,CAAC"}
|
package/dist/commands.js
CHANGED
|
@@ -1,13 +1,17 @@
|
|
|
1
1
|
/** The CLI surface from docs/plan.md, "Developer workflow and tooling". */
|
|
2
2
|
export const COMMANDS = [
|
|
3
|
-
{ name: "init", usage: "poetics init [--agents]", summary: "
|
|
4
|
-
{ name: "
|
|
3
|
+
{ name: "init", usage: "poetics init [--write] [--agents]", summary: "Adopt Poetics: detect React and Svelte, write config, and create units with a snapshot backfill; a dry run without --write. --agents is planned" },
|
|
4
|
+
{ name: "backfill", usage: "poetics backfill --snapshot [--write] | --history [<from>] [<to>] [--include-removed] [--write]", summary: "Create units for code with none (--snapshot), or reconstruct each unit's history before it was recorded (--history, over the first-parent commits after <from> up to <to>; --include-removed also recovers exports deleted before they were recorded), rationale inferred from the repository's own evidence (ADR 0011); a dry run without --write" },
|
|
5
|
+
{ name: "index", usage: "poetics index [--since <ref>] [--write] [--rationale <text>] [--agent <tool> [--model <id>]]", summary: "Record what changed in the code since a ref: versions, moves and renames with lineage, new and removed units, test links to renamed test files; a dry run without --write" },
|
|
5
6
|
{ name: "log", usage: "poetics log <unit>", summary: "Version history of one unit, with rationale and commits" },
|
|
6
7
|
{ name: "why", usage: "poetics why <unit>", summary: "The rationale chain that led to the current version" },
|
|
8
|
+
{ name: "changes", usage: "poetics changes [from] [to] [--impact]", summary: "Every recorded change between two refs and why, grouped by commit, removals included" },
|
|
7
9
|
{ name: "impact", usage: "poetics impact [ref]", summary: "Components whose closure changed since a branch or commit" },
|
|
8
10
|
{ name: "diff", usage: "poetics diff <unit> <a> <b>", summary: "Semantic diff between two versions of a unit" },
|
|
9
11
|
{ name: "verify", usage: "poetics verify [--since <ref>]", summary: "List unverified units, stale docs and unresolved edges, and unrecorded changes since a ref; non-zero exit for CI" },
|
|
10
12
|
{ name: "coverage", usage: "poetics coverage", summary: "How much of the codebase .poetics/ covers, against policy thresholds" },
|
|
13
|
+
{ name: "hash", usage: "poetics hash <file>[#name]", summary: "The indexer's content and interface hashes for the units in a file, for recording a version" },
|
|
14
|
+
{ name: "rehash", usage: "poetics rehash [--write] [--agent <tool> [--model <id>]]", summary: "Replace provisional git: hashes with b3: ones by appending rehash versions (ADR 0014); a dry run without --write" },
|
|
11
15
|
{ name: "docs", usage: "poetics docs sync", summary: "Write stored docs into TSDoc and @component comments" },
|
|
12
16
|
];
|
|
13
17
|
//# sourceMappingURL=commands.js.map
|
package/dist/commands.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"commands.js","sourceRoot":"","sources":["../src/commands.ts"],"names":[],"mappings":"AAMA,2EAA2E;AAC3E,MAAM,CAAC,MAAM,QAAQ,GAA2B;IAC9C,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,
|
|
1
|
+
{"version":3,"file":"commands.js","sourceRoot":"","sources":["../src/commands.ts"],"names":[],"mappings":"AAMA,2EAA2E;AAC3E,MAAM,CAAC,MAAM,QAAQ,GAA2B;IAC9C,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,mCAAmC,EAAE,OAAO,EAAE,iJAAiJ,EAAE;IACxN,EAAE,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,iGAAiG,EAAE,OAAO,EAAE,oVAAoV,EAAE;IAC7d,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,8FAA8F,EAAE,OAAO,EAAE,2KAA2K,EAAE;IAC9S,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,oBAAoB,EAAE,OAAO,EAAE,yDAAyD,EAAE;IAChH,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,oBAAoB,EAAE,OAAO,EAAE,qDAAqD,EAAE;IAC5G,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,wCAAwC,EAAE,OAAO,EAAE,sFAAsF,EAAE;IACrK,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,sBAAsB,EAAE,OAAO,EAAE,2DAA2D,EAAE;IACvH,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,6BAA6B,EAAE,OAAO,EAAE,8CAA8C,EAAE;IAC/G,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,gCAAgC,EAAE,OAAO,EAAE,kHAAkH,EAAE;IACxL,EAAE,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,kBAAkB,EAAE,OAAO,EAAE,sEAAsE,EAAE;IAChI,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,4BAA4B,EAAE,OAAO,EAAE,6FAA6F,EAAE;IAC7J,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,0DAA0D,EAAE,OAAO,EAAE,kHAAkH,EAAE;IAClN,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,mBAAmB,EAAE,OAAO,EAAE,sDAAsD,EAAE;CAC9G,CAAC"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import type { Note, Unit } from "@poetics/core";
|
|
2
|
+
import type { CoverageThresholds } from "@poetics/store";
|
|
3
|
+
import type { Declaration } from "./declarations.ts";
|
|
4
|
+
export interface Ratio {
|
|
5
|
+
covered: number;
|
|
6
|
+
total: number;
|
|
7
|
+
/** covered / total, or 1 when there is nothing to cover. */
|
|
8
|
+
ratio: number;
|
|
9
|
+
}
|
|
10
|
+
export interface CoverageMetrics {
|
|
11
|
+
tracked: Ratio;
|
|
12
|
+
fresh: Ratio;
|
|
13
|
+
linkedRationale: Ratio;
|
|
14
|
+
reviewed: Ratio;
|
|
15
|
+
tested: Ratio;
|
|
16
|
+
documented: Ratio;
|
|
17
|
+
}
|
|
18
|
+
export interface CoverageReport {
|
|
19
|
+
overall: CoverageMetrics;
|
|
20
|
+
/** Keyed by area: `packages/<name>` or the top-level folder. */
|
|
21
|
+
byArea: Record<string, CoverageMetrics>;
|
|
22
|
+
notes: {
|
|
23
|
+
active: number;
|
|
24
|
+
withCheck: number;
|
|
25
|
+
retired: number;
|
|
26
|
+
};
|
|
27
|
+
unsupportedFiles: string[];
|
|
28
|
+
failures: Array<{
|
|
29
|
+
metric: keyof CoverageMetrics;
|
|
30
|
+
ratio: number;
|
|
31
|
+
threshold: number;
|
|
32
|
+
}>;
|
|
33
|
+
}
|
|
34
|
+
export declare const METRICS: ReadonlyArray<readonly [keyof CoverageMetrics, string]>;
|
|
35
|
+
export declare function areaOf(file: string): string;
|
|
36
|
+
export declare function computeCoverage(declarations: readonly Declaration[], units: readonly Unit[], notes: readonly Note[], scanned: ReadonlySet<string>, unsupportedFiles: readonly string[], thresholds?: CoverageThresholds): CoverageReport;
|
|
37
|
+
export declare function formatCoverage(report: CoverageReport): string;
|
|
38
|
+
export declare function coverageFor(root: string): Promise<CoverageReport>;
|
|
39
|
+
//# sourceMappingURL=coverage.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"coverage.d.ts","sourceRoot":"","sources":["../src/coverage.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AAEhD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AAEzD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAGrD,MAAM,WAAW,KAAK;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,4DAA4D;IAC5D,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,KAAK,CAAC;IACf,KAAK,EAAE,KAAK,CAAC;IACb,eAAe,EAAE,KAAK,CAAC;IACvB,QAAQ,EAAE,KAAK,CAAC;IAChB,MAAM,EAAE,KAAK,CAAC;IACd,UAAU,EAAE,KAAK,CAAC;CACnB;AAED,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,eAAe,CAAC;IACzB,gEAAgE;IAChE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;IACxC,KAAK,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;IAC9D,gBAAgB,EAAE,MAAM,EAAE,CAAC;IAC3B,QAAQ,EAAE,KAAK,CAAC;QAAE,MAAM,EAAE,MAAM,eAAe,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACtF;AAED,eAAO,MAAM,OAAO,EAAE,aAAa,CAAC,SAAS,CAAC,MAAM,eAAe,EAAE,MAAM,CAAC,CAO3E,CAAC;AAIF,wBAAgB,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAG3C;AAiBD,wBAAgB,eAAe,CAC7B,YAAY,EAAE,SAAS,WAAW,EAAE,EACpC,KAAK,EAAE,SAAS,IAAI,EAAE,EACtB,KAAK,EAAE,SAAS,IAAI,EAAE,EACtB,OAAO,EAAE,WAAW,CAAC,MAAM,CAAC,EAC5B,gBAAgB,EAAE,SAAS,MAAM,EAAE,EACnC,UAAU,GAAE,kBAAuB,GAClC,cAAc,CA6BhB;AAID,wBAAgB,cAAc,CAAC,MAAM,EAAE,cAAc,GAAG,MAAM,CAe7D;AAED,wBAAsB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC,CAQvE"}
|
package/dist/coverage.js
ADDED
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
// How well Poetics covers a codebase: tracked and fresh units, and the quality
|
|
2
|
+
// of what is recorded about them.
|
|
3
|
+
import { isRemoved } from "@poetics/core";
|
|
4
|
+
import { filesInScope, parseNote, parseUnit, readConfig, readNoteFiles, readUnitFiles, storePaths } from "@poetics/store";
|
|
5
|
+
import { discoverDeclarations } from "./declarations.js";
|
|
6
|
+
import { compareCodeWithStore } from "./drift.js";
|
|
7
|
+
export const METRICS = [
|
|
8
|
+
["tracked", "Exports with a unit"],
|
|
9
|
+
["fresh", "Units matching their code"],
|
|
10
|
+
["linkedRationale", "Versions citing a source"],
|
|
11
|
+
["reviewed", "Agent versions reviewed"],
|
|
12
|
+
["tested", "Units with linked tests"],
|
|
13
|
+
["documented", "Units with docs"],
|
|
14
|
+
];
|
|
15
|
+
const ratio = (covered, total) => ({ covered, total, ratio: total === 0 ? 1 : covered / total });
|
|
16
|
+
export function areaOf(file) {
|
|
17
|
+
const parts = file.split("/");
|
|
18
|
+
return parts[0] === "packages" && parts.length > 2 ? `packages/${parts[1]}` : parts[0];
|
|
19
|
+
}
|
|
20
|
+
function metricsFor(declarations, units, covers) {
|
|
21
|
+
const drift = compareCodeWithStore(declarations, units, covers);
|
|
22
|
+
const tracked = units.filter((unit) => !isRemoved(unit) && covers(unit.location.file));
|
|
23
|
+
const versions = tracked.flatMap((unit) => unit.versions);
|
|
24
|
+
const agentVersions = versions.filter((v) => v.actor.kind === "agent");
|
|
25
|
+
return {
|
|
26
|
+
tracked: ratio(drift.tracked, drift.declarations),
|
|
27
|
+
fresh: ratio(drift.fresh, drift.tracked),
|
|
28
|
+
linkedRationale: ratio(versions.filter((v) => (v.links?.length ?? 0) > 0).length, versions.length),
|
|
29
|
+
reviewed: ratio(agentVersions.filter((v) => v.actor.kind === "agent" && v.actor.reviewed).length, agentVersions.length),
|
|
30
|
+
tested: ratio(tracked.filter((unit) => (unit.tests?.length ?? 0) > 0).length, tracked.length),
|
|
31
|
+
documented: ratio(tracked.filter((unit) => (unit.docs ?? "").trim() !== "").length, tracked.length),
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
export function computeCoverage(declarations, units, notes, scanned, unsupportedFiles, thresholds = {}) {
|
|
35
|
+
const covers = (file) => scanned.has(file);
|
|
36
|
+
const overall = metricsFor(declarations, units, covers);
|
|
37
|
+
const areas = new Set([...scanned].map(areaOf));
|
|
38
|
+
const byArea = {};
|
|
39
|
+
for (const area of [...areas].sort()) {
|
|
40
|
+
const inArea = (file) => covers(file) && areaOf(file) === area;
|
|
41
|
+
byArea[area] = metricsFor(declarations.filter((d) => inArea(d.file)), units.filter((u) => inArea(u.location.file)), inArea);
|
|
42
|
+
}
|
|
43
|
+
const failures = METRICS.flatMap(([metric]) => {
|
|
44
|
+
const threshold = thresholds[metric];
|
|
45
|
+
const value = overall[metric].ratio;
|
|
46
|
+
return threshold !== undefined && value < threshold ? [{ metric, ratio: value, threshold }] : [];
|
|
47
|
+
});
|
|
48
|
+
return {
|
|
49
|
+
overall,
|
|
50
|
+
byArea,
|
|
51
|
+
notes: {
|
|
52
|
+
active: notes.filter((n) => n.status === "active").length,
|
|
53
|
+
withCheck: notes.filter((n) => n.status === "active" && n.check !== undefined).length,
|
|
54
|
+
retired: notes.filter((n) => n.status !== "active").length,
|
|
55
|
+
},
|
|
56
|
+
unsupportedFiles: [...unsupportedFiles],
|
|
57
|
+
failures,
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
const pct = (r) => (r.total === 0 ? "—" : `${Math.floor(r.ratio * 1000) / 10}%`).padStart(6);
|
|
61
|
+
export function formatCoverage(report) {
|
|
62
|
+
const areas = Object.keys(report.byArea);
|
|
63
|
+
const header = ["Metric".padEnd(28), "Overall".padStart(16), ...areas.map((a) => a.padStart(Math.max(a.length, 8)))].join(" ");
|
|
64
|
+
const rows = METRICS.map(([metric, label]) => {
|
|
65
|
+
const overall = report.overall[metric];
|
|
66
|
+
return [
|
|
67
|
+
label.padEnd(28),
|
|
68
|
+
`${pct(overall)} ${`(${overall.covered}/${overall.total})`.padStart(9)}`,
|
|
69
|
+
...areas.map((a) => pct(report.byArea[a][metric]).padStart(Math.max(a.length, 8))),
|
|
70
|
+
].join(" ");
|
|
71
|
+
});
|
|
72
|
+
const lines = [header, ...rows, "", `Notes: ${report.notes.active} active (${report.notes.withCheck} with a check), ${report.notes.retired} retired.`];
|
|
73
|
+
if (report.unsupportedFiles.length > 0)
|
|
74
|
+
lines.push(`Not yet indexable: ${report.unsupportedFiles.length} file(s) (e.g. ${report.unsupportedFiles[0]}).`);
|
|
75
|
+
for (const f of report.failures)
|
|
76
|
+
lines.push(`Below threshold: ${f.metric} ${(f.ratio * 100).toFixed(1)}% < ${(f.threshold * 100).toFixed(1)}%`);
|
|
77
|
+
return lines.join("\n");
|
|
78
|
+
}
|
|
79
|
+
export async function coverageFor(root) {
|
|
80
|
+
const config = await readConfig(root);
|
|
81
|
+
const paths = storePaths(root);
|
|
82
|
+
const { declarations, unsupported } = await discoverDeclarations(root, config);
|
|
83
|
+
const { parseable } = await filesInScope(root, config);
|
|
84
|
+
const units = (await readUnitFiles(paths)).map(parseUnit);
|
|
85
|
+
const notes = (await readNoteFiles(paths)).map(parseNote);
|
|
86
|
+
return computeCoverage(declarations, units, notes, new Set(parseable), unsupported, config.policy?.coverage);
|
|
87
|
+
}
|
|
88
|
+
//# sourceMappingURL=coverage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"coverage.js","sourceRoot":"","sources":["../src/coverage.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { Hash, UnitKind } from "@poetics/core";
|
|
2
|
+
import type { Scope } from "@poetics/store";
|
|
3
|
+
import type { FrameworkPlugin } from "@poetics/adapter-typescript";
|
|
4
|
+
export interface Declaration {
|
|
5
|
+
/** Repo-relative POSIX path. */
|
|
6
|
+
file: string;
|
|
7
|
+
name: string;
|
|
8
|
+
kind: UnitKind;
|
|
9
|
+
/** Provisional hash of the declaration text, from `export` to its end, without leading TSDoc. */
|
|
10
|
+
hash: Hash;
|
|
11
|
+
/** The indexer's hash of the normalised syntax tree, which ignores formatting and comments (ADR 0014). */
|
|
12
|
+
contentHash: Hash;
|
|
13
|
+
/** 1-based, inclusive. */
|
|
14
|
+
startLine: number;
|
|
15
|
+
endLine: number;
|
|
16
|
+
}
|
|
17
|
+
/** The units the TypeScript indexer detects in one source text: exported functions, hooks and types. */
|
|
18
|
+
export declare function declarationsIn(file: string, text: string, plugins?: readonly FrameworkPlugin[]): Declaration[];
|
|
19
|
+
/** Every tracked-shape declaration in scope. */
|
|
20
|
+
export declare function discoverDeclarations(root: string, scope: Scope & {
|
|
21
|
+
adapters?: readonly string[];
|
|
22
|
+
}): Promise<{
|
|
23
|
+
declarations: Declaration[];
|
|
24
|
+
unsupported: string[];
|
|
25
|
+
}>;
|
|
26
|
+
//# sourceMappingURL=declarations.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"declarations.d.ts","sourceRoot":"","sources":["../src/declarations.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAEpD,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AAC5C,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAC;AAGnE,MAAM,WAAW,WAAW;IAC1B,gCAAgC;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,QAAQ,CAAC;IACf,iGAAiG;IACjG,IAAI,EAAE,IAAI,CAAC;IACX,0GAA0G;IAC1G,WAAW,EAAE,IAAI,CAAC;IAClB,0BAA0B;IAC1B,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,wGAAwG;AACxG,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,GAAE,SAAS,eAAe,EAAO,GAAG,WAAW,EAAE,CAWlH;AAED,gDAAgD;AAChD,wBAAsB,oBAAoB,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,GAAG;IAAE,QAAQ,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;CAAE,GAAG,OAAO,CAAC;IAAE,YAAY,EAAE,WAAW,EAAE,CAAC;IAAC,WAAW,EAAE,MAAM,EAAE,CAAA;CAAE,CAAC,CAMzK"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
// Finds the declarations Poetics tracks as units, with both hashes a version may
|
|
2
|
+
// carry: the provisional git: hash of the text, which history recorded before
|
|
3
|
+
// the rehash, and the indexer's b3: content hash. Both are syntactic, so this
|
|
4
|
+
// needs no type checker.
|
|
5
|
+
import { readFile } from "node:fs/promises";
|
|
6
|
+
import { join } from "node:path";
|
|
7
|
+
import ts from "typescript";
|
|
8
|
+
import { contentTree, detectUnits } from "@poetics/adapter-typescript";
|
|
9
|
+
import { contentHash, gitBlobHash } from "@poetics/core";
|
|
10
|
+
import { filesInScope } from "@poetics/store";
|
|
11
|
+
import { pluginsFor } from "./frameworks.js";
|
|
12
|
+
/** The units the TypeScript indexer detects in one source text: exported functions, hooks and types. */
|
|
13
|
+
export function declarationsIn(file, text, plugins = []) {
|
|
14
|
+
const source = ts.createSourceFile(file, text, ts.ScriptTarget.Latest, true);
|
|
15
|
+
return detectUnits(source, file, plugins).map((unit) => ({
|
|
16
|
+
file,
|
|
17
|
+
name: unit.name,
|
|
18
|
+
kind: unit.kind,
|
|
19
|
+
hash: gitBlobHash(text.slice(unit.span.start, unit.span.end)),
|
|
20
|
+
contentHash: contentHash(contentTree(unit)),
|
|
21
|
+
startLine: source.getLineAndCharacterOfPosition(unit.span.start).line + 1,
|
|
22
|
+
endLine: source.getLineAndCharacterOfPosition(unit.span.end).line + 1,
|
|
23
|
+
}));
|
|
24
|
+
}
|
|
25
|
+
/** Every tracked-shape declaration in scope. */
|
|
26
|
+
export async function discoverDeclarations(root, scope) {
|
|
27
|
+
const { parseable, unsupported } = await filesInScope(root, scope);
|
|
28
|
+
const declarations = [];
|
|
29
|
+
const plugins = pluginsFor(scope);
|
|
30
|
+
for (const file of parseable)
|
|
31
|
+
declarations.push(...declarationsIn(file, await readFile(join(root, file), "utf8"), plugins));
|
|
32
|
+
return { declarations, unsupported };
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=declarations.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"declarations.js","sourceRoot":"","sources":["../src/declarations.ts"],"names":[],"mappings":"AAAA,iFAAiF;AACjF,8EAA8E;AAC9E,8EAA8E;AAC9E,yBAAyB;AACzB,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,MAAM,YAAY,CAAC;AAC5B,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,6BAA6B,CAAC;AACvE,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAEzD,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAG9C,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAgB7C,wGAAwG;AACxG,MAAM,UAAU,cAAc,CAAC,IAAY,EAAE,IAAY,EAAE,UAAsC,EAAE;IACjG,MAAM,MAAM,GAAG,EAAE,CAAC,gBAAgB,CAAC,IAAI,EAAE,IAAI,EAAE,EAAE,CAAC,YAAY,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;IAC7E,OAAO,WAAW,CAAC,MAAM,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;QACvD,IAAI;QACJ,IAAI,EAAE,IAAI,CAAC,IAAI;QACf,IAAI,EAAE,IAAI,CAAC,IAAI;QACf,IAAI,EAAE,WAAW,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAC7D,WAAW,EAAE,WAAW,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;QAC3C,SAAS,EAAE,MAAM,CAAC,6BAA6B,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,IAAI,GAAG,CAAC;QACzE,OAAO,EAAE,MAAM,CAAC,6BAA6B,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,GAAG,CAAC;KACtE,CAAC,CAAC,CAAC;AACN,CAAC;AAED,gDAAgD;AAChD,MAAM,CAAC,KAAK,UAAU,oBAAoB,CAAC,IAAY,EAAE,KAA+C;IACtG,MAAM,EAAE,SAAS,EAAE,WAAW,EAAE,GAAG,MAAM,YAAY,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;IACnE,MAAM,YAAY,GAAkB,EAAE,CAAC;IACvC,MAAM,OAAO,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC;IAClC,KAAK,MAAM,IAAI,IAAI,SAAS;QAAE,YAAY,CAAC,IAAI,CAAC,GAAG,cAAc,CAAC,IAAI,EAAE,MAAM,QAAQ,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC;IAC5H,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,CAAC;AACvC,CAAC"}
|
package/dist/drift.d.ts
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { Unit } from "@poetics/core";
|
|
2
|
+
import type { Declaration } from "./declarations.ts";
|
|
3
|
+
export type DriftKind = "untracked" | "stale" | "orphaned" | "duplicate";
|
|
4
|
+
export interface DriftFinding {
|
|
5
|
+
kind: DriftKind;
|
|
6
|
+
file: string;
|
|
7
|
+
name: string;
|
|
8
|
+
uid?: string;
|
|
9
|
+
message: string;
|
|
10
|
+
}
|
|
11
|
+
export interface Drift {
|
|
12
|
+
findings: DriftFinding[];
|
|
13
|
+
/** Declarations that have a unit (fresh or not). */
|
|
14
|
+
tracked: number;
|
|
15
|
+
/** Tracked units whose latest version matches the code. */
|
|
16
|
+
fresh: number;
|
|
17
|
+
declarations: number;
|
|
18
|
+
}
|
|
19
|
+
export declare const DRIFT_SEVERITY: Record<DriftKind, "error" | "warning">;
|
|
20
|
+
/**
|
|
21
|
+
* Matches declarations to units by file and name (lineage keeps these current
|
|
22
|
+
* across renames and moves). Only units whose file satisfies `covers` can be
|
|
23
|
+
* orphaned: pass the set of files that were scanned, so units for files outside
|
|
24
|
+
* the scan (or that the parser cannot read yet, like .svelte) are left alone.
|
|
25
|
+
* Removed units are history, not code, so they never match: an export that
|
|
26
|
+
* reappears under a removed unit's name gets a new unit.
|
|
27
|
+
*/
|
|
28
|
+
export declare function compareCodeWithStore(declarations: readonly Declaration[], units: readonly Unit[], covers: (file: string) => boolean): Drift;
|
|
29
|
+
//# sourceMappingURL=drift.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"drift.d.ts","sourceRoot":"","sources":["../src/drift.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AAC1C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAErD,MAAM,MAAM,SAAS,GAAG,WAAW,GAAG,OAAO,GAAG,UAAU,GAAG,WAAW,CAAC;AAEzE,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,SAAS,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,KAAK;IACpB,QAAQ,EAAE,YAAY,EAAE,CAAC;IACzB,oDAAoD;IACpD,OAAO,EAAE,MAAM,CAAC;IAChB,2DAA2D;IAC3D,KAAK,EAAE,MAAM,CAAC;IACd,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,eAAO,MAAM,cAAc,EAAE,MAAM,CAAC,SAAS,EAAE,OAAO,GAAG,SAAS,CAKjE,CAAC;AAIF;;;;;;;GAOG;AACH,wBAAgB,oBAAoB,CAClC,YAAY,EAAE,SAAS,WAAW,EAAE,EACpC,KAAK,EAAE,SAAS,IAAI,EAAE,EACtB,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,GAChC,KAAK,CAgEP"}
|