@codexstar/bug-hunter 3.0.0 → 3.0.6

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 (78) hide show
  1. package/CHANGELOG.md +149 -83
  2. package/README.md +150 -15
  3. package/SKILL.md +94 -27
  4. package/agents/openai.yaml +4 -0
  5. package/bin/bug-hunter +9 -3
  6. package/docs/images/2026-03-12-fix-plan-rollout.png +0 -0
  7. package/docs/images/2026-03-12-hero-bug-hunter-overview.png +0 -0
  8. package/docs/images/2026-03-12-machine-readable-artifacts.png +0 -0
  9. package/docs/images/2026-03-12-pr-review-flow.png +0 -0
  10. package/docs/images/2026-03-12-security-pack.png +0 -0
  11. package/docs/images/adversarial-debate.png +0 -0
  12. package/docs/images/doc-verify-fix-plan.png +0 -0
  13. package/docs/images/hero.png +0 -0
  14. package/docs/images/pipeline-overview.png +0 -0
  15. package/docs/images/security-finding-card.png +0 -0
  16. package/docs/plans/2026-03-11-structured-output-migration-plan.md +288 -0
  17. package/docs/plans/2026-03-12-audit-bug-fixes-surgical-plan.md +193 -0
  18. package/docs/plans/2026-03-12-enterprise-security-pack-e2e-plan.md +59 -0
  19. package/docs/plans/2026-03-12-local-security-skills-integration-plan.md +39 -0
  20. package/docs/plans/2026-03-12-pr-review-strategic-fix-flow.md +78 -0
  21. package/evals/evals.json +366 -102
  22. package/modes/extended.md +2 -2
  23. package/modes/fix-loop.md +30 -30
  24. package/modes/fix-pipeline.md +32 -6
  25. package/modes/large-codebase.md +14 -15
  26. package/modes/local-sequential.md +44 -20
  27. package/modes/loop.md +56 -56
  28. package/modes/parallel.md +3 -3
  29. package/modes/scaled.md +2 -2
  30. package/modes/single-file.md +3 -3
  31. package/modes/small.md +11 -11
  32. package/package.json +11 -1
  33. package/prompts/fixer.md +37 -23
  34. package/prompts/hunter.md +39 -20
  35. package/prompts/referee.md +34 -20
  36. package/prompts/skeptic.md +25 -22
  37. package/schemas/coverage.schema.json +67 -0
  38. package/schemas/examples/findings.invalid.json +13 -0
  39. package/schemas/examples/findings.valid.json +17 -0
  40. package/schemas/findings.schema.json +76 -0
  41. package/schemas/fix-plan.schema.json +94 -0
  42. package/schemas/fix-report.schema.json +105 -0
  43. package/schemas/fix-strategy.schema.json +99 -0
  44. package/schemas/recon.schema.json +31 -0
  45. package/schemas/referee.schema.json +46 -0
  46. package/schemas/shared.schema.json +51 -0
  47. package/schemas/skeptic.schema.json +21 -0
  48. package/scripts/bug-hunter-state.cjs +35 -12
  49. package/scripts/code-index.cjs +11 -4
  50. package/scripts/fix-lock.cjs +95 -25
  51. package/scripts/payload-guard.cjs +24 -10
  52. package/scripts/pr-scope.cjs +181 -0
  53. package/scripts/prepublish-guard.cjs +82 -0
  54. package/scripts/render-report.cjs +346 -0
  55. package/scripts/run-bug-hunter.cjs +669 -33
  56. package/scripts/schema-runtime.cjs +273 -0
  57. package/scripts/schema-validate.cjs +40 -0
  58. package/scripts/tests/bug-hunter-state.test.cjs +68 -3
  59. package/scripts/tests/code-index.test.cjs +15 -0
  60. package/scripts/tests/fix-lock.test.cjs +60 -2
  61. package/scripts/tests/fixtures/flaky-worker.cjs +6 -1
  62. package/scripts/tests/fixtures/low-confidence-worker.cjs +8 -2
  63. package/scripts/tests/fixtures/success-worker.cjs +6 -1
  64. package/scripts/tests/payload-guard.test.cjs +154 -2
  65. package/scripts/tests/pr-scope.test.cjs +212 -0
  66. package/scripts/tests/render-report.test.cjs +180 -0
  67. package/scripts/tests/run-bug-hunter.test.cjs +686 -2
  68. package/scripts/tests/security-skills-integration.test.cjs +29 -0
  69. package/scripts/tests/skills-packaging.test.cjs +30 -0
  70. package/scripts/tests/worktree-harvest.test.cjs +67 -1
  71. package/scripts/worktree-harvest.cjs +62 -9
  72. package/skills/README.md +19 -0
  73. package/skills/commit-security-scan/SKILL.md +63 -0
  74. package/skills/security-review/SKILL.md +57 -0
  75. package/skills/threat-model-generation/SKILL.md +47 -0
  76. package/skills/vulnerability-validation/SKILL.md +59 -0
  77. package/templates/subagent-wrapper.md +12 -3
  78. package/modes/_dispatch.md +0 -121
@@ -0,0 +1,94 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-07/schema#",
3
+ "schemaVersion": 1,
4
+ "artifact": "fix-plan",
5
+ "title": "Bug Hunter Fix Plan Artifact",
6
+ "type": "object",
7
+ "required": [
8
+ "generatedAt",
9
+ "confidenceThreshold",
10
+ "canarySize",
11
+ "totals",
12
+ "canary",
13
+ "rollout",
14
+ "manualReview"
15
+ ],
16
+ "properties": {
17
+ "generatedAt": { "type": "string", "minLength": 1 },
18
+ "confidenceThreshold": { "type": "integer", "minimum": 1 },
19
+ "canarySize": { "type": "integer", "minimum": 1 },
20
+ "totals": {
21
+ "type": "object",
22
+ "required": ["findings", "eligible", "canary", "rollout", "manualReview"],
23
+ "properties": {
24
+ "findings": { "type": "integer", "minimum": 0 },
25
+ "eligible": { "type": "integer", "minimum": 0 },
26
+ "canary": { "type": "integer", "minimum": 0 },
27
+ "rollout": { "type": "integer", "minimum": 0 },
28
+ "manualReview": { "type": "integer", "minimum": 0 }
29
+ },
30
+ "additionalProperties": false
31
+ },
32
+ "canary": { "$ref": "#/definitions/fixPlanEntries" },
33
+ "rollout": { "$ref": "#/definitions/fixPlanEntries" },
34
+ "manualReview": { "$ref": "#/definitions/fixPlanEntries" }
35
+ },
36
+ "definitions": {
37
+ "fixPlanEntries": {
38
+ "type": "array",
39
+ "items": {
40
+ "type": "object",
41
+ "required": [
42
+ "bugId",
43
+ "severity",
44
+ "category",
45
+ "file",
46
+ "lines",
47
+ "claim",
48
+ "evidence",
49
+ "runtimeTrigger",
50
+ "crossReferences",
51
+ "confidenceScore",
52
+ "strategy",
53
+ "executionStage",
54
+ "autofixEligible",
55
+ "reason"
56
+ ],
57
+ "properties": {
58
+ "bugId": { "type": "string", "minLength": 1 },
59
+ "severity": { "type": "string", "enum": ["Critical", "Medium", "Low"] },
60
+ "category": { "type": "string", "minLength": 1 },
61
+ "file": { "type": "string", "minLength": 1 },
62
+ "lines": { "type": "string", "minLength": 1 },
63
+ "claim": { "type": "string", "minLength": 1 },
64
+ "evidence": { "type": "string", "minLength": 1 },
65
+ "runtimeTrigger": { "type": "string", "minLength": 1 },
66
+ "crossReferences": {
67
+ "type": "array",
68
+ "items": { "type": "string", "minLength": 1 }
69
+ },
70
+ "confidenceScore": { "type": "number", "minimum": 0, "maximum": 100 },
71
+ "confidenceLabel": { "type": "string", "enum": ["high", "medium", "low"] },
72
+ "stride": { "type": "string", "minLength": 1 },
73
+ "cwe": { "type": "string", "minLength": 1 },
74
+ "key": { "type": "string", "minLength": 1 },
75
+ "status": { "type": "string", "minLength": 1 },
76
+ "source": { "type": "string", "minLength": 1 },
77
+ "updatedAt": { "type": "string", "minLength": 1 },
78
+ "strategy": {
79
+ "type": "string",
80
+ "enum": ["safe-autofix", "manual-review", "larger-refactor", "architectural-remediation"]
81
+ },
82
+ "executionStage": {
83
+ "type": "string",
84
+ "enum": ["canary", "rollout", "manual-review", "report-only"]
85
+ },
86
+ "autofixEligible": { "type": "boolean" },
87
+ "reason": { "type": "string", "minLength": 1 }
88
+ },
89
+ "additionalProperties": false
90
+ }
91
+ }
92
+ },
93
+ "additionalProperties": false
94
+ }
@@ -0,0 +1,105 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-07/schema#",
3
+ "schemaVersion": 1,
4
+ "artifact": "fix-report",
5
+ "title": "Bug Hunter Fix Report Artifact",
6
+ "type": "object",
7
+ "required": [
8
+ "version",
9
+ "fix_branch",
10
+ "base_commit",
11
+ "dry_run",
12
+ "circuit_breaker_tripped",
13
+ "phase2_timeout_hit",
14
+ "fixes",
15
+ "verification",
16
+ "summary"
17
+ ],
18
+ "properties": {
19
+ "version": { "type": "string", "minLength": 1 },
20
+ "fix_branch": { "type": "string", "minLength": 1 },
21
+ "base_commit": { "type": "string", "minLength": 1 },
22
+ "dry_run": { "type": "boolean" },
23
+ "circuit_breaker_tripped": { "type": "boolean" },
24
+ "phase2_timeout_hit": { "type": "boolean" },
25
+ "fixes": {
26
+ "type": "array",
27
+ "items": {
28
+ "type": "object",
29
+ "required": ["bugId", "severity", "status", "files", "lines"],
30
+ "properties": {
31
+ "bugId": { "type": "string", "minLength": 1 },
32
+ "severity": {
33
+ "type": "string",
34
+ "enum": ["CRITICAL", "HIGH", "MEDIUM", "LOW", "Critical", "Medium", "Low"]
35
+ },
36
+ "status": { "type": "string", "minLength": 1 },
37
+ "files": {
38
+ "type": "array",
39
+ "items": { "type": "string", "minLength": 1 }
40
+ },
41
+ "lines": { "type": "string", "minLength": 1 },
42
+ "commit": { "type": "string", "minLength": 1 },
43
+ "description": { "type": "string", "minLength": 1 },
44
+ "reason": { "type": "string", "minLength": 1 }
45
+ },
46
+ "additionalProperties": false
47
+ }
48
+ },
49
+ "verification": {
50
+ "type": "object",
51
+ "required": [
52
+ "baseline_pass",
53
+ "baseline_fail",
54
+ "flaky_tests",
55
+ "final_pass",
56
+ "final_fail",
57
+ "new_failures",
58
+ "resolved_failures",
59
+ "typecheck_pass",
60
+ "build_pass",
61
+ "fixer_bugs_found"
62
+ ],
63
+ "properties": {
64
+ "baseline_pass": { "type": "integer", "minimum": 0 },
65
+ "baseline_fail": { "type": "integer", "minimum": 0 },
66
+ "flaky_tests": { "type": "integer", "minimum": 0 },
67
+ "final_pass": { "type": "integer", "minimum": 0 },
68
+ "final_fail": { "type": "integer", "minimum": 0 },
69
+ "new_failures": { "type": "integer", "minimum": 0 },
70
+ "resolved_failures": { "type": "integer", "minimum": 0 },
71
+ "typecheck_pass": { "type": "boolean" },
72
+ "build_pass": { "type": "boolean" },
73
+ "fixer_bugs_found": { "type": "integer", "minimum": 0 }
74
+ },
75
+ "additionalProperties": false
76
+ },
77
+ "summary": {
78
+ "type": "object",
79
+ "required": [
80
+ "total_confirmed",
81
+ "eligible",
82
+ "manual_review",
83
+ "fixed",
84
+ "fix_reverted",
85
+ "fix_failed",
86
+ "skipped",
87
+ "fixer_bug",
88
+ "partial"
89
+ ],
90
+ "properties": {
91
+ "total_confirmed": { "type": "integer", "minimum": 0 },
92
+ "eligible": { "type": "integer", "minimum": 0 },
93
+ "manual_review": { "type": "integer", "minimum": 0 },
94
+ "fixed": { "type": "integer", "minimum": 0 },
95
+ "fix_reverted": { "type": "integer", "minimum": 0 },
96
+ "fix_failed": { "type": "integer", "minimum": 0 },
97
+ "skipped": { "type": "integer", "minimum": 0 },
98
+ "fixer_bug": { "type": "integer", "minimum": 0 },
99
+ "partial": { "type": "integer", "minimum": 0 }
100
+ },
101
+ "additionalProperties": false
102
+ }
103
+ },
104
+ "additionalProperties": false
105
+ }
@@ -0,0 +1,99 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-07/schema#",
3
+ "schemaVersion": 1,
4
+ "artifact": "fix-strategy",
5
+ "title": "Bug Hunter Fix Strategy Artifact",
6
+ "type": "object",
7
+ "required": [
8
+ "version",
9
+ "generatedAt",
10
+ "confidenceThreshold",
11
+ "summary",
12
+ "clusters"
13
+ ],
14
+ "properties": {
15
+ "version": { "type": "string", "minLength": 1 },
16
+ "generatedAt": { "type": "string", "minLength": 1 },
17
+ "confidenceThreshold": { "type": "integer", "minimum": 1 },
18
+ "summary": {
19
+ "type": "object",
20
+ "required": [
21
+ "confirmed",
22
+ "safeAutofix",
23
+ "manualReview",
24
+ "largerRefactor",
25
+ "architecturalRemediation",
26
+ "canaryCandidates",
27
+ "rolloutCandidates"
28
+ ],
29
+ "properties": {
30
+ "confirmed": { "type": "integer", "minimum": 0 },
31
+ "safeAutofix": { "type": "integer", "minimum": 0 },
32
+ "manualReview": { "type": "integer", "minimum": 0 },
33
+ "largerRefactor": { "type": "integer", "minimum": 0 },
34
+ "architecturalRemediation": { "type": "integer", "minimum": 0 },
35
+ "canaryCandidates": { "type": "integer", "minimum": 0 },
36
+ "rolloutCandidates": { "type": "integer", "minimum": 0 }
37
+ },
38
+ "additionalProperties": false
39
+ },
40
+ "clusters": {
41
+ "type": "array",
42
+ "items": {
43
+ "type": "object",
44
+ "required": [
45
+ "clusterId",
46
+ "strategy",
47
+ "executionStage",
48
+ "autofixEligible",
49
+ "bugIds",
50
+ "files",
51
+ "maxSeverity",
52
+ "summary",
53
+ "recommendedAction",
54
+ "reasons"
55
+ ],
56
+ "properties": {
57
+ "clusterId": { "type": "string", "minLength": 1 },
58
+ "strategy": {
59
+ "type": "string",
60
+ "enum": [
61
+ "safe-autofix",
62
+ "manual-review",
63
+ "larger-refactor",
64
+ "architectural-remediation"
65
+ ]
66
+ },
67
+ "executionStage": {
68
+ "type": "string",
69
+ "enum": ["canary", "rollout", "manual-review", "report-only"]
70
+ },
71
+ "autofixEligible": { "type": "boolean" },
72
+ "bugIds": {
73
+ "type": "array",
74
+ "minItems": 1,
75
+ "items": { "type": "string", "minLength": 1 }
76
+ },
77
+ "files": {
78
+ "type": "array",
79
+ "minItems": 1,
80
+ "items": { "type": "string", "minLength": 1 }
81
+ },
82
+ "maxSeverity": {
83
+ "type": "string",
84
+ "enum": ["CRITICAL", "HIGH", "MEDIUM", "LOW", "Critical", "High", "Medium", "Low"]
85
+ },
86
+ "summary": { "type": "string", "minLength": 1 },
87
+ "recommendedAction": { "type": "string", "minLength": 1 },
88
+ "reasons": {
89
+ "type": "array",
90
+ "minItems": 1,
91
+ "items": { "type": "string", "minLength": 1 }
92
+ }
93
+ },
94
+ "additionalProperties": false
95
+ }
96
+ }
97
+ },
98
+ "additionalProperties": false
99
+ }
@@ -0,0 +1,31 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-07/schema#",
3
+ "schemaVersion": 1,
4
+ "artifact": "recon",
5
+ "title": "Bug Hunter Recon Artifact",
6
+ "type": "object",
7
+ "required": ["critical", "high", "medium", "contextOnly"],
8
+ "properties": {
9
+ "critical": {
10
+ "type": "array",
11
+ "items": { "type": "string", "minLength": 1 }
12
+ },
13
+ "high": {
14
+ "type": "array",
15
+ "items": { "type": "string", "minLength": 1 }
16
+ },
17
+ "medium": {
18
+ "type": "array",
19
+ "items": { "type": "string", "minLength": 1 }
20
+ },
21
+ "contextOnly": {
22
+ "type": "array",
23
+ "items": { "type": "string", "minLength": 1 }
24
+ },
25
+ "notes": {
26
+ "type": "array",
27
+ "items": { "type": "string", "minLength": 1 }
28
+ }
29
+ },
30
+ "additionalProperties": false
31
+ }
@@ -0,0 +1,46 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-07/schema#",
3
+ "schemaVersion": 1,
4
+ "artifact": "referee",
5
+ "title": "Bug Hunter Referee Artifact",
6
+ "type": "array",
7
+ "items": {
8
+ "type": "object",
9
+ "required": [
10
+ "bugId",
11
+ "verdict",
12
+ "trueSeverity",
13
+ "confidenceScore",
14
+ "confidenceLabel",
15
+ "verificationMode",
16
+ "analysisSummary"
17
+ ],
18
+ "properties": {
19
+ "bugId": { "type": "string", "minLength": 1 },
20
+ "verdict": {
21
+ "type": "string",
22
+ "enum": ["REAL_BUG", "NOT_A_BUG", "MANUAL_REVIEW"]
23
+ },
24
+ "trueSeverity": {
25
+ "type": "string",
26
+ "enum": ["Critical", "Medium", "Low"]
27
+ },
28
+ "confidenceScore": {
29
+ "type": "number",
30
+ "minimum": 0,
31
+ "maximum": 100
32
+ },
33
+ "confidenceLabel": {
34
+ "type": "string",
35
+ "enum": ["high", "medium", "low"]
36
+ },
37
+ "verificationMode": {
38
+ "type": "string",
39
+ "enum": ["INDEPENDENTLY_VERIFIED", "EVIDENCE_BASED"]
40
+ },
41
+ "analysisSummary": { "type": "string", "minLength": 1 },
42
+ "suggestedFix": { "type": "string", "minLength": 1 }
43
+ },
44
+ "additionalProperties": false
45
+ }
46
+ }
@@ -0,0 +1,51 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-07/schema#",
3
+ "schemaVersion": 1,
4
+ "artifact": "shared",
5
+ "title": "Bug Hunter Shared Definitions",
6
+ "$defs": {
7
+ "severity": {
8
+ "type": "string",
9
+ "enum": ["Critical", "Medium", "Low"]
10
+ },
11
+ "category": {
12
+ "type": "string",
13
+ "enum": [
14
+ "logic",
15
+ "security",
16
+ "error-handling",
17
+ "concurrency",
18
+ "edge-case",
19
+ "data-integrity",
20
+ "type-safety",
21
+ "resource-leak",
22
+ "api-contract",
23
+ "cross-file"
24
+ ]
25
+ },
26
+ "stride": {
27
+ "type": "string",
28
+ "enum": [
29
+ "Spoofing",
30
+ "Tampering",
31
+ "Repudiation",
32
+ "InfoDisclosure",
33
+ "DoS",
34
+ "ElevationOfPrivilege",
35
+ "N/A"
36
+ ]
37
+ },
38
+ "verificationMode": {
39
+ "type": "string",
40
+ "enum": ["INDEPENDENTLY_VERIFIED", "EVIDENCE_BASED"]
41
+ },
42
+ "confidenceLabel": {
43
+ "type": "string",
44
+ "enum": ["high", "medium", "low"]
45
+ },
46
+ "coverageStatus": {
47
+ "type": "string",
48
+ "enum": ["pending", "in_progress", "done", "failed"]
49
+ }
50
+ }
51
+ }
@@ -0,0 +1,21 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-07/schema#",
3
+ "schemaVersion": 1,
4
+ "artifact": "skeptic",
5
+ "title": "Bug Hunter Skeptic Artifact",
6
+ "type": "array",
7
+ "items": {
8
+ "type": "object",
9
+ "required": ["bugId", "response", "analysisSummary"],
10
+ "properties": {
11
+ "bugId": { "type": "string", "minLength": 1 },
12
+ "response": {
13
+ "type": "string",
14
+ "enum": ["ACCEPT", "DISPROVE", "MANUAL_REVIEW"]
15
+ },
16
+ "analysisSummary": { "type": "string", "minLength": 1 },
17
+ "counterEvidence": { "type": "string", "minLength": 1 }
18
+ },
19
+ "additionalProperties": false
20
+ }
21
+ }
@@ -3,6 +3,7 @@
3
3
  const crypto = require('crypto');
4
4
  const fs = require('fs');
5
5
  const path = require('path');
6
+ const { validateArtifactValue } = require('./schema-runtime.cjs');
6
7
 
7
8
  const VALID_CHUNK_STATUS = new Set(['pending', 'in_progress', 'done', 'failed']);
8
9
  const DEFAULT_CHUNK_SIZE = 30;
@@ -163,7 +164,7 @@ function assertArray(value, label) {
163
164
  }
164
165
  }
165
166
 
166
- function toConfidence(value) {
167
+ function toConfidenceScore(value) {
167
168
  if (value === null || value === undefined || value === '') {
168
169
  return null;
169
170
  }
@@ -270,19 +271,26 @@ function main() {
270
271
  }
271
272
  const state = readState(statePath);
272
273
  const findings = readJson(findingsJsonPath);
273
- assertArray(findings, 'findingsJson');
274
+ const validation = validateArtifactValue({
275
+ artifactName: 'findings',
276
+ value: findings
277
+ });
278
+ if (!validation.ok) {
279
+ throw new Error(`Invalid findings artifact: ${validation.errors.join('; ')}`);
280
+ }
274
281
 
275
282
  let inserted = 0;
276
283
  let updated = 0;
277
284
  for (const finding of findings) {
278
285
  const file = String(finding.file || '').trim();
279
- if (!file) {
280
- continue;
281
- }
282
286
  const lines = String(finding.lines || '').trim();
283
287
  const claim = String(finding.claim || '').trim();
284
288
  const severity = String(finding.severity || 'Low');
285
- const confidence = toConfidence(finding.confidence);
289
+ const category = String(finding.category || '').trim();
290
+ const evidence = String(finding.evidence || '').trim();
291
+ const runtimeTrigger = String(finding.runtimeTrigger || '').trim();
292
+ const crossReferences = Array.isArray(finding.crossReferences) ? finding.crossReferences : [];
293
+ const confidenceScore = toConfidenceScore(finding.confidenceScore);
286
294
  const bugId = String(finding.bugId || '').trim();
287
295
  const key = `${file}|${lines}|${claim}`;
288
296
  const existing = state.bugLedger.find((entry) => entry.key === key);
@@ -293,8 +301,12 @@ function main() {
293
301
  severity,
294
302
  file,
295
303
  lines,
304
+ category,
296
305
  claim,
297
- confidence,
306
+ evidence,
307
+ runtimeTrigger,
308
+ crossReferences,
309
+ confidenceScore,
298
310
  status: 'open',
299
311
  source,
300
312
  updatedAt: nowIso()
@@ -310,10 +322,14 @@ function main() {
310
322
  if (!existing.bugId && bugId) {
311
323
  existing.bugId = bugId;
312
324
  }
313
- if (existing.confidence === null && confidence !== null) {
314
- existing.confidence = confidence;
315
- } else if (existing.confidence !== null && confidence !== null) {
316
- existing.confidence = Math.max(existing.confidence, confidence);
325
+ existing.category = category || existing.category;
326
+ existing.evidence = evidence || existing.evidence;
327
+ existing.runtimeTrigger = runtimeTrigger || existing.runtimeTrigger;
328
+ existing.crossReferences = crossReferences.length > 0 ? crossReferences : existing.crossReferences;
329
+ if (existing.confidenceScore === null && confidenceScore !== null) {
330
+ existing.confidenceScore = confidenceScore;
331
+ } else if (existing.confidenceScore !== null && confidenceScore !== null) {
332
+ existing.confidenceScore = Math.max(existing.confidenceScore, confidenceScore);
317
333
  }
318
334
  existing.updatedAt = nowIso();
319
335
  existing.source = source;
@@ -323,7 +339,7 @@ function main() {
323
339
  state.metrics.findingsTotal += findings.length;
324
340
  state.metrics.findingsUnique = state.bugLedger.length;
325
341
  state.metrics.lowConfidenceFindings = state.bugLedger.filter((entry) => {
326
- return entry.confidence === null || entry.confidence < 75;
342
+ return entry.confidenceScore === null || entry.confidenceScore < 75;
327
343
  }).length;
328
344
  saveState(statePath, state);
329
345
  console.log(JSON.stringify({
@@ -495,6 +511,13 @@ function main() {
495
511
  }
496
512
  const state = readState(statePath);
497
513
  const fixPlan = readJson(fixPlanJsonPath);
514
+ const validation = validateArtifactValue({
515
+ artifactName: 'fix-plan',
516
+ value: fixPlan
517
+ });
518
+ if (!validation.ok) {
519
+ throw new Error(`Invalid fix-plan artifact: ${validation.errors.join('; ')}`);
520
+ }
498
521
  state.fixPlan = fixPlan;
499
522
  saveState(statePath, state);
500
523
  console.log(JSON.stringify({
@@ -453,11 +453,18 @@ function queryBugs(indexPath, bugsJsonPath, hopsRaw) {
453
453
  .map((bug) => String((bug && bug.file) || '').trim())
454
454
  .filter(Boolean)
455
455
  .map((filePath) => path.resolve(filePath));
456
- const tempSeedPath = path.join(path.dirname(path.resolve(bugsJsonPath)), '.seed-files.tmp.json');
456
+ const tempSeedPath = path.join(
457
+ path.dirname(path.resolve(bugsJsonPath)),
458
+ `.seed-files.${process.pid}.${Date.now()}.${crypto.randomUUID()}.tmp.json`
459
+ );
457
460
  writeJson(tempSeedPath, seedFiles);
458
- const result = query(indexPath, tempSeedPath, hopsRaw);
459
- fs.unlinkSync(tempSeedPath);
460
- return result;
461
+ try {
462
+ return query(indexPath, tempSeedPath, hopsRaw);
463
+ } finally {
464
+ if (fs.existsSync(tempSeedPath)) {
465
+ fs.unlinkSync(tempSeedPath);
466
+ }
467
+ }
461
468
  }
462
469
 
463
470
  function main() {