@isaacriehm/cairn-core 0.19.0 → 0.21.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/.tsbuildinfo +1 -1
- package/dist/attention/index.d.ts +0 -2
- package/dist/attention/index.js +0 -2
- package/dist/attention/index.js.map +1 -1
- package/dist/attention/restore.d.ts +1 -1
- package/dist/attention/restore.js +1 -1
- package/dist/attention/source-strip.d.ts +2 -2
- package/dist/attention/source-strip.js +2 -2
- package/dist/components/audit.d.ts +20 -3
- package/dist/components/audit.js +220 -51
- package/dist/components/audit.js.map +1 -1
- package/dist/doctor/index.js +96 -3
- package/dist/doctor/index.js.map +1 -1
- package/dist/gc/citation-integrity.d.ts +2 -2
- package/dist/gc/citation-integrity.js +9 -7
- package/dist/gc/citation-integrity.js.map +1 -1
- package/dist/gc/classify.js +3 -16
- package/dist/gc/classify.js.map +1 -1
- package/dist/gc/entity-orphan.js +7 -5
- package/dist/gc/entity-orphan.js.map +1 -1
- package/dist/gc/sweep.d.ts +1 -1
- package/dist/gc/sweep.js +1 -1
- package/dist/hooks/post-tool-use/ask-user-blocked.d.ts +1 -2
- package/dist/hooks/post-tool-use/ask-user-blocked.js +1 -2
- package/dist/hooks/post-tool-use/ask-user-blocked.js.map +1 -1
- package/dist/hooks/post-tool-use/citation-scanner.d.ts +2 -2
- package/dist/hooks/post-tool-use/citation-scanner.js +1 -1
- package/dist/hooks/post-tool-use/read-enricher.d.ts +1 -1
- package/dist/hooks/post-tool-use/read-enricher.js +1 -1
- package/dist/hooks/post-tool-use/write-guardian.d.ts +1 -5
- package/dist/hooks/post-tool-use/write-guardian.js +21 -14
- package/dist/hooks/post-tool-use/write-guardian.js.map +1 -1
- package/dist/hooks/runners/session-start.js +61 -1
- package/dist/hooks/runners/session-start.js.map +1 -1
- package/dist/hooks/runners/stop.js +20 -30
- package/dist/hooks/runners/stop.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/init/detect-components.d.ts +3 -2
- package/dist/init/detect-components.js +31 -13
- package/dist/init/detect-components.js.map +1 -1
- package/dist/init/detect.d.ts +1 -5
- package/dist/init/detect.js +157 -143
- package/dist/init/detect.js.map +1 -1
- package/dist/init/glob-inference.js +24 -0
- package/dist/init/glob-inference.js.map +1 -1
- package/dist/init/index.d.ts +3 -3
- package/dist/init/index.js +1 -1
- package/dist/init/index.js.map +1 -1
- package/dist/init/init.js +0 -14
- package/dist/init/init.js.map +1 -1
- package/dist/init/mapper-merge.d.ts +1 -4
- package/dist/init/mapper-merge.js +4 -17
- package/dist/init/mapper-merge.js.map +1 -1
- package/dist/init/mapper-parallel.js +1 -1
- package/dist/init/mapper-parallel.js.map +1 -1
- package/dist/init/mapper-prompts.d.ts +1 -23
- package/dist/init/mapper-prompts.js +1 -25
- package/dist/init/mapper-prompts.js.map +1 -1
- package/dist/init/mapper.d.ts +0 -6
- package/dist/init/mapper.js +0 -3
- package/dist/init/mapper.js.map +1 -1
- package/dist/init/module-slicer.js +3 -24
- package/dist/init/module-slicer.js.map +1 -1
- package/dist/init/overlay.js +5 -16
- package/dist/init/overlay.js.map +1 -1
- package/dist/init/phases/9d-comp-walk.js +1 -1
- package/dist/init/phases/9d-comp-walk.js.map +1 -1
- package/dist/init/source-comments/strip-replace.d.ts +1 -1
- package/dist/init/source-comments/strip-replace.js +2 -2
- package/dist/init/source-comments/walker.js +8 -79
- package/dist/init/source-comments/walker.js.map +1 -1
- package/dist/init/types.d.ts +8 -16
- package/dist/init/walker.d.ts +1 -1
- package/dist/init/walker.js +1 -1
- package/dist/mcp/schemas.d.ts +4 -4
- package/dist/mcp/schemas.js +1 -1
- package/dist/mcp/serve.js +9 -0
- package/dist/mcp/serve.js.map +1 -1
- package/dist/mcp/tools/decision-get.js +2 -2
- package/dist/mcp/tools/decision-get.js.map +1 -1
- package/dist/mcp/tools/index.js +0 -6
- package/dist/mcp/tools/index.js.map +1 -1
- package/dist/mcp/tools/mission-advance.d.ts +3 -4
- package/dist/mcp/tools/mission-advance.js +10 -14
- package/dist/mcp/tools/mission-advance.js.map +1 -1
- package/dist/mcp/tools/record-decision.js +7 -6
- package/dist/mcp/tools/record-decision.js.map +1 -1
- package/dist/mcp/tools/resolve-attention.js +50 -30
- package/dist/mcp/tools/resolve-attention.js.map +1 -1
- package/dist/migrate/config-io.d.ts +16 -0
- package/dist/migrate/config-io.js +71 -0
- package/dist/migrate/config-io.js.map +1 -0
- package/dist/migrate/index.d.ts +5 -0
- package/dist/migrate/index.js +5 -0
- package/dist/migrate/index.js.map +1 -0
- package/dist/migrate/migrations/0001-drop-dead-config-fields.d.ts +12 -0
- package/dist/migrate/migrations/0001-drop-dead-config-fields.js +39 -0
- package/dist/migrate/migrations/0001-drop-dead-config-fields.js.map +1 -0
- package/dist/migrate/registry.d.ts +9 -0
- package/dist/migrate/registry.js +10 -0
- package/dist/migrate/registry.js.map +1 -0
- package/dist/migrate/runner.d.ts +45 -0
- package/dist/migrate/runner.js +170 -0
- package/dist/migrate/runner.js.map +1 -0
- package/dist/migrate/semver.d.ts +11 -0
- package/dist/migrate/semver.js +35 -0
- package/dist/migrate/semver.js.map +1 -0
- package/dist/migrate/types.d.ts +39 -0
- package/dist/migrate/types.js +13 -0
- package/dist/migrate/types.js.map +1 -0
- package/dist/missions/task-link.js +3 -3
- package/dist/missions/task-link.js.map +1 -1
- package/dist/sensors/catalog.js +4 -9
- package/dist/sensors/catalog.js.map +1 -1
- package/dist/sensors/decisions.js +55 -19
- package/dist/sensors/decisions.js.map +1 -1
- package/dist/sensors/diff.d.ts +12 -0
- package/dist/sensors/diff.js +103 -0
- package/dist/sensors/diff.js.map +1 -1
- package/dist/sensors/index.d.ts +4 -5
- package/dist/sensors/index.js +2 -3
- package/dist/sensors/index.js.map +1 -1
- package/dist/sensors/runner.d.ts +34 -37
- package/dist/sensors/runner.js +63 -53
- package/dist/sensors/runner.js.map +1 -1
- package/dist/sensors/stub-catalog.d.ts +6 -3
- package/dist/sensors/stub-catalog.js +7 -19
- package/dist/sensors/stub-catalog.js.map +1 -1
- package/dist/sensors/types.d.ts +11 -55
- package/dist/sensors/types.js +4 -8
- package/dist/sensors/types.js.map +1 -1
- package/dist/session-start/build.js +5 -5
- package/dist/session-start/build.js.map +1 -1
- package/dist/session-start/templates.d.ts +1 -1
- package/dist/session-start/templates.js +1 -1
- package/dist/tasks/lifecycle.d.ts +3 -4
- package/dist/tasks/lifecycle.js +9 -12
- package/dist/tasks/lifecycle.js.map +1 -1
- package/package.json +2 -2
- package/templates/.cairn/git-hooks/pre-commit +7 -4
- package/templates/.github/workflows/cairn-check.yml +8 -0
- package/dist/attention/bulk-accept.d.ts +0 -78
- package/dist/attention/bulk-accept.js +0 -348
- package/dist/attention/bulk-accept.js.map +0 -1
- package/dist/attention/serve/api.d.ts +0 -24
- package/dist/attention/serve/api.js +0 -383
- package/dist/attention/serve/api.js.map +0 -1
- package/dist/attention/serve/index.d.ts +0 -63
- package/dist/attention/serve/index.js +0 -219
- package/dist/attention/serve/index.js.map +0 -1
- package/dist/mcp/tools/attention-serve.d.ts +0 -23
- package/dist/mcp/tools/attention-serve.js +0 -84
- package/dist/mcp/tools/attention-serve.js.map +0 -1
- package/dist/mcp/tools/attention-wait.d.ts +0 -18
- package/dist/mcp/tools/attention-wait.js +0 -84
- package/dist/mcp/tools/attention-wait.js.map +0 -1
- package/dist/mcp/tools/bulk-accept-attention.d.ts +0 -22
- package/dist/mcp/tools/bulk-accept-attention.js +0 -84
- package/dist/mcp/tools/bulk-accept-attention.js.map +0 -1
- package/dist/sensors/attestation.d.ts +0 -44
- package/dist/sensors/attestation.js +0 -262
- package/dist/sensors/attestation.js.map +0 -1
|
@@ -1,6 +1,4 @@
|
|
|
1
1
|
export { scoreDecDraft, scoreInvariant, type DraftConfidence, type DraftScoreInput, } from "./scoring.js";
|
|
2
|
-
export { bulkAcceptObvious, type BulkAcceptArgs, type BulkAcceptResult, } from "./bulk-accept.js";
|
|
3
2
|
export { findDuplicateClusters, DEFAULT_THRESHOLD_DEFINITE, DEFAULT_THRESHOLD_FLOOR, type DraftRef, type DuplicateCluster, type DedupResult, } from "./dedup.js";
|
|
4
3
|
export { parseDraftMeta, findLatestSourceCommentsAudit, runDecSourceStrip, type DraftMeta, type StripOutcomeSummary, } from "./source-strip.js";
|
|
5
4
|
export { restoreDec, type RestoreArgs, type RestoreResult, type RestoreState, } from "./restore.js";
|
|
6
|
-
export { getActiveAttentionServer, startAttentionServer, type AttentionServeOptions, type AttentionServeHandle, type DoneState, } from "./serve/index.js";
|
package/dist/attention/index.js
CHANGED
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
export { scoreDecDraft, scoreInvariant, } from "./scoring.js";
|
|
2
|
-
export { bulkAcceptObvious, } from "./bulk-accept.js";
|
|
3
2
|
export { findDuplicateClusters, DEFAULT_THRESHOLD_DEFINITE, DEFAULT_THRESHOLD_FLOOR, } from "./dedup.js";
|
|
4
3
|
export { parseDraftMeta, findLatestSourceCommentsAudit, runDecSourceStrip, } from "./source-strip.js";
|
|
5
4
|
export { restoreDec, } from "./restore.js";
|
|
6
|
-
export { getActiveAttentionServer, startAttentionServer, } from "./serve/index.js";
|
|
7
5
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/attention/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,aAAa,EACb,cAAc,GAGf,MAAM,cAAc,CAAC;AAEtB,OAAO,EACL,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/attention/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,aAAa,EACb,cAAc,GAGf,MAAM,cAAc,CAAC;AAEtB,OAAO,EACL,qBAAqB,EACrB,0BAA0B,EAC1B,uBAAuB,GAIxB,MAAM,YAAY,CAAC;AAEpB,OAAO,EACL,cAAc,EACd,6BAA6B,EAC7B,iBAAiB,GAGlB,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EACL,UAAU,GAIX,MAAM,cAAc,CAAC"}
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
* `_inbox/<id>.draft.md`, flip `status: accepted` → the original
|
|
18
18
|
* draft status, and rebuild the decisions ledger so the canonical
|
|
19
19
|
* surface no longer resolves the id. Source files keep the
|
|
20
|
-
* `// §DEC
|
|
20
|
+
* `// §DEC-<hash>` cite (we don't reverse-strip — the cite is a
|
|
21
21
|
* durable artifact of the prior accept and removing it without
|
|
22
22
|
* operator intent risks dropping a legit DEC reference if the
|
|
23
23
|
* operator never re-accepts). Operator can re-accept (idempotent
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
* `_inbox/<id>.draft.md`, flip `status: accepted` → the original
|
|
18
18
|
* draft status, and rebuild the decisions ledger so the canonical
|
|
19
19
|
* surface no longer resolves the id. Source files keep the
|
|
20
|
-
* `// §DEC
|
|
20
|
+
* `// §DEC-<hash>` cite (we don't reverse-strip — the cite is a
|
|
21
21
|
* durable artifact of the prior accept and removing it without
|
|
22
22
|
* operator intent risks dropping a legit DEC reference if the
|
|
23
23
|
* operator never re-accepts). Operator can re-accept (idempotent
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* comments) to `_inbox/` and stamps `sourceFile` + `blockId` on the
|
|
6
6
|
* frontmatter. When the operator accepts a draft — either inline via
|
|
7
7
|
* `cairn_resolve_attention` or in bulk via `cairn_bulk_accept_attention`
|
|
8
|
-
* — the original essay should be replaced with `// §DEC
|
|
8
|
+
* — the original essay should be replaced with `// §DEC-<hash>` so the
|
|
9
9
|
* file ends up carrying the canonical bare cite, not the original prose.
|
|
10
10
|
*
|
|
11
11
|
* The full block coordinates (start/end byte offsets, language) live in
|
|
@@ -34,7 +34,7 @@ export interface StripOutcomeSummary {
|
|
|
34
34
|
export declare function findLatestSourceCommentsAudit(repoRoot: string): string | null;
|
|
35
35
|
/**
|
|
36
36
|
* Strip the original source-comment block for one accepted DEC and
|
|
37
|
-
* replace it with `// §DEC
|
|
37
|
+
* replace it with `// §DEC-<hash>` (or `# §DEC-<hash>` in hash-comment
|
|
38
38
|
* languages). Reads block coordinates from the latest 7b audit YAML;
|
|
39
39
|
* skips when the audit is missing, the block id isn't found, or the
|
|
40
40
|
* source file is dirty (strip-replace's own dirty check).
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* comments) to `_inbox/` and stamps `sourceFile` + `blockId` on the
|
|
6
6
|
* frontmatter. When the operator accepts a draft — either inline via
|
|
7
7
|
* `cairn_resolve_attention` or in bulk via `cairn_bulk_accept_attention`
|
|
8
|
-
* — the original essay should be replaced with `// §DEC
|
|
8
|
+
* — the original essay should be replaced with `// §DEC-<hash>` so the
|
|
9
9
|
* file ends up carrying the canonical bare cite, not the original prose.
|
|
10
10
|
*
|
|
11
11
|
* The full block coordinates (start/end byte offsets, language) live in
|
|
@@ -136,7 +136,7 @@ export function findLatestSourceCommentsAudit(repoRoot) {
|
|
|
136
136
|
}
|
|
137
137
|
/**
|
|
138
138
|
* Strip the original source-comment block for one accepted DEC and
|
|
139
|
-
* replace it with `// §DEC
|
|
139
|
+
* replace it with `// §DEC-<hash>` (or `# §DEC-<hash>` in hash-comment
|
|
140
140
|
* languages). Reads block coordinates from the latest 7b audit YAML;
|
|
141
141
|
* skips when the audit is missing, the block id isn't found, or the
|
|
142
142
|
* source file is dirty (strip-replace's own dirty check).
|
|
@@ -1,16 +1,33 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Component audit — advisory, read-only, never blocks (port invariant 5).
|
|
3
3
|
*
|
|
4
|
+
* Language-agnostic: class extraction, unit-shape, and style attributes come
|
|
5
|
+
* from the shared `languages.ts` profile table (className for JSX, class= /
|
|
6
|
+
* :class for Vue/Svelte/HTML, SwiftUI `View`, Flutter `Widget`, …). The
|
|
7
|
+
* Tailwind-specific inline-rebuild scan (1) is gated on a detected Tailwind
|
|
8
|
+
* config — a non-Tailwind repo skips it rather than misfiring.
|
|
9
|
+
*
|
|
4
10
|
* Finds violations that predate adoption:
|
|
5
|
-
* 1. Probable inline rebuilds —
|
|
11
|
+
* 1. Probable inline rebuilds — class lists in non-component code
|
|
6
12
|
* whose Tailwind utility ROOTS closely match an indexed component's
|
|
7
13
|
* (max-w-2xl ≈ max-w-4xl, so value-tweaked copies still match).
|
|
14
|
+
* Similarity is IDF-weighted over the component corpus: a utility root
|
|
15
|
+
* that nearly every component uses (`flex`, `gap`, `mx`, `px`) carries
|
|
16
|
+
* almost no weight, so a page sharing only generic layout scaffolding
|
|
17
|
+
* does NOT match — only overlap on DISTINCTIVE class roots counts. This
|
|
18
|
+
* is self-tuning to the project's own CSS; no hardcoded utility list.
|
|
8
19
|
* 2. Name collisions — `@cairn` names colliding with a type/interface name.
|
|
20
|
+
* 3. Unregistered components — a component-shaped file (PascalCase
|
|
21
|
+
* basename, real exports, JSX markup) sitting OUTSIDE the declared
|
|
22
|
+
* component dirs. These are co-located components the registry can't
|
|
23
|
+
* see; route entry files (page.tsx/layout.tsx — lowercase) are
|
|
24
|
+
* naturally excluded, so no framework convention list is hardcoded.
|
|
25
|
+
* Surfaced as an offer to relocate or register the dir — never moved.
|
|
9
26
|
*
|
|
10
27
|
* Findings are triage input surfaced to the attention queue with EXTEND /
|
|
11
|
-
* rename recommendations; never auto-fixed.
|
|
28
|
+
* rename / register recommendations; never auto-fixed.
|
|
12
29
|
*/
|
|
13
|
-
export type ComponentAuditKind = "inline-rebuild" | "name-collision";
|
|
30
|
+
export type ComponentAuditKind = "inline-rebuild" | "name-collision" | "unregistered-component";
|
|
14
31
|
export interface ComponentAuditFinding {
|
|
15
32
|
kind: ComponentAuditKind;
|
|
16
33
|
/** Where the probable violation lives (repo-relative POSIX). */
|
package/dist/components/audit.js
CHANGED
|
@@ -1,24 +1,83 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Component audit — advisory, read-only, never blocks (port invariant 5).
|
|
3
3
|
*
|
|
4
|
+
* Language-agnostic: class extraction, unit-shape, and style attributes come
|
|
5
|
+
* from the shared `languages.ts` profile table (className for JSX, class= /
|
|
6
|
+
* :class for Vue/Svelte/HTML, SwiftUI `View`, Flutter `Widget`, …). The
|
|
7
|
+
* Tailwind-specific inline-rebuild scan (1) is gated on a detected Tailwind
|
|
8
|
+
* config — a non-Tailwind repo skips it rather than misfiring.
|
|
9
|
+
*
|
|
4
10
|
* Finds violations that predate adoption:
|
|
5
|
-
* 1. Probable inline rebuilds —
|
|
11
|
+
* 1. Probable inline rebuilds — class lists in non-component code
|
|
6
12
|
* whose Tailwind utility ROOTS closely match an indexed component's
|
|
7
13
|
* (max-w-2xl ≈ max-w-4xl, so value-tweaked copies still match).
|
|
14
|
+
* Similarity is IDF-weighted over the component corpus: a utility root
|
|
15
|
+
* that nearly every component uses (`flex`, `gap`, `mx`, `px`) carries
|
|
16
|
+
* almost no weight, so a page sharing only generic layout scaffolding
|
|
17
|
+
* does NOT match — only overlap on DISTINCTIVE class roots counts. This
|
|
18
|
+
* is self-tuning to the project's own CSS; no hardcoded utility list.
|
|
8
19
|
* 2. Name collisions — `@cairn` names colliding with a type/interface name.
|
|
20
|
+
* 3. Unregistered components — a component-shaped file (PascalCase
|
|
21
|
+
* basename, real exports, JSX markup) sitting OUTSIDE the declared
|
|
22
|
+
* component dirs. These are co-located components the registry can't
|
|
23
|
+
* see; route entry files (page.tsx/layout.tsx — lowercase) are
|
|
24
|
+
* naturally excluded, so no framework convention list is hardcoded.
|
|
25
|
+
* Surfaced as an offer to relocate or register the dir — never moved.
|
|
9
26
|
*
|
|
10
27
|
* Findings are triage input surfaced to the attention queue with EXTEND /
|
|
11
|
-
* rename recommendations; never auto-fixed.
|
|
28
|
+
* rename / register recommendations; never auto-fixed.
|
|
12
29
|
*/
|
|
13
|
-
import { readFileSync } from "node:fs";
|
|
30
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
14
31
|
import { join } from "node:path";
|
|
15
|
-
import { collectComponents, hasComponentConfig, loadComponentsConfig, walkFs, } from "@isaacriehm/cairn-state";
|
|
16
|
-
import { jaccard } from "../text/jaccard.js";
|
|
32
|
+
import { collectComponents, escapeRegExp, extractExportName, hasComponentConfig, loadComponentsConfig, profileForExtension, profileForFile, typeDeclKeywordsForFile, walkFs, } from "@isaacriehm/cairn-state";
|
|
17
33
|
const SIMILARITY_THRESHOLD = 0.7;
|
|
18
34
|
const MIN_SHARED_ROOTS = 3;
|
|
19
35
|
const MIN_CLASSES = 3;
|
|
20
|
-
|
|
36
|
+
/**
|
|
37
|
+
* A shared root only counts toward MIN_SHARED_ROOTS if it is distinctive —
|
|
38
|
+
* idf ≥ ln(2), i.e. the root appears in fewer than ~half of all components.
|
|
39
|
+
* Ubiquitous layout utilities fall below this and never satisfy the gate.
|
|
40
|
+
*/
|
|
41
|
+
const IDF_DISTINCTIVE_FLOOR = Math.log(2);
|
|
21
42
|
const VALUE_SUFFIX = /-(?:\d[^-]*|xs|sm|md|lg|xl|\dxl|auto|full|none|screen|px)$/;
|
|
43
|
+
/** Tailwind config filenames — presence gates the inline-rebuild scan. */
|
|
44
|
+
const TAILWIND_CONFIGS = [
|
|
45
|
+
"tailwind.config.js",
|
|
46
|
+
"tailwind.config.cjs",
|
|
47
|
+
"tailwind.config.mjs",
|
|
48
|
+
"tailwind.config.ts",
|
|
49
|
+
];
|
|
50
|
+
/**
|
|
51
|
+
* Whether the project uses Tailwind — the inline-rebuild scan's utility-root
|
|
52
|
+
* grammar is Tailwind-specific, so a non-Tailwind repo skips it rather than
|
|
53
|
+
* misfiring. Detected by config-file presence (root or any workspace's top
|
|
54
|
+
* segment) or a `tailwindcss` dependency, never assumed.
|
|
55
|
+
*/
|
|
56
|
+
function usesTailwind(repoRoot, config) {
|
|
57
|
+
const dirs = new Set([""]);
|
|
58
|
+
for (const ws of config.workspaces) {
|
|
59
|
+
for (const d of ws.componentDirs) {
|
|
60
|
+
const seg = d.split("/")[0];
|
|
61
|
+
if (seg)
|
|
62
|
+
dirs.add(seg);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
for (const dir of dirs) {
|
|
66
|
+
for (const name of TAILWIND_CONFIGS) {
|
|
67
|
+
if (existsSync(join(repoRoot, dir, name)))
|
|
68
|
+
return true;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
try {
|
|
72
|
+
const pkg = JSON.parse(readFileSync(join(repoRoot, "package.json"), "utf8"));
|
|
73
|
+
if (pkg.dependencies?.["tailwindcss"] ?? pkg.devDependencies?.["tailwindcss"])
|
|
74
|
+
return true;
|
|
75
|
+
}
|
|
76
|
+
catch {
|
|
77
|
+
/* no / invalid package.json */
|
|
78
|
+
}
|
|
79
|
+
return false;
|
|
80
|
+
}
|
|
22
81
|
const SKIP_DIRS = new Set([".git", ".cairn", "node_modules", "dist", ".next", "build", "coverage"]);
|
|
23
82
|
/** "max-w-2xl" → "max-w", "px-4" → "px", "items-center" → unchanged. */
|
|
24
83
|
function utilityRoot(cls) {
|
|
@@ -30,54 +89,137 @@ function utilityRoot(cls) {
|
|
|
30
89
|
} while (cur !== prev && cur.includes("-"));
|
|
31
90
|
return cur || prev;
|
|
32
91
|
}
|
|
33
|
-
|
|
92
|
+
/**
|
|
93
|
+
* Class lists found via the file's language profile style-attribute regexes
|
|
94
|
+
* (`className=` for JSX, `class=` / `:class` for Vue/Svelte/HTML, …). The
|
|
95
|
+
* captured class string is whichever of the alternation's groups matched.
|
|
96
|
+
*/
|
|
97
|
+
function classLists(source, styleAttrs) {
|
|
34
98
|
const lists = [];
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
99
|
+
for (const attr of styleAttrs) {
|
|
100
|
+
const re = new RegExp(attr.source, attr.flags.includes("g") ? attr.flags : `${attr.flags}g`);
|
|
101
|
+
let m;
|
|
102
|
+
while ((m = re.exec(source)) !== null) {
|
|
103
|
+
let captured = "";
|
|
104
|
+
for (let i = 1; i < m.length; i++) {
|
|
105
|
+
if (m[i] !== undefined) {
|
|
106
|
+
captured = m[i];
|
|
107
|
+
break;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
const raw = captured.replace(/\$\{[^}]*\}/g, " ");
|
|
111
|
+
const classes = raw.split(/\s+/).filter(Boolean);
|
|
112
|
+
if (classes.length >= MIN_CLASSES) {
|
|
113
|
+
lists.push({ classes, line: source.slice(0, m.index).split("\n").length });
|
|
114
|
+
}
|
|
115
|
+
if (re.lastIndex === m.index)
|
|
116
|
+
re.lastIndex += 1;
|
|
42
117
|
}
|
|
43
118
|
}
|
|
44
119
|
return lists;
|
|
45
120
|
}
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
return { score: jaccard(ra, rb), shared };
|
|
121
|
+
/** Style-attribute regexes for a file, or `[]` when the language is unknown. */
|
|
122
|
+
function styleAttrsFor(rel) {
|
|
123
|
+
return profileForFile(rel)?.styleAttrs ?? [];
|
|
124
|
+
}
|
|
125
|
+
/** Distinct utility roots of a class list. */
|
|
126
|
+
function rootSet(classes) {
|
|
127
|
+
return new Set(classes.map(utilityRoot));
|
|
54
128
|
}
|
|
55
129
|
function inComponentDirs(rel, config) {
|
|
56
130
|
return config.workspaces.some((ws) => ws.componentDirs.some((d) => rel === d || rel.startsWith(`${d}/`)));
|
|
57
131
|
}
|
|
132
|
+
/**
|
|
133
|
+
* If a file outside the component dirs looks like a misplaced reusable UNIT
|
|
134
|
+
* (rather than a hook/util/route entry or markup duplicated inside
|
|
135
|
+
* non-component code), return its exported names; otherwise null. The
|
|
136
|
+
* "looks like a unit" test is the file's language profile `isUnitShaped` —
|
|
137
|
+
* React PascalCase + JSX, a Vue/Svelte SFC, a SwiftUI `View`, a Flutter
|
|
138
|
+
* `Widget`, a Compose `@Composable` — never a hardcoded framework list.
|
|
139
|
+
*/
|
|
140
|
+
function misplacedUnitExports(rel, source) {
|
|
141
|
+
const profile = profileForFile(rel);
|
|
142
|
+
if (profile === null || !profile.isUnitShaped(source, rel))
|
|
143
|
+
return null;
|
|
144
|
+
const names = profile.exportSymbols(source, rel);
|
|
145
|
+
return names.length > 0 ? names : null;
|
|
146
|
+
}
|
|
58
147
|
export function runComponentAudit(repoRoot) {
|
|
59
148
|
const config = loadComponentsConfig(repoRoot);
|
|
60
149
|
if (!hasComponentConfig(config))
|
|
61
150
|
return { findings: [], scanned: 0 };
|
|
62
151
|
const { components } = collectComponents(repoRoot, config);
|
|
63
152
|
const extensions = new Set(config.workspaces.flatMap((w) => w.extensions));
|
|
64
|
-
|
|
153
|
+
// Files scanned for type-name collisions: the configured UI extensions plus
|
|
154
|
+
// their language families, so a `.tsx` project also scans sibling `.ts`
|
|
155
|
+
// type files — derived from the registry, not a hardcoded `.ts`.
|
|
156
|
+
const typeExts = new Set(extensions);
|
|
157
|
+
for (const e of extensions) {
|
|
158
|
+
for (const x of profileForExtension(e)?.extensions ?? [])
|
|
159
|
+
typeExts.add(x);
|
|
160
|
+
}
|
|
65
161
|
const skipDirs = new Set([...SKIP_DIRS, ...config.workspaces.flatMap((w) => w.exclude)]);
|
|
162
|
+
// The inline-rebuild grammar is Tailwind-specific; non-Tailwind repos skip
|
|
163
|
+
// it (unregistered-component + name-collision still run).
|
|
164
|
+
const tailwind = usesTailwind(repoRoot, config);
|
|
66
165
|
const findings = [];
|
|
67
166
|
let scanned = 0;
|
|
68
167
|
// ── 1. Inline-rebuild scan ────────────────────────────────────────────
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
168
|
+
// Each component's class lists (per the file's profile), utility roots
|
|
169
|
+
// precomputed. Skipped entirely when the project isn't on Tailwind.
|
|
170
|
+
const signatures = !tailwind
|
|
171
|
+
? []
|
|
172
|
+
: components
|
|
173
|
+
.map((c) => {
|
|
174
|
+
let src = "";
|
|
175
|
+
try {
|
|
176
|
+
src = readFileSync(join(repoRoot, c.file), "utf8");
|
|
177
|
+
}
|
|
178
|
+
catch {
|
|
179
|
+
/* skip unreadable */
|
|
180
|
+
}
|
|
181
|
+
const lists = classLists(src, styleAttrsFor(c.file)).map((l) => ({
|
|
182
|
+
line: l.line,
|
|
183
|
+
roots: rootSet(l.classes),
|
|
184
|
+
}));
|
|
185
|
+
return { name: c.tags.cairn ?? "?", file: c.file, lists };
|
|
186
|
+
})
|
|
187
|
+
.filter((c) => c.lists.length > 0);
|
|
188
|
+
// Corpus IDF: how distinctive each utility root is. A root present in many
|
|
189
|
+
// components (df → N) gets idf → 0; a rare root gets a high weight. Document
|
|
190
|
+
// = one component (union of its lists' roots), so repetition within a file
|
|
191
|
+
// doesn't inflate frequency.
|
|
192
|
+
const corpusN = signatures.length;
|
|
193
|
+
const docFreq = new Map();
|
|
194
|
+
for (const c of signatures) {
|
|
195
|
+
const compRoots = new Set();
|
|
196
|
+
for (const l of c.lists)
|
|
197
|
+
for (const r of l.roots)
|
|
198
|
+
compRoots.add(r);
|
|
199
|
+
for (const r of compRoots)
|
|
200
|
+
docFreq.set(r, (docFreq.get(r) ?? 0) + 1);
|
|
201
|
+
}
|
|
202
|
+
const idf = (root) => Math.log((corpusN + 1) / ((docFreq.get(root) ?? 0) + 1));
|
|
203
|
+
// IDF-weighted Jaccard between two root sets, plus the count of shared
|
|
204
|
+
// DISTINCTIVE roots (ubiquitous roots don't count toward the gate).
|
|
205
|
+
const weightedSimilarity = (target, comp) => {
|
|
206
|
+
let inter = 0;
|
|
207
|
+
let union = 0;
|
|
208
|
+
let shared = 0;
|
|
209
|
+
for (const r of target) {
|
|
210
|
+
const w = idf(r);
|
|
211
|
+
union += w;
|
|
212
|
+
if (comp.has(r)) {
|
|
213
|
+
inter += w;
|
|
214
|
+
if (w >= IDF_DISTINCTIVE_FLOOR)
|
|
215
|
+
shared += 1;
|
|
216
|
+
}
|
|
77
217
|
}
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
218
|
+
for (const r of comp)
|
|
219
|
+
if (!target.has(r))
|
|
220
|
+
union += idf(r);
|
|
221
|
+
return { score: union > 0 ? inter / union : 0, shared };
|
|
222
|
+
};
|
|
81
223
|
// ── 2. Name-collision prep ────────────────────────────────────────────
|
|
82
224
|
const nameToComponent = new Map();
|
|
83
225
|
for (const c of components)
|
|
@@ -105,14 +247,35 @@ export function runComponentAudit(repoRoot) {
|
|
|
105
247
|
scanned += 1;
|
|
106
248
|
// Inline rebuild — only in non-component code with a UI extension.
|
|
107
249
|
if (extensions.has(ext) && !inComponentDirs(rel, config)) {
|
|
108
|
-
|
|
250
|
+
// A unit-shaped file outside the component dirs is not a rebuild — it
|
|
251
|
+
// is a co-located component the registry can't see. Surface it (with
|
|
252
|
+
// its export names + file) as an offer to relocate/register; skip the
|
|
253
|
+
// rebuild scan for it.
|
|
254
|
+
const exports = misplacedUnitExports(rel, source);
|
|
255
|
+
if (exports !== null) {
|
|
256
|
+
const primary = extractExportName(source, rel) ?? exports[0];
|
|
257
|
+
const others = exports.filter((n) => n !== primary);
|
|
258
|
+
const dirs = config.workspaces.flatMap((w) => w.componentDirs).join(", ");
|
|
259
|
+
findings.push({
|
|
260
|
+
kind: "unregistered-component",
|
|
261
|
+
file: rel,
|
|
262
|
+
component: primary,
|
|
263
|
+
componentFile: rel,
|
|
264
|
+
message: `${primary} (${rel})${others.length > 0 ? ` — also exports ${others.join(", ")}` : ""} ` +
|
|
265
|
+
`looks like a component but lives outside the declared component dir(s) (${dirs}); the registry can't see it`,
|
|
266
|
+
recommendation: `move ${rel} into a component dir, or add its directory to the workspace's componentDirs — then header + index ${primary}`,
|
|
267
|
+
});
|
|
268
|
+
return;
|
|
269
|
+
}
|
|
270
|
+
for (const target of tailwind ? classLists(source, styleAttrsFor(rel)) : []) {
|
|
271
|
+
const troots = rootSet(target.classes);
|
|
109
272
|
let best = null;
|
|
110
273
|
for (const comp of signatures) {
|
|
111
274
|
for (const list of comp.lists) {
|
|
112
|
-
const { score, shared } =
|
|
275
|
+
const { score, shared } = weightedSimilarity(troots, list.roots);
|
|
113
276
|
if (score >= SIMILARITY_THRESHOLD && shared >= MIN_SHARED_ROOTS) {
|
|
114
277
|
if (best === null || score > best.score) {
|
|
115
|
-
best = { name: comp.name, file: comp.file,
|
|
278
|
+
best = { name: comp.name, file: comp.file, score };
|
|
116
279
|
}
|
|
117
280
|
}
|
|
118
281
|
}
|
|
@@ -131,20 +294,26 @@ export function runComponentAudit(repoRoot) {
|
|
|
131
294
|
}
|
|
132
295
|
}
|
|
133
296
|
}
|
|
134
|
-
// Name collision — across
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
297
|
+
// Name collision — across the file language's type declarations
|
|
298
|
+
// (TS interface/type/class, Swift struct/protocol, Kotlin class, …).
|
|
299
|
+
// Languages with no nominal types contribute no keywords → skipped.
|
|
300
|
+
const declKeywords = typeDeclKeywordsForFile(rel);
|
|
301
|
+
if (declKeywords.length > 0) {
|
|
302
|
+
const kw = declKeywords.map(escapeRegExp).join("|");
|
|
303
|
+
for (const [name, comp] of nameToComponent) {
|
|
304
|
+
if (comp.file === rel)
|
|
305
|
+
continue;
|
|
306
|
+
const re = new RegExp(`\\b(?:${kw})\\s+${escapeRegExp(name)}\\b`);
|
|
307
|
+
if (re.test(source)) {
|
|
308
|
+
findings.push({
|
|
309
|
+
kind: "name-collision",
|
|
310
|
+
file: rel,
|
|
311
|
+
component: name,
|
|
312
|
+
componentFile: comp.file,
|
|
313
|
+
message: `@cairn "${name}" (${comp.file}) collides with a type declaration in ${rel}`,
|
|
314
|
+
recommendation: "rename the export (and header with it)",
|
|
315
|
+
});
|
|
316
|
+
}
|
|
148
317
|
}
|
|
149
318
|
}
|
|
150
319
|
},
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"audit.js","sourceRoot":"","sources":["../../src/components/audit.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"audit.js","sourceRoot":"","sources":["../../src/components/audit.ts"],"names":[],"mappings":"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"}
|
package/dist/doctor/index.js
CHANGED
|
@@ -11,8 +11,9 @@ import { existsSync, readFileSync } from "node:fs";
|
|
|
11
11
|
import { join } from "node:path";
|
|
12
12
|
import { which } from "../sensors/shell.js";
|
|
13
13
|
import { parse as parseYaml } from "yaml";
|
|
14
|
-
import { buildDecisionsLedger, buildInvariantsLedger, hasComponentConfig, loadComponentsConfig, } from "@isaacriehm/cairn-state";
|
|
14
|
+
import { buildDecisionsLedger, buildInvariantsLedger, hasComponentConfig, loadCairnConfig, loadComponentsConfig, matchGlob, walkFs, } from "@isaacriehm/cairn-state";
|
|
15
15
|
import { runComponentCheck } from "../components/check.js";
|
|
16
|
+
import { semverCmp } from "../migrate/semver.js";
|
|
16
17
|
import { VERSION } from "../index.js";
|
|
17
18
|
import { normalizeProjectName } from "../paths/index.js";
|
|
18
19
|
import { z } from "zod";
|
|
@@ -36,6 +37,7 @@ export function runDoctor(opts) {
|
|
|
36
37
|
checks.push(checkCairnVersion(opts.repoRoot));
|
|
37
38
|
// 2. Ground state
|
|
38
39
|
checks.push(checkScopeIndex(opts.repoRoot));
|
|
40
|
+
checks.push(...checkConfigGlobs(opts.repoRoot));
|
|
39
41
|
checks.push(checkLedger(opts.repoRoot, "decisions"));
|
|
40
42
|
checks.push(checkLedger(opts.repoRoot, "invariants"));
|
|
41
43
|
// 3. Sensors
|
|
@@ -110,12 +112,18 @@ function checkCairnVersion(repoRoot) {
|
|
|
110
112
|
};
|
|
111
113
|
}
|
|
112
114
|
if (projectVersion !== VERSION) {
|
|
115
|
+
// Pin behind the CLI → the migration runner brings `.cairn/` forward and
|
|
116
|
+
// stamps the pin. Pin ahead → this CLI is the stale one; upgrade it.
|
|
117
|
+
// (Never advise downgrading the CLI to a frozen pin — that was backwards.)
|
|
118
|
+
const pinBehind = semverCmp(projectVersion, VERSION) < 0;
|
|
113
119
|
return {
|
|
114
120
|
group: "core",
|
|
115
121
|
label: "cairn version",
|
|
116
122
|
status: "warn",
|
|
117
|
-
detail:
|
|
118
|
-
|
|
123
|
+
detail: pinBehind
|
|
124
|
+
? `project pinned to ${projectVersion}; running cairn ${VERSION} — run \`cairn migrate\` to bring .cairn/ to current`
|
|
125
|
+
: `project pinned to ${projectVersion}; this CLI is older (${VERSION}) — upgrade the CLI`,
|
|
126
|
+
fixCommand: pinBehind ? "cairn migrate" : "npm install -g @isaacriehm/cairn@latest",
|
|
119
127
|
};
|
|
120
128
|
}
|
|
121
129
|
return {
|
|
@@ -191,6 +199,91 @@ function checkScopeIndex(repoRoot) {
|
|
|
191
199
|
detail: `${count} file${count === 1 ? "" : "s"} classified`,
|
|
192
200
|
};
|
|
193
201
|
}
|
|
202
|
+
/** Dirs the config-glob walk never descends into. */
|
|
203
|
+
const GLOB_WALK_SKIP_DIRS = new Set([
|
|
204
|
+
".git",
|
|
205
|
+
"node_modules",
|
|
206
|
+
".pnpm-store",
|
|
207
|
+
"dist",
|
|
208
|
+
"build",
|
|
209
|
+
".next",
|
|
210
|
+
".turbo",
|
|
211
|
+
".cache",
|
|
212
|
+
".archive",
|
|
213
|
+
"coverage",
|
|
214
|
+
".cairn",
|
|
215
|
+
]);
|
|
216
|
+
/**
|
|
217
|
+
* Config-glob staleness — warn when a `config.yaml` scope glob matches zero
|
|
218
|
+
* files in the working tree. These globs (`high_stakes_globs`,
|
|
219
|
+
* `project_globs.{route_handler,dto,generator_source,high_stakes}_globs`) are
|
|
220
|
+
* written once at adoption and never reconciled to the tree, so a later
|
|
221
|
+
* directory refactor silently neuters high-stakes weighting + the
|
|
222
|
+
* route/DTO sensors (they resolve to zero matches with no signal).
|
|
223
|
+
*
|
|
224
|
+
* Returns [] when the project declares no scope globs (nothing to validate)
|
|
225
|
+
* or the tree walk yields nothing. Stale globs collapse into a single warn
|
|
226
|
+
* check so the report stays readable; the detail lists a sample.
|
|
227
|
+
*/
|
|
228
|
+
function checkConfigGlobs(repoRoot) {
|
|
229
|
+
const cfg = loadCairnConfig(repoRoot);
|
|
230
|
+
const pairs = [];
|
|
231
|
+
const collect = (source, raw) => {
|
|
232
|
+
if (!Array.isArray(raw))
|
|
233
|
+
return;
|
|
234
|
+
for (const g of raw) {
|
|
235
|
+
if (typeof g === "string" && g.length > 0)
|
|
236
|
+
pairs.push({ source, glob: g });
|
|
237
|
+
}
|
|
238
|
+
};
|
|
239
|
+
collect("high_stakes_globs", cfg["high_stakes_globs"]);
|
|
240
|
+
const projectGlobs = cfg["project_globs"];
|
|
241
|
+
if (typeof projectGlobs === "object" && projectGlobs !== null) {
|
|
242
|
+
const pg = projectGlobs;
|
|
243
|
+
collect("project_globs.route_handler_globs", pg["route_handler_globs"]);
|
|
244
|
+
collect("project_globs.dto_globs", pg["dto_globs"]);
|
|
245
|
+
collect("project_globs.generator_source_globs", pg["generator_source_globs"]);
|
|
246
|
+
collect("project_globs.high_stakes_globs", pg["high_stakes_globs"]);
|
|
247
|
+
}
|
|
248
|
+
if (pairs.length === 0)
|
|
249
|
+
return [];
|
|
250
|
+
const files = [];
|
|
251
|
+
walkFs({
|
|
252
|
+
dir: repoRoot,
|
|
253
|
+
skipDirs: GLOB_WALK_SKIP_DIRS,
|
|
254
|
+
onFile: (rel) => {
|
|
255
|
+
files.push(rel);
|
|
256
|
+
},
|
|
257
|
+
});
|
|
258
|
+
if (files.length === 0)
|
|
259
|
+
return [];
|
|
260
|
+
const stale = pairs.filter((p) => !files.some((f) => matchGlob(f, p.glob)));
|
|
261
|
+
if (stale.length === 0) {
|
|
262
|
+
return [
|
|
263
|
+
{
|
|
264
|
+
group: "ground",
|
|
265
|
+
label: "config globs",
|
|
266
|
+
status: "ok",
|
|
267
|
+
detail: `${pairs.length} scope glob${pairs.length === 1 ? "" : "s"} all match tree files`,
|
|
268
|
+
},
|
|
269
|
+
];
|
|
270
|
+
}
|
|
271
|
+
const sample = stale
|
|
272
|
+
.slice(0, 3)
|
|
273
|
+
.map((p) => `${p.glob} (${p.source})`)
|
|
274
|
+
.join("; ");
|
|
275
|
+
const more = stale.length > 3 ? ` (+${stale.length - 3} more)` : "";
|
|
276
|
+
return [
|
|
277
|
+
{
|
|
278
|
+
group: "ground",
|
|
279
|
+
label: "config globs",
|
|
280
|
+
status: "warn",
|
|
281
|
+
detail: `${stale.length} of ${pairs.length} scope glob(s) match zero tree files — ` +
|
|
282
|
+
`stale after a directory refactor? high-stakes weighting + route/DTO sensors silently skip these: ${sample}${more}`,
|
|
283
|
+
fixCommand: "cairn init --force",
|
|
284
|
+
},
|
|
285
|
+
];
|
|
286
|
+
}
|
|
194
287
|
function checkLedger(repoRoot, kind) {
|
|
195
288
|
const path = join(repoRoot, ".cairn", "ground", kind, `${kind}.ledger.yaml`);
|
|
196
289
|
if (!existsSync(path)) {
|