audit-tools 0.32.17 → 0.32.18
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/audit/decompose/buildStructureDecomposition.d.ts +14 -0
- package/dist/audit/decompose/buildStructureDecomposition.d.ts.map +1 -0
- package/dist/audit/decompose/buildStructureDecomposition.js +107 -0
- package/dist/audit/decompose/buildStructureDecomposition.js.map +1 -0
- package/dist/audit/decompose/findings.d.ts +23 -0
- package/dist/audit/decompose/findings.d.ts.map +1 -0
- package/dist/audit/decompose/findings.js +121 -0
- package/dist/audit/decompose/findings.js.map +1 -0
- package/dist/audit/decompose/sources.d.ts +21 -0
- package/dist/audit/decompose/sources.d.ts.map +1 -0
- package/dist/audit/decompose/sources.js +168 -0
- package/dist/audit/decompose/sources.js.map +1 -0
- package/dist/audit/extractors/commentDecomposition.d.ts +52 -0
- package/dist/audit/extractors/commentDecomposition.d.ts.map +1 -0
- package/dist/audit/extractors/commentDecomposition.js +298 -0
- package/dist/audit/extractors/commentDecomposition.js.map +1 -0
- package/dist/audit/extractors/dataStateCoupling.d.ts +26 -0
- package/dist/audit/extractors/dataStateCoupling.d.ts.map +1 -0
- package/dist/audit/extractors/dataStateCoupling.js +71 -0
- package/dist/audit/extractors/dataStateCoupling.js.map +1 -0
- package/dist/audit/io/artifacts.d.ts +3 -0
- package/dist/audit/io/artifacts.d.ts.map +1 -1
- package/dist/audit/io/artifacts.js +1 -0
- package/dist/audit/io/artifacts.js.map +1 -1
- package/dist/audit/orchestrator/dependencyMap.d.ts +1 -0
- package/dist/audit/orchestrator/dependencyMap.d.ts.map +1 -1
- package/dist/audit/orchestrator/dependencyMap.js +11 -0
- package/dist/audit/orchestrator/dependencyMap.js.map +1 -1
- package/dist/audit/orchestrator/executorRunners.d.ts.map +1 -1
- package/dist/audit/orchestrator/executorRunners.js +2 -1
- package/dist/audit/orchestrator/executorRunners.js.map +1 -1
- package/dist/audit/orchestrator/executors.d.ts.map +1 -1
- package/dist/audit/orchestrator/executors.js +5 -0
- package/dist/audit/orchestrator/executors.js.map +1 -1
- package/dist/audit/orchestrator/nextStep.d.ts.map +1 -1
- package/dist/audit/orchestrator/nextStep.js +1 -0
- package/dist/audit/orchestrator/nextStep.js.map +1 -1
- package/dist/audit/orchestrator/state.d.ts.map +1 -1
- package/dist/audit/orchestrator/state.js +4 -0
- package/dist/audit/orchestrator/state.js.map +1 -1
- package/dist/audit/orchestrator/structureExecutors.d.ts +8 -0
- package/dist/audit/orchestrator/structureExecutors.d.ts.map +1 -1
- package/dist/audit/orchestrator/structureExecutors.js +30 -0
- package/dist/audit/orchestrator/structureExecutors.js.map +1 -1
- package/dist/audit/orchestrator/synthesisExecutors.d.ts.map +1 -1
- package/dist/audit/orchestrator/synthesisExecutors.js +1 -0
- package/dist/audit/orchestrator/synthesisExecutors.js.map +1 -1
- package/dist/audit/reporting/mergeFindings.d.ts +2 -1
- package/dist/audit/reporting/mergeFindings.d.ts.map +1 -1
- package/dist/audit/reporting/mergeFindings.js +3 -1
- package/dist/audit/reporting/mergeFindings.js.map +1 -1
- package/dist/audit/reporting/synthesis.d.ts +2 -0
- package/dist/audit/reporting/synthesis.d.ts.map +1 -1
- package/dist/audit/reporting/synthesis.js +1 -1
- package/dist/audit/reporting/synthesis.js.map +1 -1
- package/dist/audit/types/structureDecomposition.d.ts +27 -0
- package/dist/audit/types/structureDecomposition.d.ts.map +1 -0
- package/dist/audit/types/structureDecomposition.js +2 -0
- package/dist/audit/types/structureDecomposition.js.map +1 -0
- package/dist/shared/decompose/consensus.d.ts +66 -0
- package/dist/shared/decompose/consensus.d.ts.map +1 -0
- package/dist/shared/decompose/consensus.js +213 -0
- package/dist/shared/decompose/consensus.js.map +1 -0
- package/dist/shared/decompose/modularity.d.ts +44 -0
- package/dist/shared/decompose/modularity.d.ts.map +1 -0
- package/dist/shared/decompose/modularity.js +249 -0
- package/dist/shared/decompose/modularity.js.map +1 -0
- package/dist/shared/index.d.ts +4 -0
- package/dist/shared/index.d.ts.map +1 -1
- package/dist/shared/index.js +2 -0
- package/dist/shared/index.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { FileDisposition, GraphBundle } from "audit-tools/shared";
|
|
2
|
+
import type { RepoManifest } from "../types.js";
|
|
3
|
+
import type { StructureDecomposition } from "../types/structureDecomposition.js";
|
|
4
|
+
export interface BuildStructureDecompositionParams {
|
|
5
|
+
/** Repo root (absolute); when absent, comment/doc extraction is skipped. */
|
|
6
|
+
root?: string;
|
|
7
|
+
repoManifest: RepoManifest;
|
|
8
|
+
disposition: FileDisposition;
|
|
9
|
+
graphBundle: GraphBundle;
|
|
10
|
+
/** Injectable file reader (tests supply a map-backed reader). */
|
|
11
|
+
readFileText?: (absPath: string) => Promise<string | undefined>;
|
|
12
|
+
}
|
|
13
|
+
export declare function buildStructureDecomposition(params: BuildStructureDecompositionParams): Promise<StructureDecomposition>;
|
|
14
|
+
//# sourceMappingURL=buildStructureDecomposition.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"buildStructureDecomposition.d.ts","sourceRoot":"","sources":["../../../src/audit/decompose/buildStructureDecomposition.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EACV,eAAe,EACf,WAAW,EAEZ,MAAM,oBAAoB,CAAC;AAE5B,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,oCAAoC,CAAC;AAgBjF,MAAM,WAAW,iCAAiC;IAChD,4EAA4E;IAC5E,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,YAAY,EAAE,YAAY,CAAC;IAC3B,WAAW,EAAE,eAAe,CAAC;IAC7B,WAAW,EAAE,WAAW,CAAC;IACzB,iEAAiE;IACjE,YAAY,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC;CACjE;AAmBD,wBAAsB,2BAA2B,CAC/C,MAAM,EAAE,iCAAiC,GACxC,OAAO,CAAC,sBAAsB,CAAC,CA+EjC"}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
// Top-level Phase B orchestration: gather the structure-layer sources (behavior
|
|
2
|
+
// graphs + the two new intent extractors), run the overlay-and-delta operator,
|
|
3
|
+
// emit the non-co-localization findings, and assemble the
|
|
4
|
+
// structure_decomposition.json artifact. The single async entry point the
|
|
5
|
+
// executor calls; the pure pieces it composes are individually tested.
|
|
6
|
+
import { clustersFromPartitions, decompose } from "audit-tools/shared";
|
|
7
|
+
import { deriveCommentDecomposition, deriveDocGroups, } from "../extractors/commentDecomposition.js";
|
|
8
|
+
import { buildStructureSources } from "./sources.js";
|
|
9
|
+
import { detectNonColocalization } from "./findings.js";
|
|
10
|
+
const DOC_EXTENSION = /\.(md|markdown|adoc|rst|txt)$/i;
|
|
11
|
+
/** Threshold at which an intent source's partitions collapse into boundary groups. */
|
|
12
|
+
const INTENT_BOUNDARY_FRACTION = 0.5;
|
|
13
|
+
function toPosix(path) {
|
|
14
|
+
return path.replace(/\\/g, "/");
|
|
15
|
+
}
|
|
16
|
+
/** Convert a partition into its non-trivial member groups (size ≥ 2). */
|
|
17
|
+
function partitionGroups(partition) {
|
|
18
|
+
const byComm = new Map();
|
|
19
|
+
for (const [node, comm] of partition) {
|
|
20
|
+
const list = byComm.get(comm);
|
|
21
|
+
if (list)
|
|
22
|
+
list.push(node);
|
|
23
|
+
else
|
|
24
|
+
byComm.set(comm, [node]);
|
|
25
|
+
}
|
|
26
|
+
const groups = [];
|
|
27
|
+
for (const members of byComm.values()) {
|
|
28
|
+
if (members.length >= 2) {
|
|
29
|
+
groups.push([...members].sort((a, b) => a.localeCompare(b)));
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
return groups;
|
|
33
|
+
}
|
|
34
|
+
export async function buildStructureDecomposition(params) {
|
|
35
|
+
// In-scope code universe = disposition-included files; doc files (prose intent)
|
|
36
|
+
// are the doc_only status plus markdown/asciidoc/rst by extension.
|
|
37
|
+
const universe = [];
|
|
38
|
+
const docFiles = [];
|
|
39
|
+
for (const item of params.disposition.files) {
|
|
40
|
+
const path = toPosix(item.path);
|
|
41
|
+
if (item.status === "included")
|
|
42
|
+
universe.push(path);
|
|
43
|
+
if (item.status === "doc_only" || DOC_EXTENSION.test(path)) {
|
|
44
|
+
if (item.status !== "excluded" && item.status !== "binary") {
|
|
45
|
+
docFiles.push(path);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
const sortedUniverse = [...new Set(universe)].sort((a, b) => a.localeCompare(b));
|
|
50
|
+
const sortedDocs = [...new Set(docFiles)].sort((a, b) => a.localeCompare(b));
|
|
51
|
+
// Async intent extraction (skipped without a root — degrades to empty).
|
|
52
|
+
const commentResult = params.root
|
|
53
|
+
? await deriveCommentDecomposition({
|
|
54
|
+
root: params.root,
|
|
55
|
+
files: sortedUniverse,
|
|
56
|
+
readFileText: params.readFileText,
|
|
57
|
+
})
|
|
58
|
+
: { edges: [], scannedFiles: 0 };
|
|
59
|
+
const docGroups = params.root
|
|
60
|
+
? await deriveDocGroups({
|
|
61
|
+
root: params.root,
|
|
62
|
+
docFiles: sortedDocs,
|
|
63
|
+
codeFiles: sortedUniverse,
|
|
64
|
+
readFileText: params.readFileText,
|
|
65
|
+
})
|
|
66
|
+
: [];
|
|
67
|
+
const sources = buildStructureSources({
|
|
68
|
+
universe: sortedUniverse,
|
|
69
|
+
graphBundle: params.graphBundle,
|
|
70
|
+
commentEdges: commentResult.edges,
|
|
71
|
+
docGroups,
|
|
72
|
+
});
|
|
73
|
+
const result = decompose(sources, "structure");
|
|
74
|
+
// Finding inputs: pooled behavior partitions, all intent-declared boundaries,
|
|
75
|
+
// and the stated-purpose subset (docs + comments) for the smeared-purpose side.
|
|
76
|
+
const behaviorPartitions = sources
|
|
77
|
+
.filter((s) => s.family === "behavior")
|
|
78
|
+
.flatMap((s) => s.partitions);
|
|
79
|
+
const intentBoundaries = [];
|
|
80
|
+
const purposeGroups = [];
|
|
81
|
+
for (const source of sources) {
|
|
82
|
+
if (source.family !== "intent")
|
|
83
|
+
continue;
|
|
84
|
+
const groups = source.partitions.length === 1
|
|
85
|
+
? partitionGroups(source.partitions[0])
|
|
86
|
+
: clustersFromPartitions(source.partitions, INTENT_BOUNDARY_FRACTION);
|
|
87
|
+
intentBoundaries.push(...groups);
|
|
88
|
+
if (source.id === "docs" || source.id === "comments") {
|
|
89
|
+
purposeGroups.push(...groups);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
const findings = detectNonColocalization({
|
|
93
|
+
behaviorPartitions,
|
|
94
|
+
intentBoundaries,
|
|
95
|
+
purposeGroups,
|
|
96
|
+
});
|
|
97
|
+
return {
|
|
98
|
+
generated_at: new Date().toISOString(),
|
|
99
|
+
target: result.target,
|
|
100
|
+
node_universe_size: sortedUniverse.length,
|
|
101
|
+
source_ids: sources.map((s) => s.id),
|
|
102
|
+
consensus: result.consensus,
|
|
103
|
+
contested: result.contested,
|
|
104
|
+
findings,
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
//# sourceMappingURL=buildStructureDecomposition.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"buildStructureDecomposition.js","sourceRoot":"","sources":["../../../src/audit/decompose/buildStructureDecomposition.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { Finding } from "../types.js";
|
|
2
|
+
import type { Partition } from "audit-tools/shared";
|
|
3
|
+
export interface NonColocalizationInput {
|
|
4
|
+
/** Pooled behavior partitions (every resolution of every behavior source). */
|
|
5
|
+
behaviorPartitions: Partition[];
|
|
6
|
+
/** All intent-declared boundaries (directory + docs + comments groups). */
|
|
7
|
+
intentBoundaries: string[][];
|
|
8
|
+
/** Explicit stated-purpose groups (docs + comments only — not directory). */
|
|
9
|
+
purposeGroups: string[][];
|
|
10
|
+
agreementThreshold?: number;
|
|
11
|
+
overlapThreshold?: number;
|
|
12
|
+
/** Minimum behavior-cluster size to report a no-purpose finding. */
|
|
13
|
+
minClusterSize?: number;
|
|
14
|
+
/** Cap on findings emitted per kind (deterministic top-by-size). */
|
|
15
|
+
maxPerKind?: number;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Emit the two non-co-localization finding kinds. Deterministic: clusters/groups
|
|
19
|
+
* are processed largest-first (ties by first member), and ids are a stable
|
|
20
|
+
* instance-scoped SD-### sequence.
|
|
21
|
+
*/
|
|
22
|
+
export declare function detectNonColocalization(input: NonColocalizationInput): Finding[];
|
|
23
|
+
//# sourceMappingURL=findings.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"findings.d.ts","sourceRoot":"","sources":["../../../src/audit/decompose/findings.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AA8BpD,MAAM,WAAW,sBAAsB;IACrC,8EAA8E;IAC9E,kBAAkB,EAAE,SAAS,EAAE,CAAC;IAChC,2EAA2E;IAC3E,gBAAgB,EAAE,MAAM,EAAE,EAAE,CAAC;IAC7B,6EAA6E;IAC7E,aAAa,EAAE,MAAM,EAAE,EAAE,CAAC;IAC1B,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,oEAAoE;IACpE,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,oEAAoE;IACpE,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAOD;;;;GAIG;AACH,wBAAgB,uBAAuB,CACrC,KAAK,EAAE,sBAAsB,GAC5B,OAAO,EAAE,CA+EX"}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
// The two non-co-localization findings (Phase B; design of record
|
|
2
|
+
// spec/conceptual-design-review-design.md §"The two non-co-localizations are
|
|
3
|
+
// first-class findings"). When structure-consensus (behavior) and the
|
|
4
|
+
// intent-declared boundaries FAIL to coincide:
|
|
5
|
+
// - behavioral cluster with no coherent purpose → accidental complexity / dead
|
|
6
|
+
// subsystem (a coupling cluster no declared boundary owns).
|
|
7
|
+
// - a purpose with no behavioral cluster → a goal smeared across the codebase,
|
|
8
|
+
// never modularized (often the highest-value refactor).
|
|
9
|
+
//
|
|
10
|
+
// Deterministic LEADS, not verdicts (confidence: low): they mark where the
|
|
11
|
+
// behavior graphs and the human-declared boundaries disagree, for the Phase C
|
|
12
|
+
// charter pass to confirm against real charters. blast_radius is left unset
|
|
13
|
+
// (Phase C populates goal-graph linkage).
|
|
14
|
+
import { clustersFromPartitions } from "audit-tools/shared";
|
|
15
|
+
/** Structural boundary-integrity findings carry the architecture lens. */
|
|
16
|
+
const LENS = "architecture";
|
|
17
|
+
function createIdGenerator() {
|
|
18
|
+
let n = 1;
|
|
19
|
+
return () => `SD-${String(n++).padStart(3, "0")}`;
|
|
20
|
+
}
|
|
21
|
+
/** |subset ∩ group| / |subset|. */
|
|
22
|
+
function overlapFraction(subset, group) {
|
|
23
|
+
if (subset.length === 0)
|
|
24
|
+
return 0;
|
|
25
|
+
let hit = 0;
|
|
26
|
+
for (const m of subset)
|
|
27
|
+
if (group.has(m))
|
|
28
|
+
hit += 1;
|
|
29
|
+
return hit / subset.length;
|
|
30
|
+
}
|
|
31
|
+
/** Best fraction of `members` contained in any single group. */
|
|
32
|
+
function bestContainment(members, groups) {
|
|
33
|
+
let best = 0;
|
|
34
|
+
for (const group of groups) {
|
|
35
|
+
const set = new Set(group);
|
|
36
|
+
const frac = overlapFraction(members, set);
|
|
37
|
+
if (frac > best)
|
|
38
|
+
best = frac;
|
|
39
|
+
}
|
|
40
|
+
return best;
|
|
41
|
+
}
|
|
42
|
+
const DEFAULT_AGREEMENT = 0.5;
|
|
43
|
+
const DEFAULT_OVERLAP = 0.6;
|
|
44
|
+
const DEFAULT_MIN_CLUSTER = 3;
|
|
45
|
+
const DEFAULT_MAX_PER_KIND = 20;
|
|
46
|
+
/**
|
|
47
|
+
* Emit the two non-co-localization finding kinds. Deterministic: clusters/groups
|
|
48
|
+
* are processed largest-first (ties by first member), and ids are a stable
|
|
49
|
+
* instance-scoped SD-### sequence.
|
|
50
|
+
*/
|
|
51
|
+
export function detectNonColocalization(input) {
|
|
52
|
+
const agreementThreshold = input.agreementThreshold ?? DEFAULT_AGREEMENT;
|
|
53
|
+
const overlapThreshold = input.overlapThreshold ?? DEFAULT_OVERLAP;
|
|
54
|
+
const minClusterSize = input.minClusterSize ?? DEFAULT_MIN_CLUSTER;
|
|
55
|
+
const maxPerKind = input.maxPerKind ?? DEFAULT_MAX_PER_KIND;
|
|
56
|
+
const nextId = createIdGenerator();
|
|
57
|
+
const bySizeThenFirst = (a, b) => b.length - a.length || (a[0] ?? "").localeCompare(b[0] ?? "");
|
|
58
|
+
const findings = [];
|
|
59
|
+
// One clustering pass shared by both detectors: the full set for the
|
|
60
|
+
// purpose-side containment check, the size-filtered set for the no-purpose one.
|
|
61
|
+
const allBehaviorClusters = clustersFromPartitions(input.behaviorPartitions, agreementThreshold);
|
|
62
|
+
// --- Behavioral cluster with no coherent purpose ---
|
|
63
|
+
const behaviorClusters = allBehaviorClusters
|
|
64
|
+
.filter((c) => c.length >= minClusterSize)
|
|
65
|
+
.sort(bySizeThenFirst);
|
|
66
|
+
for (const cluster of behaviorClusters.slice(0, maxPerKind)) {
|
|
67
|
+
const best = bestContainment(cluster, input.intentBoundaries);
|
|
68
|
+
if (best + 1e-12 >= overlapThreshold)
|
|
69
|
+
continue; // aligns to a declared boundary
|
|
70
|
+
findings.push({
|
|
71
|
+
id: nextId(),
|
|
72
|
+
title: `Behavioral cluster spans declared boundaries: ${cluster.length} files`,
|
|
73
|
+
category: "non_colocalization_behavioral",
|
|
74
|
+
severity: "low",
|
|
75
|
+
confidence: "low",
|
|
76
|
+
lens: LENS,
|
|
77
|
+
summary: `These ${cluster.length} files are tightly coupled by behavior (call/import, ` +
|
|
78
|
+
`co-change, and/or shared state) yet no single declared boundary ` +
|
|
79
|
+
`(directory, doc, or comment grouping) contains most of them ` +
|
|
80
|
+
`(best overlap ${(best * 100).toFixed(0)}%). A coupling cluster no ` +
|
|
81
|
+
`declared purpose owns is accidental complexity or a dead subsystem — a ` +
|
|
82
|
+
`lead for the conceptual charter pass to confirm.`,
|
|
83
|
+
affected_files: cluster.map((path) => ({ path })),
|
|
84
|
+
evidence: [
|
|
85
|
+
`Behavioral coupling consensus across ${input.behaviorPartitions.length} resolution levels.`,
|
|
86
|
+
`Best containment in any declared boundary: ${(best * 100).toFixed(0)}% (threshold ${(overlapThreshold * 100).toFixed(0)}%).`,
|
|
87
|
+
],
|
|
88
|
+
systemic: true,
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
// --- A purpose with no behavioral cluster (smeared) ---
|
|
92
|
+
const purposeGroups = [...input.purposeGroups]
|
|
93
|
+
.filter((g) => g.length >= 2)
|
|
94
|
+
.sort(bySizeThenFirst);
|
|
95
|
+
for (const group of purposeGroups.slice(0, maxPerKind)) {
|
|
96
|
+
const best = bestContainment(group, allBehaviorClusters);
|
|
97
|
+
if (best + 1e-12 >= overlapThreshold)
|
|
98
|
+
continue; // the purpose IS a behavior cluster
|
|
99
|
+
findings.push({
|
|
100
|
+
id: nextId(),
|
|
101
|
+
title: `Declared purpose is behaviorally smeared: ${group.length} files`,
|
|
102
|
+
category: "non_colocalization_purpose",
|
|
103
|
+
severity: "low",
|
|
104
|
+
confidence: "low",
|
|
105
|
+
lens: LENS,
|
|
106
|
+
summary: `A doc/comment grouping declares these ${group.length} files a unit, but ` +
|
|
107
|
+
`they do not form a behavioral cluster — no single coupling cluster ` +
|
|
108
|
+
`contains most of them (best overlap ${(best * 100).toFixed(0)}%). A ` +
|
|
109
|
+
`purpose smeared across the codebase and never modularized is often the ` +
|
|
110
|
+
`highest-value refactor — a lead for the conceptual charter pass.`,
|
|
111
|
+
affected_files: group.map((path) => ({ path })),
|
|
112
|
+
evidence: [
|
|
113
|
+
`Declared as one unit by an intent-declared source (doc/comment).`,
|
|
114
|
+
`Best containment in any behavioral cluster: ${(best * 100).toFixed(0)}% (threshold ${(overlapThreshold * 100).toFixed(0)}%).`,
|
|
115
|
+
],
|
|
116
|
+
systemic: true,
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
return findings;
|
|
120
|
+
}
|
|
121
|
+
//# sourceMappingURL=findings.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"findings.js","sourceRoot":"","sources":["../../../src/audit/decompose/findings.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { DecompositionSource, GraphBundle } from "audit-tools/shared";
|
|
2
|
+
import { type CouplingEdge } from "../extractors/dataStateCoupling.js";
|
|
3
|
+
export interface StructureSourcesInput {
|
|
4
|
+
/** In-scope files (posix, sorted, unique) — the shared node universe. */
|
|
5
|
+
universe: string[];
|
|
6
|
+
graphBundle: GraphBundle;
|
|
7
|
+
/** Comment cross-reference edges from deriveCommentDecomposition. */
|
|
8
|
+
commentEdges: CouplingEdge[];
|
|
9
|
+
/** Doc-declared groups from deriveDocGroups. */
|
|
10
|
+
docGroups: string[][];
|
|
11
|
+
resolutions?: readonly number[];
|
|
12
|
+
/** Directory depths for the intent directory family (default [1,2,3]). */
|
|
13
|
+
directoryDepths?: number[];
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Build the structure-layer decomposition sources. Behavior sources with no edges
|
|
17
|
+
* and intent sources with no non-trivial grouping are omitted so an empty source
|
|
18
|
+
* never dilutes the agreement mean.
|
|
19
|
+
*/
|
|
20
|
+
export declare function buildStructureSources(input: StructureSourcesInput): DecompositionSource[];
|
|
21
|
+
//# sourceMappingURL=sources.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sources.d.ts","sourceRoot":"","sources":["../../../src/audit/decompose/sources.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EACV,mBAAmB,EACnB,WAAW,EAEZ,MAAM,oBAAoB,CAAC;AAI5B,OAAO,EAEL,KAAK,YAAY,EAClB,MAAM,oCAAoC,CAAC;AAqF5C,MAAM,WAAW,qBAAqB;IACpC,yEAAyE;IACzE,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,WAAW,EAAE,WAAW,CAAC;IACzB,qEAAqE;IACrE,YAAY,EAAE,YAAY,EAAE,CAAC;IAC7B,gDAAgD;IAChD,SAAS,EAAE,MAAM,EAAE,EAAE,CAAC;IACtB,WAAW,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAChC,0EAA0E;IAC1E,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;CAC5B;AAID;;;;GAIG;AACH,wBAAgB,qBAAqB,CACnC,KAAK,EAAE,qBAAqB,GAC3B,mBAAmB,EAAE,CAmFvB"}
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
// Structure-layer source adapter (Phase B): turns the audit graph substrate into
|
|
2
|
+
// the independently-sourced views the overlay-and-delta operator consumes. PURE —
|
|
3
|
+
// the async extraction (comment/doc reads, git co-change) happens in the executor;
|
|
4
|
+
// this module only shapes already-gathered signals into partitions.
|
|
5
|
+
//
|
|
6
|
+
// Behavior-exhibited sources (call/import, git co-change, data/state) each become
|
|
7
|
+
// a WEIGHTED GRAPH clustered across the resolution ladder → a multi-resolution
|
|
8
|
+
// partition family (feeds both agreed-across-source and stable-across-scale).
|
|
9
|
+
// Intent-declared sources (directory depths, docs, comments) each become one or
|
|
10
|
+
// more PARTITIONS over the same file universe (feed agreed-across-source only).
|
|
11
|
+
import { resolutionSweep } from "audit-tools/shared";
|
|
12
|
+
import { allGraphEdges } from "../extractors/graphSignals.js";
|
|
13
|
+
import { GIT_CO_CHANGE_CATEGORY } from "../extractors/gitHistory.js";
|
|
14
|
+
import { deriveDataStateCoupling, } from "../extractors/dataStateCoupling.js";
|
|
15
|
+
function toPosix(path) {
|
|
16
|
+
return path.replace(/\\/g, "/");
|
|
17
|
+
}
|
|
18
|
+
/** Aggregate undirected edges over the universe into a WeightedGraph. */
|
|
19
|
+
function weightedGraph(universe, edges) {
|
|
20
|
+
const inScope = new Set(universe);
|
|
21
|
+
const byPair = new Map();
|
|
22
|
+
for (const edge of edges) {
|
|
23
|
+
const a = toPosix(edge.a);
|
|
24
|
+
const b = toPosix(edge.b);
|
|
25
|
+
if (a === b || !inScope.has(a) || !inScope.has(b))
|
|
26
|
+
continue;
|
|
27
|
+
if (!(edge.weight > 0))
|
|
28
|
+
continue;
|
|
29
|
+
const lo = a.localeCompare(b) <= 0 ? a : b;
|
|
30
|
+
const hi = a.localeCompare(b) <= 0 ? b : a;
|
|
31
|
+
const key = `${lo} ${hi}`;
|
|
32
|
+
byPair.set(key, (byPair.get(key) ?? 0) + edge.weight);
|
|
33
|
+
}
|
|
34
|
+
const aggregated = [];
|
|
35
|
+
for (const [key, weight] of byPair) {
|
|
36
|
+
const idx = key.indexOf(" ");
|
|
37
|
+
aggregated.push({ a: key.slice(0, idx), b: key.slice(idx + 1), weight });
|
|
38
|
+
}
|
|
39
|
+
return { nodes: universe, edges: aggregated };
|
|
40
|
+
}
|
|
41
|
+
/** Directed graph edges → undirected coupling edges (weight = confidence or 1). */
|
|
42
|
+
function edgesFromGraph(raw) {
|
|
43
|
+
if (!Array.isArray(raw))
|
|
44
|
+
return [];
|
|
45
|
+
const out = [];
|
|
46
|
+
for (const edge of raw) {
|
|
47
|
+
if (!edge ||
|
|
48
|
+
typeof edge.from !== "string" ||
|
|
49
|
+
typeof edge.to !== "string") {
|
|
50
|
+
continue;
|
|
51
|
+
}
|
|
52
|
+
const weight = typeof edge.confidence === "number" && edge.confidence > 0
|
|
53
|
+
? edge.confidence
|
|
54
|
+
: 1;
|
|
55
|
+
out.push({ a: edge.from, b: edge.to, weight });
|
|
56
|
+
}
|
|
57
|
+
return out;
|
|
58
|
+
}
|
|
59
|
+
/** Build a single partition from disjoint member groups; ungrouped → singleton. */
|
|
60
|
+
function partitionFromGroups(universe, groups) {
|
|
61
|
+
const partition = new Map();
|
|
62
|
+
for (const node of universe)
|
|
63
|
+
partition.set(node, node);
|
|
64
|
+
for (const group of groups) {
|
|
65
|
+
const rep = [...group].sort((a, b) => a.localeCompare(b))[0];
|
|
66
|
+
if (!rep)
|
|
67
|
+
continue;
|
|
68
|
+
for (const member of group) {
|
|
69
|
+
const m = toPosix(member);
|
|
70
|
+
if (partition.has(m))
|
|
71
|
+
partition.set(m, rep);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
return partition;
|
|
75
|
+
}
|
|
76
|
+
/** Directory-prefix partition at a given depth (community = first `depth` segs). */
|
|
77
|
+
function directoryPartition(universe, depth) {
|
|
78
|
+
const partition = new Map();
|
|
79
|
+
for (const node of universe) {
|
|
80
|
+
const segs = node.split("/");
|
|
81
|
+
// A file with fewer than depth+1 segments has no dir at this depth → itself.
|
|
82
|
+
const community = segs.length > depth ? segs.slice(0, depth).join("/") : node;
|
|
83
|
+
partition.set(node, community);
|
|
84
|
+
}
|
|
85
|
+
return partition;
|
|
86
|
+
}
|
|
87
|
+
const DEFAULT_DIRECTORY_DEPTHS = [1, 2, 3];
|
|
88
|
+
/**
|
|
89
|
+
* Build the structure-layer decomposition sources. Behavior sources with no edges
|
|
90
|
+
* and intent sources with no non-trivial grouping are omitted so an empty source
|
|
91
|
+
* never dilutes the agreement mean.
|
|
92
|
+
*/
|
|
93
|
+
export function buildStructureSources(input) {
|
|
94
|
+
const universe = [...new Set(input.universe.map(toPosix))].sort((a, b) => a.localeCompare(b));
|
|
95
|
+
const sources = [];
|
|
96
|
+
// --- Behavior-exhibited sources ---
|
|
97
|
+
const callImport = weightedGraph(universe, allGraphEdges(input.graphBundle).map((e) => ({
|
|
98
|
+
a: e.from,
|
|
99
|
+
b: e.to,
|
|
100
|
+
weight: typeof e.confidence === "number" && e.confidence > 0 ? e.confidence : 1,
|
|
101
|
+
})));
|
|
102
|
+
if (callImport.edges.length > 0) {
|
|
103
|
+
sources.push({
|
|
104
|
+
id: "call_import",
|
|
105
|
+
family: "behavior",
|
|
106
|
+
partitions: resolutionSweep(callImport, input.resolutions),
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
const coChangeRaw = input.graphBundle.graphs[GIT_CO_CHANGE_CATEGORY];
|
|
110
|
+
const coChange = weightedGraph(universe, edgesFromGraph(coChangeRaw));
|
|
111
|
+
if (coChange.edges.length > 0) {
|
|
112
|
+
sources.push({
|
|
113
|
+
id: "co_change",
|
|
114
|
+
family: "behavior",
|
|
115
|
+
partitions: resolutionSweep(coChange, input.resolutions),
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
const dataState = weightedGraph(universe, deriveDataStateCoupling(input.graphBundle));
|
|
119
|
+
if (dataState.edges.length > 0) {
|
|
120
|
+
sources.push({
|
|
121
|
+
id: "data_state",
|
|
122
|
+
family: "behavior",
|
|
123
|
+
partitions: resolutionSweep(dataState, input.resolutions),
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
// --- Intent-declared sources ---
|
|
127
|
+
const depths = input.directoryDepths ?? DEFAULT_DIRECTORY_DEPTHS;
|
|
128
|
+
const directoryPartitions = depths.map((d) => directoryPartition(universe, d));
|
|
129
|
+
// Include the directory source only when at least one depth actually groups
|
|
130
|
+
// files (a flat repo with all files at the root yields only singletons).
|
|
131
|
+
const directoryGroups = directoryPartitions.some((p) => hasNonTrivialGroup(p));
|
|
132
|
+
if (directoryGroups) {
|
|
133
|
+
sources.push({
|
|
134
|
+
id: "directory",
|
|
135
|
+
family: "intent",
|
|
136
|
+
partitions: directoryPartitions,
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
if (input.docGroups.length > 0) {
|
|
140
|
+
sources.push({
|
|
141
|
+
id: "docs",
|
|
142
|
+
family: "intent",
|
|
143
|
+
partitions: [partitionFromGroups(universe, input.docGroups)],
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
const commentGraph = weightedGraph(universe, input.commentEdges);
|
|
147
|
+
if (commentGraph.edges.length > 0) {
|
|
148
|
+
// Comment cross-references are a coupling graph; cluster it at the ladder so a
|
|
149
|
+
// comment web forms boundaries the same way behavior graphs do.
|
|
150
|
+
sources.push({
|
|
151
|
+
id: "comments",
|
|
152
|
+
family: "intent",
|
|
153
|
+
partitions: resolutionSweep(commentGraph, input.resolutions),
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
return sources;
|
|
157
|
+
}
|
|
158
|
+
function hasNonTrivialGroup(partition) {
|
|
159
|
+
const counts = new Map();
|
|
160
|
+
for (const comm of partition.values()) {
|
|
161
|
+
counts.set(comm, (counts.get(comm) ?? 0) + 1);
|
|
162
|
+
}
|
|
163
|
+
for (const count of counts.values())
|
|
164
|
+
if (count >= 2)
|
|
165
|
+
return true;
|
|
166
|
+
return false;
|
|
167
|
+
}
|
|
168
|
+
//# sourceMappingURL=sources.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sources.js","sourceRoot":"","sources":["../../../src/audit/decompose/sources.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import type { CouplingEdge } from "./dataStateCoupling.js";
|
|
2
|
+
/**
|
|
3
|
+
* Extract concatenated comment text from source, honoring the file's comment
|
|
4
|
+
* syntax and skipping string literals (single/double/backtick, backslash-escaped)
|
|
5
|
+
* so a comment marker inside a string is not misread. A single-pass char scanner:
|
|
6
|
+
* normal → string → line-comment → block-comment. Degrades gracefully (an
|
|
7
|
+
* unterminated block just consumes to EOF).
|
|
8
|
+
*/
|
|
9
|
+
export declare function extractCommentText(source: string, path: string): string;
|
|
10
|
+
export interface CommentDecompositionResult {
|
|
11
|
+
/** Intent-declared coupling edges from comment cross-references (undirected). */
|
|
12
|
+
edges: CouplingEdge[];
|
|
13
|
+
/** Number of files whose source was read + scanned. */
|
|
14
|
+
scannedFiles: number;
|
|
15
|
+
}
|
|
16
|
+
export interface CommentDecompositionParams {
|
|
17
|
+
root: string;
|
|
18
|
+
/** In-scope repo-relative file paths. */
|
|
19
|
+
files: string[];
|
|
20
|
+
/**
|
|
21
|
+
* Injectable file reader (absolute path → text | undefined). Defaults to a
|
|
22
|
+
* size-capped node:fs read; tests supply a map-backed reader.
|
|
23
|
+
*/
|
|
24
|
+
readFileText?: (absPath: string) => Promise<string | undefined>;
|
|
25
|
+
/** Skip files larger than this many bytes when reading (default 512 KiB). */
|
|
26
|
+
maxBytes?: number;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Derive intent-declared coupling edges from comment cross-references across the
|
|
30
|
+
* in-scope files. For each file, its comment text is scanned for the distinctive
|
|
31
|
+
* reference tokens of OTHER files; a match adds an undirected edge. Deterministic:
|
|
32
|
+
* files are processed in sorted order and edges are canonicalized + sorted.
|
|
33
|
+
*/
|
|
34
|
+
export declare function deriveCommentDecomposition(params: CommentDecompositionParams): Promise<CommentDecompositionResult>;
|
|
35
|
+
export interface DocGroupsParams {
|
|
36
|
+
root: string;
|
|
37
|
+
/** Doc files (prose) to mine — README / ADRs / other markdown. */
|
|
38
|
+
docFiles: string[];
|
|
39
|
+
/** In-scope code files a doc may name (the grouping universe). */
|
|
40
|
+
codeFiles: string[];
|
|
41
|
+
readFileText?: (absPath: string) => Promise<string | undefined>;
|
|
42
|
+
maxBytes?: number;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Derive intent-declared groups from docs: each doc's ENTIRE text (docs are
|
|
46
|
+
* prose, not comment-embedded) is scanned for the reference tokens of in-scope
|
|
47
|
+
* code files; every code file a single doc names becomes one group (the doc
|
|
48
|
+
* declares a module). Returns disjoint member groups of size ≥ 2 (a doc naming
|
|
49
|
+
* one file declares no grouping), lexically sorted. Deterministic.
|
|
50
|
+
*/
|
|
51
|
+
export declare function deriveDocGroups(params: DocGroupsParams): Promise<string[][]>;
|
|
52
|
+
//# sourceMappingURL=commentDecomposition.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"commentDecomposition.d.ts","sourceRoot":"","sources":["../../../src/audit/extractors/commentDecomposition.ts"],"names":[],"mappings":"AA0BA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAiD3D;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAoEvE;AA8CD,MAAM,WAAW,0BAA0B;IACzC,iFAAiF;IACjF,KAAK,EAAE,YAAY,EAAE,CAAC;IACtB,uDAAuD;IACvD,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,0BAA0B;IACzC,IAAI,EAAE,MAAM,CAAC;IACb,yCAAyC;IACzC,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB;;;OAGG;IACH,YAAY,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC;IAChE,6EAA6E;IAC7E,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAiBD;;;;;GAKG;AACH,wBAAsB,0BAA0B,CAC9C,MAAM,EAAE,0BAA0B,GACjC,OAAO,CAAC,0BAA0B,CAAC,CA0DrC;AAED,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,kEAAkE;IAClE,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,kEAAkE;IAClE,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,YAAY,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC;IAChE,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;;;;;GAMG;AACH,wBAAsB,eAAe,CACnC,MAAM,EAAE,eAAe,GACtB,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CA0CrB"}
|