@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,108 @@
1
+ ---
2
+ name: variant-scanner
3
+ tools: Glob, Grep, Read, Bash, Agent
4
+ model: sonnet
5
+ color: green
6
+ permissionMode: bypassPermissions
7
+ effort: low
8
+ description: Phase 12 per-finding variant analysis agent that takes a confirmed vulnerability and searches for structural variants using the attack pattern registry's detection signatures, CodeQL on-demand queries, DFD/CFD slice analysis including Phase 10 Addendum discoveries, and chamber variant candidates
9
+ ---
10
+
11
+ You are a variant hunter for Phase 12 of a security audit. You receive a single confirmed finding and search the entire codebase for structural variants — the same vulnerability pattern in different locations.
12
+
13
+ ## Inputs
14
+
15
+ You receive:
16
+ - **Finding path**: `archon/findings-draft/<phase>-<NNN>-<slug>.md`
17
+ - **NNN range**: your assigned finding ID range for variant drafts
18
+ - **KB path**: `archon/attack-surface/knowledge-base-report.md`
19
+
20
+ ## Context Loading
21
+
22
+ 1. Read the finding draft to understand the root cause and code pattern
23
+ 2. Read `archon/attack-pattern-registry.json` — find the matching pattern entry
24
+ 3. Read `## Phase 10 Addendum` in the KB — new attack surfaces discovered during chamber debates
25
+ 4. Check `archon/chamber-workspace/*/variant-candidates/` for pre-identified candidates
26
+ 5. Read `archon/codeql-artifacts/entry-points.json` and `sinks.json` for structurally similar
27
+ entry/sink combinations
28
+
29
+ ## Variant Search Strategy
30
+
31
+ ### 1. Registry-Driven Search
32
+ If the attack pattern registry has a `detection_signature` for this pattern:
33
+ - Run the CodeQL query against `archon/codeql-artifacts/db/`
34
+ - Run the Semgrep rule against the codebase
35
+ - Run the grep pattern across the codebase
36
+ - Each match is a variant candidate
37
+
38
+ ### 2. AST-Level Structural Search
39
+ Write and run a CodeQL query that searches for the same AST-level structure:
40
+ ```bash
41
+ codeql query run \
42
+ --database=archon/codeql-artifacts/db/ \
43
+ --output=archon/tmp/variant.bqrs \
44
+ -- archon/codeql-queries/variant-<slug>.ql
45
+ codeql bqrs decode --format=json archon/tmp/variant.bqrs
46
+ ```
47
+
48
+ ### 3. Flow Shape Search
49
+ Look for the same flow shape (source type -> transformation pattern -> sink type) in:
50
+ - Sibling components sharing the same framework
51
+ - Alternate transports (HTTP, WebSocket, gRPC, CLI)
52
+ - Background job consumers processing the same data
53
+
54
+ ### 4. Phase 10 Addendum Targets
55
+ Read the `## Phase 10 Addendum` for newly discovered attack surfaces. Check if the confirmed
56
+ finding's pattern appears on any of these new surfaces.
57
+
58
+ ### 5. Chamber Variant Candidates
59
+ Check `archon/chamber-workspace/*/variant-candidates/` for pre-identified candidates
60
+ matching this finding's root cause.
61
+
62
+ ## Variant Validation
63
+
64
+ For each candidate variant:
65
+ 1. Confirm the same root cause is present (not just syntactic similarity)
66
+ 2. Confirm attacker-controlled input reaches the variant location
67
+ 3. Confirm no blocking protection exists that was absent in the original
68
+ 4. Assign severity (start at MEDIUM; upgrade to HIGH for remote + trust boundary + no preconditions; CRITICAL for RCE/auth bypass + unauthenticated + internet-facing)
69
+
70
+ Only retain variants rated **Medium or higher**.
71
+
72
+ ## Output
73
+
74
+ Write each confirmed variant to `archon/findings-draft/p12-<NNN>-<slug>.md` using this template:
75
+
76
+ ```
77
+ Phase: 10
78
+ Sequence: NNN
79
+ Slug: <slug>
80
+ Verdict: VALID
81
+ Rationale: <one-sentence>
82
+ Severity-Original: <MEDIUM|HIGH|CRITICAL>
83
+ PoC-Status: pending
84
+ Origin-Finding: <path to original finding>
85
+ Origin-Pattern: <attack pattern registry ID>
86
+
87
+ ## Summary
88
+ ## Location
89
+ ## Attacker Control
90
+ ## Trust Boundary Crossed
91
+ ## Impact
92
+ ## Evidence
93
+ ## Reproduction Steps
94
+ ```
95
+
96
+ Fields:
97
+ - `Phase: 10`
98
+ - `Verdict: VALID`
99
+ - Reference the original finding as the pattern source
100
+ - Include code path evidence
101
+
102
+ Update `archon/attack-pattern-registry.json` — append each confirmed variant to
103
+ the pattern's `confirmed_instances`.
104
+
105
+ ## Completion
106
+
107
+ When all search strategies are exhausted, report to the orchestrator:
108
+ "Variant analysis complete for <finding-slug>. Variants found: <count>."
@@ -0,0 +1,110 @@
1
+ ---
2
+ name: variant-spotter
3
+ tools: Glob, Grep, Read, Bash
4
+ model: sonnet
5
+ color: cyan
6
+ permissionMode: bypassPermissions
7
+ effort: low
8
+ background: true
9
+ description: Phase 10 Review Chamber concurrent variant hunter that monitors debate transcripts for confirmed vulnerability patterns and immediately searches for structural variants in sibling components, alternate transports, and adjacent enforcement paths, front-loading Phase 12 variant analysis while chamber context is hot
10
+ ---
11
+
12
+ You are a concurrent variant hunter operating alongside a Review Chamber debate. While the chamber debates specific hypotheses, you search for the same vulnerability patterns elsewhere in the codebase. Your work front-loads Phase 12 variant analysis.
13
+
14
+ ## Your Chamber Assignment
15
+
16
+ Read the chamber's `debate.md` to understand:
17
+ - Which threat cluster the chamber is investigating
18
+ - Confirmed findings (look for `Verdict: VALID` entries in Synthesis rounds)
19
+
20
+ ## Monitoring Protocol
21
+
22
+ 1. Read `archon/chamber-workspace/<chamber-id>/debate.md` after each round marker appears (`## Round N`). When a `Status: CLOSED` header is found, stop monitoring and report completion.
23
+ 2. When a hypothesis receives `Verdict: VALID`, extract:
24
+ - The root cause pattern (e.g., "ObjectInputStream.readObject() without filter")
25
+ - The affected code location
26
+ - The detection approach used by the Tracer
27
+ 3. Also read `archon/attack-pattern-registry.json` for patterns from other chambers
28
+
29
+ ## Variant Search Strategy
30
+
31
+ For each confirmed pattern:
32
+
33
+ ### 1. Grep-Based Discovery
34
+ Search the entire codebase for the same code pattern:
35
+ ```bash
36
+ # Example: find all ObjectInputStream.readObject() calls
37
+ grep -rn "ObjectInputStream.*readObject" --include="*.java" .
38
+ ```
39
+
40
+ ### 2. CodeQL Structural Search
41
+ If a detection signature exists in the attack pattern registry, run it:
42
+ ```bash
43
+ codeql query run \
44
+ --database=archon/codeql-artifacts/db/ \
45
+ --output=archon/tmp/variant-search.bqrs \
46
+ -- archon/codeql-queries/on-demand-variant-<slug>.ql
47
+ codeql bqrs decode --format=json archon/tmp/variant-search.bqrs
48
+ ```
49
+
50
+ ### 3. Sibling Component Check
51
+ If the confirmed finding is in component A, check components B, C, D that share the same:
52
+ - Trust boundary
53
+ - Data flow pattern
54
+ - Framework usage
55
+ - Dependency
56
+
57
+ ### 4. Alternate Transport Check
58
+ If the confirmed finding is via HTTP, check the same logic via:
59
+ - WebSocket
60
+ - gRPC
61
+ - GraphQL
62
+ - CLI interface
63
+ - Background job/queue consumer
64
+
65
+ ## Output
66
+
67
+ Write each variant candidate to its own file:
68
+
69
+ ```
70
+ archon/chamber-workspace/<chamber-id>/variant-candidates/<slug>.md
71
+ ```
72
+
73
+ Format:
74
+
75
+ ```markdown
76
+ # Variant Candidate: <title>
77
+
78
+ Origin-Finding: <finding draft path of the original confirmed vulnerability>
79
+ Origin-Pattern: <attack pattern registry ID if exists>
80
+
81
+ ## Location
82
+ File: <path>
83
+ Function: <name>
84
+ Line: <number>
85
+
86
+ ## Similarity
87
+ - Same root cause: <yes/no, explanation>
88
+ - Same code pattern: <yes/no, grep evidence>
89
+ - Same trust boundary: <yes/no>
90
+ - Same attacker-reachable: <unknown — needs Tracer verification>
91
+
92
+ ## Quick Assessment
93
+ <Brief assessment of whether this looks like a real variant or a false match.
94
+ Note: this is a preliminary assessment, NOT a verdict. The Synthesizer or Phase 12
95
+ will make the final determination.>
96
+ ```
97
+
98
+ ## Scope Rules
99
+
100
+ - Search the ENTIRE codebase, not just the chamber's assigned DFD slices
101
+ - Do NOT participate in the debate — you read transcripts but never write to debate.md
102
+ - Do NOT issue verdicts on variants — write candidates for the Synthesizer to evaluate
103
+ - Prioritize patterns confirmed at HIGH or CRITICAL severity
104
+ - Skip patterns where the detection signature has already been run by SAST (Phase 4 coverage)
105
+
106
+ ## Handoff to Phase 12
107
+
108
+ Variant candidates not processed by the Synthesizer before chamber closure are preserved in
109
+ `archon/chamber-workspace/<chamber-id>/variant-candidates/` for Phase 12 variant analysis
110
+ to consume as its starting target list.
@@ -0,0 +1,376 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { spawnSync } from "node:child_process";
4
+ import {
5
+ chmodSync,
6
+ copyFileSync,
7
+ existsSync,
8
+ mkdirSync,
9
+ readFileSync,
10
+ rmSync,
11
+ statSync,
12
+ writeFileSync,
13
+ } from "node:fs";
14
+ import { homedir } from "node:os";
15
+ import { dirname, isAbsolute, join, resolve } from "node:path";
16
+ import { fileURLToPath } from "node:url";
17
+
18
+ const DEFAULT_PROVIDER = "openai-codex";
19
+ const DEFAULT_MODEL = "gpt-5.5";
20
+ const DEFAULT_THINKING_LEVEL = "high";
21
+ const DEFAULT_THEME = "piolium-srcery";
22
+
23
+ const PACKAGE_DIR = resolve(dirname(fileURLToPath(import.meta.url)), "..");
24
+
25
+ function main(argv) {
26
+ const paths = resolvePaths();
27
+ const [command, ...rest] = argv;
28
+
29
+ if (command === "--help" || command === "-h") {
30
+ printHelp();
31
+ return 0;
32
+ }
33
+ if (command === "doctor") {
34
+ bootstrapConfig(paths, { syncEmptyAuth: true });
35
+ return runDoctor(paths);
36
+ }
37
+ if (command === "auth") {
38
+ bootstrapConfig(paths);
39
+ return runAuthCommand(paths, rest);
40
+ }
41
+ if (command === "reset-auth") {
42
+ bootstrapConfig(paths, { createAuth: false });
43
+ return resetAuth(paths);
44
+ }
45
+ if (command === "login") {
46
+ bootstrapConfig(paths);
47
+ return runPi(["/login", ...rest], paths);
48
+ }
49
+
50
+ bootstrapConfig(paths, { syncEmptyAuth: true });
51
+ return runPi(command === "--" ? rest : argv, paths);
52
+ }
53
+
54
+ function resolvePaths() {
55
+ const homeDir = expandHome(process.env.PIOLIUM_HOME || join(homedir(), ".piolium"));
56
+ const packageDir = resolve(expandHome(process.env.PIOLIUM_PACKAGE_DIR || PACKAGE_DIR));
57
+ const agentDir = resolve(expandHome(process.env.PIOLIUM_AGENT_DIR || join(homeDir, "agent")));
58
+ const sessionDir = resolve(
59
+ expandHome(process.env.PIOLIUM_SESSION_DIR || join(agentDir, "session")),
60
+ );
61
+ const sourcePiAgentDir = resolve(
62
+ expandHome(process.env.PIOLIUM_SOURCE_PI_AGENT_DIR || join(homedir(), ".pi", "agent")),
63
+ );
64
+ return {
65
+ homeDir,
66
+ packageDir,
67
+ agentDir,
68
+ sessionDir,
69
+ settingsPath: join(agentDir, "settings.json"),
70
+ authPath: join(agentDir, "auth.json"),
71
+ sourcePiSettingsPath: join(sourcePiAgentDir, "settings.json"),
72
+ sourcePiAuthPath: join(sourcePiAgentDir, "auth.json"),
73
+ };
74
+ }
75
+
76
+ function expandHome(value) {
77
+ if (value === "~") return homedir();
78
+ if (value.startsWith("~/")) return join(homedir(), value.slice(2));
79
+ return value;
80
+ }
81
+
82
+ function bootstrapConfig(paths, options = {}) {
83
+ const { createAuth = true, syncEmptyAuth = false } = options;
84
+ mkdirSync(paths.agentDir, { recursive: true });
85
+ mkdirSync(paths.sessionDir, { recursive: true });
86
+ ensureSettings(paths);
87
+ if (createAuth) ensureEmptyAuth(paths);
88
+ if (syncEmptyAuth) syncEmptyAuthFromPi(paths);
89
+ }
90
+
91
+ function ensureSettings(paths) {
92
+ const current = readJsonObject(paths.settingsPath, { strict: true }) || {};
93
+ const source = readJsonObject(paths.sourcePiSettingsPath) || {};
94
+ const next = { ...current };
95
+ const packages = Array.isArray(next.packages) ? [...next.packages] : [];
96
+ if (
97
+ !packages.some((entry) =>
98
+ packageEntryMatches(entry, paths.packageDir, dirname(paths.settingsPath)),
99
+ )
100
+ ) {
101
+ packages.unshift(paths.packageDir);
102
+ next.packages = packages;
103
+ }
104
+ for (const key of ["defaultProvider", "defaultModel", "defaultThinkingLevel", "theme"]) {
105
+ if (next[key] !== undefined) continue;
106
+ if (source[key] !== undefined) next[key] = source[key];
107
+ }
108
+ next.defaultProvider ??= DEFAULT_PROVIDER;
109
+ next.defaultModel ??= DEFAULT_MODEL;
110
+ next.defaultThinkingLevel ??= DEFAULT_THINKING_LEVEL;
111
+ next.theme ??= DEFAULT_THEME;
112
+ next.sessionDir ??= paths.sessionDir;
113
+ writeJsonObjectIfChanged(paths.settingsPath, current, next, 0o600);
114
+ }
115
+
116
+ function packageEntryMatches(entry, packageDir, baseDir) {
117
+ const value = typeof entry === "string" ? entry : entry?.source;
118
+ if (typeof value !== "string") return false;
119
+ const resolved = isAbsolute(expandHome(value))
120
+ ? resolve(expandHome(value))
121
+ : resolve(baseDir, expandHome(value));
122
+ return resolved === packageDir;
123
+ }
124
+
125
+ function ensureEmptyAuth(paths) {
126
+ if (existsSync(paths.authPath)) return;
127
+ writeFileSync(paths.authPath, "{}\n", "utf8");
128
+ chmodIfPossible(paths.authPath, 0o600);
129
+ }
130
+
131
+ function syncEmptyAuthFromPi(paths) {
132
+ if (!isEmptyAuthFile(paths.authPath) || !existsSync(paths.sourcePiAuthPath)) return;
133
+ if (isEmptyAuthFile(paths.sourcePiAuthPath)) return;
134
+ console.warn(
135
+ `[piolium] warning: ${paths.authPath} is empty; syncing auth from ${paths.sourcePiAuthPath}.`,
136
+ );
137
+ copyAuthFile(paths.sourcePiAuthPath, paths.authPath, "Synced");
138
+ }
139
+
140
+ function runAuthCommand(paths, args) {
141
+ const [command, ...rest] = args;
142
+ if (command === "import") return importAuth(paths, rest);
143
+ if (command === "sync") return syncAuth(paths, rest);
144
+ if (command === "path") {
145
+ console.log(paths.authPath);
146
+ return 0;
147
+ }
148
+ console.error(
149
+ "Usage: piolium auth sync | piolium auth import [--force] [--from <auth.json>] | piolium auth path",
150
+ );
151
+ return 2;
152
+ }
153
+
154
+ function importAuth(paths, args) {
155
+ let sourcePath = paths.sourcePiAuthPath;
156
+ let force = false;
157
+ for (let i = 0; i < args.length; i++) {
158
+ const arg = args[i];
159
+ if (arg === "--force") {
160
+ force = true;
161
+ } else if (arg === "--from" && args[i + 1]) {
162
+ sourcePath = resolve(expandHome(args[++i]));
163
+ } else if (arg?.startsWith("--from=")) {
164
+ sourcePath = resolve(expandHome(arg.slice("--from=".length)));
165
+ } else {
166
+ console.error(`Unknown auth import argument: ${arg}`);
167
+ return 2;
168
+ }
169
+ }
170
+ if (!existsSync(sourcePath)) {
171
+ console.error(`No source auth file found at ${sourcePath}`);
172
+ return 1;
173
+ }
174
+ const targetExists = existsSync(paths.authPath);
175
+ if (targetExists && !force && !isEmptyAuthFile(paths.authPath)) {
176
+ console.error(
177
+ `${paths.authPath} already contains credentials. Re-run with --force to replace it.`,
178
+ );
179
+ return 1;
180
+ }
181
+ mkdirSync(dirname(paths.authPath), { recursive: true });
182
+ copyFileSync(sourcePath, paths.authPath);
183
+ chmodIfPossible(paths.authPath, 0o600);
184
+ console.log(`Imported auth into ${paths.authPath}`);
185
+ return 0;
186
+ }
187
+
188
+ function syncAuth(paths, args) {
189
+ if (args.length > 0) {
190
+ console.error("Usage: piolium auth sync");
191
+ return 2;
192
+ }
193
+ return copyAuthFile(paths.sourcePiAuthPath, paths.authPath, "Synced");
194
+ }
195
+
196
+ function copyAuthFile(sourcePath, targetPath, verb) {
197
+ if (!existsSync(sourcePath)) {
198
+ console.error(`No source auth file found at ${sourcePath}`);
199
+ return 1;
200
+ }
201
+ if (resolve(sourcePath) === resolve(targetPath)) {
202
+ console.log(`Auth already points at ${targetPath}`);
203
+ return 0;
204
+ }
205
+ mkdirSync(dirname(targetPath), { recursive: true });
206
+ copyFileSync(sourcePath, targetPath);
207
+ chmodIfPossible(targetPath, 0o600);
208
+ console.log(`${verb} auth from ${sourcePath} into ${targetPath}`);
209
+ return 0;
210
+ }
211
+
212
+ function resetAuth(paths) {
213
+ if (existsSync(paths.authPath)) rmSync(paths.authPath, { force: true });
214
+ ensureEmptyAuth(paths);
215
+ console.log(`Reset auth at ${paths.authPath}`);
216
+ return 0;
217
+ }
218
+
219
+ function runDoctor(paths) {
220
+ const piPath = resolveCommand(process.env.PIOLIUM_PI_BIN || "pi");
221
+ const authState = authStatus(paths.authPath);
222
+ const settings = readJsonObject(paths.settingsPath);
223
+ const hasPackage =
224
+ !!settings &&
225
+ Array.isArray(settings.packages) &&
226
+ settings.packages.some((entry) =>
227
+ packageEntryMatches(entry, paths.packageDir, dirname(paths.settingsPath)),
228
+ );
229
+
230
+ console.log("Piolium standalone");
231
+ console.log(` home: ${paths.homeDir}`);
232
+ console.log(
233
+ ` package: ${existsSync(paths.packageDir) ? "ok" : "missing"} ${paths.packageDir}`,
234
+ );
235
+ console.log(` agent: ${paths.agentDir}`);
236
+ console.log(` sessions: ${paths.sessionDir}`);
237
+ console.log(` settings: ${hasPackage ? "ok" : "missing package entry"} ${paths.settingsPath}`);
238
+ console.log(` auth: ${authState} ${paths.authPath}`);
239
+ console.log(` pi: ${piPath || "not found"}`);
240
+ if (!piPath) return 1;
241
+ return existsSync(paths.packageDir) && hasPackage ? 0 : 1;
242
+ }
243
+
244
+ function runPi(args, paths) {
245
+ const piCommand = process.env.PIOLIUM_PI_BIN || "pi";
246
+ const finalArgs = hasSessionDirArg(args) ? args : ["--session-dir", paths.sessionDir, ...args];
247
+ const consoleStream = defaultConsoleStreamEnv(finalArgs);
248
+ const result = spawnSync(piCommand, finalArgs, {
249
+ stdio: "inherit",
250
+ env: {
251
+ ...process.env,
252
+ PI_CODING_AGENT_DIR: paths.agentDir,
253
+ ...(consoleStream === undefined ? {} : { PIOLIUM_CONSOLE_STREAM: consoleStream }),
254
+ },
255
+ });
256
+ if (result.error) {
257
+ console.error(`Failed to run ${piCommand}: ${result.error.message}`);
258
+ return 1;
259
+ }
260
+ return result.status ?? 1;
261
+ }
262
+
263
+ function defaultConsoleStreamEnv(args) {
264
+ if (process.env.PIOLIUM_CONSOLE_STREAM !== undefined) return process.env.PIOLIUM_CONSOLE_STREAM;
265
+ return hasPioliumPrompt(args) ? "1" : undefined;
266
+ }
267
+
268
+ function hasPioliumPrompt(args) {
269
+ for (let i = 0; i < args.length; i++) {
270
+ const arg = args[i];
271
+ if ((arg === "-p" || arg === "--prompt") && args[i + 1]?.includes("/piolium-")) return true;
272
+ if ((arg.startsWith("-p=") || arg.startsWith("--prompt=")) && arg.includes("/piolium-")) {
273
+ return true;
274
+ }
275
+ }
276
+ return false;
277
+ }
278
+
279
+ function hasSessionDirArg(args) {
280
+ return args.some((arg) => arg === "--session-dir" || arg.startsWith("--session-dir="));
281
+ }
282
+
283
+ function readJsonObject(path, options = {}) {
284
+ if (!existsSync(path)) return undefined;
285
+ try {
286
+ const parsed = JSON.parse(readFileSync(path, "utf8"));
287
+ return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : undefined;
288
+ } catch (error) {
289
+ if (options.strict) {
290
+ const message = error instanceof Error ? error.message : String(error);
291
+ throw new Error(`Invalid JSON in ${path}: ${message}`);
292
+ }
293
+ return undefined;
294
+ }
295
+ }
296
+
297
+ function writeJsonObjectIfChanged(path, before, after, mode) {
298
+ const beforeText = JSON.stringify(before, null, 2);
299
+ const afterText = `${JSON.stringify(after, null, 2)}\n`;
300
+ if (existsSync(path) && `${beforeText}\n` === afterText) return;
301
+ mkdirSync(dirname(path), { recursive: true });
302
+ writeFileSync(path, afterText, "utf8");
303
+ chmodIfPossible(path, mode);
304
+ }
305
+
306
+ function isEmptyAuthFile(path) {
307
+ try {
308
+ const text = readFileSync(path, "utf8").trim();
309
+ return text === "" || text === "{}";
310
+ } catch {
311
+ return true;
312
+ }
313
+ }
314
+
315
+ function authStatus(path) {
316
+ if (!existsSync(path)) return "missing";
317
+ if (isEmptyAuthFile(path)) return "empty";
318
+ try {
319
+ const size = statSync(path).size;
320
+ return size > 0 ? "configured" : "empty";
321
+ } catch {
322
+ return "unknown";
323
+ }
324
+ }
325
+
326
+ function chmodIfPossible(path, mode) {
327
+ try {
328
+ chmodSync(path, mode);
329
+ } catch {
330
+ // Best effort only. Some filesystems ignore POSIX modes.
331
+ }
332
+ }
333
+
334
+ function resolveCommand(command) {
335
+ if (command.includes("/") && existsSync(command)) return command;
336
+ const result = spawnSync("sh", ["-c", `command -v "$1"`, "sh", command], {
337
+ encoding: "utf8",
338
+ });
339
+ return result.status === 0 ? result.stdout.trim() : undefined;
340
+ }
341
+
342
+ function printHelp() {
343
+ console.log(`piolium - isolated Pi launcher for Piolium
344
+
345
+ Usage:
346
+ piolium [pi args...]
347
+ piolium login
348
+ piolium doctor
349
+ piolium auth sync
350
+ piolium auth import [--force] [--from <auth.json>]
351
+ piolium auth path
352
+ piolium reset-auth
353
+
354
+ Environment:
355
+ PIOLIUM_HOME Default: ~/.piolium
356
+ PIOLIUM_PACKAGE_DIR Default: directory containing this package
357
+ PIOLIUM_AGENT_DIR Default: ~/.piolium/agent
358
+ PIOLIUM_SESSION_DIR Default: ~/.piolium/agent/session
359
+ PIOLIUM_SOURCE_PI_AGENT_DIR Default: ~/.pi/agent
360
+ PIOLIUM_PI_BIN Default: pi
361
+
362
+ Examples:
363
+ piolium
364
+ piolium -p "/piolium-balanced --fresh"
365
+ piolium auth sync
366
+ piolium auth import
367
+ `);
368
+ }
369
+
370
+ try {
371
+ const exitCode = main(process.argv.slice(2));
372
+ process.exit(exitCode);
373
+ } catch (error) {
374
+ console.error(error instanceof Error ? error.message : String(error));
375
+ process.exit(1);
376
+ }
@@ -0,0 +1,6 @@
1
+ // Hand-written shim for the bundled `yaml` package (extensions/piolium/_vendor/yaml.bundle.mjs).
2
+ // We only consume `parse` and `stringify`; everything else is intentionally
3
+ // omitted to keep the surface minimal.
4
+
5
+ export function parse(src: string, options?: unknown): unknown;
6
+ export function stringify(value: unknown, options?: { lineWidth?: number; [k: string]: unknown }): string;