@isaacriehm/cairn-core 0.22.5 → 0.22.6
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 -1
- package/dist/attention/index.js +0 -1
- package/dist/attention/index.js.map +1 -1
- package/dist/doctor/index.js +1 -86
- package/dist/doctor/index.js.map +1 -1
- package/dist/gc/apply.d.ts +1 -1
- package/dist/gc/apply.js +1 -1
- package/dist/gc/classify.d.ts +4 -8
- package/dist/gc/classify.js +6 -12
- package/dist/gc/classify.js.map +1 -1
- package/dist/gc/index.d.ts +1 -1
- package/dist/gc/index.js +1 -1
- package/dist/gc/sweep.d.ts +1 -3
- package/dist/gc/sweep.js +2 -7
- package/dist/gc/sweep.js.map +1 -1
- package/dist/gc/types.d.ts +5 -6
- package/dist/gc/types.js +4 -5
- package/dist/gc/types.js.map +1 -1
- package/dist/init/baseline-audit.js +3 -16
- package/dist/init/baseline-audit.js.map +1 -1
- package/dist/init/index.d.ts +0 -2
- package/dist/init/index.js +0 -1
- package/dist/init/index.js.map +1 -1
- package/dist/init/init.d.ts +2 -2
- package/dist/init/init.js +12 -27
- package/dist/init/init.js.map +1 -1
- package/dist/init/mapper-merge.d.ts +1 -4
- package/dist/init/mapper-merge.js +6 -22
- package/dist/init/mapper-merge.js.map +1 -1
- package/dist/init/mapper-parallel.d.ts +0 -4
- package/dist/init/mapper-parallel.js +3 -69
- package/dist/init/mapper-parallel.js.map +1 -1
- package/dist/init/mapper-prompts.d.ts +1 -25
- package/dist/init/mapper-prompts.js +2 -20
- package/dist/init/mapper-prompts.js.map +1 -1
- package/dist/init/mapper.d.ts +0 -4
- package/dist/init/mapper.js +2 -9
- package/dist/init/mapper.js.map +1 -1
- package/dist/init/overlay.js +6 -8
- package/dist/init/overlay.js.map +1 -1
- package/dist/init/phases/11-baseline.js +0 -10
- package/dist/init/phases/11-baseline.js.map +1 -1
- package/dist/init/phases/4-seed.js +0 -4
- package/dist/init/phases/4-seed.js.map +1 -1
- package/dist/init/source-comments/ingest.d.ts +0 -8
- package/dist/init/source-comments/ingest.js.map +1 -1
- package/dist/init/walker.d.ts +2 -3
- package/dist/init/walker.js +2 -3
- package/dist/init/walker.js.map +1 -1
- package/dist/init/workflow-block.d.ts +0 -4
- package/dist/init/workflow-block.js +0 -16
- package/dist/init/workflow-block.js.map +1 -1
- package/dist/mcp/schemas.d.ts +8 -8
- package/dist/mcp/tools/mission-set-exit-gate.d.ts +1 -1
- package/dist/migrate/migrations/0004-drop-glob-settings.d.ts +16 -0
- package/dist/migrate/migrations/0004-drop-glob-settings.js +34 -0
- package/dist/migrate/migrations/0004-drop-glob-settings.js.map +1 -0
- package/dist/migrate/registry.js +2 -0
- package/dist/migrate/registry.js.map +1 -1
- package/dist/profiles/types.d.ts +0 -2
- package/dist/profiles/unknown.d.ts +2 -2
- package/dist/profiles/unknown.js +2 -3
- package/dist/profiles/unknown.js.map +1 -1
- package/dist/sensors/diff.d.ts +1 -1
- package/dist/sensors/diff.js +1 -1
- package/dist/sensors/index.d.ts +2 -3
- package/dist/sensors/index.js +1 -2
- package/dist/sensors/index.js.map +1 -1
- package/dist/sensors/runner.d.ts +7 -10
- package/dist/sensors/runner.js +6 -39
- package/dist/sensors/runner.js.map +1 -1
- package/dist/sensors/types.d.ts +0 -13
- package/package.json +2 -2
- package/templates/.cairn/config/sensors.yaml +3 -89
- package/templates/.cairn/config/workflow.md +2 -5
- package/dist/attention/scoring.d.ts +0 -47
- package/dist/attention/scoring.js +0 -87
- package/dist/attention/scoring.js.map +0 -1
- package/dist/hooks/read-enrich.d.ts +0 -6
- package/dist/hooks/read-enrich.js +0 -11
- package/dist/hooks/read-enrich.js.map +0 -1
- package/dist/hooks/write-guard.d.ts +0 -6
- package/dist/hooks/write-guard.js +0 -11
- package/dist/hooks/write-guard.js.map +0 -1
- package/dist/init/glob-inference.d.ts +0 -16
- package/dist/init/glob-inference.js +0 -132
- package/dist/init/glob-inference.js.map +0 -1
- package/dist/init/phases/12-strip.d.ts +0 -10
- package/dist/init/phases/12-strip.js +0 -88
- package/dist/init/phases/12-strip.js.map +0 -1
- package/dist/sensors/structural.d.ts +0 -31
- package/dist/sensors/structural.js +0 -196
- package/dist/sensors/structural.js.map +0 -1
|
@@ -1,87 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Confidence scoring for source-comment-derived DEC drafts and
|
|
3
|
-
* invariant proposals.
|
|
4
|
-
*
|
|
5
|
-
* Phase 7b emits one DEC draft per "rationale"-class essay comment and
|
|
6
|
-
* one invariant per "constraint"-class essay comment. On a busy
|
|
7
|
-
* monorepo the classifier easily produces 400+ drafts — no human will
|
|
8
|
-
* sort through that interactively, so we score each draft by a small
|
|
9
|
-
* set of heuristics and bulk-accept the obvious ones during attention
|
|
10
|
-
* drain. Operator triages only the medium / low-confidence remainder.
|
|
11
|
-
*
|
|
12
|
-
* Heuristic stance:
|
|
13
|
-
* - **DEC drafts** are attribution-of-existing-prose. Cost of keeping
|
|
14
|
-
* a borderline draft is near zero (queryable rationale metadata).
|
|
15
|
-
* Bias accepts upward — score ≥7 → high.
|
|
16
|
-
* - **Invariants** become enforcement signals; false positives turn
|
|
17
|
-
* into noise during sensor sweeps. Bias accepts downward —
|
|
18
|
-
* stricter signal required (modal verb + reason + high-stakes
|
|
19
|
-
* location) before high-confidence accept.
|
|
20
|
-
*
|
|
21
|
-
* Scoring is pure. Inputs are the parsed draft fields; no filesystem.
|
|
22
|
-
*/
|
|
23
|
-
import { matchAnyGlob } from "@isaacriehm/cairn-state";
|
|
24
|
-
const DECISION_VERBS = /\b(chose|chosen|choose|decided|prefer|preferred|because|locked|enforce|enforced|require|required|adopt|adopted|standardize|standardized|switch|migrated|deprecate|reject|rejected)\b/i;
|
|
25
|
-
const JSDOC_TAGS = /@(domain|scope|orgScope|see|param|returns|throws|deprecated|since|module|namespace|file|fileoverview|public|private|protected|internal|readonly|override|sealed|immutable|invariant)\b/;
|
|
26
|
-
const INVARIANT_MODALS = /\b(MUST|MUSTN'T|MUST NOT|NEVER|ALWAYS|SHALL|SHALL NOT|CANNOT|FORBID|FORBIDDEN|REQUIRED|REQUIRES)\b/i;
|
|
27
|
-
const REASON_MARKERS = /\b(because|to (prevent|ensure|avoid|guarantee|preserve|enforce|stop)|otherwise)\b/i;
|
|
28
|
-
function inHighStakes(file, globs) {
|
|
29
|
-
return matchAnyGlob(file, globs.high_stakes_globs ?? []);
|
|
30
|
-
}
|
|
31
|
-
function inRoutesOrDtos(file, globs) {
|
|
32
|
-
const combined = [
|
|
33
|
-
...(globs.route_handler_globs ?? []),
|
|
34
|
-
...(globs.dto_globs ?? []),
|
|
35
|
-
];
|
|
36
|
-
return matchAnyGlob(file, combined);
|
|
37
|
-
}
|
|
38
|
-
/**
|
|
39
|
-
* Score a DEC draft. Max 8 / threshold 7→high / 4→medium.
|
|
40
|
-
*/
|
|
41
|
-
export function scoreDecDraft(input) {
|
|
42
|
-
let score = 0;
|
|
43
|
-
if (inHighStakes(input.sourceFile, input.globs))
|
|
44
|
-
score += 3;
|
|
45
|
-
if (inRoutesOrDtos(input.sourceFile, input.globs))
|
|
46
|
-
score += 1;
|
|
47
|
-
const proseLen = input.prose.trim().length;
|
|
48
|
-
if (proseLen >= 80 && proseLen <= 800)
|
|
49
|
-
score += 2;
|
|
50
|
-
const titleLen = input.title.trim().length;
|
|
51
|
-
if (titleLen >= 10 && titleLen <= 80)
|
|
52
|
-
score += 1;
|
|
53
|
-
if (DECISION_VERBS.test(input.prose))
|
|
54
|
-
score += 2;
|
|
55
|
-
if (JSDOC_TAGS.test(input.rawComment))
|
|
56
|
-
score += 1;
|
|
57
|
-
if (score >= 7)
|
|
58
|
-
return "high";
|
|
59
|
-
if (score >= 4)
|
|
60
|
-
return "medium";
|
|
61
|
-
return "low";
|
|
62
|
-
}
|
|
63
|
-
/**
|
|
64
|
-
* Score an invariant proposal. Max 9 / threshold 7→high / 4→medium.
|
|
65
|
-
* Stricter than DEC scoring: requires modal verb + reason + high-stakes
|
|
66
|
-
* location for high confidence, since false-positive invariants become
|
|
67
|
-
* sensor-sweep noise downstream.
|
|
68
|
-
*/
|
|
69
|
-
export function scoreInvariant(input) {
|
|
70
|
-
let score = 0;
|
|
71
|
-
if (inHighStakes(input.sourceFile, input.globs))
|
|
72
|
-
score += 3;
|
|
73
|
-
const modalText = `${input.title}\n${input.prose}`;
|
|
74
|
-
if (INVARIANT_MODALS.test(modalText))
|
|
75
|
-
score += 3;
|
|
76
|
-
if (REASON_MARKERS.test(input.prose))
|
|
77
|
-
score += 2;
|
|
78
|
-
const proseLen = input.prose.trim().length;
|
|
79
|
-
if (proseLen >= 50 && proseLen <= 600)
|
|
80
|
-
score += 1;
|
|
81
|
-
if (score >= 7)
|
|
82
|
-
return "high";
|
|
83
|
-
if (score >= 4)
|
|
84
|
-
return "medium";
|
|
85
|
-
return "low";
|
|
86
|
-
}
|
|
87
|
-
//# sourceMappingURL=scoring.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"scoring.js","sourceRoot":"","sources":["../../src/attention/scoring.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAkBvD,MAAM,cAAc,GAClB,uLAAuL,CAAC;AAE1L,MAAM,UAAU,GAAG,wLAAwL,CAAC;AAE5M,MAAM,gBAAgB,GACpB,qGAAqG,CAAC;AAExG,MAAM,cAAc,GAAG,oFAAoF,CAAC;AAE5G,SAAS,YAAY,CAAC,IAAY,EAAE,KAAmB;IACrD,OAAO,YAAY,CAAC,IAAI,EAAE,KAAK,CAAC,iBAAiB,IAAI,EAAE,CAAC,CAAC;AAC3D,CAAC;AAED,SAAS,cAAc,CAAC,IAAY,EAAE,KAAmB;IACvD,MAAM,QAAQ,GAAG;QACf,GAAG,CAAC,KAAK,CAAC,mBAAmB,IAAI,EAAE,CAAC;QACpC,GAAG,CAAC,KAAK,CAAC,SAAS,IAAI,EAAE,CAAC;KAC3B,CAAC;IACF,OAAO,YAAY,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;AACtC,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,aAAa,CAAC,KAAsB;IAClD,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,IAAI,YAAY,CAAC,KAAK,CAAC,UAAU,EAAE,KAAK,CAAC,KAAK,CAAC;QAAE,KAAK,IAAI,CAAC,CAAC;IAC5D,IAAI,cAAc,CAAC,KAAK,CAAC,UAAU,EAAE,KAAK,CAAC,KAAK,CAAC;QAAE,KAAK,IAAI,CAAC,CAAC;IAC9D,MAAM,QAAQ,GAAG,KAAK,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,MAAM,CAAC;IAC3C,IAAI,QAAQ,IAAI,EAAE,IAAI,QAAQ,IAAI,GAAG;QAAE,KAAK,IAAI,CAAC,CAAC;IAClD,MAAM,QAAQ,GAAG,KAAK,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,MAAM,CAAC;IAC3C,IAAI,QAAQ,IAAI,EAAE,IAAI,QAAQ,IAAI,EAAE;QAAE,KAAK,IAAI,CAAC,CAAC;IACjD,IAAI,cAAc,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC;QAAE,KAAK,IAAI,CAAC,CAAC;IACjD,IAAI,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC;QAAE,KAAK,IAAI,CAAC,CAAC;IAElD,IAAI,KAAK,IAAI,CAAC;QAAE,OAAO,MAAM,CAAC;IAC9B,IAAI,KAAK,IAAI,CAAC;QAAE,OAAO,QAAQ,CAAC;IAChC,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,cAAc,CAAC,KAAsB;IACnD,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,IAAI,YAAY,CAAC,KAAK,CAAC,UAAU,EAAE,KAAK,CAAC,KAAK,CAAC;QAAE,KAAK,IAAI,CAAC,CAAC;IAC5D,MAAM,SAAS,GAAG,GAAG,KAAK,CAAC,KAAK,KAAK,KAAK,CAAC,KAAK,EAAE,CAAC;IACnD,IAAI,gBAAgB,CAAC,IAAI,CAAC,SAAS,CAAC;QAAE,KAAK,IAAI,CAAC,CAAC;IACjD,IAAI,cAAc,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC;QAAE,KAAK,IAAI,CAAC,CAAC;IACjD,MAAM,QAAQ,GAAG,KAAK,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,MAAM,CAAC;IAC3C,IAAI,QAAQ,IAAI,EAAE,IAAI,QAAQ,IAAI,GAAG;QAAE,KAAK,IAAI,CAAC,CAAC;IAElD,IAAI,KAAK,IAAI,CAAC;QAAE,OAAO,MAAM,CAAC;IAC9B,IAAI,KAAK,IAAI,CAAC;QAAE,OAAO,QAAQ,CAAC;IAChC,OAAO,KAAK,CAAC;AACf,CAAC"}
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
/**
|
|
3
|
-
* Bin entrypoint — `node cairn-core/dist/hooks/read-enrich.js`.
|
|
4
|
-
* PostToolUse on Read; injects citation legend.
|
|
5
|
-
*/
|
|
6
|
-
import { runReadEnricher } from "./post-tool-use/index.js";
|
|
7
|
-
runReadEnricher().catch((err) => {
|
|
8
|
-
process.stderr.write(`[cairn read-enrich] ${err instanceof Error ? err.message : String(err)}\n`);
|
|
9
|
-
process.exit(1);
|
|
10
|
-
});
|
|
11
|
-
//# sourceMappingURL=read-enrich.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"read-enrich.js","sourceRoot":"","sources":["../../src/hooks/read-enrich.ts"],"names":[],"mappings":";AACA;;;GAGG;AAEH,OAAO,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAE3D,eAAe,EAAE,CAAC,KAAK,CAAC,CAAC,GAAY,EAAE,EAAE;IACvC,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,uBAAuB,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAC5E,CAAC;IACF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
/**
|
|
3
|
-
* Bin entrypoint — `node cairn-core/dist/hooks/write-guard.js`.
|
|
4
|
-
* PostToolUse on Write/Edit; copy-safety + scope reminder.
|
|
5
|
-
*/
|
|
6
|
-
import { runWriteGuardian } from "./post-tool-use/index.js";
|
|
7
|
-
runWriteGuardian().catch((err) => {
|
|
8
|
-
process.stderr.write(`[cairn write-guard] ${err instanceof Error ? err.message : String(err)}\n`);
|
|
9
|
-
process.exit(1);
|
|
10
|
-
});
|
|
11
|
-
//# sourceMappingURL=write-guard.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"write-guard.js","sourceRoot":"","sources":["../../src/hooks/write-guard.ts"],"names":[],"mappings":";AACA;;;GAGG;AAEH,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAE5D,gBAAgB,EAAE,CAAC,KAAK,CAAC,CAAC,GAAY,EAAE,EAAE;IACxC,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,uBAAuB,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAC5E,CAAC;IACF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Deterministic glob baseline derived from framework conventions detected
|
|
3
|
-
* in Phase 1. The mapper LLM still adds project-specific globs on top;
|
|
4
|
-
* these are always included regardless of LLM output.
|
|
5
|
-
*
|
|
6
|
-
* Pure function. Uses existsSync for file-presence checks only.
|
|
7
|
-
*/
|
|
8
|
-
import type { DetectionResult } from "./types.js";
|
|
9
|
-
export interface InferredGlobs {
|
|
10
|
-
route_handler_globs: string[];
|
|
11
|
-
dto_globs: string[];
|
|
12
|
-
generator_source_globs: string[];
|
|
13
|
-
high_stakes_globs: string[];
|
|
14
|
-
off_limits_globs: string[];
|
|
15
|
-
}
|
|
16
|
-
export declare function inferGlobsFromDetection(detection: DetectionResult, repoRoot: string): InferredGlobs;
|
|
@@ -1,132 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Deterministic glob baseline derived from framework conventions detected
|
|
3
|
-
* in Phase 1. The mapper LLM still adds project-specific globs on top;
|
|
4
|
-
* these are always included regardless of LLM output.
|
|
5
|
-
*
|
|
6
|
-
* Pure function. Uses existsSync for file-presence checks only.
|
|
7
|
-
*/
|
|
8
|
-
import { existsSync } from "node:fs";
|
|
9
|
-
import { join } from "node:path";
|
|
10
|
-
export function inferGlobsFromDetection(detection, repoRoot) {
|
|
11
|
-
const route_handler_globs = [];
|
|
12
|
-
const dto_globs = [];
|
|
13
|
-
const generator_source_globs = [];
|
|
14
|
-
const sigs = detection.stack_signatures;
|
|
15
|
-
const has = (rel) => existsSync(join(repoRoot, rel));
|
|
16
|
-
// ── NestJS ───────────────────────────────────────────────
|
|
17
|
-
if (has("nest-cli.json")) {
|
|
18
|
-
route_handler_globs.push("**/*.controller.ts");
|
|
19
|
-
dto_globs.push("**/*.dto.ts");
|
|
20
|
-
}
|
|
21
|
-
// ── Ruby ─────────────────────────────────────────────────
|
|
22
|
-
if (sigs.some((s) => s.kind === "ruby")) {
|
|
23
|
-
route_handler_globs.push("app/controllers/**/*.rb");
|
|
24
|
-
dto_globs.push("app/forms/**/*.rb", "app/serializers/**/*.rb");
|
|
25
|
-
}
|
|
26
|
-
// ── Python ───────────────────────────────────────────────
|
|
27
|
-
if (sigs.some((s) => s.kind === "python")) {
|
|
28
|
-
route_handler_globs.push("**/views.py", "**/routes.py", "**/api/**/*.py");
|
|
29
|
-
}
|
|
30
|
-
// ── Go ───────────────────────────────────────────────────
|
|
31
|
-
if (sigs.some((s) => s.kind === "go")) {
|
|
32
|
-
route_handler_globs.push("**/handlers/**/*.go", "**/routes/**/*.go");
|
|
33
|
-
}
|
|
34
|
-
// ── Rust ─────────────────────────────────────────────────
|
|
35
|
-
if (sigs.some((s) => s.kind === "rust")) {
|
|
36
|
-
route_handler_globs.push("**/handlers.rs", "**/routes.rs");
|
|
37
|
-
}
|
|
38
|
-
// ── Java (Spring) ────────────────────────────────────────
|
|
39
|
-
if (sigs.some((s) => s.kind === "java")) {
|
|
40
|
-
route_handler_globs.push("**/*Controller.java", "**/*Resource.java");
|
|
41
|
-
dto_globs.push("**/dto/**/*.java", "**/*Dto.java", "**/*Request.java");
|
|
42
|
-
}
|
|
43
|
-
// ── Kotlin (Spring / Ktor) ───────────────────────────────
|
|
44
|
-
if (sigs.some((s) => s.kind === "kotlin")) {
|
|
45
|
-
route_handler_globs.push("**/*Controller.kt", "**/routes/**/*.kt");
|
|
46
|
-
dto_globs.push("**/dto/**/*.kt", "**/*Dto.kt", "**/*Request.kt");
|
|
47
|
-
}
|
|
48
|
-
// ── C# (.NET) ────────────────────────────────────────────
|
|
49
|
-
if (sigs.some((s) => s.kind === "csharp")) {
|
|
50
|
-
route_handler_globs.push("**/Controllers/**/*.cs", "**/*Controller.cs");
|
|
51
|
-
dto_globs.push("**/Dtos/**/*.cs", "**/*Dto.cs");
|
|
52
|
-
}
|
|
53
|
-
// ── PHP (Laravel / Symfony) ──────────────────────────────
|
|
54
|
-
if (sigs.some((s) => s.kind === "php")) {
|
|
55
|
-
route_handler_globs.push("app/Http/Controllers/**/*.php", "**/*Controller.php");
|
|
56
|
-
dto_globs.push("app/Http/Requests/**/*.php");
|
|
57
|
-
}
|
|
58
|
-
// ── Elixir (Phoenix) ─────────────────────────────────────
|
|
59
|
-
if (sigs.some((s) => s.kind === "elixir")) {
|
|
60
|
-
route_handler_globs.push("lib/**/*_controller.ex", "lib/**/controllers/**/*.ex");
|
|
61
|
-
}
|
|
62
|
-
// ── Prisma ───────────────────────────────────────────────
|
|
63
|
-
if (has("prisma/schema.prisma")) {
|
|
64
|
-
generator_source_globs.push("prisma/schema.prisma");
|
|
65
|
-
}
|
|
66
|
-
// ── Drizzle ──────────────────────────────────────────────
|
|
67
|
-
if (has("drizzle.config.ts") ||
|
|
68
|
-
has("drizzle.config.js") ||
|
|
69
|
-
has("drizzle.config.mjs")) {
|
|
70
|
-
generator_source_globs.push("**/db/schema.ts", "**/schema.ts");
|
|
71
|
-
}
|
|
72
|
-
// ── Protobuf ─────────────────────────────────────────────
|
|
73
|
-
if (hasGlob(repoRoot, ".proto")) {
|
|
74
|
-
generator_source_globs.push("**/*.proto");
|
|
75
|
-
}
|
|
76
|
-
// ── GraphQL ──────────────────────────────────────────────
|
|
77
|
-
if (hasGlob(repoRoot, ".graphql") || hasGlob(repoRoot, ".gql")) {
|
|
78
|
-
generator_source_globs.push("**/*.graphql", "**/*.gql");
|
|
79
|
-
}
|
|
80
|
-
// ── OpenAPI / Swagger ────────────────────────────────────
|
|
81
|
-
if (has("openapi.json") ||
|
|
82
|
-
has("openapi.yaml") ||
|
|
83
|
-
has("swagger.json") ||
|
|
84
|
-
has("swagger.yaml")) {
|
|
85
|
-
generator_source_globs.push("openapi.{json,yaml}", "swagger.{json,yaml}");
|
|
86
|
-
}
|
|
87
|
-
// ── Always-on ────────────────────────────────────────────
|
|
88
|
-
const high_stakes_globs = [
|
|
89
|
-
"**/auth/**",
|
|
90
|
-
"**/billing/**",
|
|
91
|
-
"**/payment*/**",
|
|
92
|
-
"**/security/**",
|
|
93
|
-
"**/secrets/**",
|
|
94
|
-
];
|
|
95
|
-
const off_limits_globs = [
|
|
96
|
-
"**/vendor/**",
|
|
97
|
-
"**/__generated__/**",
|
|
98
|
-
"**/*.generated.ts",
|
|
99
|
-
"**/*.pb.go",
|
|
100
|
-
];
|
|
101
|
-
return {
|
|
102
|
-
route_handler_globs,
|
|
103
|
-
dto_globs,
|
|
104
|
-
generator_source_globs,
|
|
105
|
-
high_stakes_globs,
|
|
106
|
-
off_limits_globs,
|
|
107
|
-
};
|
|
108
|
-
}
|
|
109
|
-
/**
|
|
110
|
-
* Returns true if any conventional top-level directory or file associated
|
|
111
|
-
* with the given extension exists. Checks known common locations only —
|
|
112
|
-
* avoids recursive tree walks for init performance.
|
|
113
|
-
*
|
|
114
|
-
* Proto: look for protos/, proto/, or *.proto at root.
|
|
115
|
-
* GraphQL: look for schema.graphql/schema.gql at root or graphql/ dir.
|
|
116
|
-
*/
|
|
117
|
-
function hasGlob(repoRoot, ext) {
|
|
118
|
-
if (ext === ".proto") {
|
|
119
|
-
return (existsSync(join(repoRoot, "protos")) ||
|
|
120
|
-
existsSync(join(repoRoot, "proto")) ||
|
|
121
|
-
existsSync(join(repoRoot, "schema.proto")) ||
|
|
122
|
-
existsSync(join(repoRoot, "service.proto")));
|
|
123
|
-
}
|
|
124
|
-
if (ext === ".graphql" || ext === ".gql") {
|
|
125
|
-
return (existsSync(join(repoRoot, "graphql")) ||
|
|
126
|
-
existsSync(join(repoRoot, "schema.graphql")) ||
|
|
127
|
-
existsSync(join(repoRoot, "schema.gql")) ||
|
|
128
|
-
existsSync(join(repoRoot, "graph")));
|
|
129
|
-
}
|
|
130
|
-
return false;
|
|
131
|
-
}
|
|
132
|
-
//# sourceMappingURL=glob-inference.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"glob-inference.js","sourceRoot":"","sources":["../../src/init/glob-inference.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Phase 12-strip — per-module strip-replace consent.
|
|
3
|
-
*
|
|
4
|
-
* Surfaces each ingestion-flagged module as an A/B/C choice (strip /
|
|
5
|
-
* keep / skip). Tracks remaining modules in
|
|
6
|
-
* `outputs["12-strip"].pending` and emits one question at a time
|
|
7
|
-
* until the queue is empty.
|
|
8
|
-
*/
|
|
9
|
-
import type { PhaseResult, PhaseState } from "./types.js";
|
|
10
|
-
export declare function runPhase12Strip(state: PhaseState): Promise<PhaseResult>;
|
|
@@ -1,88 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Phase 12-strip — per-module strip-replace consent.
|
|
3
|
-
*
|
|
4
|
-
* Surfaces each ingestion-flagged module as an A/B/C choice (strip /
|
|
5
|
-
* keep / skip). Tracks remaining modules in
|
|
6
|
-
* `outputs["12-strip"].pending` and emits one question at a time
|
|
7
|
-
* until the queue is empty.
|
|
8
|
-
*/
|
|
9
|
-
import { advancePhase, isSelfAdoptState } from "./orchestrator.js";
|
|
10
|
-
export async function runPhase12Strip(state) {
|
|
11
|
-
if (isSelfAdoptState(state)) {
|
|
12
|
-
const skipped = { pending: [], decisions: {} };
|
|
13
|
-
const next = {
|
|
14
|
-
...state,
|
|
15
|
-
outputs: { ...state.outputs, "12-strip": skipped },
|
|
16
|
-
answer: undefined,
|
|
17
|
-
};
|
|
18
|
-
return {
|
|
19
|
-
status: "complete",
|
|
20
|
-
nextPhase: "13-multidev",
|
|
21
|
-
state: advancePhase(next),
|
|
22
|
-
};
|
|
23
|
-
}
|
|
24
|
-
const existing = state.outputs["12-strip"];
|
|
25
|
-
const modules = computeFlaggedModules(state);
|
|
26
|
-
// Initialize on first entry.
|
|
27
|
-
let s = existing ?? { pending: [...modules], decisions: {} };
|
|
28
|
-
// Operator just answered → record + dequeue.
|
|
29
|
-
if (state.answer !== undefined && state.answer.length > 0 && s.pending.length > 0) {
|
|
30
|
-
const head = s.pending[0];
|
|
31
|
-
const choice = normalizeChoice(state.answer);
|
|
32
|
-
s = {
|
|
33
|
-
pending: s.pending.slice(1),
|
|
34
|
-
decisions: { ...s.decisions, [head]: choice },
|
|
35
|
-
};
|
|
36
|
-
}
|
|
37
|
-
if (s.pending.length === 0) {
|
|
38
|
-
const next = {
|
|
39
|
-
...state,
|
|
40
|
-
outputs: { ...state.outputs, "12-strip": s },
|
|
41
|
-
answer: undefined,
|
|
42
|
-
};
|
|
43
|
-
return {
|
|
44
|
-
status: "complete",
|
|
45
|
-
nextPhase: "13-multidev",
|
|
46
|
-
state: advancePhase(next),
|
|
47
|
-
};
|
|
48
|
-
}
|
|
49
|
-
const head = s.pending[0];
|
|
50
|
-
const question = {
|
|
51
|
-
id: `12-strip:${head}`,
|
|
52
|
-
prompt: `Strip the source-comment essay in ${head}?`,
|
|
53
|
-
options: [
|
|
54
|
-
{
|
|
55
|
-
id: "strip",
|
|
56
|
-
label: "strip — DEC is the source of truth",
|
|
57
|
-
},
|
|
58
|
-
{
|
|
59
|
-
id: "keep",
|
|
60
|
-
label: "keep — leave comment alongside DEC",
|
|
61
|
-
},
|
|
62
|
-
{
|
|
63
|
-
id: "skip",
|
|
64
|
-
label: "skip — decide later",
|
|
65
|
-
},
|
|
66
|
-
],
|
|
67
|
-
default: "skip",
|
|
68
|
-
};
|
|
69
|
-
return {
|
|
70
|
-
status: "needs_input",
|
|
71
|
-
question,
|
|
72
|
-
state: { ...state, outputs: { ...state.outputs, "12-strip": s }, answer: undefined },
|
|
73
|
-
};
|
|
74
|
-
}
|
|
75
|
-
function normalizeChoice(answer) {
|
|
76
|
-
switch (answer) {
|
|
77
|
-
case "strip":
|
|
78
|
-
case "keep":
|
|
79
|
-
case "skip":
|
|
80
|
-
return answer;
|
|
81
|
-
default:
|
|
82
|
-
return "skip";
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
function computeFlaggedModules(_state) {
|
|
86
|
-
return [];
|
|
87
|
-
}
|
|
88
|
-
//# sourceMappingURL=12-strip.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"12-strip.js","sourceRoot":"","sources":["../../../src/init/phases/12-strip.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Layer C — generic project-agnostic structural sensors.
|
|
3
|
-
*
|
|
4
|
-
* Triggered when the diff touches files matching the project's glob keys.
|
|
5
|
-
* Each sensor inspects the POST-change content of those files (not just
|
|
6
|
-
* the diff) — Layer C is "do these load-bearing files follow contract",
|
|
7
|
-
* which is stricter than Layer A's "did this run add new debt".
|
|
8
|
-
*
|
|
9
|
-
* route-handler-non-empty — every method in a route/controller class has a
|
|
10
|
-
* non-trivial body. Catches "added handler that
|
|
11
|
-
* does nothing" disguised as completion.
|
|
12
|
-
* dto-no-fake-fields — @IsOptional() fields with no other validator
|
|
13
|
-
* are fake-thoroughness; they look like work and
|
|
14
|
-
* do nothing.
|
|
15
|
-
*
|
|
16
|
-
* Both are pattern-based; profiles plug stack-specific globs. The regex is
|
|
17
|
-
* intentionally conservative (false-negatives over false-positives) — sensors
|
|
18
|
-
* that fail-loud-on-noise get disabled which defeats the purpose.
|
|
19
|
-
*/
|
|
20
|
-
import type { DiffEntry, SensorResult } from "./types.js";
|
|
21
|
-
/** Run route-handler-non-empty against changed files matching globs. */
|
|
22
|
-
export declare function runRouteHandlerNonEmpty(args: {
|
|
23
|
-
diff: DiffEntry[];
|
|
24
|
-
globs: string[] | undefined;
|
|
25
|
-
}): SensorResult;
|
|
26
|
-
/** Run dto-no-fake-fields against changed files matching globs. */
|
|
27
|
-
export declare function runDtoNoFakeFields(args: {
|
|
28
|
-
diff: DiffEntry[];
|
|
29
|
-
globs: string[] | undefined;
|
|
30
|
-
}): SensorResult;
|
|
31
|
-
/** 1-based line number from a character offset. */
|
|
@@ -1,196 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Layer C — generic project-agnostic structural sensors.
|
|
3
|
-
*
|
|
4
|
-
* Triggered when the diff touches files matching the project's glob keys.
|
|
5
|
-
* Each sensor inspects the POST-change content of those files (not just
|
|
6
|
-
* the diff) — Layer C is "do these load-bearing files follow contract",
|
|
7
|
-
* which is stricter than Layer A's "did this run add new debt".
|
|
8
|
-
*
|
|
9
|
-
* route-handler-non-empty — every method in a route/controller class has a
|
|
10
|
-
* non-trivial body. Catches "added handler that
|
|
11
|
-
* does nothing" disguised as completion.
|
|
12
|
-
* dto-no-fake-fields — @IsOptional() fields with no other validator
|
|
13
|
-
* are fake-thoroughness; they look like work and
|
|
14
|
-
* do nothing.
|
|
15
|
-
*
|
|
16
|
-
* Both are pattern-based; profiles plug stack-specific globs. The regex is
|
|
17
|
-
* intentionally conservative (false-negatives over false-positives) — sensors
|
|
18
|
-
* that fail-loud-on-noise get disabled which defeats the purpose.
|
|
19
|
-
*/
|
|
20
|
-
import { lineOf, matchAnyGlob } from "@isaacriehm/cairn-state";
|
|
21
|
-
const ROUTE_SENSOR_ID = "route-handler-non-empty";
|
|
22
|
-
const DTO_SENSOR_ID = "dto-no-fake-fields";
|
|
23
|
-
/** Method body that's effectively a no-op — language-agnostic regex. */
|
|
24
|
-
const EMPTY_BODY_PATTERNS = [
|
|
25
|
-
// TypeScript/JavaScript class method with empty body or null/undefined return.
|
|
26
|
-
{
|
|
27
|
-
regex: /^\s*(?:public|private|protected|async)?\s*(?:async\s+)?(\w+)\s*\([^)]*\)\s*(?::\s*[^{]+)?\{\s*(?:return\s*(?:null|undefined)?\s*;?)?\s*\}/gm,
|
|
28
|
-
reason: "empty / return-null / return-undefined body",
|
|
29
|
-
},
|
|
30
|
-
// throw new Error('not implemented').
|
|
31
|
-
{
|
|
32
|
-
regex: /\b(\w+)\s*\([^)]*\)\s*(?::\s*[^{]+)?\{\s*throw\s+new\s+Error\s*\(\s*['"`][^'"`]*not[\s_]?implemented/gi,
|
|
33
|
-
reason: "throws not-implemented",
|
|
34
|
-
},
|
|
35
|
-
// Python: `def foo(...): pass` with nothing else.
|
|
36
|
-
{
|
|
37
|
-
regex: /def\s+(\w+)\s*\([^)]*\)\s*(?:->[^:]+)?:\s*\n\s*pass\s*\n/g,
|
|
38
|
-
reason: "Python def with `pass` body",
|
|
39
|
-
},
|
|
40
|
-
// Python: `def foo(...): return None`.
|
|
41
|
-
{
|
|
42
|
-
regex: /def\s+(\w+)\s*\([^)]*\)\s*(?:->[^:]+)?:\s*\n\s*return(?:\s+None)?\s*\n/g,
|
|
43
|
-
reason: "Python def returning None",
|
|
44
|
-
},
|
|
45
|
-
];
|
|
46
|
-
/** Detect a class context for TypeScript/JavaScript controllers. */
|
|
47
|
-
const TS_CONTROLLER_HINT = /\bclass\s+\w+(?:Controller|Resource|Resolver|Handler)\b|@(?:Controller|Resource|Resolver|Handler)\b|extends\s+(?:Controller|Resource)\b/;
|
|
48
|
-
/** Detect Python route registration. */
|
|
49
|
-
const PY_ROUTE_HINT = /@(?:app|router|blueprint|bp)\.(?:get|post|put|patch|delete|route)\b|@route\b|class\s+\w+(?:View|Resource)\b/;
|
|
50
|
-
/** Run route-handler-non-empty against changed files matching globs. */
|
|
51
|
-
export function runRouteHandlerNonEmpty(args) {
|
|
52
|
-
const startedAt = Date.now();
|
|
53
|
-
const findings = [];
|
|
54
|
-
if (!args.globs || args.globs.length === 0) {
|
|
55
|
-
return {
|
|
56
|
-
sensor_id: ROUTE_SENSOR_ID,
|
|
57
|
-
ok: true,
|
|
58
|
-
duration_ms: Date.now() - startedAt,
|
|
59
|
-
findings,
|
|
60
|
-
skipped: { reason: "route_handler_globs not configured for this project" },
|
|
61
|
-
};
|
|
62
|
-
}
|
|
63
|
-
const inScope = args.diff.filter((d) => d.status !== "deleted" && matchAnyGlob(d.path, args.globs ?? []));
|
|
64
|
-
if (inScope.length === 0) {
|
|
65
|
-
return {
|
|
66
|
-
sensor_id: ROUTE_SENSOR_ID,
|
|
67
|
-
ok: true,
|
|
68
|
-
duration_ms: Date.now() - startedAt,
|
|
69
|
-
findings,
|
|
70
|
-
skipped: { reason: "no diff entries match route_handler_globs" },
|
|
71
|
-
};
|
|
72
|
-
}
|
|
73
|
-
for (const entry of inScope) {
|
|
74
|
-
const text = entry.afterContent ?? "";
|
|
75
|
-
if (text.length === 0)
|
|
76
|
-
continue;
|
|
77
|
-
if (!isRouteHandlerFile(entry.path, text))
|
|
78
|
-
continue;
|
|
79
|
-
for (const { regex, reason } of EMPTY_BODY_PATTERNS) {
|
|
80
|
-
const re = new RegExp(regex.source, regex.flags);
|
|
81
|
-
let m;
|
|
82
|
-
while ((m = re.exec(text)) !== null) {
|
|
83
|
-
const methodName = m[1] ?? "<anon>";
|
|
84
|
-
if (METHOD_ALLOWLIST.has(methodName))
|
|
85
|
-
continue;
|
|
86
|
-
const line = lineOf(text, m.index);
|
|
87
|
-
findings.push({
|
|
88
|
-
sensor_id: ROUTE_SENSOR_ID,
|
|
89
|
-
path: entry.path,
|
|
90
|
-
line,
|
|
91
|
-
matched_text: m[0].slice(0, 200),
|
|
92
|
-
message: `${entry.path}:${line} route-handler method \`${methodName}\` — ${reason}`,
|
|
93
|
-
severity: "hard",
|
|
94
|
-
});
|
|
95
|
-
if (re.lastIndex === m.index)
|
|
96
|
-
re.lastIndex += 1;
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
return {
|
|
101
|
-
sensor_id: ROUTE_SENSOR_ID,
|
|
102
|
-
ok: findings.length === 0,
|
|
103
|
-
duration_ms: Date.now() - startedAt,
|
|
104
|
-
findings,
|
|
105
|
-
};
|
|
106
|
-
}
|
|
107
|
-
/** Run dto-no-fake-fields against changed files matching globs. */
|
|
108
|
-
export function runDtoNoFakeFields(args) {
|
|
109
|
-
const startedAt = Date.now();
|
|
110
|
-
const findings = [];
|
|
111
|
-
if (!args.globs || args.globs.length === 0) {
|
|
112
|
-
return {
|
|
113
|
-
sensor_id: DTO_SENSOR_ID,
|
|
114
|
-
ok: true,
|
|
115
|
-
duration_ms: Date.now() - startedAt,
|
|
116
|
-
findings,
|
|
117
|
-
skipped: { reason: "dto_globs not configured for this project" },
|
|
118
|
-
};
|
|
119
|
-
}
|
|
120
|
-
const inScope = args.diff.filter((d) => d.status !== "deleted" && matchAnyGlob(d.path, args.globs ?? []));
|
|
121
|
-
if (inScope.length === 0) {
|
|
122
|
-
return {
|
|
123
|
-
sensor_id: DTO_SENSOR_ID,
|
|
124
|
-
ok: true,
|
|
125
|
-
duration_ms: Date.now() - startedAt,
|
|
126
|
-
findings,
|
|
127
|
-
skipped: { reason: "no diff entries match dto_globs" },
|
|
128
|
-
};
|
|
129
|
-
}
|
|
130
|
-
for (const entry of inScope) {
|
|
131
|
-
const text = entry.afterContent ?? "";
|
|
132
|
-
if (text.length === 0)
|
|
133
|
-
continue;
|
|
134
|
-
findings.push(...findFakeOptionalFields(entry.path, text));
|
|
135
|
-
}
|
|
136
|
-
return {
|
|
137
|
-
sensor_id: DTO_SENSOR_ID,
|
|
138
|
-
ok: findings.every((f) => f.severity !== "hard"),
|
|
139
|
-
duration_ms: Date.now() - startedAt,
|
|
140
|
-
findings,
|
|
141
|
-
};
|
|
142
|
-
}
|
|
143
|
-
/**
|
|
144
|
-
* `@IsOptional()` followed by a property declaration with NO additional
|
|
145
|
-
* validator decorator on the same or preceding line(s). Capture group 1 is
|
|
146
|
-
* the field name.
|
|
147
|
-
*/
|
|
148
|
-
function findFakeOptionalFields(path, text) {
|
|
149
|
-
const findings = [];
|
|
150
|
-
// Match `@IsOptional()\n fieldName?: Type;` with no other validator.
|
|
151
|
-
const re = /@IsOptional\s*\(\s*\)\s*\n((?:\s*@[A-Z]\w+\s*\([^)]*\)\s*\n)*)\s*(\w+)\s*\??\s*:\s*[^;\n]+;?/g;
|
|
152
|
-
let m;
|
|
153
|
-
while ((m = re.exec(text)) !== null) {
|
|
154
|
-
const otherDecorators = m[1] ?? "";
|
|
155
|
-
const field = m[2] ?? "";
|
|
156
|
-
// If only `@IsOptional()` and nothing else, that's fake-thoroughness.
|
|
157
|
-
if (otherDecorators.trim().length === 0) {
|
|
158
|
-
const line = lineOf(text, m.index);
|
|
159
|
-
findings.push({
|
|
160
|
-
sensor_id: DTO_SENSOR_ID,
|
|
161
|
-
path,
|
|
162
|
-
line,
|
|
163
|
-
matched_text: m[0].slice(0, 200),
|
|
164
|
-
message: `${path}:${line} field \`${field}\` decorated only with @IsOptional() — add a validator (@IsString, @IsNumber, etc.) or remove the decorator`,
|
|
165
|
-
severity: "soft",
|
|
166
|
-
});
|
|
167
|
-
}
|
|
168
|
-
if (re.lastIndex === m.index)
|
|
169
|
-
re.lastIndex += 1;
|
|
170
|
-
}
|
|
171
|
-
return findings;
|
|
172
|
-
}
|
|
173
|
-
/** Methods we don't want to flag: constructors, framework hooks, etc. */
|
|
174
|
-
const METHOD_ALLOWLIST = new Set([
|
|
175
|
-
"constructor",
|
|
176
|
-
"ngOnInit",
|
|
177
|
-
"ngOnDestroy",
|
|
178
|
-
"onModuleInit",
|
|
179
|
-
"onModuleDestroy",
|
|
180
|
-
"onApplicationBootstrap",
|
|
181
|
-
"onApplicationShutdown",
|
|
182
|
-
"render",
|
|
183
|
-
]);
|
|
184
|
-
/** Heuristic: file LOOKS like a route/controller before regex-scanning bodies. */
|
|
185
|
-
function isRouteHandlerFile(path, text) {
|
|
186
|
-
if (TS_CONTROLLER_HINT.test(text))
|
|
187
|
-
return true;
|
|
188
|
-
if (PY_ROUTE_HINT.test(text))
|
|
189
|
-
return true;
|
|
190
|
-
// Conservative fallback — if the path matches the glob but the file doesn't
|
|
191
|
-
// declare a class or route decorator, skip rather than false-positive.
|
|
192
|
-
void path;
|
|
193
|
-
return false;
|
|
194
|
-
}
|
|
195
|
-
/** 1-based line number from a character offset. */
|
|
196
|
-
//# sourceMappingURL=structural.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"structural.js","sourceRoot":"","sources":["../../src/sensors/structural.ts"],"names":[],"mappings":"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"}
|