auditor-lambda 0.3.40 → 0.5.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.
Files changed (193) hide show
  1. package/audit-code-wrapper-lib.mjs +20 -2
  2. package/dist/cli/args.d.ts +59 -0
  3. package/dist/cli/args.js +244 -0
  4. package/dist/cli/dispatch.d.ts +80 -0
  5. package/dist/cli/dispatch.js +532 -0
  6. package/dist/cli/prompts.d.ts +37 -0
  7. package/dist/cli/prompts.js +225 -0
  8. package/dist/cli/steps.d.ts +29 -0
  9. package/dist/cli/steps.js +30 -0
  10. package/dist/cli/waveManifest.d.ts +40 -0
  11. package/dist/cli/waveManifest.js +41 -0
  12. package/dist/cli/workerResult.d.ts +18 -0
  13. package/dist/cli/workerResult.js +42 -0
  14. package/dist/cli.d.ts +2 -22
  15. package/dist/cli.js +442 -975
  16. package/dist/extractors/analyzers/css.d.ts +2 -0
  17. package/dist/extractors/analyzers/css.js +101 -0
  18. package/dist/extractors/analyzers/html.d.ts +2 -0
  19. package/dist/extractors/analyzers/html.js +92 -0
  20. package/dist/extractors/analyzers/merge.d.ts +14 -0
  21. package/dist/extractors/analyzers/merge.js +85 -0
  22. package/dist/extractors/analyzers/python.d.ts +2 -0
  23. package/dist/extractors/analyzers/python.js +104 -0
  24. package/dist/extractors/analyzers/registry.d.ts +33 -0
  25. package/dist/extractors/analyzers/registry.js +100 -0
  26. package/dist/extractors/analyzers/resourceUrl.d.ts +7 -0
  27. package/dist/extractors/analyzers/resourceUrl.js +25 -0
  28. package/dist/extractors/analyzers/sql.d.ts +2 -0
  29. package/dist/extractors/analyzers/sql.js +19 -0
  30. package/dist/extractors/analyzers/treeSitter.d.ts +34 -0
  31. package/dist/extractors/analyzers/treeSitter.js +111 -0
  32. package/dist/extractors/analyzers/types.d.ts +53 -0
  33. package/dist/extractors/analyzers/typescript.d.ts +2 -0
  34. package/dist/extractors/analyzers/typescript.js +257 -0
  35. package/dist/extractors/browserExtension.d.ts +1 -3
  36. package/dist/extractors/browserExtension.js +2 -2
  37. package/dist/extractors/designAssessment.d.ts +1 -3
  38. package/dist/extractors/disposition.d.ts +2 -1
  39. package/dist/extractors/disposition.js +11 -1
  40. package/dist/extractors/flows.d.ts +1 -3
  41. package/dist/extractors/flows.js +2 -2
  42. package/dist/extractors/graph.d.ts +2 -2
  43. package/dist/extractors/graph.js +171 -327
  44. package/dist/extractors/graphManifestEdges.d.ts +1 -1
  45. package/dist/extractors/graphPathUtils.d.ts +1 -1
  46. package/dist/extractors/graphPythonImports.d.ts +18 -0
  47. package/dist/extractors/graphPythonImports.js +362 -0
  48. package/dist/extractors/pathPatterns.d.ts +6 -0
  49. package/dist/extractors/pathPatterns.js +8 -0
  50. package/dist/extractors/risk.d.ts +1 -2
  51. package/dist/extractors/surfaces.d.ts +1 -3
  52. package/dist/extractors/surfaces.js +2 -2
  53. package/dist/io/artifacts.d.ts +12 -5
  54. package/dist/io/artifacts.js +13 -1
  55. package/dist/io/runArtifacts.js +1 -1
  56. package/dist/mcp/server.js +1 -1
  57. package/dist/orchestrator/advance.d.ts +21 -0
  58. package/dist/orchestrator/advance.js +69 -7
  59. package/dist/orchestrator/auditTaskUtils.d.ts +4 -0
  60. package/dist/orchestrator/auditTaskUtils.js +27 -0
  61. package/dist/orchestrator/dependencyMap.js +27 -0
  62. package/dist/orchestrator/edgeReasoning.d.ts +39 -0
  63. package/dist/orchestrator/edgeReasoning.js +125 -0
  64. package/dist/orchestrator/executors.js +11 -1
  65. package/dist/orchestrator/fileAnchors.d.ts +1 -1
  66. package/dist/orchestrator/fileIntegrity.d.ts +7 -0
  67. package/dist/orchestrator/fileIntegrity.js +41 -0
  68. package/dist/orchestrator/flowCoverage.d.ts +1 -1
  69. package/dist/orchestrator/flowPlanning.d.ts +1 -1
  70. package/dist/orchestrator/flowRequeue.d.ts +1 -1
  71. package/dist/orchestrator/graphEnrichmentExecutor.d.ts +29 -0
  72. package/dist/orchestrator/graphEnrichmentExecutor.js +196 -0
  73. package/dist/orchestrator/internalExecutors.d.ts +13 -2
  74. package/dist/orchestrator/internalExecutors.js +112 -16
  75. package/dist/orchestrator/localCommands.js +6 -25
  76. package/dist/orchestrator/nextStep.d.ts +2 -1
  77. package/dist/orchestrator/nextStep.js +3 -1
  78. package/dist/orchestrator/planning.d.ts +1 -1
  79. package/dist/orchestrator/requeueCommand.d.ts +1 -1
  80. package/dist/orchestrator/reviewPackets.d.ts +37 -4
  81. package/dist/orchestrator/reviewPackets.js +113 -158
  82. package/dist/orchestrator/runtimeValidation.d.ts +1 -1
  83. package/dist/orchestrator/runtimeValidation.js +4 -31
  84. package/dist/orchestrator/scope.d.ts +62 -0
  85. package/dist/orchestrator/scope.js +227 -0
  86. package/dist/orchestrator/state.js +2 -0
  87. package/dist/orchestrator/taskBuilder.d.ts +1 -1
  88. package/dist/orchestrator/taskBuilder.js +1 -12
  89. package/dist/orchestrator/unionFind.d.ts +7 -0
  90. package/dist/orchestrator/unionFind.js +32 -0
  91. package/dist/orchestrator/unitBuilder.d.ts +2 -2
  92. package/dist/orchestrator/unitBuilder.js +4 -18
  93. package/dist/prompts/renderWorkerPrompt.js +18 -1
  94. package/dist/providers/claudeCodeProvider.d.ts +4 -4
  95. package/dist/providers/claudeCodeProvider.js +9 -3
  96. package/dist/providers/constants.d.ts +1 -1
  97. package/dist/providers/constants.js +1 -1
  98. package/dist/providers/index.d.ts +1 -2
  99. package/dist/providers/index.js +5 -4
  100. package/dist/providers/localSubprocessProvider.d.ts +2 -2
  101. package/dist/providers/localSubprocessProvider.js +1 -1
  102. package/dist/providers/opencodeProvider.d.ts +4 -4
  103. package/dist/providers/opencodeProvider.js +7 -2
  104. package/dist/providers/spawnLoggedCommand.d.ts +3 -1
  105. package/dist/providers/spawnLoggedCommand.js +21 -0
  106. package/dist/providers/subprocessTemplateProvider.d.ts +4 -4
  107. package/dist/providers/subprocessTemplateProvider.js +8 -3
  108. package/dist/providers/vscodeTaskProvider.d.ts +3 -4
  109. package/dist/providers/vscodeTaskProvider.js +2 -2
  110. package/dist/quota/discoveredLimits.js +1 -1
  111. package/dist/quota/hostLimits.d.ts +1 -2
  112. package/dist/quota/hostLimits.js +4 -46
  113. package/dist/quota/index.d.ts +18 -15
  114. package/dist/quota/index.js +4 -9
  115. package/dist/quota/scheduler.d.ts +1 -3
  116. package/dist/quota/scheduler.js +1 -2
  117. package/dist/reporting/synthesis.d.ts +37 -3
  118. package/dist/reporting/synthesis.js +97 -16
  119. package/dist/reporting/synthesisNarrativePrompt.d.ts +7 -0
  120. package/dist/reporting/synthesisNarrativePrompt.js +60 -0
  121. package/dist/reporting/workBlocks.d.ts +2 -11
  122. package/dist/supervisor/operatorHandoff.js +1 -1
  123. package/dist/supervisor/runLedger.d.ts +1 -1
  124. package/dist/supervisor/runLedger.js +2 -2
  125. package/dist/supervisor/sessionConfig.d.ts +8 -1
  126. package/dist/supervisor/sessionConfig.js +22 -3
  127. package/dist/types/analyzerCapability.d.ts +16 -0
  128. package/dist/types/auditScope.d.ts +43 -0
  129. package/dist/types/auditScope.js +14 -0
  130. package/dist/types/reviewPlanning.d.ts +1 -1
  131. package/dist/types/synthesisNarrative.d.ts +7 -0
  132. package/dist/types/synthesisNarrative.js +5 -0
  133. package/dist/types/workerSession.d.ts +6 -0
  134. package/dist/types.d.ts +2 -19
  135. package/dist/validation/artifacts.d.ts +1 -1
  136. package/dist/validation/artifacts.js +10 -1
  137. package/dist/validation/auditResults.d.ts +1 -1
  138. package/dist/validation/auditResults.js +1 -1
  139. package/dist/validation/sessionConfig.d.ts +2 -3
  140. package/dist/validation/sessionConfig.js +25 -3
  141. package/package.json +7 -3
  142. package/schemas/analyzer_capability.schema.json +47 -0
  143. package/schemas/audit_findings.schema.json +141 -0
  144. package/schemas/finding.schema.json +2 -1
  145. package/schemas/graph_bundle.schema.json +5 -0
  146. package/schemas/scope.schema.json +46 -0
  147. package/scripts/postinstall.mjs +0 -1
  148. package/dist/io/json.d.ts +0 -10
  149. package/dist/io/json.js +0 -142
  150. package/dist/providers/types.d.ts +0 -33
  151. package/dist/quota/compositeQuotaSource.d.ts +0 -7
  152. package/dist/quota/compositeQuotaSource.js +0 -20
  153. package/dist/quota/errorParsers/claudeCodeErrorParser.d.ts +0 -6
  154. package/dist/quota/errorParsers/claudeCodeErrorParser.js +0 -39
  155. package/dist/quota/errorParsers/genericErrorParser.d.ts +0 -9
  156. package/dist/quota/errorParsers/genericErrorParser.js +0 -7
  157. package/dist/quota/errorParsers/index.d.ts +0 -5
  158. package/dist/quota/errorParsers/index.js +0 -12
  159. package/dist/quota/errorParsing.d.ts +0 -7
  160. package/dist/quota/errorParsing.js +0 -69
  161. package/dist/quota/fileLock.d.ts +0 -6
  162. package/dist/quota/fileLock.js +0 -64
  163. package/dist/quota/learnedQuotaSource.d.ts +0 -7
  164. package/dist/quota/learnedQuotaSource.js +0 -25
  165. package/dist/quota/limits.d.ts +0 -16
  166. package/dist/quota/limits.js +0 -77
  167. package/dist/quota/quotaSource.d.ts +0 -12
  168. package/dist/quota/slidingWindow.d.ts +0 -4
  169. package/dist/quota/slidingWindow.js +0 -28
  170. package/dist/quota/state.d.ts +0 -15
  171. package/dist/quota/state.js +0 -148
  172. package/dist/quota/types.d.ts +0 -67
  173. package/dist/quota/types.js +0 -1
  174. package/dist/reporting/rootCause.d.ts +0 -10
  175. package/dist/reporting/rootCause.js +0 -146
  176. package/dist/types/disposition.d.ts +0 -9
  177. package/dist/types/disposition.js +0 -1
  178. package/dist/types/flows.d.ts +0 -17
  179. package/dist/types/flows.js +0 -1
  180. package/dist/types/graph.d.ts +0 -22
  181. package/dist/types/graph.js +0 -1
  182. package/dist/types/risk.d.ts +0 -9
  183. package/dist/types/risk.js +0 -1
  184. package/dist/types/runLedger.d.ts +0 -17
  185. package/dist/types/runLedger.js +0 -6
  186. package/dist/types/sessionConfig.d.ts +0 -79
  187. package/dist/types/sessionConfig.js +0 -15
  188. package/dist/types/surfaces.d.ts +0 -15
  189. package/dist/types/surfaces.js +0 -1
  190. package/dist/validation/basic.d.ts +0 -13
  191. package/dist/validation/basic.js +0 -46
  192. /package/dist/{providers → extractors/analyzers}/types.js +0 -0
  193. /package/dist/{quota/quotaSource.js → types/analyzerCapability.js} +0 -0
@@ -1,148 +0,0 @@
1
- import { mkdir, readFile, writeFile } from "node:fs/promises";
2
- import { homedir } from "node:os";
3
- import { join } from "node:path";
4
- import { withFileLock } from "./fileLock.js";
5
- const STATE_DIR = join(homedir(), ".audit-code");
6
- const STATE_PATH = join(STATE_DIR, "quota-state.json");
7
- // A bucket needs at least this much success weight before we trust it.
8
- const MIN_EVIDENCE_WEIGHT = 0.5;
9
- export function getQuotaStatePath() {
10
- return STATE_PATH;
11
- }
12
- export function decayWeight(weight, elapsedHours, halfLifeHours) {
13
- if (halfLifeHours <= 0 || weight <= 0)
14
- return 0;
15
- return weight * Math.pow(0.5, elapsedHours / halfLifeHours);
16
- }
17
- export function applyDecayToEntry(entry, halfLifeHours) {
18
- const elapsedHours = (Date.now() - new Date(entry.updated_at).getTime()) / (1000 * 60 * 60);
19
- if (elapsedHours < 0.001)
20
- return entry;
21
- const decayed = {};
22
- for (const [key, bucket] of Object.entries(entry.buckets)) {
23
- decayed[key] = {
24
- success_weight: decayWeight(bucket.success_weight, elapsedHours, halfLifeHours),
25
- failure_weight: decayWeight(bucket.failure_weight, elapsedHours, halfLifeHours),
26
- };
27
- }
28
- return { ...entry, buckets: decayed };
29
- }
30
- function isQuotaState(value) {
31
- if (value === null || typeof value !== "object" || Array.isArray(value))
32
- return false;
33
- const obj = value;
34
- const version = obj["version"];
35
- return (version === 1 || version === 2) && typeof obj["entries"] === "object";
36
- }
37
- export async function readQuotaState() {
38
- try {
39
- const raw = await readFile(STATE_PATH, "utf8");
40
- const parsed = JSON.parse(raw);
41
- if (isQuotaState(parsed)) {
42
- if (parsed.version === 1) {
43
- for (const entry of Object.values(parsed.entries)) {
44
- entry.consecutive_429_count ??= 0;
45
- }
46
- }
47
- return parsed;
48
- }
49
- process.stderr.write(`[quota] ignoring invalid quota state at ${STATE_PATH}: expected { version: 1|2, entries: object }\n`);
50
- }
51
- catch (error) {
52
- if (error.code === "ENOENT") {
53
- return { version: 2, entries: {} };
54
- }
55
- process.stderr.write(`[quota] ignoring unreadable quota state at ${STATE_PATH}: ${error instanceof Error ? error.message : String(error)}\n`);
56
- }
57
- return { version: 2, entries: {} };
58
- }
59
- export async function writeQuotaState(state) {
60
- await mkdir(STATE_DIR, { recursive: true });
61
- const normalized = { ...state, version: 2 };
62
- await writeFile(STATE_PATH, JSON.stringify(normalized, null, 2) + "\n", "utf8");
63
- }
64
- /**
65
- * Returns the highest concurrency level for which decayed success evidence
66
- * exceeds failure evidence, with a minimum of 1.
67
- */
68
- export function computeMaxSafeConcurrency(entry, halfLifeHours, maxToCheck = 32) {
69
- const decayed = applyDecayToEntry(entry, halfLifeHours);
70
- let maxSafe = 1;
71
- for (let n = 1; n <= maxToCheck; n++) {
72
- const bucket = decayed.buckets[String(n)];
73
- if (!bucket)
74
- break;
75
- if (bucket.success_weight >= MIN_EVIDENCE_WEIGHT &&
76
- bucket.success_weight > bucket.failure_weight) {
77
- maxSafe = n;
78
- }
79
- else {
80
- break;
81
- }
82
- }
83
- return maxSafe;
84
- }
85
- const RAMP_UP_MIN_SUCCESSES = 2;
86
- export function computeRampUpConcurrency(entry, halfLifeHours, maxToCheck = 32) {
87
- const maxSafe = computeMaxSafeConcurrency(entry, halfLifeHours, maxToCheck);
88
- const decayed = applyDecayToEntry(entry, halfLifeHours);
89
- const bucket = decayed.buckets[String(maxSafe)];
90
- if (bucket &&
91
- bucket.success_weight >= RAMP_UP_MIN_SUCCESSES &&
92
- bucket.failure_weight === 0) {
93
- return maxSafe + 1;
94
- }
95
- return maxSafe;
96
- }
97
- function blankEntry() {
98
- return { updated_at: new Date().toISOString(), buckets: {}, cooldown_until: null, last_429_at: null };
99
- }
100
- const BASE_COOLDOWN_MS = 60_000;
101
- const MAX_COOLDOWN_MS = 15 * 60_000;
102
- export function computeBackoffCooldownMs(consecutive429Count) {
103
- const ms = BASE_COOLDOWN_MS * Math.pow(2, Math.max(0, consecutive429Count - 1));
104
- return Math.min(ms, MAX_COOLDOWN_MS);
105
- }
106
- export function computeBackoffFailureWeight(consecutive429Count) {
107
- return 1.0 + 0.5 * Math.max(0, consecutive429Count - 1);
108
- }
109
- const LOCK_PATH = STATE_PATH + ".lock";
110
- export async function recordWaveOutcome(providerModelKey, outcome, halfLifeHours) {
111
- await withFileLock(LOCK_PATH, () => recordWaveOutcomeUnsafe(providerModelKey, outcome, halfLifeHours));
112
- }
113
- async function recordWaveOutcomeUnsafe(providerModelKey, outcome, halfLifeHours) {
114
- const state = await readQuotaState();
115
- const entry = applyDecayToEntry(state.entries[providerModelKey] ?? blankEntry(), halfLifeHours);
116
- if (outcome.outcome === "success") {
117
- entry.consecutive_429_count = 0;
118
- for (let n = 1; n <= outcome.concurrency; n++) {
119
- const bucket = entry.buckets[String(n)] ?? { success_weight: 0, failure_weight: 0 };
120
- bucket.success_weight += 1.0;
121
- entry.buckets[String(n)] = bucket;
122
- }
123
- }
124
- else {
125
- const prev429Count = entry.consecutive_429_count ?? 0;
126
- const new429Count = outcome.outcome === "rate_limited" ? prev429Count + 1 : prev429Count;
127
- entry.consecutive_429_count = new429Count;
128
- entry.last_429_at = new Date().toISOString();
129
- if (outcome.outcome === "rate_limited" && new429Count > 0) {
130
- const backoffMs = computeBackoffCooldownMs(new429Count);
131
- entry.cooldown_until = new Date(Date.now() + backoffMs).toISOString();
132
- }
133
- else if (outcome.cooldown_until) {
134
- entry.cooldown_until = outcome.cooldown_until;
135
- }
136
- const failureWeight = outcome.outcome === "rate_limited"
137
- ? computeBackoffFailureWeight(new429Count)
138
- : 1.0;
139
- for (let n = outcome.concurrency; n <= outcome.concurrency + 4; n++) {
140
- const bucket = entry.buckets[String(n)] ?? { success_weight: 0, failure_weight: 0 };
141
- bucket.failure_weight += failureWeight;
142
- entry.buckets[String(n)] = bucket;
143
- }
144
- }
145
- entry.updated_at = new Date().toISOString();
146
- state.entries[providerModelKey] = entry;
147
- await writeQuotaState(state);
148
- }
@@ -1,67 +0,0 @@
1
- export type LimitSource = "explicit_config" | "cli_flags" | "known_metadata" | "learned" | "default";
2
- export type LimitConfidence = "high" | "medium" | "low";
3
- export type HostConcurrencyLimitSource = "cli_flags" | "session_config" | "environment";
4
- export interface HostConcurrencyLimit {
5
- active_subagents: number;
6
- source: HostConcurrencyLimitSource;
7
- description: string;
8
- }
9
- export interface ResolvedLimits {
10
- context_tokens: number;
11
- output_tokens: number;
12
- requests_per_minute: number | null;
13
- input_tokens_per_minute: number | null;
14
- output_tokens_per_minute: number | null;
15
- }
16
- export interface ConcurrencyBucket {
17
- success_weight: number;
18
- failure_weight: number;
19
- }
20
- export interface QuotaStateEntry {
21
- updated_at: string;
22
- buckets: Record<string, ConcurrencyBucket>;
23
- cooldown_until: string | null;
24
- last_429_at: string | null;
25
- consecutive_429_count?: number;
26
- }
27
- export interface QuotaState {
28
- version: 1 | 2;
29
- entries: Record<string, QuotaStateEntry>;
30
- }
31
- export interface WaveSchedule {
32
- wave_size: number;
33
- estimated_wave_tokens: number;
34
- cooldown_until: string | null;
35
- confidence: LimitConfidence;
36
- source: LimitSource;
37
- resolved_limits: ResolvedLimits;
38
- host_concurrency_limit: HostConcurrencyLimit | null;
39
- model: string | null;
40
- quota_source_snapshot?: import("./quotaSource.js").QuotaUsageSnapshot | null;
41
- }
42
- export interface BackoffState {
43
- consecutive_429_count: number;
44
- current_cooldown_ms: number;
45
- current_failure_weight: number;
46
- }
47
- export interface DispatchQuota {
48
- contract_version: "audit-code-dispatch-quota/v1alpha1" | "audit-code-dispatch-quota/v1alpha2";
49
- run_id: string;
50
- model: string | null;
51
- resolved_limits: ResolvedLimits;
52
- confidence: LimitConfidence;
53
- source: LimitSource;
54
- host_concurrency_limit: HostConcurrencyLimit | null;
55
- wave_size: number;
56
- estimated_wave_tokens: number;
57
- cooldown_until: string | null;
58
- quota_source_snapshot?: import("./quotaSource.js").QuotaUsageSnapshot | null;
59
- backoff_state?: BackoffState | null;
60
- }
61
- export interface ObservedWaveOutcome {
62
- concurrency: number;
63
- estimated_tokens: number;
64
- outcome: "success" | "rate_limited" | "timeout";
65
- cooldown_until?: string | null;
66
- reset_at?: string | null;
67
- }
@@ -1 +0,0 @@
1
- export {};
@@ -1,10 +0,0 @@
1
- import type { Finding } from "../types.js";
2
- import type { ExternalAnalyzerResults } from "../types/externalAnalyzer.js";
3
- import type { RuntimeValidationReport } from "../types/runtimeValidation.js";
4
- export interface RootCauseCluster {
5
- id: string;
6
- title: string;
7
- summary: string;
8
- finding_ids: string[];
9
- }
10
- export declare function buildRootCauseClusters(findings: Finding[], runtimeReport?: RuntimeValidationReport, externalAnalyzerResults?: ExternalAnalyzerResults): RootCauseCluster[];
@@ -1,146 +0,0 @@
1
- function severityRank(severity) {
2
- switch (severity) {
3
- case "critical":
4
- return 5;
5
- case "high":
6
- return 4;
7
- case "medium":
8
- return 3;
9
- case "low":
10
- return 2;
11
- case "info":
12
- return 1;
13
- }
14
- }
15
- function summarizeRuntime(report) {
16
- if (!report) {
17
- return "No runtime validation evidence attached.";
18
- }
19
- const counts = new Map();
20
- for (const result of report.results) {
21
- counts.set(result.status, (counts.get(result.status) ?? 0) + 1);
22
- }
23
- return [...counts.entries()]
24
- .map(([status, count]) => `${status}:${count}`)
25
- .join(", ");
26
- }
27
- function summarizeExternal(results) {
28
- if (!results)
29
- return "No external analyzer signals attached.";
30
- return `${results.tool}:${results.results.length}`;
31
- }
32
- const STOP_WORDS = new Set([
33
- "a",
34
- "an",
35
- "and",
36
- "are",
37
- "be",
38
- "by",
39
- "for",
40
- "from",
41
- "in",
42
- "into",
43
- "is",
44
- "missing",
45
- "not",
46
- "of",
47
- "on",
48
- "or",
49
- "that",
50
- "the",
51
- "this",
52
- "to",
53
- "under",
54
- "when",
55
- "with",
56
- ]);
57
- function normalizeToken(token) {
58
- if (token.endsWith("ies") && token.length > 4) {
59
- return `${token.slice(0, -3)}y`;
60
- }
61
- if (token.endsWith("ing") && token.length > 6) {
62
- return token.slice(0, -3);
63
- }
64
- if (token.endsWith("ed") && token.length > 5) {
65
- return token.slice(0, -2);
66
- }
67
- if (token.endsWith("s") && token.length > 4) {
68
- return token.slice(0, -1);
69
- }
70
- return token;
71
- }
72
- function extractSemanticTerms(finding) {
73
- const source = [
74
- finding.title,
75
- finding.summary,
76
- ...(finding.evidence ?? []).slice(0, 2),
77
- ]
78
- .join(" ")
79
- .toLowerCase()
80
- .replace(/[^a-z0-9]+/g, " ");
81
- const terms = source
82
- .split(/\s+/)
83
- .map(normalizeToken)
84
- .filter((token) => token.length >= 3 &&
85
- !STOP_WORDS.has(token) &&
86
- token !== finding.lens &&
87
- token !== finding.category &&
88
- !/^\d+$/.test(token));
89
- return [...new Set(terms)];
90
- }
91
- function clusterKey(finding) {
92
- const semanticTerms = extractSemanticTerms(finding).slice(0, 3).join(" ");
93
- return `${finding.lens}:${finding.category}:${semanticTerms || finding.title.toLowerCase()}`;
94
- }
95
- function representativeFinding(grouped) {
96
- return [...grouped].sort((a, b) => {
97
- const severityDelta = severityRank(b.severity) - severityRank(a.severity);
98
- if (severityDelta !== 0)
99
- return severityDelta;
100
- const systemicDelta = Number(Boolean(b.systemic)) - Number(Boolean(a.systemic));
101
- if (systemicDelta !== 0)
102
- return systemicDelta;
103
- return a.title.localeCompare(b.title);
104
- })[0];
105
- }
106
- function titleForCluster(grouped) {
107
- return representativeFinding(grouped).title;
108
- }
109
- function summarizeFiles(grouped) {
110
- const paths = [
111
- ...new Set(grouped.flatMap((finding) => finding.affected_files.map((file) => file.path))),
112
- ].sort();
113
- if (paths.length === 0) {
114
- return "no representative files recorded";
115
- }
116
- if (paths.length <= 3) {
117
- return paths.join(", ");
118
- }
119
- return `${paths.slice(0, 3).join(", ")}, +${paths.length - 3} more`;
120
- }
121
- export function buildRootCauseClusters(findings, runtimeReport, externalAnalyzerResults) {
122
- const groups = new Map();
123
- for (const finding of findings) {
124
- const key = clusterKey(finding);
125
- const existing = groups.get(key) ?? [];
126
- existing.push(finding);
127
- groups.set(key, existing);
128
- }
129
- const runtimeSummary = summarizeRuntime(runtimeReport);
130
- const externalSummary = summarizeExternal(externalAnalyzerResults);
131
- return [...groups.entries()]
132
- .map(([key, grouped], index) => {
133
- const representative = representativeFinding(grouped);
134
- const systemicCount = grouped.filter((finding) => finding.systemic).length;
135
- const theme = key.split(":").slice(2).join(":") || representative.title;
136
- return {
137
- id: `cluster-${index + 1}`,
138
- title: titleForCluster(grouped),
139
- summary: `Theme "${theme}" groups ${grouped.length} finding(s) across ${summarizeFiles(grouped)}; ` +
140
- `highest severity ${representative.severity}; systemic flags ${systemicCount}. ` +
141
- `Runtime validation status: ${runtimeSummary}. External analyzer summary: ${externalSummary}.`,
142
- finding_ids: grouped.map((finding) => finding.id),
143
- };
144
- })
145
- .sort((a, b) => a.title.localeCompare(b.title));
146
- }
@@ -1,9 +0,0 @@
1
- export type FileDispositionStatus = "included" | "excluded" | "generated" | "vendor" | "binary" | "doc_only";
2
- export interface FileDispositionItem {
3
- path: string;
4
- status: FileDispositionStatus;
5
- reason?: string;
6
- }
7
- export interface FileDisposition {
8
- files: FileDispositionItem[];
9
- }
@@ -1 +0,0 @@
1
- export {};
@@ -1,17 +0,0 @@
1
- export declare const FLOW_CONFIDENCE_LEVELS: readonly ["high", "low"];
2
- export type FlowConfidenceLevel = (typeof FLOW_CONFIDENCE_LEVELS)[number];
3
- /** A critical user or system flow that must be covered by the audit. */
4
- export interface CriticalFlow {
5
- id: string;
6
- name: string;
7
- entrypoints: string[];
8
- paths: string[];
9
- concerns: string[];
10
- confidence?: FlowConfidenceLevel;
11
- notes?: string[];
12
- }
13
- /** The set of critical flows inferred from intake artifacts. */
14
- export interface CriticalFlowManifest {
15
- flows: CriticalFlow[];
16
- fallback_required?: boolean;
17
- }
@@ -1 +0,0 @@
1
- export const FLOW_CONFIDENCE_LEVELS = ["high", "low"];
@@ -1,22 +0,0 @@
1
- export interface GraphEdge {
2
- from: string;
3
- to: string;
4
- kind?: string;
5
- direction?: "directed" | "undirected";
6
- confidence?: number;
7
- reason?: string;
8
- }
9
- export interface RouteEdge {
10
- path: string;
11
- handler: string;
12
- method?: string;
13
- }
14
- export interface GraphBundle {
15
- graphs: {
16
- imports?: GraphEdge[];
17
- calls?: GraphEdge[];
18
- references?: GraphEdge[];
19
- routes?: RouteEdge[];
20
- [key: string]: unknown;
21
- };
22
- }
@@ -1 +0,0 @@
1
- export {};
@@ -1,9 +0,0 @@
1
- export interface RiskItem {
2
- unit_id: string;
3
- risk_score: number;
4
- signals: string[];
5
- notes?: string[];
6
- }
7
- export interface RiskRegister {
8
- items: RiskItem[];
9
- }
@@ -1 +0,0 @@
1
- export {};
@@ -1,17 +0,0 @@
1
- export declare const RUN_LEDGER_STATUSES: readonly ["completed", "blocked", "failed", "no_progress"];
2
- export type RunLedgerStatus = (typeof RUN_LEDGER_STATUSES)[number];
3
- /** One persisted supervisor run entry, including the terminal worker outcome. */
4
- export interface RunLedgerEntry {
5
- run_id: string;
6
- provider: string;
7
- obligation_id: string | null;
8
- selected_executor: string | null;
9
- status: RunLedgerStatus;
10
- started_at: string;
11
- ended_at: string;
12
- result_path: string;
13
- }
14
- /** Append-only ledger used to explain how the audit advanced over time. */
15
- export interface RunLedger {
16
- runs: RunLedgerEntry[];
17
- }
@@ -1,6 +0,0 @@
1
- export const RUN_LEDGER_STATUSES = [
2
- "completed",
3
- "blocked",
4
- "failed",
5
- "no_progress",
6
- ];
@@ -1,79 +0,0 @@
1
- export declare const PROVIDER_NAMES: readonly ["auto", "local-subprocess", "subprocess-template", "claude-code", "opencode", "vscode-task"];
2
- export type ProviderName = (typeof PROVIDER_NAMES)[number];
3
- export type ResolvedProviderName = Exclude<ProviderName, "auto">;
4
- export declare const SESSION_UI_MODES: readonly ["visible", "headless"];
5
- export type SessionUiMode = (typeof SESSION_UI_MODES)[number];
6
- export interface SubprocessTemplateConfig {
7
- command_template: string[];
8
- env?: Record<string, string>;
9
- }
10
- export interface ClaudeCodeConfig {
11
- command?: string;
12
- extra_args?: string[];
13
- dangerously_skip_permissions?: boolean;
14
- }
15
- export interface OpenCodeConfig {
16
- command?: string;
17
- extra_args?: string[];
18
- }
19
- export interface VSCodeTaskConfig {
20
- command_template: string[];
21
- env?: Record<string, string>;
22
- }
23
- export interface QuotaModelLimits {
24
- context_tokens?: number;
25
- output_tokens?: number;
26
- requests_per_minute?: number;
27
- input_tokens_per_minute?: number;
28
- output_tokens_per_minute?: number;
29
- }
30
- export interface QuotaConfig {
31
- /** Set to false to disable all quota scheduling (default: true). */
32
- enabled?: boolean;
33
- /** Whether to probe the provider for live limits (default: "auto"). */
34
- probe?: "auto" | "never" | "force";
35
- /** Fraction of known limits to actually use (default: 0.8). */
36
- safety_margin?: number;
37
- /** Concurrency ceiling for hosted providers with no learned data (default: 1). */
38
- unknown_hosted_concurrency?: number;
39
- /** Concurrency for local providers with no learned data (default: "unlimited"). */
40
- unknown_local_concurrency?: number | "unlimited";
41
- /** Assumed context window when the model is not recognized (default: 32000). */
42
- default_context_tokens?: number;
43
- /** Tokens reserved for model output per request (default: 4096). */
44
- reserved_output_tokens?: number;
45
- /** Half-life of empirical success/failure evidence in hours (default: 24). */
46
- empirical_half_life_hours?: number;
47
- /** Allow the scheduler to try concurrency maxSafe+1 after consecutive successes (default: true). */
48
- ramp_up_enabled?: boolean;
49
- /** Conservative concurrency cap for the first wave when no learned history
50
- * and no discovered RPM/TPM limits exist (default: 3). */
51
- first_contact_concurrency?: number;
52
- /** Hard host ceiling for simultaneously active conversation subagents. */
53
- host_active_subagent_limit?: number;
54
- /** Per-model overrides keyed by "provider/model". */
55
- models?: Record<string, QuotaModelLimits>;
56
- }
57
- export declare const PROVIDER_SECTION_KEYS: {
58
- readonly "subprocess-template": "subprocess_template";
59
- readonly "claude-code": "claude_code";
60
- readonly opencode: "opencode";
61
- readonly "vscode-task": "vscode_task";
62
- };
63
- /**
64
- * Provider names use CLI-friendly hyphenation, while nested provider config
65
- * sections stay snake_case because they serialize directly into JSON files.
66
- */
67
- export interface SessionConfig {
68
- provider?: ProviderName;
69
- timeout_ms?: number;
70
- ui_mode?: SessionUiMode;
71
- host_can_dispatch_subagents?: boolean;
72
- subprocess_template?: SubprocessTemplateConfig;
73
- claude_code?: ClaudeCodeConfig;
74
- opencode?: OpenCodeConfig;
75
- vscode_task?: VSCodeTaskConfig;
76
- agent_task_batch_size?: number;
77
- parallel_workers?: number;
78
- quota?: QuotaConfig;
79
- }
@@ -1,15 +0,0 @@
1
- export const PROVIDER_NAMES = [
2
- "auto",
3
- "local-subprocess",
4
- "subprocess-template",
5
- "claude-code",
6
- "opencode",
7
- "vscode-task",
8
- ];
9
- export const SESSION_UI_MODES = ["visible", "headless"];
10
- export const PROVIDER_SECTION_KEYS = {
11
- "subprocess-template": "subprocess_template",
12
- "claude-code": "claude_code",
13
- opencode: "opencode",
14
- "vscode-task": "vscode_task",
15
- };
@@ -1,15 +0,0 @@
1
- export declare const SURFACE_KINDS: readonly ["interface", "background"];
2
- export type SurfaceKind = (typeof SURFACE_KINDS)[number];
3
- /** Discovered execution surfaces that define where the product can be reached. */
4
- export interface SurfaceRecord {
5
- id: string;
6
- kind: SurfaceKind;
7
- entrypoint: string;
8
- exposure?: string;
9
- methods?: string[];
10
- notes?: string[];
11
- }
12
- /** Intake output that summarizes externally reachable product surfaces. */
13
- export interface SurfaceManifest {
14
- surfaces: SurfaceRecord[];
15
- }
@@ -1 +0,0 @@
1
- export const SURFACE_KINDS = ["interface", "background"];
@@ -1,13 +0,0 @@
1
- export type ValidationSeverity = "error" | "warning";
2
- export interface ValidationIssue {
3
- path: string;
4
- message: string;
5
- severity: ValidationSeverity;
6
- }
7
- export declare function describeValue(value: unknown): string;
8
- export declare function isRecord(value: unknown): value is Record<string, unknown>;
9
- export declare function createValidationIssue(path: string, message: string, severity?: ValidationSeverity): ValidationIssue;
10
- export declare function pushValidationIssue(issues: ValidationIssue[], path: string, message: string, severity?: ValidationSeverity): void;
11
- export declare function prefixValidationIssues(prefix: string, issues: ValidationIssue[]): ValidationIssue[];
12
- export declare function formatValidationIssues(issues: ValidationIssue[]): string;
13
- export declare function requireKeys(value: unknown, path: string, keys: readonly string[]): ValidationIssue[];
@@ -1,46 +0,0 @@
1
- export function describeValue(value) {
2
- if (Array.isArray(value)) {
3
- return "array";
4
- }
5
- if (value === null) {
6
- return "null";
7
- }
8
- return typeof value;
9
- }
10
- export function isRecord(value) {
11
- return typeof value === "object" && value !== null && !Array.isArray(value);
12
- }
13
- export function createValidationIssue(path, message, severity = "error") {
14
- return { path, message, severity };
15
- }
16
- export function pushValidationIssue(issues, path, message, severity = "error") {
17
- issues.push(createValidationIssue(path, message, severity));
18
- }
19
- export function prefixValidationIssues(prefix, issues) {
20
- return issues.map((issue) => ({
21
- ...issue,
22
- path: issue.path.length === 0
23
- ? prefix
24
- : issue.path === prefix || issue.path.startsWith(`${prefix}.`)
25
- ? issue.path
26
- : `${prefix}.${issue.path}`,
27
- }));
28
- }
29
- export function formatValidationIssues(issues) {
30
- return issues
31
- .map((issue) => ` [${issue.severity}] ${issue.path}: ${issue.message}`)
32
- .join("\n");
33
- }
34
- export function requireKeys(value, path, keys) {
35
- const issues = [];
36
- if (!isRecord(value)) {
37
- pushValidationIssue(issues, path, `Expected an object, got ${describeValue(value)}.`);
38
- return issues;
39
- }
40
- for (const key of keys) {
41
- if (!(key in value)) {
42
- pushValidationIssue(issues, path, `Missing required key: ${key}`);
43
- }
44
- }
45
- return issues;
46
- }