@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.
- package/dist/bundle-invalidation.d.ts +33 -0
- package/dist/bundle-invalidation.d.ts.map +1 -0
- package/dist/bundle-invalidation.js +98 -0
- package/dist/bundle-invalidation.js.map +1 -0
- package/dist/bundle.d.ts.map +1 -1
- package/dist/bundle.js +16 -4
- package/dist/bundle.js.map +1 -1
- package/dist/candidates.d.ts +18 -0
- package/dist/candidates.d.ts.map +1 -1
- package/dist/candidates.js +76 -2
- package/dist/candidates.js.map +1 -1
- package/dist/confidence.d.ts +2 -2
- package/dist/confidence.d.ts.map +1 -1
- package/dist/confidence.js +118 -2
- package/dist/confidence.js.map +1 -1
- package/dist/conflict-zones.d.ts +18 -0
- package/dist/conflict-zones.d.ts.map +1 -0
- package/dist/conflict-zones.js +66 -0
- package/dist/conflict-zones.js.map +1 -0
- package/dist/debt-detection.d.ts +15 -0
- package/dist/debt-detection.d.ts.map +1 -0
- package/dist/debt-detection.js +80 -0
- package/dist/debt-detection.js.map +1 -0
- package/dist/index.d.ts +13 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +12 -1
- package/dist/index.js.map +1 -1
- package/dist/intent/drift.d.ts +31 -0
- package/dist/intent/drift.d.ts.map +1 -0
- package/dist/intent/drift.js +120 -0
- package/dist/intent/drift.js.map +1 -0
- package/dist/intent/hash.d.ts +19 -0
- package/dist/intent/hash.d.ts.map +1 -0
- package/dist/intent/hash.js +38 -0
- package/dist/intent/hash.js.map +1 -0
- package/dist/intent/index.d.ts +5 -0
- package/dist/intent/index.d.ts.map +1 -0
- package/dist/intent/index.js +4 -0
- package/dist/intent/index.js.map +1 -0
- package/dist/intent/normalize.d.ts +23 -0
- package/dist/intent/normalize.d.ts.map +1 -0
- package/dist/intent/normalize.js +35 -0
- package/dist/intent/normalize.js.map +1 -0
- package/dist/intent/types.d.ts +37 -0
- package/dist/intent/types.d.ts.map +1 -0
- package/dist/intent/types.js +2 -0
- package/dist/intent/types.js.map +1 -0
- package/dist/loop-detection.d.ts +28 -0
- package/dist/loop-detection.d.ts.map +1 -0
- package/dist/loop-detection.js +124 -0
- package/dist/loop-detection.js.map +1 -0
- package/dist/review-candidates.d.ts +23 -0
- package/dist/review-candidates.d.ts.map +1 -0
- package/dist/review-candidates.js +230 -0
- package/dist/review-candidates.js.map +1 -0
- package/dist/review-coverage.d.ts +33 -0
- package/dist/review-coverage.d.ts.map +1 -0
- package/dist/review-coverage.js +110 -0
- package/dist/review-coverage.js.map +1 -0
- package/dist/scope-contract.d.ts +26 -0
- package/dist/scope-contract.d.ts.map +1 -0
- package/dist/scope-contract.js +79 -0
- package/dist/scope-contract.js.map +1 -0
- package/dist/scorer.d.ts.map +1 -1
- package/dist/scorer.js +21 -2
- package/dist/scorer.js.map +1 -1
- package/dist/security-surface.d.ts +13 -0
- package/dist/security-surface.d.ts.map +1 -0
- package/dist/security-surface.js +45 -0
- package/dist/security-surface.js.map +1 -0
- package/dist/task-type.d.ts.map +1 -1
- package/dist/task-type.js +4 -2
- package/dist/task-type.js.map +1 -1
- 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 @@
|
|
|
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"}
|