@delegance/claude-autopilot 2.0.0 → 2.1.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/CHANGELOG.md CHANGED
@@ -1,5 +1,12 @@
1
1
  # Changelog
2
2
 
3
+ ## [2.1.0] — 2026-04-22
4
+
5
+ ### Added
6
+ - **Risk-weighted file ordering** (`src/core/chunking/risk-ranker.ts`) — ranks files before sending to LLM: protected paths (score 100) → auth/security (80) → payment/billing (70) → core logic (50) → config files (40) → everything else (30) → tests (10) → docs (5); ensures most sensitive code appears at the start of the LLM's context window
7
+ - `BuildChunksInput.protectedPaths` — passed from config through review-phase to ranker so glob patterns from `protectedPaths:` config key are respected
8
+ - 9 new tests for `rankByRisk` — **224 total**
9
+
3
10
  ## [2.0.0] — 2026-04-22
4
11
 
5
12
  ### Added
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@delegance/claude-autopilot",
3
- "version": "2.0.0",
3
+ "version": "2.1.0",
4
4
  "type": "module",
5
5
  "description": "Claude Code automation pipeline: spec → plan → implement → validate → PR",
6
6
  "keywords": [
@@ -2,6 +2,7 @@ import * as fs from 'node:fs/promises';
2
2
  import * as path from 'node:path';
3
3
  import type { ReviewEngine, ReviewInput } from '../../adapters/review-engine/types.ts';
4
4
  import type { AutopilotConfig } from '../config/types.ts';
5
+ import { rankByRisk } from './risk-ranker.ts';
5
6
 
6
7
  export interface ReviewChunk {
7
8
  content: string;
@@ -15,6 +16,7 @@ export interface BuildChunksInput {
15
16
  chunking?: AutopilotConfig['chunking'];
16
17
  engine: ReviewEngine;
17
18
  cwd?: string;
19
+ protectedPaths?: string[];
18
20
  }
19
21
 
20
22
  const DEFAULT_SMALL_TIER_TOKENS = 8000;
@@ -24,7 +26,8 @@ export async function buildReviewChunks(input: BuildChunksInput): Promise<Review
24
26
  const smallMax = input.chunking?.smallTierMaxTokens ?? DEFAULT_SMALL_TIER_TOKENS;
25
27
  const fileMax = input.chunking?.perFileMaxTokens ?? DEFAULT_FILE_TIER_TOKENS;
26
28
 
27
- const fileContents = await readFiles(input.touchedFiles, input.cwd);
29
+ const ranked = rankByRisk(input.touchedFiles, { protectedPaths: input.protectedPaths });
30
+ const fileContents = await readFiles(ranked, input.cwd);
28
31
 
29
32
  if (input.strategy === 'single-pass') {
30
33
  const combined = formatBatch(fileContents);
@@ -0,0 +1,56 @@
1
+ import { minimatch } from 'minimatch';
2
+
3
+ interface RankOptions {
4
+ protectedPaths?: string[];
5
+ }
6
+
7
+ const AUTH_PATTERNS = [
8
+ /auth/i, /login/i, /logout/i, /session/i, /token/i, /jwt/i, /oauth/i,
9
+ /password/i, /credential/i, /secret/i, /permission/i, /role/i, /acl/i,
10
+ ];
11
+
12
+ const PAYMENT_PATTERNS = [
13
+ /payment/i, /billing/i, /stripe/i, /checkout/i, /invoice/i, /charge/i,
14
+ /subscription/i, /wallet/i, /transaction/i, /refund/i,
15
+ ];
16
+
17
+ const CORE_PATTERNS = [
18
+ /\/services\//i, /\/core\//i, /\/api\//i, /\/routes?\//i,
19
+ /\/controllers?\//i, /\/models?\//i, /\/middleware\//i, /\/handlers?\//i,
20
+ ];
21
+
22
+ const TEST_EXT = /\.(test|spec)\.[a-z]+$/i;
23
+ const DOC_EXT = /\.(md|txt|rst|adoc)$/i;
24
+ const CONFIG_EXT = /\.(ya?ml|json|toml|ini|env)$/i;
25
+ const CONFIG_NAMES = /(config|settings|env|constants)\./i;
26
+
27
+ function scoreFile(file: string, protectedPaths: string[]): number {
28
+ const norm = file.replace(/\\/g, '/');
29
+
30
+ // Protected paths are highest risk
31
+ for (const pattern of protectedPaths) {
32
+ if (minimatch(norm, pattern, { matchBase: false }) ||
33
+ minimatch(norm, pattern, { matchBase: true })) {
34
+ return 100;
35
+ }
36
+ }
37
+
38
+ if (TEST_EXT.test(norm)) return 10;
39
+ if (DOC_EXT.test(norm)) return 5;
40
+
41
+ if (AUTH_PATTERNS.some(p => p.test(norm))) return 80;
42
+ if (PAYMENT_PATTERNS.some(p => p.test(norm))) return 70;
43
+ if (CORE_PATTERNS.some(p => p.test(norm))) return 50;
44
+ if (CONFIG_EXT.test(norm) || CONFIG_NAMES.test(norm)) return 40;
45
+
46
+ return 30;
47
+ }
48
+
49
+ /**
50
+ * Returns files sorted highest-risk first so LLM sees the most sensitive code
51
+ * at the start of its context window.
52
+ */
53
+ export function rankByRisk(files: string[], options: RankOptions = {}): string[] {
54
+ const protectedPaths = options.protectedPaths ?? [];
55
+ return [...files].sort((a, b) => scoreFile(b, protectedPaths) - scoreFile(a, protectedPaths));
56
+ }
@@ -34,6 +34,7 @@ export async function runReviewPhase(input: ReviewPhaseInput): Promise<ReviewPha
34
34
  chunking: input.config.chunking,
35
35
  engine: input.engine,
36
36
  cwd: input.cwd,
37
+ protectedPaths: input.config.protectedPaths,
37
38
  });
38
39
 
39
40
  const allFindings: Finding[] = [];