@codeledger/selector 0.2.1 → 0.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (74) hide show
  1. package/dist/bundle-invalidation.d.ts +33 -0
  2. package/dist/bundle-invalidation.d.ts.map +1 -0
  3. package/dist/bundle-invalidation.js +98 -0
  4. package/dist/bundle-invalidation.js.map +1 -0
  5. package/dist/bundle.d.ts.map +1 -1
  6. package/dist/bundle.js +16 -4
  7. package/dist/bundle.js.map +1 -1
  8. package/dist/candidates.d.ts +18 -0
  9. package/dist/candidates.d.ts.map +1 -1
  10. package/dist/candidates.js +76 -2
  11. package/dist/candidates.js.map +1 -1
  12. package/dist/confidence.d.ts +2 -2
  13. package/dist/confidence.d.ts.map +1 -1
  14. package/dist/confidence.js +118 -2
  15. package/dist/confidence.js.map +1 -1
  16. package/dist/conflict-zones.d.ts +18 -0
  17. package/dist/conflict-zones.d.ts.map +1 -0
  18. package/dist/conflict-zones.js +66 -0
  19. package/dist/conflict-zones.js.map +1 -0
  20. package/dist/debt-detection.d.ts +15 -0
  21. package/dist/debt-detection.d.ts.map +1 -0
  22. package/dist/debt-detection.js +80 -0
  23. package/dist/debt-detection.js.map +1 -0
  24. package/dist/index.d.ts +13 -1
  25. package/dist/index.d.ts.map +1 -1
  26. package/dist/index.js +12 -1
  27. package/dist/index.js.map +1 -1
  28. package/dist/intent/drift.d.ts +31 -0
  29. package/dist/intent/drift.d.ts.map +1 -0
  30. package/dist/intent/drift.js +120 -0
  31. package/dist/intent/drift.js.map +1 -0
  32. package/dist/intent/hash.d.ts +19 -0
  33. package/dist/intent/hash.d.ts.map +1 -0
  34. package/dist/intent/hash.js +38 -0
  35. package/dist/intent/hash.js.map +1 -0
  36. package/dist/intent/index.d.ts +5 -0
  37. package/dist/intent/index.d.ts.map +1 -0
  38. package/dist/intent/index.js +4 -0
  39. package/dist/intent/index.js.map +1 -0
  40. package/dist/intent/normalize.d.ts +23 -0
  41. package/dist/intent/normalize.d.ts.map +1 -0
  42. package/dist/intent/normalize.js +35 -0
  43. package/dist/intent/normalize.js.map +1 -0
  44. package/dist/intent/types.d.ts +37 -0
  45. package/dist/intent/types.d.ts.map +1 -0
  46. package/dist/intent/types.js +2 -0
  47. package/dist/intent/types.js.map +1 -0
  48. package/dist/loop-detection.d.ts +28 -0
  49. package/dist/loop-detection.d.ts.map +1 -0
  50. package/dist/loop-detection.js +124 -0
  51. package/dist/loop-detection.js.map +1 -0
  52. package/dist/review-candidates.d.ts +23 -0
  53. package/dist/review-candidates.d.ts.map +1 -0
  54. package/dist/review-candidates.js +230 -0
  55. package/dist/review-candidates.js.map +1 -0
  56. package/dist/review-coverage.d.ts +33 -0
  57. package/dist/review-coverage.d.ts.map +1 -0
  58. package/dist/review-coverage.js +110 -0
  59. package/dist/review-coverage.js.map +1 -0
  60. package/dist/scope-contract.d.ts +26 -0
  61. package/dist/scope-contract.d.ts.map +1 -0
  62. package/dist/scope-contract.js +79 -0
  63. package/dist/scope-contract.js.map +1 -0
  64. package/dist/scorer.d.ts.map +1 -1
  65. package/dist/scorer.js +21 -2
  66. package/dist/scorer.js.map +1 -1
  67. package/dist/security-surface.d.ts +13 -0
  68. package/dist/security-surface.d.ts.map +1 -0
  69. package/dist/security-surface.js +45 -0
  70. package/dist/security-surface.js.map +1 -0
  71. package/dist/task-type.d.ts.map +1 -1
  72. package/dist/task-type.js +4 -2
  73. package/dist/task-type.js.map +1 -1
  74. package/package.json +3 -3
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Deterministic normalization for intent governance.
3
+ *
4
+ * Rules:
5
+ * 1. Trim whitespace
6
+ * 2. Lowercase
7
+ * 3. Collapse internal whitespace to single spaces
8
+ * 4. Remove non-semantic punctuation: ,;:!? (keep / - _ . for paths/flags/extensions)
9
+ * 4b. Remove periods only at word boundaries or end of string (preserve .ts, .js, etc.)
10
+ * 5. Normalize path separators to /
11
+ * 6. Remove trailing /
12
+ * 7. Sort arrays lexicographically
13
+ * 8. Remove duplicates
14
+ */
15
+ /**
16
+ * Normalize a single string value.
17
+ */
18
+ export function norm(s) {
19
+ return s
20
+ .trim()
21
+ .toLowerCase()
22
+ .replace(/\\/g, '/') // normalize path separators early (before punctuation removal)
23
+ .replace(/[,;:!?]/g, '') // remove non-semantic punctuation (NOT periods)
24
+ .replace(/\.(?=\s|$)/g, '') // remove periods only at word boundaries or end of string
25
+ .replace(/\s+/g, ' ')
26
+ .replace(/\/+$/, ''); // remove trailing /
27
+ }
28
+ /**
29
+ * Normalize an array of strings: norm each, deduplicate, sort.
30
+ */
31
+ export function normArr(xs) {
32
+ const set = new Set(xs.map(norm).filter(Boolean));
33
+ return Array.from(set).sort();
34
+ }
35
+ //# sourceMappingURL=normalize.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"normalize.js","sourceRoot":"","sources":["../../src/intent/normalize.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH;;GAEG;AACH,MAAM,UAAU,IAAI,CAAC,CAAS;IAC5B,OAAO,CAAC;SACL,IAAI,EAAE;SACN,WAAW,EAAE;SACb,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,+DAA+D;SACnF,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC,gDAAgD;SACxE,OAAO,CAAC,aAAa,EAAE,EAAE,CAAC,CAAC,0DAA0D;SACrF,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC;SACpB,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,CAAC,oBAAoB;AAC9C,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,OAAO,CAAC,EAAY;IAClC,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC;IAClD,OAAO,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;AAChC,CAAC"}
@@ -0,0 +1,37 @@
1
+ import type { AddressedFile, BundleInvalidationReport } from '@codeledger/types';
2
+ /** Structured, normalized representation of the session's objective */
3
+ export interface TaskContractV1 {
4
+ version: 1;
5
+ objective: string;
6
+ deliverable: string | null;
7
+ scope_in: string[];
8
+ scope_out: string[];
9
+ constraints: string[];
10
+ acceptance_criteria: string[];
11
+ risk_flags: string[];
12
+ repo_paths_in_scope: string[];
13
+ timestamp: string;
14
+ }
15
+ export type DriftLevel = 'NONE' | 'MINOR' | 'MAJOR' | 'CRITICAL';
16
+ export interface DriftReason {
17
+ field: keyof Omit<TaskContractV1, 'version' | 'timestamp'>;
18
+ distance: number;
19
+ }
20
+ export interface DriftResult {
21
+ drift_score: number;
22
+ drift_level: DriftLevel;
23
+ reasons: DriftReason[];
24
+ }
25
+ /** Event record written to intent_drift.jsonl */
26
+ export interface IntentDriftEvent {
27
+ ts: string;
28
+ type: 'INTENT_DRIFT';
29
+ baseline_hash: string;
30
+ current_hash: string;
31
+ drift_score: number;
32
+ drift_level: DriftLevel;
33
+ reasons: DriftReason[];
34
+ recommended_action: 'NONE' | 'LOG_ONLY' | 'REFRESH_BUNDLE' | 'REQUIRE_ACK';
35
+ }
36
+ export type { AddressedFile, BundleInvalidationReport, };
37
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/intent/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,wBAAwB,EAAE,MAAM,mBAAmB,CAAC;AAIjF,uEAAuE;AACvE,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,CAAC,CAAC;IACX,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,mBAAmB,EAAE,MAAM,EAAE,CAAC;IAC9B,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,mBAAmB,EAAE,MAAM,EAAE,CAAC;IAC9B,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,MAAM,UAAU,GAAG,MAAM,GAAG,OAAO,GAAG,OAAO,GAAG,UAAU,CAAC;AAEjE,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,MAAM,IAAI,CAAC,cAAc,EAAE,SAAS,GAAG,WAAW,CAAC,CAAC;IAC3D,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,WAAW;IAC1B,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,UAAU,CAAC;IACxB,OAAO,EAAE,WAAW,EAAE,CAAC;CACxB;AAED,iDAAiD;AACjD,MAAM,WAAW,gBAAgB;IAC/B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,cAAc,CAAC;IACrB,aAAa,EAAE,MAAM,CAAC;IACtB,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,UAAU,CAAC;IACxB,OAAO,EAAE,WAAW,EAAE,CAAC;IACvB,kBAAkB,EAAE,MAAM,GAAG,UAAU,GAAG,gBAAgB,GAAG,aAAa,CAAC;CAC5E;AAGD,YAAY,EACV,aAAa,EACb,wBAAwB,GACzB,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/intent/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,28 @@
1
+ import type { LoopDetectionConfig, LoopDetectionReport } from '@codeledger/types';
2
+ /** Default thresholds for loop detection */
3
+ export declare const DEFAULT_LOOP_THRESHOLDS: LoopDetectionConfig;
4
+ /** Entry in the session activity log — tracks tool usage for pattern detection */
5
+ export interface ActivityEntry {
6
+ type: 'test_run' | 'file_edit' | 'command';
7
+ target: string;
8
+ success: boolean;
9
+ /** Hash of failure output for duplicate detection */
10
+ output_hash?: string;
11
+ }
12
+ /**
13
+ * Analyze a session's activity log for stuck patterns.
14
+ *
15
+ * All detection is numeric and deterministic — pattern matching on
16
+ * activity sequences with configurable thresholds.
17
+ */
18
+ export declare function detectStuckPatterns(activities: ActivityEntry[], config?: LoopDetectionConfig): LoopDetectionReport;
19
+ /**
20
+ * Parse git log and diff output into activity entries for loop detection.
21
+ * This enables post-hoc analysis from git state without requiring
22
+ * real-time event ledger integration.
23
+ */
24
+ export declare function buildActivityLogFromGit(_commitLog: string[], fileEdits: Map<string, number>, testResults: Array<{
25
+ name: string;
26
+ pass: boolean;
27
+ }>): ActivityEntry[];
28
+ //# sourceMappingURL=loop-detection.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loop-detection.d.ts","sourceRoot":"","sources":["../src/loop-detection.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAgB,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAEhG,4CAA4C;AAC5C,eAAO,MAAM,uBAAuB,EAAE,mBAIrC,CAAC;AAEF,kFAAkF;AAClF,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,UAAU,GAAG,WAAW,GAAG,SAAS,CAAC;IAC3C,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,OAAO,CAAC;IACjB,qDAAqD;IACrD,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CACjC,UAAU,EAAE,aAAa,EAAE,EAC3B,MAAM,GAAE,mBAA6C,GACpD,mBAAmB,CAqDrB;AA8DD;;;;GAIG;AACH,wBAAgB,uBAAuB,CACrC,UAAU,EAAE,MAAM,EAAE,EACpB,SAAS,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,EAC9B,WAAW,EAAE,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,OAAO,CAAA;CAAE,CAAC,GAClD,aAAa,EAAE,CAoBjB"}
@@ -0,0 +1,124 @@
1
+ /** Default thresholds for loop detection */
2
+ export const DEFAULT_LOOP_THRESHOLDS = {
3
+ max_test_retries: 3,
4
+ max_file_edits: 5,
5
+ max_command_retries: 3,
6
+ };
7
+ /**
8
+ * Analyze a session's activity log for stuck patterns.
9
+ *
10
+ * All detection is numeric and deterministic — pattern matching on
11
+ * activity sequences with configurable thresholds.
12
+ */
13
+ export function detectStuckPatterns(activities, config = DEFAULT_LOOP_THRESHOLDS) {
14
+ const episodes = [];
15
+ // 1. Repeated test failures without progress
16
+ const testFailStreaks = detectRepeatedFailures(activities.filter((a) => a.type === 'test_run'), config.max_test_retries);
17
+ for (const streak of testFailStreaks) {
18
+ episodes.push({
19
+ type: 'repeated_test_failure',
20
+ target: streak.target,
21
+ count: streak.count,
22
+ message: `Test "${streak.target}" failed ${streak.count} consecutive times with no file changes between runs`,
23
+ });
24
+ }
25
+ // 2. Same file edited excessively
26
+ const fileEditCounts = new Map();
27
+ for (const a of activities) {
28
+ if (a.type === 'file_edit') {
29
+ fileEditCounts.set(a.target, (fileEditCounts.get(a.target) ?? 0) + 1);
30
+ }
31
+ }
32
+ for (const [file, count] of fileEditCounts) {
33
+ if (count > config.max_file_edits) {
34
+ episodes.push({
35
+ type: 'repeated_file_edit',
36
+ target: file,
37
+ count,
38
+ message: `File "${file}" was edited ${count} times (threshold: ${config.max_file_edits})`,
39
+ });
40
+ }
41
+ }
42
+ // 3. Same command fails repeatedly with identical output
43
+ const commandFailStreaks = detectRepeatedCommandFailures(activities.filter((a) => a.type === 'command'), config.max_command_retries);
44
+ for (const streak of commandFailStreaks) {
45
+ episodes.push({
46
+ type: 'repeated_command_failure',
47
+ target: streak.target,
48
+ count: streak.count,
49
+ message: `Command "${streak.target}" failed ${streak.count} times with identical output`,
50
+ });
51
+ }
52
+ return {
53
+ stuck_episodes: episodes,
54
+ total_episodes: episodes.length,
55
+ };
56
+ }
57
+ /**
58
+ * Find sequences of test failures with no intervening file changes.
59
+ * A file_edit activity between test runs resets the counter.
60
+ */
61
+ function detectRepeatedFailures(testActivities, threshold) {
62
+ const streaks = [];
63
+ const currentStreak = new Map();
64
+ for (const a of testActivities) {
65
+ if (!a.success) {
66
+ const count = (currentStreak.get(a.target) ?? 0) + 1;
67
+ currentStreak.set(a.target, count);
68
+ if (count >= threshold) {
69
+ // Only report once per target at the threshold
70
+ if (count === threshold) {
71
+ streaks.push({ target: a.target, count });
72
+ }
73
+ }
74
+ }
75
+ else {
76
+ // Test passed — reset streak for this target
77
+ currentStreak.delete(a.target);
78
+ }
79
+ }
80
+ return streaks;
81
+ }
82
+ /**
83
+ * Find commands that fail repeatedly with the same output hash.
84
+ */
85
+ function detectRepeatedCommandFailures(commandActivities, threshold) {
86
+ const streaks = [];
87
+ // Group by target + output_hash
88
+ const failCounts = new Map();
89
+ for (const a of commandActivities) {
90
+ if (!a.success && a.output_hash) {
91
+ const key = `${a.target}::${a.output_hash}`;
92
+ const count = (failCounts.get(key) ?? 0) + 1;
93
+ failCounts.set(key, count);
94
+ if (count === threshold) {
95
+ streaks.push({ target: a.target, count });
96
+ }
97
+ }
98
+ }
99
+ return streaks;
100
+ }
101
+ /**
102
+ * Parse git log and diff output into activity entries for loop detection.
103
+ * This enables post-hoc analysis from git state without requiring
104
+ * real-time event ledger integration.
105
+ */
106
+ export function buildActivityLogFromGit(_commitLog, fileEdits, testResults) {
107
+ const activities = [];
108
+ // Add file edits
109
+ for (const [file, count] of fileEdits) {
110
+ for (let i = 0; i < count; i++) {
111
+ activities.push({ type: 'file_edit', target: file, success: true });
112
+ }
113
+ }
114
+ // Add test results
115
+ for (const result of testResults) {
116
+ activities.push({
117
+ type: 'test_run',
118
+ target: result.name,
119
+ success: result.pass,
120
+ });
121
+ }
122
+ return activities;
123
+ }
124
+ //# sourceMappingURL=loop-detection.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loop-detection.js","sourceRoot":"","sources":["../src/loop-detection.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,23 @@
1
+ import type { RepoIndex, DepGraph, ReviewCandidate } from '@codeledger/types';
2
+ /**
3
+ * Generate review-mode candidates from a task prompt.
4
+ *
5
+ * Unlike edit-mode candidates (which predict files-to-edit), review-mode
6
+ * candidates identify files that MUST be read to verify a review task.
7
+ *
8
+ * Heuristics:
9
+ * 1. Extract file paths mentioned in the task prompt (literal path references)
10
+ * 2. Extract package/module names → resolve to entry points
11
+ * 3. For export/API review tasks: identify index.ts and re-export files
12
+ * 4. For feature review tasks: use keyword matching + dependency graph
13
+ * 5. Mark each file as MUST_READ (directly referenced) or SHOULD_READ (inferred)
14
+ */
15
+ export declare function generateReviewCandidates(task: string, repoIndex: RepoIndex, depGraph: DepGraph): ReviewCandidate[];
16
+ /**
17
+ * Split review candidates into must-read and should-read lists.
18
+ */
19
+ export declare function splitReviewCandidates(candidates: ReviewCandidate[]): {
20
+ mustRead: string[];
21
+ shouldRead: string[];
22
+ };
23
+ //# sourceMappingURL=review-candidates.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"review-candidates.d.ts","sourceRoot":"","sources":["../src/review-candidates.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,SAAS,EACT,QAAQ,EACR,eAAe,EAEhB,MAAM,mBAAmB,CAAC;AAE3B;;;;;;;;;;;;GAYG;AACH,wBAAgB,wBAAwB,CACtC,IAAI,EAAE,MAAM,EACZ,SAAS,EAAE,SAAS,EACpB,QAAQ,EAAE,QAAQ,GACjB,eAAe,EAAE,CA0FnB;AAyID;;GAEG;AACH,wBAAgB,qBAAqB,CACnC,UAAU,EAAE,eAAe,EAAE,GAC5B;IAAE,QAAQ,EAAE,MAAM,EAAE,CAAC;IAAC,UAAU,EAAE,MAAM,EAAE,CAAA;CAAE,CAa9C"}
@@ -0,0 +1,230 @@
1
+ /**
2
+ * Generate review-mode candidates from a task prompt.
3
+ *
4
+ * Unlike edit-mode candidates (which predict files-to-edit), review-mode
5
+ * candidates identify files that MUST be read to verify a review task.
6
+ *
7
+ * Heuristics:
8
+ * 1. Extract file paths mentioned in the task prompt (literal path references)
9
+ * 2. Extract package/module names → resolve to entry points
10
+ * 3. For export/API review tasks: identify index.ts and re-export files
11
+ * 4. For feature review tasks: use keyword matching + dependency graph
12
+ * 5. Mark each file as MUST_READ (directly referenced) or SHOULD_READ (inferred)
13
+ */
14
+ export function generateReviewCandidates(task, repoIndex, depGraph) {
15
+ const candidates = new Map();
16
+ const repoFiles = new Set(repoIndex.files.map((f) => f.path));
17
+ // Stage 1: Extract explicit file path references from the task
18
+ const explicitPaths = extractExplicitPaths(task, repoFiles);
19
+ for (const path of explicitPaths) {
20
+ candidates.set(path, {
21
+ path,
22
+ review_reason: 'explicit_reference',
23
+ requirement: 'must_read',
24
+ relevance: 1.0,
25
+ });
26
+ }
27
+ // Stage 2: Extract package/module references → resolve entry points
28
+ const packageEntries = resolvePackageEntries(task, repoIndex);
29
+ for (const path of packageEntries) {
30
+ if (!candidates.has(path)) {
31
+ candidates.set(path, {
32
+ path,
33
+ review_reason: 'package_entry',
34
+ requirement: 'must_read',
35
+ relevance: 0.9,
36
+ });
37
+ }
38
+ }
39
+ // Stage 3: For export/API review tasks, identify export surfaces
40
+ if (isExportReviewTask(task)) {
41
+ const exportSurfaces = findExportSurfaces(repoIndex);
42
+ for (const path of exportSurfaces) {
43
+ if (!candidates.has(path)) {
44
+ candidates.set(path, {
45
+ path,
46
+ review_reason: 'export_surface',
47
+ requirement: 'must_read',
48
+ relevance: 0.85,
49
+ });
50
+ }
51
+ }
52
+ }
53
+ // Stage 4: Keyword-inferred candidates from task text
54
+ const keywords = extractReviewKeywords(task);
55
+ if (keywords.length > 0) {
56
+ const keywordMatches = matchKeywordsToFiles(keywords, repoIndex);
57
+ for (const { path, relevance } of keywordMatches) {
58
+ if (!candidates.has(path)) {
59
+ const requirement = relevance >= 0.7 ? 'must_read' : 'should_read';
60
+ candidates.set(path, {
61
+ path,
62
+ review_reason: 'keyword_inferred',
63
+ requirement,
64
+ relevance,
65
+ });
66
+ }
67
+ }
68
+ }
69
+ // Stage 5: Expand must-read files via dependency graph
70
+ const mustReadPaths = [...candidates.entries()]
71
+ .filter(([_, c]) => c.requirement === 'must_read')
72
+ .map(([p]) => p);
73
+ for (const seedPath of mustReadPaths) {
74
+ const deps = depGraph.imports[seedPath];
75
+ if (!deps)
76
+ continue;
77
+ for (const dep of deps) {
78
+ if (!repoFiles.has(dep))
79
+ continue;
80
+ if (!candidates.has(dep)) {
81
+ candidates.set(dep, {
82
+ path: dep,
83
+ review_reason: 'dependency_chain',
84
+ requirement: 'should_read',
85
+ relevance: 0.6,
86
+ });
87
+ }
88
+ }
89
+ }
90
+ // Sort: must_read first, then by relevance descending
91
+ const result = [...candidates.values()].sort((a, b) => {
92
+ if (a.requirement !== b.requirement) {
93
+ return a.requirement === 'must_read' ? -1 : 1;
94
+ }
95
+ return b.relevance - a.relevance;
96
+ });
97
+ return result;
98
+ }
99
+ /**
100
+ * Extract file paths explicitly mentioned in the task text.
101
+ * Matches patterns like `packages/types/src/index.ts` or `src/foo.js`.
102
+ */
103
+ function extractExplicitPaths(task, repoFiles) {
104
+ // Match anything that looks like a relative file path
105
+ const pathPattern = /(?:^|\s|["'`(])([a-zA-Z0-9_./\-]+\.[a-zA-Z]{1,6})(?:$|\s|["'`),])/g;
106
+ const found = [];
107
+ let match;
108
+ while ((match = pathPattern.exec(task)) !== null) {
109
+ const candidate = match[1];
110
+ // Check if this path exists in the repo
111
+ if (repoFiles.has(candidate)) {
112
+ found.push(candidate);
113
+ }
114
+ }
115
+ return [...new Set(found)];
116
+ }
117
+ /**
118
+ * Resolve package/module names mentioned in the task to their entry points.
119
+ * E.g., "packages/selector" → "packages/selector/src/index.ts"
120
+ */
121
+ function resolvePackageEntries(task, repoIndex) {
122
+ const dirPattern = /(?:packages|src|lib)\/[a-zA-Z0-9_-]+/g;
123
+ const dirs = [];
124
+ let match;
125
+ while ((match = dirPattern.exec(task)) !== null) {
126
+ dirs.push(match[0]);
127
+ }
128
+ const entries = [];
129
+ for (const dir of dirs) {
130
+ // Look for index files in this directory
131
+ const indexCandidates = [
132
+ `${dir}/src/index.ts`,
133
+ `${dir}/src/index.js`,
134
+ `${dir}/index.ts`,
135
+ `${dir}/index.js`,
136
+ ];
137
+ for (const candidate of indexCandidates) {
138
+ const found = repoIndex.files.find((f) => f.path === candidate);
139
+ if (found) {
140
+ entries.push(found.path);
141
+ break;
142
+ }
143
+ }
144
+ }
145
+ return [...new Set(entries)];
146
+ }
147
+ /** Detect if the task is about reviewing exports, APIs, or public interfaces */
148
+ function isExportReviewTask(task) {
149
+ const lower = task.toLowerCase();
150
+ const exportKeywords = ['export', 'api', 'public interface', 'surface', 'contract', 're-export'];
151
+ return exportKeywords.some((kw) => lower.includes(kw));
152
+ }
153
+ /** Find files that are export surfaces (index.ts, barrel files) */
154
+ function findExportSurfaces(repoIndex) {
155
+ return repoIndex.files
156
+ .filter((f) => {
157
+ const name = f.path.split('/').pop() ?? '';
158
+ return name === 'index.ts' || name === 'index.js';
159
+ })
160
+ .map((f) => f.path);
161
+ }
162
+ /** Extract review-relevant keywords from a task prompt */
163
+ function extractReviewKeywords(task) {
164
+ const stopWords = new Set([
165
+ 'the', 'a', 'an', 'is', 'are', 'was', 'were', 'be', 'been', 'being',
166
+ 'have', 'has', 'had', 'do', 'does', 'did', 'will', 'would', 'could',
167
+ 'should', 'may', 'might', 'shall', 'can', 'need', 'must', 'ought',
168
+ 'i', 'you', 'he', 'she', 'it', 'we', 'they', 'me', 'him', 'her',
169
+ 'us', 'them', 'my', 'your', 'his', 'its', 'our', 'their',
170
+ 'this', 'that', 'these', 'those', 'and', 'or', 'but', 'if', 'then',
171
+ 'of', 'in', 'on', 'at', 'to', 'for', 'with', 'from', 'by', 'as',
172
+ 'into', 'through', 'during', 'before', 'after', 'above', 'below',
173
+ 'not', 'no', 'nor', 'so', 'very', 'just', 'all', 'each', 'every',
174
+ 'review', 'verify', 'check', 'audit', 'ensure', 'confirm', 'validate',
175
+ ]);
176
+ const words = task.toLowerCase().replace(/[^a-z0-9_\-]/g, ' ').split(/\s+/);
177
+ return words
178
+ .filter((w) => w.length >= 3 && !stopWords.has(w))
179
+ .slice(0, 20);
180
+ }
181
+ /** Match keywords to repo files by path and content keyword overlap */
182
+ function matchKeywordsToFiles(keywords, repoIndex) {
183
+ const results = [];
184
+ const keywordSet = new Set(keywords);
185
+ for (const file of repoIndex.files) {
186
+ if (file.is_test)
187
+ continue;
188
+ let score = 0;
189
+ const pathLower = file.path.toLowerCase();
190
+ // Path-based matching
191
+ for (const kw of keywords) {
192
+ if (pathLower.includes(kw)) {
193
+ score += 0.3;
194
+ }
195
+ }
196
+ // Content keyword matching
197
+ if (file.content_keywords) {
198
+ const contentSet = new Set(file.content_keywords);
199
+ for (const kw of keywordSet) {
200
+ if (contentSet.has(kw)) {
201
+ score += 0.15;
202
+ }
203
+ }
204
+ }
205
+ const relevance = Math.min(score, 1.0);
206
+ if (relevance >= 0.15) {
207
+ results.push({ path: file.path, relevance });
208
+ }
209
+ }
210
+ // Sort by relevance descending
211
+ results.sort((a, b) => b.relevance - a.relevance);
212
+ return results.slice(0, 50);
213
+ }
214
+ /**
215
+ * Split review candidates into must-read and should-read lists.
216
+ */
217
+ export function splitReviewCandidates(candidates) {
218
+ const mustRead = [];
219
+ const shouldRead = [];
220
+ for (const c of candidates) {
221
+ if (c.requirement === 'must_read') {
222
+ mustRead.push(c.path);
223
+ }
224
+ else {
225
+ shouldRead.push(c.path);
226
+ }
227
+ }
228
+ return { mustRead, shouldRead };
229
+ }
230
+ //# sourceMappingURL=review-candidates.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"review-candidates.js","sourceRoot":"","sources":["../src/review-candidates.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,33 @@
1
+ import type { ReviewCoverageReport, FileReadDepth, ISODateTime, RepoIndex } from '@codeledger/types';
2
+ /**
3
+ * Read depth info for a file (from ReadTracker or equivalent).
4
+ * This is the input interface — decoupled from the instrument package.
5
+ */
6
+ export interface ReadDepthInput {
7
+ path: string;
8
+ total_lines: number;
9
+ lines_read: number;
10
+ read_depth: number;
11
+ first_read_at: ISODateTime;
12
+ read_count: number;
13
+ }
14
+ /**
15
+ * Compute review coverage by comparing the review bundle's required files
16
+ * against the session's actual read data.
17
+ *
18
+ * Three metrics:
19
+ * 1. File Coverage — did the agent open the file at all?
20
+ * 2. Depth-Weighted Coverage — how much of each file was actually read?
21
+ * 3. Temporal Alignment — did reads happen BEFORE claims, or after?
22
+ */
23
+ export declare function computeReviewCoverage(requiredFiles: string[], readDepths: ReadDepthInput[], readPaths: Set<string>, repoIndex: RepoIndex, firstClaimTs?: ISODateTime): ReviewCoverageReport;
24
+ /**
25
+ * Evaluate whether coverage meets a threshold.
26
+ * Returns true if both file coverage and depth coverage meet their thresholds.
27
+ */
28
+ export declare function meetsCoverageThreshold(report: ReviewCoverageReport, fileCoverageThreshold: number, depthCoverageThreshold: number): boolean;
29
+ /**
30
+ * Get files that were only shallowly read (below a depth threshold).
31
+ */
32
+ export declare function getShallowReads(report: ReviewCoverageReport, shallowThreshold: number): FileReadDepth[];
33
+ //# sourceMappingURL=review-coverage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"review-coverage.d.ts","sourceRoot":"","sources":["../src/review-coverage.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,oBAAoB,EACpB,aAAa,EACb,WAAW,EACX,SAAS,EACV,MAAM,mBAAmB,CAAC;AAE3B;;;GAGG;AACH,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,WAAW,CAAC;IAC3B,UAAU,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;;;GAQG;AACH,wBAAgB,qBAAqB,CACnC,aAAa,EAAE,MAAM,EAAE,EACvB,UAAU,EAAE,cAAc,EAAE,EAC5B,SAAS,EAAE,GAAG,CAAC,MAAM,CAAC,EACtB,SAAS,EAAE,SAAS,EACpB,YAAY,CAAC,EAAE,WAAW,GACzB,oBAAoB,CA8FtB;AAED;;;GAGG;AACH,wBAAgB,sBAAsB,CACpC,MAAM,EAAE,oBAAoB,EAC5B,qBAAqB,EAAE,MAAM,EAC7B,sBAAsB,EAAE,MAAM,GAC7B,OAAO,CAKT;AAED;;GAEG;AACH,wBAAgB,eAAe,CAC7B,MAAM,EAAE,oBAAoB,EAC5B,gBAAgB,EAAE,MAAM,GACvB,aAAa,EAAE,CAIjB"}