@vigolium/piolium 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (271) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +117 -0
  3. package/agents/access-auditor.md +300 -0
  4. package/agents/assumption-breaker.md +154 -0
  5. package/agents/attack-designer.md +116 -0
  6. package/agents/code-scanner.md +139 -0
  7. package/agents/concurrency-auditor.md +238 -0
  8. package/agents/confirm-writer.md +257 -0
  9. package/agents/context-reviewer.md +274 -0
  10. package/agents/cross-verifier.md +165 -0
  11. package/agents/cve-scout.md +381 -0
  12. package/agents/env-builder.md +282 -0
  13. package/agents/env-profiler.md +205 -0
  14. package/agents/evidence-collector.md +140 -0
  15. package/agents/finding-grader.md +142 -0
  16. package/agents/finding-writer.md +148 -0
  17. package/agents/flow-tracer.md +106 -0
  18. package/agents/goal-backtracer.md +146 -0
  19. package/agents/history-miner.md +467 -0
  20. package/agents/independent-verifier.md +118 -0
  21. package/agents/intent-mapper.md +183 -0
  22. package/agents/longshot-collector.md +128 -0
  23. package/agents/longshot-prober.md +126 -0
  24. package/agents/patch-auditor.md +73 -0
  25. package/agents/poc-author.md +124 -0
  26. package/agents/poc-runner.md +194 -0
  27. package/agents/probe-lead.md +269 -0
  28. package/agents/red-challenger.md +101 -0
  29. package/agents/report-composer.md +208 -0
  30. package/agents/review-adjudicator.md +216 -0
  31. package/agents/spec-auditor.md +155 -0
  32. package/agents/taint-tracer.md +265 -0
  33. package/agents/test-locator.md +209 -0
  34. package/agents/threat-modeler.md +132 -0
  35. package/agents/variant-scanner.md +108 -0
  36. package/agents/variant-spotter.md +110 -0
  37. package/bin/piolium.mjs +376 -0
  38. package/extensions/piolium/_vendor/yaml.bundle.d.mts +6 -0
  39. package/extensions/piolium/_vendor/yaml.bundle.mjs +139 -0
  40. package/extensions/piolium/agent-runner.ts +322 -0
  41. package/extensions/piolium/agents.ts +266 -0
  42. package/extensions/piolium/audit-state.ts +522 -0
  43. package/extensions/piolium/bundled-resources.ts +97 -0
  44. package/extensions/piolium/candidate-scan.ts +966 -0
  45. package/extensions/piolium/command-target.ts +177 -0
  46. package/extensions/piolium/console-stream.ts +57 -0
  47. package/extensions/piolium/export-results.ts +380 -0
  48. package/extensions/piolium/findings.ts +448 -0
  49. package/extensions/piolium/heartbeat.ts +182 -0
  50. package/extensions/piolium/help.ts +234 -0
  51. package/extensions/piolium/index.ts +1865 -0
  52. package/extensions/piolium/longshot.ts +530 -0
  53. package/extensions/piolium/matcher-suggestions.ts +196 -0
  54. package/extensions/piolium/matcher-utils.ts +83 -0
  55. package/extensions/piolium/modes/balanced.ts +750 -0
  56. package/extensions/piolium/modes/confirm-bootstrap.ts +186 -0
  57. package/extensions/piolium/modes/confirm.ts +697 -0
  58. package/extensions/piolium/modes/deep.ts +917 -0
  59. package/extensions/piolium/modes/diff.ts +177 -0
  60. package/extensions/piolium/modes/lite.ts +540 -0
  61. package/extensions/piolium/modes/longshot.ts +595 -0
  62. package/extensions/piolium/modes/merge.ts +204 -0
  63. package/extensions/piolium/modes/phase-runner.ts +267 -0
  64. package/extensions/piolium/modes/reinvest.ts +546 -0
  65. package/extensions/piolium/modes/revisit.ts +279 -0
  66. package/extensions/piolium/modes.ts +48 -0
  67. package/extensions/piolium/phase-labels.ts +123 -0
  68. package/extensions/piolium/phase-status-strip.ts +92 -0
  69. package/extensions/piolium/prompt-prefix-editor.ts +39 -0
  70. package/extensions/piolium/providers/anthropic-vertex.ts +836 -0
  71. package/extensions/piolium/recon.ts +409 -0
  72. package/extensions/piolium/result-stats.ts +105 -0
  73. package/extensions/piolium/retry.ts +120 -0
  74. package/extensions/piolium/scheduler.ts +212 -0
  75. package/extensions/piolium/secrets.ts +368 -0
  76. package/extensions/piolium/tools/web-tools.ts +148 -0
  77. package/package.json +77 -0
  78. package/skills/agentic-actions-auditor/SKILL.md +327 -0
  79. package/skills/agentic-actions-auditor/references/action-profiles.md +186 -0
  80. package/skills/agentic-actions-auditor/references/cross-file-resolution.md +209 -0
  81. package/skills/agentic-actions-auditor/references/foundations.md +94 -0
  82. package/skills/agentic-actions-auditor/references/vector-a-env-var-intermediary.md +77 -0
  83. package/skills/agentic-actions-auditor/references/vector-b-direct-expression-injection.md +83 -0
  84. package/skills/agentic-actions-auditor/references/vector-c-cli-data-fetch.md +83 -0
  85. package/skills/agentic-actions-auditor/references/vector-d-pr-target-checkout.md +88 -0
  86. package/skills/agentic-actions-auditor/references/vector-e-error-log-injection.md +88 -0
  87. package/skills/agentic-actions-auditor/references/vector-f-subshell-expansion.md +82 -0
  88. package/skills/agentic-actions-auditor/references/vector-g-eval-of-ai-output.md +91 -0
  89. package/skills/agentic-actions-auditor/references/vector-h-dangerous-sandbox-configs.md +102 -0
  90. package/skills/agentic-actions-auditor/references/vector-i-wildcard-allowlists.md +88 -0
  91. package/skills/audit/SKILL.md +562 -0
  92. package/skills/audit/assets/icon.svg +7 -0
  93. package/skills/audit/hooks/scripts/validate_phase_output.py +550 -0
  94. package/skills/audit/references/adversarial-review.md +148 -0
  95. package/skills/audit/references/architecture-aware-sast.md +306 -0
  96. package/skills/audit/references/audit-workflow.md +737 -0
  97. package/skills/audit/references/chamber-protocol.md +384 -0
  98. package/skills/audit/references/creative-attack-modes.md +221 -0
  99. package/skills/audit/references/deep-analysis.md +273 -0
  100. package/skills/audit/references/domain-attack-playbooks.md +1129 -0
  101. package/skills/audit/references/knowledge-base-template.md +513 -0
  102. package/skills/audit/references/real-env-validation.md +191 -0
  103. package/skills/audit/references/report-templates.md +417 -0
  104. package/skills/audit/references/triage-and-prereqs.md +134 -0
  105. package/skills/audit/scripts/consolidate_drafts.py +554 -0
  106. package/skills/audit/scripts/partition_findings.py +152 -0
  107. package/skills/audit/scripts/rg-hotspots.sh +121 -0
  108. package/skills/audit/scripts/stamp_file_state.py +349 -0
  109. package/skills/code-reviewer/SKILL.md +65 -0
  110. package/skills/codeql/SKILL.md +281 -0
  111. package/skills/codeql/references/build-fixes.md +90 -0
  112. package/skills/codeql/references/diagnostic-query-templates.md +339 -0
  113. package/skills/codeql/references/extension-yaml-format.md +209 -0
  114. package/skills/codeql/references/important-only-suite.md +153 -0
  115. package/skills/codeql/references/language-details.md +207 -0
  116. package/skills/codeql/references/macos-arm64e-workaround.md +179 -0
  117. package/skills/codeql/references/performance-tuning.md +111 -0
  118. package/skills/codeql/references/quality-assessment.md +172 -0
  119. package/skills/codeql/references/ruleset-catalog.md +63 -0
  120. package/skills/codeql/references/run-all-suite.md +92 -0
  121. package/skills/codeql/references/sarif-processing.md +79 -0
  122. package/skills/codeql/references/threat-models.md +51 -0
  123. package/skills/codeql/workflows/build-database.md +280 -0
  124. package/skills/codeql/workflows/create-data-extensions.md +261 -0
  125. package/skills/codeql/workflows/run-analysis.md +301 -0
  126. package/skills/differential-review/SKILL.md +220 -0
  127. package/skills/differential-review/adversarial.md +203 -0
  128. package/skills/differential-review/methodology.md +234 -0
  129. package/skills/differential-review/patterns.md +300 -0
  130. package/skills/differential-review/reporting.md +369 -0
  131. package/skills/fp-check/SKILL.md +125 -0
  132. package/skills/fp-check/references/bug-class-verification.md +114 -0
  133. package/skills/fp-check/references/deep-verification.md +143 -0
  134. package/skills/fp-check/references/evidence-templates.md +91 -0
  135. package/skills/fp-check/references/false-positive-patterns.md +115 -0
  136. package/skills/fp-check/references/gate-reviews.md +27 -0
  137. package/skills/fp-check/references/standard-verification.md +78 -0
  138. package/skills/insecure-defaults/SKILL.md +117 -0
  139. package/skills/insecure-defaults/references/examples.md +409 -0
  140. package/skills/last30days/SKILL.md +444 -0
  141. package/skills/sarif-parsing/SKILL.md +483 -0
  142. package/skills/sarif-parsing/resources/jq-queries.md +162 -0
  143. package/skills/sarif-parsing/resources/sarif_helpers.py +331 -0
  144. package/skills/security-threat-model/LICENSE.txt +201 -0
  145. package/skills/security-threat-model/SKILL.md +81 -0
  146. package/skills/security-threat-model/agents/openai.yaml +4 -0
  147. package/skills/security-threat-model/references/prompt-template.md +255 -0
  148. package/skills/security-threat-model/references/security-controls-and-assets.md +32 -0
  149. package/skills/semgrep/SKILL.md +212 -0
  150. package/skills/semgrep/references/rulesets.md +162 -0
  151. package/skills/semgrep/references/scan-modes.md +110 -0
  152. package/skills/semgrep/references/scanner-task-prompt.md +140 -0
  153. package/skills/semgrep/scripts/merge_sarif.py +203 -0
  154. package/skills/semgrep/workflows/scan-workflow.md +311 -0
  155. package/skills/semgrep-rule-creator/SKILL.md +168 -0
  156. package/skills/semgrep-rule-creator/references/quick-reference.md +202 -0
  157. package/skills/semgrep-rule-creator/references/workflow.md +240 -0
  158. package/skills/semgrep-rule-variant-creator/SKILL.md +205 -0
  159. package/skills/semgrep-rule-variant-creator/references/applicability-analysis.md +250 -0
  160. package/skills/semgrep-rule-variant-creator/references/language-syntax-guide.md +324 -0
  161. package/skills/semgrep-rule-variant-creator/references/workflow.md +518 -0
  162. package/skills/sharp-edges/SKILL.md +292 -0
  163. package/skills/sharp-edges/references/auth-patterns.md +252 -0
  164. package/skills/sharp-edges/references/case-studies.md +274 -0
  165. package/skills/sharp-edges/references/config-patterns.md +333 -0
  166. package/skills/sharp-edges/references/crypto-apis.md +190 -0
  167. package/skills/sharp-edges/references/lang-c.md +205 -0
  168. package/skills/sharp-edges/references/lang-csharp.md +285 -0
  169. package/skills/sharp-edges/references/lang-go.md +270 -0
  170. package/skills/sharp-edges/references/lang-java.md +263 -0
  171. package/skills/sharp-edges/references/lang-javascript.md +269 -0
  172. package/skills/sharp-edges/references/lang-kotlin.md +265 -0
  173. package/skills/sharp-edges/references/lang-php.md +245 -0
  174. package/skills/sharp-edges/references/lang-python.md +274 -0
  175. package/skills/sharp-edges/references/lang-ruby.md +273 -0
  176. package/skills/sharp-edges/references/lang-rust.md +272 -0
  177. package/skills/sharp-edges/references/lang-swift.md +287 -0
  178. package/skills/sharp-edges/references/language-specific.md +588 -0
  179. package/skills/spec-to-code-compliance/SKILL.md +357 -0
  180. package/skills/spec-to-code-compliance/resources/COMPLETENESS_CHECKLIST.md +69 -0
  181. package/skills/spec-to-code-compliance/resources/IR_EXAMPLES.md +417 -0
  182. package/skills/spec-to-code-compliance/resources/OUTPUT_REQUIREMENTS.md +105 -0
  183. package/skills/supply-chain-risk-auditor/SKILL.md +67 -0
  184. package/skills/supply-chain-risk-auditor/resources/results-template.md +41 -0
  185. package/skills/variant-analysis/METHODOLOGY.md +327 -0
  186. package/skills/variant-analysis/SKILL.md +142 -0
  187. package/skills/variant-analysis/resources/codeql/cpp.ql +119 -0
  188. package/skills/variant-analysis/resources/codeql/go.ql +69 -0
  189. package/skills/variant-analysis/resources/codeql/java.ql +71 -0
  190. package/skills/variant-analysis/resources/codeql/javascript.ql +63 -0
  191. package/skills/variant-analysis/resources/codeql/python.ql +80 -0
  192. package/skills/variant-analysis/resources/semgrep/cpp.yaml +98 -0
  193. package/skills/variant-analysis/resources/semgrep/go.yaml +63 -0
  194. package/skills/variant-analysis/resources/semgrep/java.yaml +61 -0
  195. package/skills/variant-analysis/resources/semgrep/javascript.yaml +60 -0
  196. package/skills/variant-analysis/resources/semgrep/python.yaml +72 -0
  197. package/skills/variant-analysis/resources/variant-report-template.md +75 -0
  198. package/skills/vuln-report/SKILL.md +137 -0
  199. package/skills/vuln-report/agents/openai.yaml +4 -0
  200. package/skills/vuln-report/references/report-template.md +135 -0
  201. package/skills/wooyun-legacy/SKILL.md +367 -0
  202. package/skills/wooyun-legacy/references/bank-penetration.md +222 -0
  203. package/skills/wooyun-legacy/references/checklists/command-execution-checklist.md +119 -0
  204. package/skills/wooyun-legacy/references/checklists/csrf-checklist.md +74 -0
  205. package/skills/wooyun-legacy/references/checklists/file-upload-checklist.md +108 -0
  206. package/skills/wooyun-legacy/references/checklists/info-disclosure-checklist.md +114 -0
  207. package/skills/wooyun-legacy/references/checklists/logic-flaws-checklist.md +95 -0
  208. package/skills/wooyun-legacy/references/checklists/misconfig-checklist.md +124 -0
  209. package/skills/wooyun-legacy/references/checklists/path-traversal-checklist.md +87 -0
  210. package/skills/wooyun-legacy/references/checklists/rce-checklist.md +93 -0
  211. package/skills/wooyun-legacy/references/checklists/sql-injection-checklist.md +97 -0
  212. package/skills/wooyun-legacy/references/checklists/ssrf-checklist.md +99 -0
  213. package/skills/wooyun-legacy/references/checklists/unauthorized-access-checklist.md +89 -0
  214. package/skills/wooyun-legacy/references/checklists/weak-password-checklist.md +115 -0
  215. package/skills/wooyun-legacy/references/checklists/xss-checklist.md +103 -0
  216. package/skills/wooyun-legacy/references/checklists/xxe-checklist.md +130 -0
  217. package/skills/wooyun-legacy/references/info-disclosure.md +975 -0
  218. package/skills/wooyun-legacy/references/logic-flaws.md +721 -0
  219. package/skills/wooyun-legacy/references/path-traversal.md +1191 -0
  220. package/skills/wooyun-legacy/references/telecom-penetration.md +156 -0
  221. package/skills/wooyun-legacy/references/unauthorized-access.md +980 -0
  222. package/skills/wooyun-legacy/references/xss.md +746 -0
  223. package/skills/zeroize-audit/SKILL.md +371 -0
  224. package/skills/zeroize-audit/configs/c.yaml +21 -0
  225. package/skills/zeroize-audit/configs/default.yaml +128 -0
  226. package/skills/zeroize-audit/configs/rust.yaml +83 -0
  227. package/skills/zeroize-audit/prompts/report_template.md +238 -0
  228. package/skills/zeroize-audit/prompts/system.md +163 -0
  229. package/skills/zeroize-audit/prompts/task.md +97 -0
  230. package/skills/zeroize-audit/references/compile-commands.md +231 -0
  231. package/skills/zeroize-audit/references/detection-strategy.md +191 -0
  232. package/skills/zeroize-audit/references/ir-analysis.md +252 -0
  233. package/skills/zeroize-audit/references/mcp-analysis.md +221 -0
  234. package/skills/zeroize-audit/references/poc-generation.md +470 -0
  235. package/skills/zeroize-audit/references/rust-zeroization-patterns.md +867 -0
  236. package/skills/zeroize-audit/schemas/input.json +83 -0
  237. package/skills/zeroize-audit/schemas/output.json +140 -0
  238. package/skills/zeroize-audit/tools/analyze_asm.sh +202 -0
  239. package/skills/zeroize-audit/tools/analyze_cfg.py +381 -0
  240. package/skills/zeroize-audit/tools/analyze_heap.sh +211 -0
  241. package/skills/zeroize-audit/tools/analyze_ir_semantic.py +429 -0
  242. package/skills/zeroize-audit/tools/diff_ir.sh +135 -0
  243. package/skills/zeroize-audit/tools/diff_rust_mir.sh +189 -0
  244. package/skills/zeroize-audit/tools/emit_asm.sh +67 -0
  245. package/skills/zeroize-audit/tools/emit_ir.sh +77 -0
  246. package/skills/zeroize-audit/tools/emit_rust_asm.sh +178 -0
  247. package/skills/zeroize-audit/tools/emit_rust_ir.sh +150 -0
  248. package/skills/zeroize-audit/tools/emit_rust_mir.sh +158 -0
  249. package/skills/zeroize-audit/tools/extract_compile_flags.py +284 -0
  250. package/skills/zeroize-audit/tools/generate_poc.py +1329 -0
  251. package/skills/zeroize-audit/tools/mcp/apply_confidence_gates.py +113 -0
  252. package/skills/zeroize-audit/tools/mcp/check_mcp.sh +68 -0
  253. package/skills/zeroize-audit/tools/mcp/normalize_mcp_evidence.py +125 -0
  254. package/skills/zeroize-audit/tools/scripts/check_llvm_patterns.py +481 -0
  255. package/skills/zeroize-audit/tools/scripts/check_mir_patterns.py +554 -0
  256. package/skills/zeroize-audit/tools/scripts/check_rust_asm.py +424 -0
  257. package/skills/zeroize-audit/tools/scripts/check_rust_asm_aarch64.py +300 -0
  258. package/skills/zeroize-audit/tools/scripts/check_rust_asm_x86.py +283 -0
  259. package/skills/zeroize-audit/tools/scripts/find_dangerous_apis.py +375 -0
  260. package/skills/zeroize-audit/tools/scripts/semantic_audit.py +923 -0
  261. package/skills/zeroize-audit/tools/track_dataflow.sh +196 -0
  262. package/skills/zeroize-audit/tools/validate_rust_toolchain.sh +298 -0
  263. package/skills/zeroize-audit/workflows/phase-0-preflight.md +150 -0
  264. package/skills/zeroize-audit/workflows/phase-1-source-analysis.md +144 -0
  265. package/skills/zeroize-audit/workflows/phase-2-compiler-analysis.md +139 -0
  266. package/skills/zeroize-audit/workflows/phase-3-interim-report.md +46 -0
  267. package/skills/zeroize-audit/workflows/phase-4-poc-generation.md +46 -0
  268. package/skills/zeroize-audit/workflows/phase-5-poc-validation.md +136 -0
  269. package/skills/zeroize-audit/workflows/phase-6-final-report.md +44 -0
  270. package/skills/zeroize-audit/workflows/phase-7-test-generation.md +42 -0
  271. package/themes/piolium-srcery.json +94 -0
@@ -0,0 +1,152 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ Route confirmed vs theoretical findings AFTER poc-author has run.
4
+
5
+ `consolidate_drafts.py` puts every actionable finding in
6
+ `<archon_dir>/findings/<ID>-<slug>/`. poc-author then attempts a PoC for
7
+ each and writes `PoC-Status: executed | theoretical | blocked` back into the
8
+ finding's `draft.md`. This script reads that field and demotes any finding
9
+ that did NOT reach `PoC-Status: executed` into
10
+ `<archon_dir>/findings-theoretical/<ID>-<slug>/` (same directory shape, IDs
11
+ unchanged so cross-references stay stable).
12
+
13
+ Bucket contract:
14
+ findings/ -> confirmed, PoC executed (the actionable bucket)
15
+ findings-theoretical/ -> no PoC / theoretical / blocked, plus the
16
+ triage-skipped findings consolidate_drafts.py
17
+ already placed there.
18
+
19
+ The script is idempotent: re-running it never moves an already-`executed`
20
+ finding, and a re-demoted finding overwrites any stale same-ID directory in
21
+ the theoretical bucket. It is a no-op for modes that never build PoCs
22
+ (nothing is `executed`, but those modes simply don't invoke this script).
23
+
24
+ Usage:
25
+ partition_findings.py [archon_dir]
26
+
27
+ archon_dir defaults to "archon". Exit codes:
28
+ 0 success (including "nothing to move")
29
+ 2 usage error / archon_dir missing
30
+ 3 I/O error during partition
31
+ """
32
+
33
+ import json
34
+ import os
35
+ import re
36
+ import shutil
37
+ import sys
38
+ from pathlib import Path
39
+
40
+ FINDING_DIR_RE = re.compile(r"^[CHM]\d+-")
41
+ # Same shape as consolidate_drafts.py's KV_RE, intentionally duplicated:
42
+ # every vendored script under skills/audit/scripts/ is standalone (copied
43
+ # verbatim at install time, no cross-script imports). Keep the two in sync.
44
+ KV_RE = re.compile(r"^([A-Za-z][A-Za-z0-9 _-]*):\s*(.*)$")
45
+
46
+
47
+ def read_poc_status(draft_path: Path) -> str:
48
+ """Return the lowercased PoC-Status value from a finding draft, or "" if
49
+ absent.
50
+
51
+ poc-author writes `PoC-Status:` back into an already-materialised
52
+ `draft.md` *after* consolidation, so it does not always land inside the
53
+ strict leading `Key: Value` block (which terminates at the first blank
54
+ line or `## ` heading). Demoting a genuinely confirmed finding because
55
+ the field sat one line outside that block is the costly failure
56
+ direction, so scan the WHOLE file for a `PoC-Status:` line and take the
57
+ last occurrence (re-runs append an updated value). This matches how
58
+ finding-writer and merge mode read the field loosely.
59
+ """
60
+ if not draft_path.is_file():
61
+ return ""
62
+ found = ""
63
+ try:
64
+ with draft_path.open() as f:
65
+ for line in f:
66
+ m = KV_RE.match(line.rstrip("\n"))
67
+ if m and m.group(1).strip().lower() == "poc-status":
68
+ found = m.group(2).strip().lower()
69
+ except OSError:
70
+ pass
71
+ return found
72
+
73
+
74
+ def move_into(src: Path, dest_dir: Path) -> Path:
75
+ """Move `src` directory into `dest_dir`, replacing any same-named target
76
+ so the operation is idempotent. Returns the destination path.
77
+ """
78
+ dest_dir.mkdir(parents=True, exist_ok=True)
79
+ target = dest_dir / src.name
80
+ if target.exists():
81
+ shutil.rmtree(target)
82
+ shutil.move(str(src), str(target))
83
+ return target
84
+
85
+
86
+ def partition(archon_dir: Path) -> int:
87
+ findings_dir = archon_dir / "findings"
88
+ theoretical_dir = archon_dir / "findings-theoretical"
89
+
90
+ kept: list[str] = []
91
+ moved: list[dict] = []
92
+
93
+ if findings_dir.is_dir():
94
+ for entry in sorted(os.listdir(findings_dir)):
95
+ folder = findings_dir / entry
96
+ if not folder.is_dir() or not FINDING_DIR_RE.match(entry):
97
+ continue
98
+ status = read_poc_status(folder / "draft.md")
99
+ if status == "executed":
100
+ kept.append(entry)
101
+ continue
102
+ dest = move_into(folder, theoretical_dir)
103
+ moved.append(
104
+ {
105
+ "id": entry.split("-", 1)[0],
106
+ "dir": entry,
107
+ "poc_status": status or "missing",
108
+ "to": str(dest),
109
+ }
110
+ )
111
+
112
+ manifest = {
113
+ "archon_dir": str(archon_dir),
114
+ "kept": kept,
115
+ "moved": moved,
116
+ "counts": {"kept": len(kept), "moved": len(moved)},
117
+ }
118
+ (archon_dir / "findings-draft").mkdir(parents=True, exist_ok=True)
119
+ (archon_dir / "findings-draft" / "partition-manifest.json").write_text(
120
+ json.dumps(manifest, indent=2) + "\n"
121
+ )
122
+ print(json.dumps(manifest, indent=2))
123
+ print(
124
+ f"partition: {len(kept)} confirmed stay in findings/, "
125
+ f"{len(moved)} demoted to findings-theoretical/ "
126
+ f"(no PoC / theoretical / blocked)",
127
+ file=sys.stderr,
128
+ )
129
+ return 0
130
+
131
+
132
+ def main() -> None:
133
+ argv = sys.argv[1:]
134
+ if argv and argv[0] in ("-h", "--help"):
135
+ print(__doc__)
136
+ sys.exit(0)
137
+ if len(argv) > 1:
138
+ print("usage: partition_findings.py [archon_dir]", file=sys.stderr)
139
+ sys.exit(2)
140
+ archon_dir = Path(argv[0]) if argv else Path("archon")
141
+ if not archon_dir.is_dir():
142
+ print(f"error: archon dir not found: {archon_dir}", file=sys.stderr)
143
+ sys.exit(2)
144
+ try:
145
+ sys.exit(partition(archon_dir))
146
+ except OSError as e:
147
+ print(f"error: I/O failure during partition: {e}", file=sys.stderr)
148
+ sys.exit(3)
149
+
150
+
151
+ if __name__ == "__main__":
152
+ main()
@@ -0,0 +1,121 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+
4
+ # Fast, noisy-first security hotspot discovery.
5
+ # Goal: find review starting points (sinks and risky APIs), not prove vulns.
6
+ #
7
+ # Usage:
8
+ # scripts/rg-hotspots.sh # scan repo from cwd
9
+ # scripts/rg-hotspots.sh path/ # scan a subdir
10
+ #
11
+ # Tips:
12
+ # - Pipe into a pager: `... | less -R`
13
+ # - Narrow scope for signal: `... api/` or `... src/auth/`
14
+
15
+ root="${1:-.}"
16
+
17
+ if ! command -v rg >/dev/null 2>&1; then
18
+ echo "error: rg (ripgrep) not found in PATH" >&2
19
+ exit 2
20
+ fi
21
+
22
+ rg_base=(
23
+ --no-heading
24
+ --line-number
25
+ --hidden
26
+ --follow
27
+ --smart-case
28
+ --glob '!.git/**'
29
+ --glob '!**/node_modules/**'
30
+ --glob '!**/dist/**'
31
+ --glob '!**/build/**'
32
+ --glob '!**/target/**'
33
+ --glob '!**/.next/**'
34
+ --glob '!**/vendor/**'
35
+ --glob '!**/.venv/**'
36
+ --glob '!**/venv/**'
37
+ )
38
+
39
+ section() {
40
+ echo
41
+ echo "== $1"
42
+ }
43
+
44
+ run() {
45
+ local label="$1"
46
+ shift
47
+ section "$label"
48
+ # `|| true` because some sections will have no matches (not an error).
49
+ rg "${rg_base[@]}" "$@" "$root" || true
50
+ }
51
+
52
+ section "RG Hotspots"
53
+ echo "root: $root"
54
+
55
+ run "Command Execution / Dangerous Eval" \
56
+ -e 'Runtime\.getRuntime\(\)\.exec' \
57
+ -e 'ProcessBuilder\s*\(' \
58
+ -e '\bexec(ute)?\s*\(' \
59
+ -e '\bsystem\s*\(' \
60
+ -e '\bpopen\s*\(' \
61
+ -e 'child_process\.(exec|execSync|spawn|spawnSync)\b' \
62
+ -e '\bos\.system\b' \
63
+ -e '\bsubprocess\.(run|Popen|call|check_output)\b' \
64
+ -e '\beval\s*\(' \
65
+ -e '\bFunction\s*\(' \
66
+ -e 'vm\.run(In(New)?Context|InThisContext)\b'
67
+
68
+ run "Deserialization / Template Injection Primitives" \
69
+ -e '\bpickle\.loads\b' \
70
+ -e '\byaml\.load\s*\(' \
71
+ -e '\bObjectInputStream\b' \
72
+ -e '\breadObject\s*\(' \
73
+ -e '\bunserialize\s*\(' \
74
+ -e '\bMarshal\.load\b' \
75
+ -e '\bERB\.new\b' \
76
+ -e '\bnew\s+Template\b' \
77
+ -e '\bMustache\.' \
78
+ -e '\bHandlebars\.' \
79
+ -e '\bEJS\b'
80
+
81
+ run "SSRF / URL Fetching / HTTP Clients (review call sites)" \
82
+ -e '\brequests\.(get|post|put|delete|head|patch)\b' \
83
+ -e '\burllib\.(request|parse)\b' \
84
+ -e '\bhttpx\.(get|post|Client)\b' \
85
+ -e '\baxios\.' \
86
+ -e '\bfetch\s*\(' \
87
+ -e '\bgot\s*\(' \
88
+ -e '\bnew\s+URL\s*\(' \
89
+ -e '\bnet/http\b' \
90
+ -e '\bhttp\.NewRequest\b' \
91
+ -e '\bhttp\.Client\b'
92
+
93
+ run "SQL / Query Construction (review interpolation/concatenation)" \
94
+ -e '\bSELECT\b|\bINSERT\b|\bUPDATE\b|\bDELETE\b' \
95
+ -e '\bquery(Raw)?\s*\(' \
96
+ -e '\bexecute\s*\(' \
97
+ -e '\bprepare\s*\('
98
+
99
+ run "File & Path Handling (review traversal/allowlists)" \
100
+ -e '\bopen\s*\(' \
101
+ -e '\bos\.path\.join\b|\bpath\.join\b|\bfilepath\.Join\b' \
102
+ -e '\bread(File|FileSync)\s*\(' \
103
+ -e '\bwrite(File|FileSync)\s*\(' \
104
+ -e '\bcreate(Read|Write)Stream\s*\(' \
105
+ -e '\bSendFile\b|\bsendFile\s*\('
106
+
107
+ run "AuthN/AuthZ Signals (review enforcement points)" \
108
+ -e '\bauthori[sz]e\b' \
109
+ -e '\bpermission(s)?\b' \
110
+ -e '\brole(s)?\b' \
111
+ -e '\bisAdmin\b|\badminOnly\b' \
112
+ -e '\bRBAC\b|\bABAC\b'
113
+
114
+ run "Secrets (high false positives; prioritize obvious tokens/keys)" \
115
+ -e 'AKIA[0-9A-Z]{16}' \
116
+ -e 'ASIA[0-9A-Z]{16}' \
117
+ -e '-----BEGIN (RSA|EC|OPENSSH) PRIVATE KEY-----' \
118
+ -e 'xox[baprs]-[0-9A-Za-z-]+' \
119
+ -e 'ghp_[0-9A-Za-z]{30,}' \
120
+ -e 'AIza[0-9A-Za-z\-_]{35}' \
121
+ -e '\b(api[_-]?key|secret|token|passwd|password)\b\s*[:=]\s*["'\''][^"'\'']{8,}["'\'']'
@@ -0,0 +1,349 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ Walk the target repository, hash every source file, and write
4
+ archon/file-state.json — a per-file lattice that records which audit IDs
5
+ have touched which file. Run this as a side-effect of the final phase of
6
+ any audit (balanced Phase B8, deep Phase D13) so the next audit can compute
7
+ an incremental scope (changed/new/deleted files) against the prior state.
8
+
9
+ The state file is additive across runs: a re-run merges the new audit_id
10
+ into each file's `last_audits[]` rather than overwriting.
11
+
12
+ Usage:
13
+ stamp_file_state.py [--target <path>] [--archon-dir <path>] [--audit-id <id>] [--phases <n,n,...>]
14
+
15
+ Defaults:
16
+ --target cwd
17
+ --archon-dir <target>/archon
18
+ --audit-id read from <archon-dir>/audit-state.json's last entry
19
+ --phases all integer keys from the last audit's `phases` map
20
+
21
+ Excludes:
22
+ Standard noise (.git/, node_modules/, vendor/, __pycache__/, dist/,
23
+ build/, .venv/, target/, .archon-merge-staging-*/) and the archon/
24
+ directory itself. Only files smaller than DEFAULT_MAX_BYTES (~512KB)
25
+ are hashed; larger files get a `large_file: true` marker without a
26
+ hash so the next audit still sees that they exist.
27
+
28
+ Exit codes:
29
+ 0 success
30
+ 1 no audit_id available (no prior audit-state.json and none provided)
31
+ 2 usage error / target missing
32
+ 3 I/O failure during walk or write
33
+ """
34
+
35
+ from __future__ import annotations
36
+
37
+ import argparse
38
+ import hashlib
39
+ import json
40
+ import os
41
+ import sys
42
+ from datetime import datetime, timezone
43
+ from pathlib import Path
44
+ from typing import Optional
45
+
46
+ DEFAULT_MAX_BYTES = 512 * 1024 # 512 KB cap per file before we skip hashing
47
+
48
+ EXCLUDED_DIR_NAMES = {
49
+ ".git",
50
+ ".hg",
51
+ ".svn",
52
+ "node_modules",
53
+ "vendor",
54
+ "__pycache__",
55
+ ".venv",
56
+ "venv",
57
+ ".tox",
58
+ "dist",
59
+ "build",
60
+ "target",
61
+ ".next",
62
+ ".nuxt",
63
+ ".cache",
64
+ ".pytest_cache",
65
+ ".mypy_cache",
66
+ ".ruff_cache",
67
+ ".gradle",
68
+ ".idea",
69
+ ".vscode",
70
+ "archon",
71
+ }
72
+
73
+ EXCLUDED_DIR_PREFIXES = (".archon-merge-staging-", "bak-archon-")
74
+
75
+ # Hashed only — extensions are intentionally broad. If a file has no
76
+ # extension we still hash it as long as it's not obviously a binary blob
77
+ # (we sniff the first chunk for null bytes).
78
+ TEXT_HINT_EXTENSIONS = {
79
+ # source
80
+ ".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs",
81
+ ".py", ".rb", ".go", ".rs", ".java", ".kt", ".scala",
82
+ ".c", ".cc", ".cpp", ".h", ".hpp", ".m", ".mm",
83
+ ".cs", ".fs", ".vb", ".swift", ".dart",
84
+ ".php", ".pl", ".pm", ".lua", ".r", ".jl", ".ex", ".exs",
85
+ ".erl", ".hrl", ".clj", ".cljs", ".elm", ".purs",
86
+ ".sh", ".bash", ".zsh", ".fish", ".ps1", ".bat", ".cmd",
87
+ ".sql", ".graphql", ".gql", ".proto", ".thrift", ".avsc",
88
+ # config / infra
89
+ ".json", ".yaml", ".yml", ".toml", ".ini", ".env", ".conf",
90
+ ".tf", ".hcl", ".tfvars", ".dockerfile",
91
+ # docs
92
+ ".md", ".mdx", ".rst", ".txt",
93
+ }
94
+
95
+
96
+ def is_excluded_dir(name: str) -> bool:
97
+ if name in EXCLUDED_DIR_NAMES:
98
+ return True
99
+ return any(name.startswith(p) for p in EXCLUDED_DIR_PREFIXES)
100
+
101
+
102
+ def looks_like_text(path: Path, sniff_bytes: int = 4096) -> bool:
103
+ """Cheap binary sniff. We hash anything that has a text-y extension or
104
+ that doesn't trip the null-byte heuristic in its first chunk."""
105
+ if path.suffix.lower() in TEXT_HINT_EXTENSIONS:
106
+ return True
107
+ # No extension or unfamiliar extension — sniff content.
108
+ try:
109
+ with path.open("rb") as f:
110
+ chunk = f.read(sniff_bytes)
111
+ except OSError:
112
+ return False
113
+ if not chunk:
114
+ return True # empty file is fine
115
+ return b"\x00" not in chunk
116
+
117
+
118
+ def hash_file(path: Path) -> str:
119
+ h = hashlib.sha256()
120
+ with path.open("rb") as f:
121
+ for buf in iter(lambda: f.read(64 * 1024), b""):
122
+ h.update(buf)
123
+ return h.hexdigest()
124
+
125
+
126
+ def walk_target(target: Path) -> list[Path]:
127
+ out: list[Path] = []
128
+ target = target.resolve()
129
+ for root, dirs, files in os.walk(target):
130
+ # Prune in place — modifying `dirs` skips them entirely.
131
+ dirs[:] = [d for d in dirs if not is_excluded_dir(d)]
132
+ root_path = Path(root)
133
+ for name in files:
134
+ full = root_path / name
135
+ if not full.is_file():
136
+ continue
137
+ try:
138
+ if full.is_symlink():
139
+ continue
140
+ except OSError:
141
+ continue
142
+ out.append(full)
143
+ return sorted(out)
144
+
145
+
146
+ def load_prior(state_path: Path) -> dict:
147
+ if not state_path.is_file():
148
+ return {"audits": [], "files": {}}
149
+ try:
150
+ return json.loads(state_path.read_text())
151
+ except (OSError, json.JSONDecodeError):
152
+ return {"audits": [], "files": {}}
153
+
154
+
155
+ def detect_audit_id(archon_dir: Path) -> Optional[tuple[str, list[int]]]:
156
+ """Pull the most recent audit's id + phase keys from audit-state.json.
157
+ Returns (audit_id, phase_numbers) or None if the file is unreadable.
158
+ """
159
+ audit_state = archon_dir / "audit-state.json"
160
+ if not audit_state.is_file():
161
+ return None
162
+ try:
163
+ data = json.loads(audit_state.read_text())
164
+ except (OSError, json.JSONDecodeError):
165
+ return None
166
+ audits = data.get("audits") or []
167
+ if not audits:
168
+ return None
169
+ last = audits[-1]
170
+ audit_id = (last.get("audit_id") or "").strip()
171
+ if not audit_id:
172
+ return None
173
+ phase_map = last.get("phases") or {}
174
+ phases: list[int] = []
175
+ for key in phase_map.keys():
176
+ try:
177
+ phases.append(int(key))
178
+ except (TypeError, ValueError):
179
+ continue
180
+ phases.sort()
181
+ return audit_id, phases
182
+
183
+
184
+ def stamp(
185
+ target: Path,
186
+ archon_dir: Path,
187
+ audit_id: str,
188
+ phases: list[int],
189
+ max_bytes: int = DEFAULT_MAX_BYTES,
190
+ ) -> dict:
191
+ state_path = archon_dir / "file-state.json"
192
+ state = load_prior(state_path)
193
+ files: dict = state.get("files") or {}
194
+ audits_seen: list = state.get("audits") or []
195
+
196
+ target = target.resolve()
197
+ paths = walk_target(target)
198
+ seen_rel: set[str] = set()
199
+
200
+ for full in paths:
201
+ try:
202
+ rel = str(full.relative_to(target))
203
+ except ValueError:
204
+ continue
205
+ seen_rel.add(rel)
206
+
207
+ try:
208
+ stat = full.stat()
209
+ except OSError:
210
+ continue
211
+
212
+ prior = files.get(rel) or {}
213
+ large = stat.st_size > max_bytes
214
+ text = looks_like_text(full) if not large else False
215
+
216
+ record: dict = {
217
+ "size": stat.st_size,
218
+ "last_audit_id": audit_id,
219
+ }
220
+ prior_audits = list(prior.get("last_audits") or [])
221
+ if audit_id not in prior_audits:
222
+ prior_audits.append(audit_id)
223
+ record["last_audits"] = prior_audits[-10:] # cap history per file
224
+
225
+ prior_phases = list(prior.get("last_phases") or [])
226
+ merged_phases = sorted(set(prior_phases) | set(phases))
227
+ record["last_phases"] = merged_phases
228
+
229
+ if large:
230
+ record["large_file"] = True
231
+ # Preserve any prior hash so a follow-up tool can still detect
232
+ # truncation back below the cap.
233
+ if "hash" in prior:
234
+ record["hash"] = prior["hash"]
235
+ elif not text:
236
+ record["binary"] = True
237
+ if "hash" in prior:
238
+ record["hash"] = prior["hash"]
239
+ else:
240
+ try:
241
+ record["hash"] = hash_file(full)
242
+ except OSError as exc:
243
+ record["hash_error"] = str(exc)
244
+
245
+ files[rel] = record
246
+
247
+ # Mark deleted files (present in prior state, missing from this walk).
248
+ for rel, prior in list(files.items()):
249
+ if rel in seen_rel:
250
+ continue
251
+ prior["deleted_in_audit"] = audit_id
252
+ files[rel] = prior
253
+
254
+ if audit_id not in audits_seen:
255
+ audits_seen.append(audit_id)
256
+
257
+ state.update(
258
+ {
259
+ "schema_version": 1,
260
+ "audit_id": audit_id,
261
+ "audits": audits_seen[-25:],
262
+ "stamped_at": datetime.now(timezone.utc).isoformat(),
263
+ "target": str(target),
264
+ "files": files,
265
+ }
266
+ )
267
+
268
+ state_path.parent.mkdir(parents=True, exist_ok=True)
269
+ state_path.write_text(json.dumps(state, indent=2, sort_keys=True) + "\n")
270
+
271
+ counts = {
272
+ "tracked": len(files),
273
+ "with_hash": sum(1 for r in files.values() if r.get("hash")),
274
+ "large_skipped": sum(1 for r in files.values() if r.get("large_file")),
275
+ "binary_skipped": sum(1 for r in files.values() if r.get("binary")),
276
+ "deleted": sum(1 for r in files.values() if r.get("deleted_in_audit")),
277
+ }
278
+ return counts
279
+
280
+
281
+ def parse_phases_arg(raw: str) -> list[int]:
282
+ if not raw:
283
+ return []
284
+ out: list[int] = []
285
+ for piece in raw.split(","):
286
+ piece = piece.strip()
287
+ if not piece:
288
+ continue
289
+ try:
290
+ out.append(int(piece))
291
+ except ValueError:
292
+ print(f"warning: ignoring non-integer phase {piece!r}", file=sys.stderr)
293
+ return sorted(set(out))
294
+
295
+
296
+ def main() -> None:
297
+ parser = argparse.ArgumentParser(description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter)
298
+ parser.add_argument("--target", default=".", help="Target repository path (default: cwd)")
299
+ parser.add_argument("--archon-dir", default=None, help="Archon data dir (default: <target>/archon)")
300
+ parser.add_argument("--audit-id", default=None, help="Override the audit id to stamp (default: read from audit-state.json)")
301
+ parser.add_argument("--phases", default=None, help="Comma-separated phase numbers to mark on each file (default: all phases from current audit)")
302
+ parser.add_argument("--max-bytes", type=int, default=DEFAULT_MAX_BYTES, help="Skip hashing for files larger than this many bytes")
303
+ args = parser.parse_args()
304
+
305
+ target = Path(args.target).resolve()
306
+ if not target.is_dir():
307
+ print(f"error: target is not a directory: {target}", file=sys.stderr)
308
+ sys.exit(2)
309
+
310
+ archon_dir = Path(args.archon_dir) if args.archon_dir else target / "archon"
311
+ archon_dir.mkdir(parents=True, exist_ok=True)
312
+
313
+ audit_id = args.audit_id
314
+ phases: list[int] = parse_phases_arg(args.phases or "")
315
+
316
+ if not audit_id or not phases:
317
+ detected = detect_audit_id(archon_dir)
318
+ if detected is None and not audit_id:
319
+ print(
320
+ "error: no audit_id provided and audit-state.json is unreadable",
321
+ file=sys.stderr,
322
+ )
323
+ sys.exit(1)
324
+ if detected is not None:
325
+ det_id, det_phases = detected
326
+ if not audit_id:
327
+ audit_id = det_id
328
+ if not phases:
329
+ phases = det_phases
330
+
331
+ try:
332
+ counts = stamp(target, archon_dir, audit_id, phases, max_bytes=args.max_bytes)
333
+ except OSError as exc:
334
+ print(f"error: I/O failure during stamp: {exc}", file=sys.stderr)
335
+ sys.exit(3)
336
+
337
+ state_path = archon_dir / "file-state.json"
338
+ print(
339
+ f"file-state stamped at {state_path}: "
340
+ f"{counts['tracked']} tracked "
341
+ f"({counts['with_hash']} hashed, "
342
+ f"{counts['large_skipped']} large-skipped, "
343
+ f"{counts['binary_skipped']} binary-skipped, "
344
+ f"{counts['deleted']} marked deleted)"
345
+ )
346
+
347
+
348
+ if __name__ == "__main__":
349
+ main()
@@ -0,0 +1,65 @@
1
+ ---
2
+ name: code-reviewer
3
+ description:
4
+ Use this skill to review code. It supports both local changes (staged or working tree)
5
+ and remote Pull Requests (by ID or URL). It focuses on correctness, maintainability,
6
+ and adherence to project standards.
7
+ ---
8
+
9
+ # Code Reviewer
10
+
11
+ This skill guides the agent in conducting professional and thorough code reviews for both local development and remote Pull Requests.
12
+
13
+ ## Workflow
14
+
15
+ ### 1. Determine Review Target
16
+ * **Remote PR**: If the user provides a PR number or URL (e.g., "Review PR #123"), target that remote PR.
17
+ * **Local Changes**: If no specific PR is mentioned, or if the user asks to "review my changes", target the current local file system states (staged and unstaged changes).
18
+
19
+ ### 2. Preparation
20
+
21
+ #### For Remote PRs:
22
+ 1. **Checkout**: Use the GitHub CLI to checkout the PR.
23
+ ```bash
24
+ gh pr checkout <PR_NUMBER>
25
+ ```
26
+ 2. **Preflight**: Execute the project's standard verification suite to catch automated failures early.
27
+ ```bash
28
+ npm run preflight
29
+ ```
30
+ 3. **Context**: Read the PR description and any existing comments to understand the goal and history.
31
+
32
+ #### For Local Changes:
33
+ 1. **Identify Changes**:
34
+ * Check status: `git status`
35
+ * Read diffs: `git diff` (working tree) and/or `git diff --staged` (staged).
36
+ 2. **Preflight (Optional)**: If the changes are substantial, ask the user if they want to run `npm run preflight` before reviewing.
37
+
38
+ ### 3. In-Depth Analysis
39
+ Analyze the code changes based on the following pillars:
40
+
41
+ * **Correctness**: Does the code achieve its stated purpose without bugs or logical errors?
42
+ * **Maintainability**: Is the code clean, well-structured, and easy to understand and modify in the future? Consider factors like code clarity, modularity, and adherence to established design patterns.
43
+ * **Readability**: Is the code well-commented (where necessary) and consistently formatted according to our project's coding style guidelines?
44
+ * **Efficiency**: Are there any obvious performance bottlenecks or resource inefficiencies introduced by the changes?
45
+ * **Security**: Are there any potential security vulnerabilities or insecure coding practices?
46
+ * **Edge Cases and Error Handling**: Does the code appropriately handle edge cases and potential errors?
47
+ * **Testability**: Is the new or modified code adequately covered by tests (even if preflight checks pass)? Suggest additional test cases that would improve coverage or robustness.
48
+
49
+ ### 4. Provide Feedback
50
+
51
+ #### Structure
52
+ * **Summary**: A high-level overview of the review.
53
+ * **Findings**:
54
+ * **Critical**: Bugs, security issues, or breaking changes.
55
+ * **Improvements**: Suggestions for better code quality or performance.
56
+ * **Nitpicks**: Formatting or minor style issues (optional).
57
+ * **Conclusion**: Clear recommendation (Approved / Request Changes).
58
+
59
+ #### Tone
60
+ * Be constructive, professional, and friendly.
61
+ * Explain *why* a change is requested.
62
+ * For approvals, acknowledge the specific value of the contribution.
63
+
64
+ ### 5. Cleanup (Remote PRs only)
65
+ * After the review, ask the user if they want to switch back to the default branch (e.g., `main` or `master`).