auditor-lambda 0.3.40 → 0.3.41

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 (148) 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 +528 -0
  6. package/dist/cli/prompts.d.ts +18 -0
  7. package/dist/cli/prompts.js +130 -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 +160 -973
  16. package/dist/extractors/browserExtension.d.ts +1 -3
  17. package/dist/extractors/browserExtension.js +2 -2
  18. package/dist/extractors/designAssessment.d.ts +1 -3
  19. package/dist/extractors/disposition.d.ts +2 -1
  20. package/dist/extractors/disposition.js +3 -0
  21. package/dist/extractors/flows.d.ts +1 -3
  22. package/dist/extractors/flows.js +2 -2
  23. package/dist/extractors/graph.d.ts +1 -2
  24. package/dist/extractors/graph.js +4 -326
  25. package/dist/extractors/graphManifestEdges.d.ts +1 -1
  26. package/dist/extractors/graphPathUtils.d.ts +1 -1
  27. package/dist/extractors/graphPythonImports.d.ts +3 -0
  28. package/dist/extractors/graphPythonImports.js +326 -0
  29. package/dist/extractors/risk.d.ts +1 -2
  30. package/dist/extractors/surfaces.d.ts +1 -3
  31. package/dist/extractors/surfaces.js +2 -2
  32. package/dist/io/artifacts.d.ts +1 -5
  33. package/dist/io/artifacts.js +1 -1
  34. package/dist/io/runArtifacts.js +1 -1
  35. package/dist/mcp/server.js +1 -1
  36. package/dist/orchestrator/advance.d.ts +1 -0
  37. package/dist/orchestrator/advance.js +8 -5
  38. package/dist/orchestrator/auditTaskUtils.d.ts +4 -0
  39. package/dist/orchestrator/auditTaskUtils.js +27 -0
  40. package/dist/orchestrator/fileAnchors.d.ts +1 -1
  41. package/dist/orchestrator/fileIntegrity.d.ts +7 -0
  42. package/dist/orchestrator/fileIntegrity.js +41 -0
  43. package/dist/orchestrator/flowCoverage.d.ts +1 -1
  44. package/dist/orchestrator/flowPlanning.d.ts +1 -1
  45. package/dist/orchestrator/flowRequeue.d.ts +1 -1
  46. package/dist/orchestrator/internalExecutors.d.ts +3 -1
  47. package/dist/orchestrator/internalExecutors.js +23 -5
  48. package/dist/orchestrator/nextStep.d.ts +2 -1
  49. package/dist/orchestrator/nextStep.js +1 -1
  50. package/dist/orchestrator/planning.d.ts +1 -1
  51. package/dist/orchestrator/requeueCommand.d.ts +1 -1
  52. package/dist/orchestrator/reviewPackets.d.ts +1 -1
  53. package/dist/orchestrator/reviewPackets.js +21 -113
  54. package/dist/orchestrator/runtimeValidation.d.ts +1 -1
  55. package/dist/orchestrator/taskBuilder.d.ts +1 -1
  56. package/dist/orchestrator/taskBuilder.js +1 -12
  57. package/dist/orchestrator/unionFind.d.ts +7 -0
  58. package/dist/orchestrator/unionFind.js +32 -0
  59. package/dist/orchestrator/unitBuilder.d.ts +2 -2
  60. package/dist/orchestrator/unitBuilder.js +4 -18
  61. package/dist/prompts/renderWorkerPrompt.js +18 -1
  62. package/dist/providers/claudeCodeProvider.d.ts +4 -4
  63. package/dist/providers/claudeCodeProvider.js +9 -3
  64. package/dist/providers/constants.d.ts +1 -1
  65. package/dist/providers/constants.js +1 -1
  66. package/dist/providers/index.d.ts +1 -2
  67. package/dist/providers/index.js +5 -4
  68. package/dist/providers/localSubprocessProvider.d.ts +2 -2
  69. package/dist/providers/localSubprocessProvider.js +1 -1
  70. package/dist/providers/opencodeProvider.d.ts +4 -4
  71. package/dist/providers/opencodeProvider.js +7 -2
  72. package/dist/providers/spawnLoggedCommand.d.ts +3 -1
  73. package/dist/providers/spawnLoggedCommand.js +21 -0
  74. package/dist/providers/subprocessTemplateProvider.d.ts +4 -4
  75. package/dist/providers/subprocessTemplateProvider.js +8 -3
  76. package/dist/providers/vscodeTaskProvider.d.ts +3 -4
  77. package/dist/providers/vscodeTaskProvider.js +2 -2
  78. package/dist/quota/discoveredLimits.js +1 -1
  79. package/dist/quota/hostLimits.d.ts +1 -2
  80. package/dist/quota/hostLimits.js +4 -46
  81. package/dist/quota/index.d.ts +18 -15
  82. package/dist/quota/index.js +4 -9
  83. package/dist/quota/scheduler.d.ts +1 -3
  84. package/dist/quota/scheduler.js +1 -2
  85. package/dist/reporting/synthesis.d.ts +1 -2
  86. package/dist/reporting/synthesis.js +2 -0
  87. package/dist/reporting/workBlocks.d.ts +1 -2
  88. package/dist/supervisor/operatorHandoff.js +1 -1
  89. package/dist/supervisor/runLedger.d.ts +1 -1
  90. package/dist/supervisor/runLedger.js +2 -2
  91. package/dist/supervisor/sessionConfig.d.ts +1 -1
  92. package/dist/supervisor/sessionConfig.js +1 -3
  93. package/dist/types/reviewPlanning.d.ts +1 -1
  94. package/dist/types/workerSession.d.ts +6 -0
  95. package/dist/validation/artifacts.d.ts +1 -1
  96. package/dist/validation/artifacts.js +1 -1
  97. package/dist/validation/auditResults.d.ts +1 -1
  98. package/dist/validation/auditResults.js +1 -1
  99. package/dist/validation/sessionConfig.d.ts +2 -3
  100. package/dist/validation/sessionConfig.js +2 -3
  101. package/package.json +4 -2
  102. package/scripts/postinstall.mjs +0 -1
  103. package/dist/io/json.d.ts +0 -10
  104. package/dist/io/json.js +0 -142
  105. package/dist/providers/types.d.ts +0 -33
  106. package/dist/providers/types.js +0 -1
  107. package/dist/quota/compositeQuotaSource.d.ts +0 -7
  108. package/dist/quota/compositeQuotaSource.js +0 -20
  109. package/dist/quota/errorParsers/claudeCodeErrorParser.d.ts +0 -6
  110. package/dist/quota/errorParsers/claudeCodeErrorParser.js +0 -39
  111. package/dist/quota/errorParsers/genericErrorParser.d.ts +0 -9
  112. package/dist/quota/errorParsers/genericErrorParser.js +0 -7
  113. package/dist/quota/errorParsers/index.d.ts +0 -5
  114. package/dist/quota/errorParsers/index.js +0 -12
  115. package/dist/quota/errorParsing.d.ts +0 -7
  116. package/dist/quota/errorParsing.js +0 -69
  117. package/dist/quota/fileLock.d.ts +0 -6
  118. package/dist/quota/fileLock.js +0 -64
  119. package/dist/quota/learnedQuotaSource.d.ts +0 -7
  120. package/dist/quota/learnedQuotaSource.js +0 -25
  121. package/dist/quota/limits.d.ts +0 -16
  122. package/dist/quota/limits.js +0 -77
  123. package/dist/quota/quotaSource.d.ts +0 -12
  124. package/dist/quota/quotaSource.js +0 -1
  125. package/dist/quota/slidingWindow.d.ts +0 -4
  126. package/dist/quota/slidingWindow.js +0 -28
  127. package/dist/quota/state.d.ts +0 -15
  128. package/dist/quota/state.js +0 -148
  129. package/dist/quota/types.d.ts +0 -67
  130. package/dist/quota/types.js +0 -1
  131. package/dist/reporting/rootCause.d.ts +0 -10
  132. package/dist/reporting/rootCause.js +0 -146
  133. package/dist/types/disposition.d.ts +0 -9
  134. package/dist/types/disposition.js +0 -1
  135. package/dist/types/flows.d.ts +0 -17
  136. package/dist/types/flows.js +0 -1
  137. package/dist/types/graph.d.ts +0 -22
  138. package/dist/types/graph.js +0 -1
  139. package/dist/types/risk.d.ts +0 -9
  140. package/dist/types/risk.js +0 -1
  141. package/dist/types/runLedger.d.ts +0 -17
  142. package/dist/types/runLedger.js +0 -6
  143. package/dist/types/sessionConfig.d.ts +0 -79
  144. package/dist/types/sessionConfig.js +0 -15
  145. package/dist/types/surfaces.d.ts +0 -15
  146. package/dist/types/surfaces.js +0 -1
  147. package/dist/validation/basic.d.ts +0 -13
  148. package/dist/validation/basic.js +0 -46
@@ -0,0 +1,326 @@
1
+ import { posix } from "node:path";
2
+ import { graphEdge, normalizeGraphPath, resolveCandidate, } from "./graphPathUtils.js";
3
+ const PYTHON_SOURCE_EXTENSIONS = [".py", ".pyi"];
4
+ const PYTHON_PACKAGE_INDEX_FILES = ["__init__.py", "__init__.pyi"];
5
+ const IMPORT_EDGE_CONFIDENCE = 0.95;
6
+ export function isPythonSourcePath(path) {
7
+ const normalized = normalizeGraphPath(path).toLowerCase();
8
+ return PYTHON_SOURCE_EXTENSIONS.some((extension) => normalized.endsWith(extension));
9
+ }
10
+ function stripPythonLineComment(line) {
11
+ let quote;
12
+ let escaped = false;
13
+ for (let index = 0; index < line.length; index++) {
14
+ const char = line[index];
15
+ if (escaped) {
16
+ escaped = false;
17
+ continue;
18
+ }
19
+ if (quote) {
20
+ if (char === "\\") {
21
+ escaped = true;
22
+ continue;
23
+ }
24
+ if (char === quote) {
25
+ quote = undefined;
26
+ }
27
+ continue;
28
+ }
29
+ if (char === "'" || char === '"') {
30
+ quote = char;
31
+ continue;
32
+ }
33
+ if (char === "#") {
34
+ return line.slice(0, index);
35
+ }
36
+ }
37
+ return line;
38
+ }
39
+ function pythonParenDelta(line) {
40
+ let quote;
41
+ let escaped = false;
42
+ let delta = 0;
43
+ for (const char of line) {
44
+ if (escaped) {
45
+ escaped = false;
46
+ continue;
47
+ }
48
+ if (quote) {
49
+ if (char === "\\") {
50
+ escaped = true;
51
+ continue;
52
+ }
53
+ if (char === quote) {
54
+ quote = undefined;
55
+ }
56
+ continue;
57
+ }
58
+ if (char === "'" || char === '"') {
59
+ quote = char;
60
+ continue;
61
+ }
62
+ if (char === "(") {
63
+ delta += 1;
64
+ }
65
+ else if (char === ")") {
66
+ delta -= 1;
67
+ }
68
+ }
69
+ return delta;
70
+ }
71
+ function pythonLogicalLines(content) {
72
+ const logicalLines = [];
73
+ let pending = "";
74
+ let parenDepth = 0;
75
+ for (const rawLine of content.split(/\r?\n/)) {
76
+ const stripped = stripPythonLineComment(rawLine).trim();
77
+ if (stripped.length === 0) {
78
+ continue;
79
+ }
80
+ if (pending.length === 0 && !/^(?:import|from)\s+/i.test(stripped)) {
81
+ continue;
82
+ }
83
+ const continued = stripped.endsWith("\\");
84
+ const line = continued ? stripped.slice(0, -1).trimEnd() : stripped;
85
+ pending = pending.length > 0 ? `${pending} ${line}` : line;
86
+ parenDepth += pythonParenDelta(line);
87
+ if (!continued && parenDepth <= 0) {
88
+ logicalLines.push(pending.replace(/\s+/g, " ").trim());
89
+ pending = "";
90
+ parenDepth = 0;
91
+ }
92
+ }
93
+ if (pending.length > 0) {
94
+ logicalLines.push(pending.replace(/\s+/g, " ").trim());
95
+ }
96
+ return logicalLines;
97
+ }
98
+ function unwrapPythonImportList(value) {
99
+ let trimmed = value.trim();
100
+ if (trimmed.startsWith("(") && trimmed.endsWith(")")) {
101
+ trimmed = trimmed.slice(1, -1).trim();
102
+ }
103
+ return trimmed;
104
+ }
105
+ function splitPythonImportList(value) {
106
+ const items = [];
107
+ let current = "";
108
+ let quote;
109
+ let escaped = false;
110
+ let parenDepth = 0;
111
+ for (const char of unwrapPythonImportList(value)) {
112
+ if (escaped) {
113
+ current += char;
114
+ escaped = false;
115
+ continue;
116
+ }
117
+ if (quote) {
118
+ current += char;
119
+ if (char === "\\") {
120
+ escaped = true;
121
+ }
122
+ else if (char === quote) {
123
+ quote = undefined;
124
+ }
125
+ continue;
126
+ }
127
+ if (char === "'" || char === '"') {
128
+ current += char;
129
+ quote = char;
130
+ continue;
131
+ }
132
+ if (char === "(") {
133
+ parenDepth += 1;
134
+ current += char;
135
+ continue;
136
+ }
137
+ if (char === ")") {
138
+ parenDepth -= 1;
139
+ current += char;
140
+ continue;
141
+ }
142
+ if (char === "," && parenDepth === 0) {
143
+ const item = current.trim();
144
+ if (item.length > 0) {
145
+ items.push(item);
146
+ }
147
+ current = "";
148
+ continue;
149
+ }
150
+ current += char;
151
+ }
152
+ const item = current.trim();
153
+ if (item.length > 0) {
154
+ items.push(item);
155
+ }
156
+ return items;
157
+ }
158
+ function stripPythonAlias(value) {
159
+ return value.replace(/\s+as\s+[A-Za-z_]\w*$/i, "").trim();
160
+ }
161
+ function isPythonIdentifier(value) {
162
+ return /^[A-Za-z_]\w*$/.test(value);
163
+ }
164
+ function isPythonAbsoluteModuleSpecifier(value) {
165
+ return /^[A-Za-z_]\w*(?:\.[A-Za-z_]\w*)*$/.test(value);
166
+ }
167
+ function isPythonRelativeModuleSpecifier(value) {
168
+ return /^\.+(?:[A-Za-z_]\w*(?:\.[A-Za-z_]\w*)*)?$/.test(value);
169
+ }
170
+ function isPythonModuleSpecifier(value) {
171
+ return (isPythonAbsoluteModuleSpecifier(value) ||
172
+ isPythonRelativeModuleSpecifier(value));
173
+ }
174
+ function pythonModulePath(specifier) {
175
+ return specifier.split(".").filter(Boolean).join("/");
176
+ }
177
+ function resolvePythonPathCandidate(candidate, pathLookup) {
178
+ const normalized = normalizeGraphPath(candidate).replace(/\/+$/, "");
179
+ if (normalized.length === 0 || normalized === "." || normalized === "..") {
180
+ return undefined;
181
+ }
182
+ return resolveCandidate(normalized, pathLookup);
183
+ }
184
+ function pythonPathMatchesModule(path, modulePath) {
185
+ const normalizedPath = normalizeGraphPath(path).toLowerCase();
186
+ const normalizedModulePath = normalizeGraphPath(modulePath).toLowerCase();
187
+ return (PYTHON_SOURCE_EXTENSIONS.some((extension) => {
188
+ const moduleFile = `${normalizedModulePath}${extension}`;
189
+ return (normalizedPath === moduleFile ||
190
+ normalizedPath.endsWith(`/${moduleFile}`));
191
+ }) ||
192
+ PYTHON_PACKAGE_INDEX_FILES.some((indexFile) => {
193
+ const packageFile = posix.join(normalizedModulePath, indexFile);
194
+ return (normalizedPath === packageFile ||
195
+ normalizedPath.endsWith(`/${packageFile}`));
196
+ }));
197
+ }
198
+ function commonDirectoryPrefixLength(left, right) {
199
+ const leftParts = normalizeGraphPath(left).split("/").filter(Boolean);
200
+ const rightParts = normalizeGraphPath(right).split("/").filter(Boolean);
201
+ let count = 0;
202
+ while (count < leftParts.length &&
203
+ count < rightParts.length &&
204
+ leftParts[count].toLowerCase() === rightParts[count].toLowerCase()) {
205
+ count += 1;
206
+ }
207
+ return count;
208
+ }
209
+ function resolvePythonAbsoluteModuleSpecifier(fromPath, specifier, pathLookup) {
210
+ const modulePath = pythonModulePath(specifier);
211
+ const direct = resolvePythonPathCandidate(modulePath, pathLookup);
212
+ if (direct) {
213
+ return direct;
214
+ }
215
+ const matches = [...new Set(pathLookup.values())].filter((path) => isPythonSourcePath(path) && pythonPathMatchesModule(path, modulePath));
216
+ if (matches.length === 1) {
217
+ return matches[0];
218
+ }
219
+ if (matches.length === 0) {
220
+ return undefined;
221
+ }
222
+ const fromDir = posix.dirname(normalizeGraphPath(fromPath));
223
+ const scored = matches
224
+ .map((target) => ({
225
+ target,
226
+ score: commonDirectoryPrefixLength(fromDir, posix.dirname(normalizeGraphPath(target))),
227
+ }))
228
+ .sort((a, b) => b.score - a.score || a.target.localeCompare(b.target));
229
+ const bestScore = scored[0]?.score ?? 0;
230
+ const bestMatches = scored.filter((item) => item.score === bestScore);
231
+ if (bestScore > 0 && bestMatches.length === 1) {
232
+ return bestMatches[0].target;
233
+ }
234
+ const srcMatches = matches.filter((target) => normalizeGraphPath(target).toLowerCase().startsWith("src/"));
235
+ return srcMatches.length === 1 ? srcMatches[0] : undefined;
236
+ }
237
+ function resolvePythonRelativeModuleSpecifier(fromPath, specifier, pathLookup) {
238
+ const match = /^(\.+)(.*)$/.exec(specifier);
239
+ if (!match) {
240
+ return undefined;
241
+ }
242
+ const level = match[1].length;
243
+ const remainder = match[2] ?? "";
244
+ let baseDir = posix.dirname(normalizeGraphPath(fromPath));
245
+ for (let index = 1; index < level; index++) {
246
+ const next = posix.dirname(baseDir);
247
+ if (next === baseDir) {
248
+ return undefined;
249
+ }
250
+ baseDir = next;
251
+ }
252
+ const modulePath = pythonModulePath(remainder);
253
+ const candidate = modulePath.length > 0 ? posix.join(baseDir, modulePath) : baseDir;
254
+ return resolvePythonPathCandidate(candidate, pathLookup);
255
+ }
256
+ function resolvePythonModuleSpecifier(fromPath, specifier, pathLookup) {
257
+ if (isPythonRelativeModuleSpecifier(specifier)) {
258
+ return resolvePythonRelativeModuleSpecifier(fromPath, specifier, pathLookup);
259
+ }
260
+ if (isPythonAbsoluteModuleSpecifier(specifier)) {
261
+ return resolvePythonAbsoluteModuleSpecifier(fromPath, specifier, pathLookup);
262
+ }
263
+ return undefined;
264
+ }
265
+ function appendPythonImportedSpecifier(moduleSpecifier, importedName) {
266
+ return moduleSpecifier.endsWith(".")
267
+ ? `${moduleSpecifier}${importedName}`
268
+ : `${moduleSpecifier}.${importedName}`;
269
+ }
270
+ function addPythonImportEdge(edges, fromPath, target, kind, specifier) {
271
+ if (!target || target === fromPath) {
272
+ return;
273
+ }
274
+ edges.push(graphEdge({
275
+ from: fromPath,
276
+ to: target,
277
+ kind,
278
+ confidence: IMPORT_EDGE_CONFIDENCE,
279
+ reason: `Resolved Python import specifier '${specifier}'.`,
280
+ }));
281
+ }
282
+ export function extractPythonImportEdges(fromPath, content, pathLookup) {
283
+ if (!isPythonSourcePath(fromPath)) {
284
+ return [];
285
+ }
286
+ const edges = [];
287
+ for (const line of pythonLogicalLines(content)) {
288
+ const importMatch = /^import\s+(.+)$/i.exec(line);
289
+ if (importMatch) {
290
+ for (const rawSpecifier of splitPythonImportList(importMatch[1] ?? "")) {
291
+ const specifier = stripPythonAlias(rawSpecifier);
292
+ if (!isPythonAbsoluteModuleSpecifier(specifier)) {
293
+ continue;
294
+ }
295
+ addPythonImportEdge(edges, fromPath, resolvePythonModuleSpecifier(fromPath, specifier, pathLookup), "python-import", specifier);
296
+ }
297
+ continue;
298
+ }
299
+ const fromImportMatch = /^from\s+([.\w]+)\s+import\s+(.+)$/i.exec(line);
300
+ if (!fromImportMatch) {
301
+ continue;
302
+ }
303
+ const moduleSpecifier = fromImportMatch[1] ?? "";
304
+ if (!isPythonModuleSpecifier(moduleSpecifier)) {
305
+ continue;
306
+ }
307
+ const importedNames = splitPythonImportList(fromImportMatch[2] ?? "")
308
+ .map(stripPythonAlias)
309
+ .filter((name) => name !== "*" && isPythonIdentifier(name));
310
+ const submoduleTargets = importedNames
311
+ .map((name) => appendPythonImportedSpecifier(moduleSpecifier, name))
312
+ .map((specifier) => ({
313
+ specifier,
314
+ target: resolvePythonModuleSpecifier(fromPath, specifier, pathLookup),
315
+ }))
316
+ .filter((item) => item.target);
317
+ if (submoduleTargets.length > 0) {
318
+ for (const { specifier, target } of submoduleTargets) {
319
+ addPythonImportEdge(edges, fromPath, target, "python-from-import", specifier);
320
+ }
321
+ continue;
322
+ }
323
+ addPythonImportEdge(edges, fromPath, resolvePythonModuleSpecifier(fromPath, moduleSpecifier, pathLookup), "python-from-import", moduleSpecifier);
324
+ }
325
+ return edges;
326
+ }
@@ -1,5 +1,4 @@
1
1
  import type { UnitManifest } from "../types.js";
2
2
  import type { ExternalAnalyzerResults } from "../types/externalAnalyzer.js";
3
- import type { CriticalFlowManifest } from "../types/flows.js";
4
- import type { RiskRegister } from "../types/risk.js";
3
+ import type { CriticalFlowManifest, RiskRegister } from "@audit-tools/shared";
5
4
  export declare function buildRiskRegister(unitManifest: UnitManifest, criticalFlows?: CriticalFlowManifest, externalAnalyzerResults?: ExternalAnalyzerResults): RiskRegister;
@@ -1,7 +1,5 @@
1
1
  import type { RepoManifest } from "../types.js";
2
- import type { FileDisposition } from "../types/disposition.js";
3
- import type { GraphBundle } from "../types/graph.js";
4
- import type { SurfaceManifest } from "../types/surfaces.js";
2
+ import type { FileDisposition, GraphBundle, SurfaceManifest } from "@audit-tools/shared";
5
3
  /**
6
4
  * Detects likely execution surfaces from file paths using the shared extractor
7
5
  * heuristics, primarily to seed later audit planning.
@@ -1,5 +1,5 @@
1
1
  import { buildBrowserExtensionSurfacesFromGraph } from "./browserExtension.js";
2
- import { isAuditExcludedStatus } from "./disposition.js";
2
+ import { buildDispositionMap, isAuditExcludedStatus } from "./disposition.js";
3
3
  import { EXTRACTOR_HEURISTIC_NOTE, isBackgroundSurfacePath, isNetworkSurfacePath, isSurfacePath, normalizeExtractorPath, } from "./pathPatterns.js";
4
4
  function methodsForPath(path) {
5
5
  const normalized = normalizeExtractorPath(path);
@@ -15,7 +15,7 @@ function methodsForPath(path) {
15
15
  export function buildSurfaceManifest(repoManifest, disposition, options = {}) {
16
16
  const surfaces = [];
17
17
  const seen = new Set();
18
- const dispositionMap = new Map(disposition?.files.map((item) => [item.path, item.status]) ?? []);
18
+ const dispositionMap = buildDispositionMap(disposition);
19
19
  function addSurface(surface) {
20
20
  const key = `${surface.kind}:${surface.entrypoint}`;
21
21
  if (seen.has(key)) {
@@ -2,15 +2,11 @@ import { cp, rm } from "node:fs/promises";
2
2
  import type { AuditResult, AuditTask, CoverageMatrix, RepoManifest, UnitManifest } from "../types.js";
3
3
  import type { AuditState } from "../types/auditState.js";
4
4
  import type { ArtifactMetadataManifest } from "../types/artifactMetadata.js";
5
- import type { FileDisposition } from "../types/disposition.js";
5
+ import type { FileDisposition, CriticalFlowManifest, GraphBundle, RiskRegister, SurfaceManifest } from "@audit-tools/shared";
6
6
  import type { ExternalAnalyzerResults } from "../types/externalAnalyzer.js";
7
7
  import type { FlowCoverageManifest } from "../types/flowCoverage.js";
8
- import type { CriticalFlowManifest } from "../types/flows.js";
9
- import type { GraphBundle } from "../types/graph.js";
10
- import type { RiskRegister } from "../types/risk.js";
11
8
  import type { AuditPlanMetrics, ReviewPacket } from "../types/reviewPlanning.js";
12
9
  import type { RuntimeValidationReport, RuntimeValidationTaskManifest } from "../types/runtimeValidation.js";
13
- import type { SurfaceManifest } from "../types/surfaces.js";
14
10
  import type { DesignAssessment } from "../types/designAssessment.js";
15
11
  import type { ToolingManifest } from "../types/toolingManifest.js";
16
12
  type ArtifactPayloadMap = {
@@ -1,6 +1,6 @@
1
1
  import { cp, rm, unlink } from "node:fs/promises";
2
2
  import { join } from "node:path";
3
- import { isFileMissingError, readOptionalJsonFile, readOptionalNdjsonFile, readOptionalTextFile, writeJsonFile, writeNdjsonFile, writeTextFile, } from "./json.js";
3
+ import { isFileMissingError, readOptionalJsonFile, readOptionalNdjsonFile, readOptionalTextFile, writeJsonFile, writeNdjsonFile, writeTextFile, } from "@audit-tools/shared";
4
4
  import { buildToolingManifest } from "./toolingManifest.js";
5
5
  function jsonArtifact(fileName, phase) {
6
6
  return {
@@ -1,7 +1,7 @@
1
1
  import { mkdir, readFile, rm, writeFile } from "node:fs/promises";
2
2
  import { dirname, join, resolve } from "node:path";
3
3
  import { fileURLToPath } from "node:url";
4
- import { writeJsonFile } from "./json.js";
4
+ import { writeJsonFile } from "@audit-tools/shared";
5
5
  const moduleDir = dirname(fileURLToPath(import.meta.url));
6
6
  const packageRoot = resolve(moduleDir, "..", "..");
7
7
  const auditResultSchemaPath = join(packageRoot, "schemas", "audit_result.schema.json");
@@ -3,7 +3,7 @@ import { spawn } from "node:child_process";
3
3
  import { dirname, join, resolve } from "node:path";
4
4
  import { fileURLToPath } from "node:url";
5
5
  import { loadArtifactBundle } from "../io/artifacts.js";
6
- import { readOptionalTextFile } from "../io/json.js";
6
+ import { readOptionalTextFile } from "@audit-tools/shared";
7
7
  import { deriveAuditState } from "../orchestrator/state.js";
8
8
  import { decideNextStep } from "../orchestrator/nextStep.js";
9
9
  import { buildAuditCodeHandoff, } from "../supervisor/operatorHandoff.js";
@@ -10,6 +10,7 @@ export interface AdvanceAuditOptions {
10
10
  runtimeValidationUpdates?: RuntimeValidationReport;
11
11
  externalAnalyzerResults?: ExternalAnalyzerResults;
12
12
  preferredExecutor?: string;
13
+ opentoken?: boolean;
13
14
  }
14
15
  export interface AdvanceAuditResult {
15
16
  audit_state: AuditState;
@@ -1,4 +1,4 @@
1
- import { decideNextStep } from "./nextStep.js";
1
+ import { decideNextStep, findObligation } from "./nextStep.js";
2
2
  import { deriveAuditState } from "./state.js";
3
3
  import { computeArtifactMetadata } from "./artifactMetadata.js";
4
4
  import { runIntakeExecutor, runStructureExecutor, runPlanningExecutor, runResultIngestionExecutor, runRuntimeValidationExecutor, runRuntimeValidationUpdateExecutor, runSynthesisExecutor, runDesignAssessmentExecutor, runDesignReviewAutoComplete, runExternalAnalyzerImportExecutor, } from "./internalExecutors.js";
@@ -70,7 +70,9 @@ export async function advanceAudit(bundle, options = {}) {
70
70
  case "runtime_validation_executor":
71
71
  if (!options.root)
72
72
  throw new Error("advanceAudit runtime_validation_executor requires root");
73
- run = await runRuntimeValidationExecutor(bundle, options.root);
73
+ run = await runRuntimeValidationExecutor(bundle, options.root, {
74
+ opentoken: options.opentoken,
75
+ });
74
76
  break;
75
77
  case "synthesis_executor":
76
78
  run = runSynthesisExecutor(bundle, options.auditResults);
@@ -95,7 +97,7 @@ export async function advanceAudit(bundle, options = {}) {
95
97
  throw new Error("advanceAudit syntax_resolution_executor requires root");
96
98
  run = runSyntaxResolutionExecutor(bundle, options.root);
97
99
  break;
98
- default:
100
+ default: {
99
101
  const state = deriveAuditState(bundle);
100
102
  state.last_executor = selectedExecutor;
101
103
  state.last_obligation = selectedObligation ?? undefined;
@@ -109,6 +111,7 @@ export async function advanceAudit(bundle, options = {}) {
109
111
  next_likely_step: selectedObligation,
110
112
  updated_bundle: { ...bundle, audit_state: state },
111
113
  };
114
+ }
112
115
  }
113
116
  }
114
117
  catch (error) {
@@ -124,7 +127,7 @@ export async function advanceAudit(bundle, options = {}) {
124
127
  updatedState.last_executor = selectedExecutor;
125
128
  updatedState.last_obligation = selectedObligation ?? undefined;
126
129
  const finalizedBundle = { ...metadataBundle, audit_state: updatedState };
127
- const followupDecision = decideNextStep(finalizedBundle);
130
+ const nextObligation = findObligation(updatedState.obligations);
128
131
  return {
129
132
  audit_state: updatedState,
130
133
  selected_obligation: selectedObligation,
@@ -136,7 +139,7 @@ export async function advanceAudit(bundle, options = {}) {
136
139
  "audit_state.json",
137
140
  ],
138
141
  progress_summary: run.progress_summary,
139
- next_likely_step: followupDecision.selected_obligation,
142
+ next_likely_step: nextObligation?.id ?? null,
140
143
  updated_bundle: finalizedBundle,
141
144
  };
142
145
  }
@@ -0,0 +1,4 @@
1
+ import type { AuditTask, Lens } from "../types.js";
2
+ export declare const LENS_ORDER: Lens[];
3
+ export declare function priorityRank(priority: AuditTask["priority"]): number;
4
+ export declare function sortLenses(lenses: Iterable<Lens>): Lens[];
@@ -0,0 +1,27 @@
1
+ export const LENS_ORDER = [
2
+ "security",
3
+ "correctness",
4
+ "reliability",
5
+ "data_integrity",
6
+ "performance",
7
+ "operability",
8
+ "config_deployment",
9
+ "observability",
10
+ "maintainability",
11
+ "tests",
12
+ ];
13
+ export function priorityRank(priority) {
14
+ switch (priority) {
15
+ case "high":
16
+ return 3;
17
+ case "medium":
18
+ return 2;
19
+ case "low":
20
+ default:
21
+ return 1;
22
+ }
23
+ }
24
+ export function sortLenses(lenses) {
25
+ const set = new Set(lenses);
26
+ return LENS_ORDER.filter((lens) => set.has(lens));
27
+ }
@@ -1,5 +1,5 @@
1
1
  import type { ExternalAnalyzerResults } from "../types/externalAnalyzer.js";
2
- import type { GraphBundle } from "../types/graph.js";
2
+ import type { GraphBundle } from "@audit-tools/shared";
3
3
  export type FileAnchorKind = "boundary" | "import" | "export" | "symbol" | "route" | "keyword" | "graph" | "analyzer_signal";
4
4
  export interface FileAnchor {
5
5
  kind: FileAnchorKind;
@@ -0,0 +1,7 @@
1
+ import type { RepoManifest } from "../types.js";
2
+ export interface FileIntegrityResult {
3
+ changed_files: string[];
4
+ missing_files: string[];
5
+ is_clean: boolean;
6
+ }
7
+ export declare function checkFileIntegrity(root: string, manifest: RepoManifest, scope?: string[]): Promise<FileIntegrityResult>;
@@ -0,0 +1,41 @@
1
+ import { createHash } from "node:crypto";
2
+ import { readFile } from "node:fs/promises";
3
+ import { join, isAbsolute } from "node:path";
4
+ import { existsSync } from "node:fs";
5
+ async function hashFile(absolutePath) {
6
+ const content = await readFile(absolutePath);
7
+ return createHash("sha256").update(content).digest("hex");
8
+ }
9
+ export async function checkFileIntegrity(root, manifest, scope) {
10
+ const changed = [];
11
+ const missing = [];
12
+ const scopeSet = scope ? new Set(scope) : null;
13
+ const files = scopeSet
14
+ ? manifest.files.filter((f) => scopeSet.has(f.path))
15
+ : manifest.files;
16
+ for (const record of files) {
17
+ if (!record.hash)
18
+ continue;
19
+ const absolute = isAbsolute(record.path)
20
+ ? record.path
21
+ : join(root, record.path);
22
+ if (!existsSync(absolute)) {
23
+ missing.push(record.path);
24
+ continue;
25
+ }
26
+ try {
27
+ const currentHash = await hashFile(absolute);
28
+ if (currentHash !== record.hash) {
29
+ changed.push(record.path);
30
+ }
31
+ }
32
+ catch {
33
+ missing.push(record.path);
34
+ }
35
+ }
36
+ return {
37
+ changed_files: changed,
38
+ missing_files: missing,
39
+ is_clean: changed.length === 0 && missing.length === 0,
40
+ };
41
+ }
@@ -1,4 +1,4 @@
1
1
  import type { CoverageMatrix } from "../types.js";
2
2
  import type { FlowCoverageManifest } from "../types/flowCoverage.js";
3
- import type { CriticalFlowManifest } from "../types/flows.js";
3
+ import type { CriticalFlowManifest } from "@audit-tools/shared";
4
4
  export declare function buildFlowCoverage(criticalFlows: CriticalFlowManifest, coverageMatrix: CoverageMatrix): FlowCoverageManifest;
@@ -1,5 +1,5 @@
1
1
  import type { Lens } from "../types.js";
2
- import type { CriticalFlowManifest } from "../types/flows.js";
2
+ import type { CriticalFlowManifest } from "@audit-tools/shared";
3
3
  export interface FlowReviewBlock {
4
4
  flow_id: string;
5
5
  lens: Lens;
@@ -1,5 +1,5 @@
1
1
  import type { ExternalAnalyzerResults } from "../types/externalAnalyzer.js";
2
2
  import type { AuditTask, CoverageMatrix } from "../types.js";
3
3
  import type { FlowCoverageManifest } from "../types/flowCoverage.js";
4
- import type { CriticalFlowManifest } from "../types/flows.js";
4
+ import type { CriticalFlowManifest } from "@audit-tools/shared";
5
5
  export declare function buildFlowRequeueTasks(criticalFlows: CriticalFlowManifest, flowCoverage: FlowCoverageManifest, coverageMatrix: CoverageMatrix, externalAnalyzerResults?: ExternalAnalyzerResults): AuditTask[];
@@ -17,7 +17,9 @@ export declare function runDesignAssessmentExecutor(bundle: ArtifactBundle): Exe
17
17
  export declare function runDesignReviewAutoComplete(bundle: ArtifactBundle): ExecutorRunResult;
18
18
  export declare function runPlanningExecutor(bundle: ArtifactBundle, root: string, lineIndex?: Record<string, number>): Promise<ExecutorRunResult>;
19
19
  export declare function runResultIngestionExecutor(bundle: ArtifactBundle, results: AuditResult[]): ExecutorRunResult;
20
- export declare function runRuntimeValidationExecutor(bundle: ArtifactBundle, root: string): Promise<ExecutorRunResult>;
20
+ export declare function runRuntimeValidationExecutor(bundle: ArtifactBundle, root: string, options?: {
21
+ opentoken?: boolean;
22
+ }): Promise<ExecutorRunResult>;
21
23
  export declare function runRuntimeValidationUpdateExecutor(bundle: ArtifactBundle, updates: RuntimeValidationReport): ExecutorRunResult;
22
24
  export declare function runSynthesisExecutor(bundle: ArtifactBundle, results?: AuditResult[]): ExecutorRunResult;
23
25
  export declare function runExternalAnalyzerImportExecutor(bundle: ArtifactBundle, externalResults: ExternalAnalyzerResults): ExecutorRunResult;
@@ -56,8 +56,21 @@ function appendSelectiveDeepeningTasks(params) {
56
56
  artifacts: ["audit_tasks.json", "audit_plan_metrics.json", "review_packets.json"],
57
57
  };
58
58
  }
59
- async function runCommand(command, cwd) {
60
- const spawnCommand = resolveRuntimeValidationSpawnCommand(command);
59
+ function resolveOpentokenWrap(resolved, platform = process.platform) {
60
+ if (platform === "win32") {
61
+ const shell = process.env.ComSpec ?? "cmd.exe";
62
+ const inner = [resolved.command, ...resolved.args]
63
+ .map((v) => (/^[A-Za-z0-9_./:=@+-]+$/.test(v) ? v : `"${v.replace(/(["^&|<>%])/g, "^$1")}"`))
64
+ .join(" ");
65
+ return { command: shell, args: ["/d", "/s", "/c", `opentoken wrap ${inner}`] };
66
+ }
67
+ return { command: "opentoken", args: ["wrap", resolved.command, ...resolved.args] };
68
+ }
69
+ async function runCommand(command, cwd, options = {}) {
70
+ let spawnCommand = resolveRuntimeValidationSpawnCommand(command);
71
+ if (options.opentoken) {
72
+ spawnCommand = resolveOpentokenWrap(spawnCommand);
73
+ }
61
74
  const displayCommand = command.join(" ");
62
75
  return await new Promise((resolve) => {
63
76
  const child = spawn(spawnCommand.command, spawnCommand.args, {
@@ -121,7 +134,7 @@ export async function runIntakeExecutor(bundle, root) {
121
134
  const repoManifest = await buildRepoManifestFromFs({
122
135
  root,
123
136
  ignore,
124
- hash_files: false,
137
+ hash_files: true,
125
138
  });
126
139
  const disposition = buildFileDisposition(repoManifest);
127
140
  const auditableCount = disposition.files.filter((file) => !isAuditExcludedStatus(file.status)).length;
@@ -192,6 +205,11 @@ export function runDesignAssessmentExecutor(bundle) {
192
205
  criticalFlows: bundle.critical_flows,
193
206
  riskRegister: bundle.risk_register,
194
207
  });
208
+ const previous = bundle.design_assessment;
209
+ if (previous?.reviewed) {
210
+ designAssessment.reviewed = true;
211
+ designAssessment.review_findings = previous.review_findings ?? [];
212
+ }
195
213
  return {
196
214
  updated: {
197
215
  ...bundle,
@@ -354,7 +372,7 @@ export function runResultIngestionExecutor(bundle, results) {
354
372
  : ""),
355
373
  };
356
374
  }
357
- export async function runRuntimeValidationExecutor(bundle, root) {
375
+ export async function runRuntimeValidationExecutor(bundle, root, options = {}) {
358
376
  if (!bundle.runtime_validation_tasks) {
359
377
  throw new Error("Cannot execute runtime validation without runtime_validation_tasks");
360
378
  }
@@ -378,7 +396,7 @@ export async function runRuntimeValidationExecutor(bundle, root) {
378
396
  continue;
379
397
  }
380
398
  const signature = task.command.join("\0");
381
- const outcome = byCommand.get(signature) ?? (await runCommand(task.command, root));
399
+ const outcome = byCommand.get(signature) ?? (await runCommand(task.command, root, { opentoken: options.opentoken }));
382
400
  byCommand.set(signature, outcome);
383
401
  byTaskId.set(task.id, {
384
402
  task_id: task.id,