mindforge-cc 11.8.2 → 11.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (361) hide show
  1. package/.agent/mindforge/wf-orchestrate-review.md +35 -0
  2. package/.agent/mindforge/wf-verification-loop.md +45 -0
  3. package/.agent/mindforge/wf-workflow-optimizer.md +51 -0
  4. package/.agent/skills/article-illustrator/SKILL.md +7 -7
  5. package/.agent/skills/arxiv/SKILL.md +6 -6
  6. package/.agent/skills/code-wiki/SKILL.md +11 -11
  7. package/.agent/skills/concept-diagrams/SKILL.md +6 -6
  8. package/.agent/skills/concept-diagrams/examples/apartment-floor-plan-conversion.md +244 -0
  9. package/.agent/skills/concept-diagrams/examples/automated-password-reset-flow.md +276 -0
  10. package/.agent/skills/concept-diagrams/examples/autonomous-llm-research-agent-flow.md +240 -0
  11. package/.agent/skills/concept-diagrams/examples/banana-journey-tree-to-smoothie.md +161 -0
  12. package/.agent/skills/concept-diagrams/examples/commercial-aircraft-structure.md +209 -0
  13. package/.agent/skills/concept-diagrams/examples/cpu-ooo-microarchitecture.md +236 -0
  14. package/.agent/skills/concept-diagrams/examples/electricity-grid-flow.md +182 -0
  15. package/.agent/skills/concept-diagrams/examples/feature-film-production-pipeline.md +172 -0
  16. package/.agent/skills/concept-diagrams/examples/hospital-emergency-department-flow.md +165 -0
  17. package/.agent/skills/concept-diagrams/examples/ml-benchmark-grouped-bar-chart.md +114 -0
  18. package/.agent/skills/concept-diagrams/examples/place-order-uml-sequence.md +325 -0
  19. package/.agent/skills/concept-diagrams/examples/smart-city-infrastructure.md +173 -0
  20. package/.agent/skills/concept-diagrams/examples/smartphone-layer-anatomy.md +154 -0
  21. package/.agent/skills/concept-diagrams/examples/sn2-reaction-mechanism.md +247 -0
  22. package/.agent/skills/concept-diagrams/examples/wind-turbine-structure.md +338 -0
  23. package/.agent/skills/concept-diagrams/templates/template.html +174 -0
  24. package/.agent/skills/domain-intel/SKILL.md +7 -7
  25. package/.agent/skills/duckduckgo-search/SKILL.md +17 -17
  26. package/.agent/skills/github-auth/scripts/gh-env.sh +66 -0
  27. package/.agent/skills/github-code-review/SKILL.md +9 -9
  28. package/.agent/skills/github-pr-workflow/SKILL.md +3 -3
  29. package/.agent/skills/godmode/SKILL.md +8 -8
  30. package/.agent/skills/jupyter-live-kernel/SKILL.md +3 -3
  31. package/.agent/skills/kanban-orchestrator/SKILL.md +10 -10
  32. package/.agent/skills/kanban-worker/SKILL.md +6 -6
  33. package/.agent/skills/llm-wiki/SKILL.md +7 -7
  34. package/.agent/skills/mindforge-autonomous/SKILL.md +1 -1
  35. package/.agent/skills/mindforge-complete-milestone/SKILL.md +1 -1
  36. package/.agent/skills/mindforge-discuss-phase/SKILL.md +1 -1
  37. package/.agent/skills/mindforge-do/SKILL.md +1 -1
  38. package/.agent/skills/mindforge-execute-phase/SKILL.md +1 -1
  39. package/.agent/skills/mindforge-list-workspaces/SKILL.md +1 -1
  40. package/.agent/skills/mindforge-manager/SKILL.md +1 -1
  41. package/.agent/skills/mindforge-neural-orchestrator/SKILL.md +1 -1
  42. package/.agent/skills/mindforge-new-milestone/SKILL.md +4 -4
  43. package/.agent/skills/mindforge-new-project/SKILL.md +4 -4
  44. package/.agent/skills/mindforge-new-workspace/SKILL.md +1 -1
  45. package/.agent/skills/mindforge-note/SKILL.md +1 -1
  46. package/.agent/skills/mindforge-plan-phase/SKILL.md +1 -1
  47. package/.agent/skills/mindforge-profile-user/SKILL.md +1 -1
  48. package/.agent/skills/mindforge-remove-workspace/SKILL.md +1 -1
  49. package/.agent/skills/mindforge-research-phase/SKILL.md +1 -1
  50. package/.agent/skills/mindforge-ui-phase/SKILL.md +1 -1
  51. package/.agent/skills/mindforge-ui-review/SKILL.md +1 -1
  52. package/.agent/skills/mindforge-verify-work/SKILL.md +1 -1
  53. package/.agent/skills/mindforge-workspace-isolated/SKILL.md +1 -1
  54. package/.agent/skills/node-inspect-debugger/SKILL.md +1 -1
  55. package/.agent/skills/obsidian/SKILL.md +15 -15
  56. package/.agent/skills/osint-investigation/SKILL.md +3 -2
  57. package/.agent/skills/osint-investigation/references/sources/courtlistener.md +98 -0
  58. package/.agent/skills/osint-investigation/references/sources/gdelt.md +104 -0
  59. package/.agent/skills/osint-investigation/references/sources/icij-offshore.md +104 -0
  60. package/.agent/skills/osint-investigation/references/sources/nyc-acris.md +90 -0
  61. package/.agent/skills/osint-investigation/references/sources/ofac-sdn.md +92 -0
  62. package/.agent/skills/osint-investigation/references/sources/opencorporates.md +103 -0
  63. package/.agent/skills/osint-investigation/references/sources/sec-edgar.md +83 -0
  64. package/.agent/skills/osint-investigation/references/sources/senate-ld.md +89 -0
  65. package/.agent/skills/osint-investigation/references/sources/usaspending.md +97 -0
  66. package/.agent/skills/osint-investigation/references/sources/wayback.md +93 -0
  67. package/.agent/skills/osint-investigation/references/sources/wikipedia.md +107 -0
  68. package/.agent/skills/osint-investigation/scripts/_http.py +82 -0
  69. package/.agent/skills/osint-investigation/scripts/_normalize.py +67 -0
  70. package/.agent/skills/osint-investigation/scripts/build_findings.py +221 -0
  71. package/.agent/skills/osint-investigation/scripts/entity_resolution.py +228 -0
  72. package/.agent/skills/osint-investigation/scripts/fetch_courtlistener.py +149 -0
  73. package/.agent/skills/osint-investigation/scripts/fetch_gdelt.py +161 -0
  74. package/.agent/skills/osint-investigation/scripts/fetch_icij_offshore.py +234 -0
  75. package/.agent/skills/osint-investigation/scripts/fetch_nyc_acris.py +203 -0
  76. package/.agent/skills/osint-investigation/scripts/fetch_ofac_sdn.py +175 -0
  77. package/.agent/skills/osint-investigation/scripts/fetch_opencorporates.py +191 -0
  78. package/.agent/skills/osint-investigation/scripts/fetch_sec_edgar.py +184 -0
  79. package/.agent/skills/osint-investigation/scripts/fetch_senate_ld.py +146 -0
  80. package/.agent/skills/osint-investigation/scripts/fetch_usaspending.py +170 -0
  81. package/.agent/skills/osint-investigation/scripts/fetch_wayback.py +142 -0
  82. package/.agent/skills/osint-investigation/scripts/fetch_wikipedia.py +266 -0
  83. package/.agent/skills/osint-investigation/scripts/timing_analysis.py +252 -0
  84. package/.agent/skills/oss-forensics/SKILL.md +10 -9
  85. package/.agent/skills/oss-forensics/scripts/evidence-store.py +313 -0
  86. package/.agent/skills/parallel-cli/SKILL.md +2 -2
  87. package/.agent/skills/pinggy-tunnel/SKILL.md +3 -3
  88. package/.agent/skills/pixel-art/SKILL.md +2 -2
  89. package/.agent/skills/plan/SKILL.md +10 -10
  90. package/.agent/skills/requesting-code-review/SKILL.md +4 -6
  91. package/.agent/skills/research-paper-writing/SKILL.md +32 -32
  92. package/.agent/skills/rest-graphql-debug/SKILL.md +31 -32
  93. package/.agent/skills/s6-container-supervision/SKILL.md +1 -1
  94. package/.agent/skills/scrapling/SKILL.md +1 -1
  95. package/.agent/skills/sherlock/SKILL.md +1 -1
  96. package/.agent/skills/simplify-code/SKILL.md +5 -7
  97. package/.agent/skills/skill-authoring/SKILL.md +4 -4
  98. package/.agent/skills/spike/SKILL.md +11 -13
  99. package/.agent/skills/subagent-driven-development/SKILL.md +7 -11
  100. package/.agent/skills/systematic-debugging/SKILL.md +13 -14
  101. package/.agent/skills/test-driven-development/SKILL.md +6 -7
  102. package/.agent/skills/video-orchestrator/SKILL.md +1 -1
  103. package/.agent/skills/web-pentest/SKILL.md +7 -7
  104. package/.mindforge/config.json +3 -2
  105. package/.mindforge/dynamic-workflows/REGISTRY.md +4 -1
  106. package/.mindforge/dynamic-workflows/index.json +910 -840
  107. package/.mindforge/dynamic-workflows/scripts/accessibility-audit.js +88 -90
  108. package/.mindforge/dynamic-workflows/scripts/ai-model-eval.js +59 -61
  109. package/.mindforge/dynamic-workflows/scripts/api-contract-test.js +87 -85
  110. package/.mindforge/dynamic-workflows/scripts/api-migration.js +120 -122
  111. package/.mindforge/dynamic-workflows/scripts/architecture-modernization.js +84 -86
  112. package/.mindforge/dynamic-workflows/scripts/code-audit.js +75 -77
  113. package/.mindforge/dynamic-workflows/scripts/code-explainer.js +99 -101
  114. package/.mindforge/dynamic-workflows/scripts/competitive-analysis.js +62 -64
  115. package/.mindforge/dynamic-workflows/scripts/competitive-teardown.js +106 -108
  116. package/.mindforge/dynamic-workflows/scripts/cost-analysis.js +78 -80
  117. package/.mindforge/dynamic-workflows/scripts/data-pipeline-validate.js +47 -49
  118. package/.mindforge/dynamic-workflows/scripts/database-migration.js +85 -87
  119. package/.mindforge/dynamic-workflows/scripts/debug-detective.js +97 -99
  120. package/.mindforge/dynamic-workflows/scripts/dependency-health.js +81 -83
  121. package/.mindforge/dynamic-workflows/scripts/design-system-audit.js +84 -86
  122. package/.mindforge/dynamic-workflows/scripts/documentation-gen.js +65 -67
  123. package/.mindforge/dynamic-workflows/scripts/feature-planner.js +78 -80
  124. package/.mindforge/dynamic-workflows/scripts/incident-response.js +81 -83
  125. package/.mindforge/dynamic-workflows/scripts/multi-repo-sync.js +49 -51
  126. package/.mindforge/dynamic-workflows/scripts/mutation-testing.js +113 -115
  127. package/.mindforge/dynamic-workflows/scripts/onboard-codebase.js +79 -81
  128. package/.mindforge/dynamic-workflows/scripts/orchestrate-review.js +115 -0
  129. package/.mindforge/dynamic-workflows/scripts/perf-optimize.js +97 -99
  130. package/.mindforge/dynamic-workflows/scripts/pr-review.js +61 -63
  131. package/.mindforge/dynamic-workflows/scripts/refactor-plan.js +88 -90
  132. package/.mindforge/dynamic-workflows/scripts/release-prep.js +79 -81
  133. package/.mindforge/dynamic-workflows/scripts/security-hardening.js +117 -119
  134. package/.mindforge/dynamic-workflows/scripts/security-threat-model.js +119 -121
  135. package/.mindforge/dynamic-workflows/scripts/tdd-sprint.js +80 -82
  136. package/.mindforge/dynamic-workflows/scripts/tech-evaluation.js +50 -52
  137. package/.mindforge/dynamic-workflows/scripts/test-coverage-gap.js +68 -70
  138. package/.mindforge/dynamic-workflows/scripts/ux-heuristic-audit.js +89 -91
  139. package/.mindforge/dynamic-workflows/scripts/verification-loop.js +138 -0
  140. package/.mindforge/dynamic-workflows/scripts/workflow-optimizer.js +136 -0
  141. package/.mindforge/dynamic-workflows/scripts/writer-reviewer.js +63 -65
  142. package/.mindforge/memory/sync-manifest.json +1 -1
  143. package/.mindforge/personas/advisor-researcher.md +2 -2
  144. package/.mindforge/personas/api-load-tester.md +1 -1
  145. package/.mindforge/personas/authentication-architect.md +1 -1
  146. package/.mindforge/personas/backup-recovery-specialist.md +1 -1
  147. package/.mindforge/personas/build-optimizer.md +1 -1
  148. package/.mindforge/personas/caching-strategist.md +1 -1
  149. package/.mindforge/personas/chaos-engineer.md +1 -1
  150. package/.mindforge/personas/compliance-auditor.md +1 -1
  151. package/.mindforge/personas/config-management-expert.md +1 -1
  152. package/.mindforge/personas/coverage-specialist.md +1 -1
  153. package/.mindforge/personas/debug-specialist.md +2 -2
  154. package/.mindforge/personas/debugger.md +2 -2
  155. package/.mindforge/personas/dependency-auditor.md +1 -1
  156. package/.mindforge/personas/developer.md +1 -1
  157. package/.mindforge/personas/devops-engineer.md +1 -1
  158. package/.mindforge/personas/executor.md +1 -1
  159. package/.mindforge/personas/go-specialist.md +1 -1
  160. package/.mindforge/personas/incident-commander.md +1 -1
  161. package/.mindforge/personas/java-specialist.md +1 -1
  162. package/.mindforge/personas/kubernetes-debugger.md +1 -1
  163. package/.mindforge/personas/logging-architect.md +1 -1
  164. package/.mindforge/personas/mf-planner.md +1 -1
  165. package/.mindforge/personas/mf-researcher.md +1 -1
  166. package/.mindforge/personas/mf-reviewer.md +1 -1
  167. package/.mindforge/personas/nyquist-auditor.md +1 -1
  168. package/.mindforge/personas/observability-engineer.md +1 -1
  169. package/.mindforge/personas/performance-optimizer.md +1 -1
  170. package/.mindforge/personas/phase-researcher.md +5 -5
  171. package/.mindforge/personas/planner.md +1 -1
  172. package/.mindforge/personas/project-researcher.md +2 -2
  173. package/.mindforge/personas/python-specialist.md +1 -1
  174. package/.mindforge/personas/qa-engineer.md +1 -1
  175. package/.mindforge/personas/release-manager.md +1 -1
  176. package/.mindforge/personas/research-agent.md +4 -4
  177. package/.mindforge/personas/roadmapper-extend.md +1 -1
  178. package/.mindforge/personas/rust-specialist.md +1 -1
  179. package/.mindforge/personas/security-reviewer.md +1 -1
  180. package/.mindforge/personas/tech-writer.md +1 -1
  181. package/.mindforge/personas/typescript-wizard.md +1 -1
  182. package/.mindforge/personas/ui-researcher.md +1 -1
  183. package/.mindforge/skills/accessibility/SKILL.md +3 -3
  184. package/.mindforge/skills/agent-architecture-audit/SKILL.md +11 -0
  185. package/.mindforge/skills/agent-loops/SKILL.md +1 -1
  186. package/.mindforge/skills/arxiv/SKILL.md +6 -6
  187. package/.mindforge/skills/arxiv/scripts/search_arxiv.py +114 -0
  188. package/.mindforge/skills/code-tour/SKILL.md +2 -2
  189. package/.mindforge/skills/code-wiki/SKILL.md +11 -11
  190. package/.mindforge/skills/code-wiki/templates/README.md +31 -0
  191. package/.mindforge/skills/code-wiki/templates/architecture.md +30 -0
  192. package/.mindforge/skills/code-wiki/templates/getting-started.md +47 -0
  193. package/.mindforge/skills/code-wiki/templates/module.md +38 -0
  194. package/.mindforge/skills/concept-diagrams/SKILL.md +6 -6
  195. package/.mindforge/skills/concept-diagrams/examples/apartment-floor-plan-conversion.md +244 -0
  196. package/.mindforge/skills/concept-diagrams/examples/automated-password-reset-flow.md +276 -0
  197. package/.mindforge/skills/concept-diagrams/examples/autonomous-llm-research-agent-flow.md +240 -0
  198. package/.mindforge/skills/concept-diagrams/examples/banana-journey-tree-to-smoothie.md +161 -0
  199. package/.mindforge/skills/concept-diagrams/examples/commercial-aircraft-structure.md +209 -0
  200. package/.mindforge/skills/concept-diagrams/examples/cpu-ooo-microarchitecture.md +236 -0
  201. package/.mindforge/skills/concept-diagrams/examples/electricity-grid-flow.md +182 -0
  202. package/.mindforge/skills/concept-diagrams/examples/feature-film-production-pipeline.md +172 -0
  203. package/.mindforge/skills/concept-diagrams/examples/hospital-emergency-department-flow.md +165 -0
  204. package/.mindforge/skills/concept-diagrams/examples/ml-benchmark-grouped-bar-chart.md +114 -0
  205. package/.mindforge/skills/concept-diagrams/examples/place-order-uml-sequence.md +325 -0
  206. package/.mindforge/skills/concept-diagrams/examples/smart-city-infrastructure.md +173 -0
  207. package/.mindforge/skills/concept-diagrams/examples/smartphone-layer-anatomy.md +154 -0
  208. package/.mindforge/skills/concept-diagrams/examples/sn2-reaction-mechanism.md +247 -0
  209. package/.mindforge/skills/concept-diagrams/examples/wind-turbine-structure.md +338 -0
  210. package/.mindforge/skills/concept-diagrams/references/dashboard-patterns.md +43 -0
  211. package/.mindforge/skills/concept-diagrams/references/infrastructure-patterns.md +144 -0
  212. package/.mindforge/skills/concept-diagrams/references/physical-shape-cookbook.md +42 -0
  213. package/.mindforge/skills/concept-diagrams/templates/template.html +174 -0
  214. package/.mindforge/skills/creative-ideation/references/full-prompt-library.md +110 -0
  215. package/.mindforge/skills/documentation/SKILL.md +1 -1
  216. package/.mindforge/skills/domain-intel/SKILL.md +7 -7
  217. package/.mindforge/skills/domain-intel/scripts/domain_intel.py +397 -0
  218. package/.mindforge/skills/duckduckgo-search/SKILL.md +17 -17
  219. package/.mindforge/skills/duckduckgo-search/scripts/duckduckgo.sh +28 -0
  220. package/.mindforge/skills/environment-management/SKILL.md +1 -1
  221. package/.mindforge/skills/github-code-review/SKILL.md +9 -9
  222. package/.mindforge/skills/github-code-review/references/review-output-template.md +74 -0
  223. package/.mindforge/skills/github-issues/templates/bug-report.md +35 -0
  224. package/.mindforge/skills/github-issues/templates/feature-request.md +31 -0
  225. package/.mindforge/skills/github-pr-workflow/SKILL.md +3 -3
  226. package/.mindforge/skills/github-pr-workflow/references/ci-troubleshooting.md +183 -0
  227. package/.mindforge/skills/github-pr-workflow/references/conventional-commits.md +71 -0
  228. package/.mindforge/skills/github-pr-workflow/templates/pr-body-bugfix.md +35 -0
  229. package/.mindforge/skills/github-pr-workflow/templates/pr-body-feature.md +33 -0
  230. package/.mindforge/skills/incident-response/SKILL.md +1 -1
  231. package/.mindforge/skills/jupyter-live-kernel/SKILL.md +3 -3
  232. package/.mindforge/skills/kanban-orchestrator/SKILL.md +10 -10
  233. package/.mindforge/skills/kanban-worker/SKILL.md +6 -6
  234. package/.mindforge/skills/meme-generation/SKILL.md +1 -1
  235. package/.mindforge/skills/meme-generation/scripts/generate_meme.py +470 -0
  236. package/.mindforge/skills/meme-generation/scripts/templates.json +97 -0
  237. package/.mindforge/skills/obsidian/SKILL.md +15 -15
  238. package/.mindforge/skills/orch-pipeline/SKILL.md +2 -2
  239. package/.mindforge/skills/osint-investigation/SKILL.md +3 -2
  240. package/.mindforge/skills/osint-investigation/references/sources/courtlistener.md +98 -0
  241. package/.mindforge/skills/osint-investigation/references/sources/gdelt.md +104 -0
  242. package/.mindforge/skills/osint-investigation/references/sources/icij-offshore.md +104 -0
  243. package/.mindforge/skills/osint-investigation/references/sources/nyc-acris.md +90 -0
  244. package/.mindforge/skills/osint-investigation/references/sources/ofac-sdn.md +92 -0
  245. package/.mindforge/skills/osint-investigation/references/sources/opencorporates.md +103 -0
  246. package/.mindforge/skills/osint-investigation/references/sources/sec-edgar.md +83 -0
  247. package/.mindforge/skills/osint-investigation/references/sources/senate-ld.md +89 -0
  248. package/.mindforge/skills/osint-investigation/references/sources/usaspending.md +97 -0
  249. package/.mindforge/skills/osint-investigation/references/sources/wayback.md +93 -0
  250. package/.mindforge/skills/osint-investigation/references/sources/wikipedia.md +107 -0
  251. package/.mindforge/skills/osint-investigation/scripts/_http.py +82 -0
  252. package/.mindforge/skills/osint-investigation/scripts/_normalize.py +67 -0
  253. package/.mindforge/skills/osint-investigation/scripts/build_findings.py +221 -0
  254. package/.mindforge/skills/osint-investigation/scripts/entity_resolution.py +228 -0
  255. package/.mindforge/skills/osint-investigation/scripts/fetch_courtlistener.py +149 -0
  256. package/.mindforge/skills/osint-investigation/scripts/fetch_gdelt.py +161 -0
  257. package/.mindforge/skills/osint-investigation/scripts/fetch_icij_offshore.py +234 -0
  258. package/.mindforge/skills/osint-investigation/scripts/fetch_nyc_acris.py +203 -0
  259. package/.mindforge/skills/osint-investigation/scripts/fetch_ofac_sdn.py +175 -0
  260. package/.mindforge/skills/osint-investigation/scripts/fetch_opencorporates.py +191 -0
  261. package/.mindforge/skills/osint-investigation/scripts/fetch_sec_edgar.py +184 -0
  262. package/.mindforge/skills/osint-investigation/scripts/fetch_senate_ld.py +146 -0
  263. package/.mindforge/skills/osint-investigation/scripts/fetch_usaspending.py +170 -0
  264. package/.mindforge/skills/osint-investigation/scripts/fetch_wayback.py +142 -0
  265. package/.mindforge/skills/osint-investigation/scripts/fetch_wikipedia.py +266 -0
  266. package/.mindforge/skills/osint-investigation/scripts/timing_analysis.py +252 -0
  267. package/.mindforge/skills/osint-investigation/templates/source-template.md +59 -0
  268. package/.mindforge/skills/oss-forensics/SKILL.md +6 -6
  269. package/.mindforge/skills/oss-forensics/references/evidence-types.md +89 -0
  270. package/.mindforge/skills/oss-forensics/references/github-archive-guide.md +184 -0
  271. package/.mindforge/skills/oss-forensics/references/investigation-templates.md +131 -0
  272. package/.mindforge/skills/oss-forensics/references/recovery-techniques.md +164 -0
  273. package/.mindforge/skills/oss-forensics/scripts/evidence-store.py +313 -0
  274. package/.mindforge/skills/oss-forensics/templates/forensic-report.md +151 -0
  275. package/.mindforge/skills/oss-forensics/templates/malicious-package-report.md +43 -0
  276. package/.mindforge/skills/pixel-art/SKILL.md +2 -2
  277. package/.mindforge/skills/pixel-art/references/palettes.md +49 -0
  278. package/.mindforge/skills/plan/SKILL.md +10 -10
  279. package/.mindforge/skills/requesting-code-review/SKILL.md +4 -6
  280. package/.mindforge/skills/research-paper-writing/SKILL.md +32 -32
  281. package/.mindforge/skills/research-paper-writing/references/autoreason-methodology.md +394 -0
  282. package/.mindforge/skills/research-paper-writing/references/checklists.md +434 -0
  283. package/.mindforge/skills/research-paper-writing/references/citation-workflow.md +563 -0
  284. package/.mindforge/skills/research-paper-writing/references/experiment-patterns.md +728 -0
  285. package/.mindforge/skills/research-paper-writing/references/human-evaluation.md +476 -0
  286. package/.mindforge/skills/research-paper-writing/references/paper-types.md +481 -0
  287. package/.mindforge/skills/research-paper-writing/references/reviewer-guidelines.md +433 -0
  288. package/.mindforge/skills/research-paper-writing/references/sources.md +191 -0
  289. package/.mindforge/skills/research-paper-writing/references/writing-guide.md +474 -0
  290. package/.mindforge/skills/research-paper-writing/templates/README.md +251 -0
  291. package/.mindforge/skills/scrapling/SKILL.md +1 -1
  292. package/.mindforge/skills/security-review/SKILL.md +1 -1
  293. package/.mindforge/skills/sherlock/SKILL.md +1 -1
  294. package/.mindforge/skills/simplify-code/SKILL.md +5 -7
  295. package/.mindforge/skills/spike/SKILL.md +11 -13
  296. package/.mindforge/skills/subagent-driven-development/SKILL.md +7 -11
  297. package/.mindforge/skills/subagent-driven-development/references/context-budget-discipline.md +53 -0
  298. package/.mindforge/skills/subagent-driven-development/references/gates-taxonomy.md +93 -0
  299. package/.mindforge/skills/systematic-debugging/SKILL.md +13 -14
  300. package/.mindforge/skills/test-driven-development/SKILL.md +7 -8
  301. package/.mindforge/skills/testing-standards/SKILL.md +1 -1
  302. package/.mindforge/skills/web-pentest/SKILL.md +2 -2
  303. package/.mindforge/skills/web-pentest/references/bypass-techniques.md +133 -0
  304. package/.mindforge/skills/web-pentest/references/exploitation-techniques.md +204 -0
  305. package/.mindforge/skills/web-pentest/references/scope-enforcement.md +110 -0
  306. package/.mindforge/skills/web-pentest/references/vuln-taxonomy.md +81 -0
  307. package/.mindforge/skills/web-pentest/templates/authorization.md +69 -0
  308. package/.mindforge/skills/web-pentest/templates/pentest-report.md +178 -0
  309. package/.mindforge/skills/writing-skills/SKILL.md +4 -3
  310. package/CHANGELOG.md +35 -0
  311. package/MINDFORGE.md +3 -3
  312. package/README.md +9 -7
  313. package/RELEASENOTES.md +65 -2
  314. package/SECURITY.md +5 -3
  315. package/bin/autonomous/auto-runner.js +5 -2
  316. package/bin/engine/skill-loader.js +4 -0
  317. package/bin/governance/rbac.js +4 -0
  318. package/bin/memory/eis-client.js +1 -0
  319. package/bin/mindforge-cli.js +5 -0
  320. package/bin/models/bedrock-provider.js +192 -0
  321. package/bin/models/model-client.js +19 -0
  322. package/bin/spawn-agent.js +9 -2
  323. package/docs/commands-reference.md +68 -6
  324. package/docs/faq.md +38 -1
  325. package/docs/getting-started.md +27 -12
  326. package/docs/sdk-reference.md +36 -3
  327. package/docs/troubleshooting.md +59 -1
  328. package/docs/user-guide.md +7 -4
  329. package/package.json +3 -3
  330. package/.claude/commands/mindforge/skill-tdd.md +0 -53
  331. package/.claude/commands/mindforge/skills-index.md +0 -118
  332. package/.claude/commands/mindforge/systematic-debug.md +0 -60
  333. package/.claude/commands/mindforge/wf-accessibility-audit.md +0 -31
  334. package/.claude/commands/mindforge/wf-ai-model-eval.md +0 -31
  335. package/.claude/commands/mindforge/wf-api-migration.md +0 -31
  336. package/.claude/commands/mindforge/wf-architecture-modernization.md +0 -32
  337. package/.claude/commands/mindforge/wf-catalog.md +0 -59
  338. package/.claude/commands/mindforge/wf-code-audit.md +0 -31
  339. package/.claude/commands/mindforge/wf-code-explainer.md +0 -31
  340. package/.claude/commands/mindforge/wf-competitive-analysis.md +0 -31
  341. package/.claude/commands/mindforge/wf-competitive-teardown.md +0 -31
  342. package/.claude/commands/mindforge/wf-cost-analysis.md +0 -31
  343. package/.claude/commands/mindforge/wf-data-pipeline-validate.md +0 -31
  344. package/.claude/commands/mindforge/wf-database-migration.md +0 -31
  345. package/.claude/commands/mindforge/wf-debug-detective.md +0 -32
  346. package/.claude/commands/mindforge/wf-design-system-audit.md +0 -31
  347. package/.claude/commands/mindforge/wf-documentation-gen.md +0 -31
  348. package/.claude/commands/mindforge/wf-feature-planner.md +0 -31
  349. package/.claude/commands/mindforge/wf-incident-response.md +0 -31
  350. package/.claude/commands/mindforge/wf-multi-repo-sync.md +0 -31
  351. package/.claude/commands/mindforge/wf-mutation-testing.md +0 -31
  352. package/.claude/commands/mindforge/wf-onboard-codebase.md +0 -31
  353. package/.claude/commands/mindforge/wf-perf-optimize.md +0 -31
  354. package/.claude/commands/mindforge/wf-pr-review.md +0 -31
  355. package/.claude/commands/mindforge/wf-refactor-plan.md +0 -31
  356. package/.claude/commands/mindforge/wf-release-prep.md +0 -31
  357. package/.claude/commands/mindforge/wf-security-threat-model.md +0 -31
  358. package/.claude/commands/mindforge/wf-tdd-sprint.md +0 -31
  359. package/.claude/commands/mindforge/wf-tech-evaluation.md +0 -31
  360. package/.claude/commands/mindforge/wf-ux-heuristic-audit.md +0 -31
  361. package/.claude/commands/mindforge/wf-writer-reviewer.md +0 -30
@@ -0,0 +1,252 @@
1
+ #!/usr/bin/env python3
2
+ """Permutation test for donation/contract timing correlation (stdlib-only).
3
+
4
+ For each (donor, vendor) pair, compute the mean number of days between each
5
+ donation and the nearest contract award. Then shuffle contract award dates
6
+ N times within the observation window and compute the same statistic. The
7
+ one-tailed p-value is the fraction of permutations whose mean is <= the
8
+ observed mean (smaller distance = tighter clustering).
9
+
10
+ Adapted from ShinMegamiBoson/OpenPlanter (MIT). Differences:
11
+ - Pure stdlib (no pandas / numpy)
12
+ - Domain-agnostic (no snow-vendor / CRITICAL-politician filter)
13
+ - Configurable column names via flags
14
+ - Optional --seed for reproducibility
15
+ """
16
+ from __future__ import annotations
17
+
18
+ import argparse
19
+ import csv
20
+ import datetime as dt
21
+ import json
22
+ import random
23
+ import statistics
24
+ from collections import defaultdict
25
+ from pathlib import Path
26
+
27
+ _DATE_FORMATS = ("%Y-%m-%d", "%m/%d/%Y", "%Y/%m/%d", "%m-%d-%Y", "%Y%m%d")
28
+
29
+
30
+ def parse_date(raw: str) -> dt.date | None:
31
+ if not raw:
32
+ return None
33
+ raw = raw.strip()
34
+ for fmt in _DATE_FORMATS:
35
+ try:
36
+ return dt.datetime.strptime(raw, fmt).date()
37
+ except ValueError:
38
+ continue
39
+ return None
40
+
41
+
42
+ def _read(path: str) -> list[dict[str, str]]:
43
+ with open(path, newline="", encoding="utf-8") as fh:
44
+ return list(csv.DictReader(fh))
45
+
46
+
47
+ def _nearest_distance(donation_date: dt.date, awards: list[dt.date]) -> int:
48
+ """Absolute days to nearest award date."""
49
+ return min(abs((donation_date - a).days) for a in awards)
50
+
51
+
52
+ def _permute(
53
+ awards_count: int,
54
+ donations: list[dt.date],
55
+ date_min: dt.date,
56
+ date_max: dt.date,
57
+ rng: random.Random,
58
+ ) -> float:
59
+ """One permutation: draw uniform random award dates, compute mean nearest-distance."""
60
+ span_days = (date_max - date_min).days or 1
61
+ rand_awards = [
62
+ date_min + dt.timedelta(days=rng.randint(0, span_days))
63
+ for _ in range(awards_count)
64
+ ]
65
+ distances = [_nearest_distance(d, rand_awards) for d in donations]
66
+ return statistics.mean(distances)
67
+
68
+
69
+ def analyze(
70
+ donations_path: str,
71
+ donation_date_col: str,
72
+ donation_amount_col: str,
73
+ donation_donor_col: str,
74
+ donation_recipient_col: str,
75
+ contracts_path: str,
76
+ contract_date_col: str,
77
+ contract_vendor_col: str,
78
+ cross_links_path: str | None,
79
+ n_permutations: int = 1000,
80
+ min_donations: int = 3,
81
+ p_threshold: float = 0.05,
82
+ seed: int | None = None,
83
+ out_path: str = "timing.json",
84
+ ) -> dict:
85
+ rng = random.Random(seed)
86
+
87
+ donations = _read(donations_path)
88
+ contracts = _read(contracts_path)
89
+
90
+ # Allow optional join through cross_links — donor (left) ↔ vendor (right).
91
+ # When present, donor strings get mapped to matched vendor names so the
92
+ # vendor-date index lookup actually finds the contracts.
93
+ matched_pairs: set[tuple[str, str]] | None = None
94
+ donor_to_vendors: dict[str, set[str]] = defaultdict(set)
95
+ if cross_links_path:
96
+ matched_pairs = set()
97
+ for row in _read(cross_links_path):
98
+ left = row.get("left_name", "")
99
+ right = row.get("right_name", "")
100
+ matched_pairs.add((left, right))
101
+ donor_to_vendors[left].add(right)
102
+
103
+ # Index contract dates by vendor name.
104
+ vendor_to_award_dates: dict[str, list[dt.date]] = defaultdict(list)
105
+ all_award_dates: list[dt.date] = []
106
+ for row in contracts:
107
+ d = parse_date(row.get(contract_date_col, ""))
108
+ if not d:
109
+ continue
110
+ vendor_to_award_dates[row.get(contract_vendor_col, "").strip()].append(d)
111
+ all_award_dates.append(d)
112
+
113
+ if not all_award_dates:
114
+ raise SystemExit(f"No parseable dates in {contracts_path}/{contract_date_col}")
115
+ global_min = min(all_award_dates)
116
+ global_max = max(all_award_dates)
117
+
118
+ # Group donations by (donor, recipient).
119
+ grouped: dict[tuple[str, str], list[tuple[dt.date, float]]] = defaultdict(list)
120
+ for row in donations:
121
+ donor = row.get(donation_donor_col, "").strip()
122
+ recip = row.get(donation_recipient_col, "").strip()
123
+ d = parse_date(row.get(donation_date_col, ""))
124
+ try:
125
+ amt = float(row.get(donation_amount_col, "0") or 0)
126
+ except ValueError:
127
+ amt = 0.0
128
+ if not (donor and recip and d):
129
+ continue
130
+ grouped[(donor, recip)].append((d, amt))
131
+
132
+ results = []
133
+ skipped = 0
134
+ for (donor, recip), records in grouped.items():
135
+ if len(records) < min_donations:
136
+ skipped += 1
137
+ continue
138
+ # Only test if donor appears in cross-links (when provided). The
139
+ # (donor, candidate) tuple itself is NOT what's in matched_pairs —
140
+ # cross_links pairs are (donor, vendor). We use the cross-link to
141
+ # map donor → vendor name(s) so the vendor-date index resolves.
142
+ if matched_pairs is not None and donor not in donor_to_vendors:
143
+ skipped += 1
144
+ continue
145
+ # Try direct donor→awards first, then go through cross-link vendor names.
146
+ award_dates = list(vendor_to_award_dates.get(donor, []))
147
+ if not award_dates:
148
+ award_dates = list(vendor_to_award_dates.get(recip, []))
149
+ if not award_dates and donor_to_vendors.get(donor):
150
+ for vendor_name in donor_to_vendors[donor]:
151
+ award_dates.extend(vendor_to_award_dates.get(vendor_name, []))
152
+ if not award_dates:
153
+ skipped += 1
154
+ continue
155
+
156
+ donation_dates = [d for (d, _) in records]
157
+ observed = statistics.mean(
158
+ _nearest_distance(d, award_dates) for d in donation_dates
159
+ )
160
+
161
+ permuted_means = [
162
+ _permute(len(award_dates), donation_dates, global_min, global_max, rng)
163
+ for _ in range(n_permutations)
164
+ ]
165
+ p_value = sum(1 for m in permuted_means if m <= observed) / n_permutations
166
+ null_mean = statistics.mean(permuted_means)
167
+ null_std = statistics.pstdev(permuted_means) or 1.0
168
+ effect_size = (null_mean - observed) / null_std
169
+
170
+ results.append(
171
+ {
172
+ "donor": donor,
173
+ "recipient": recip,
174
+ "n_donations": len(records),
175
+ "n_award_dates": len(award_dates),
176
+ "observed_mean_days": round(observed, 2),
177
+ "null_mean_days": round(null_mean, 2),
178
+ "p_value": round(p_value, 4),
179
+ "effect_size_sd": round(effect_size, 2),
180
+ "significant": p_value < p_threshold,
181
+ "total_donation_amount": round(sum(a for (_, a) in records), 2),
182
+ }
183
+ )
184
+
185
+ results.sort(key=lambda r: r["p_value"])
186
+
187
+ payload = {
188
+ "metadata": {
189
+ "n_permutations": n_permutations,
190
+ "min_donations": min_donations,
191
+ "p_threshold": p_threshold,
192
+ "seed": seed,
193
+ "n_pairs_tested": len(results),
194
+ "n_pairs_skipped": skipped,
195
+ "n_significant": sum(1 for r in results if r["significant"]),
196
+ "observation_window": [global_min.isoformat(), global_max.isoformat()],
197
+ },
198
+ "results": results,
199
+ }
200
+
201
+ Path(out_path).write_text(json.dumps(payload, indent=2))
202
+ return payload
203
+
204
+
205
+ def main() -> int:
206
+ p = argparse.ArgumentParser(description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter)
207
+ p.add_argument("--donations", required=True)
208
+ p.add_argument("--donation-date-col", required=True)
209
+ p.add_argument("--donation-amount-col", required=True)
210
+ p.add_argument("--donation-donor-col", required=True)
211
+ p.add_argument("--donation-recipient-col", required=True)
212
+ p.add_argument("--contracts", required=True)
213
+ p.add_argument("--contract-date-col", required=True)
214
+ p.add_argument("--contract-vendor-col", required=True)
215
+ p.add_argument(
216
+ "--cross-links",
217
+ help="Optional cross_links.csv to restrict (donor, vendor) pairs",
218
+ )
219
+ p.add_argument("--permutations", type=int, default=1000)
220
+ p.add_argument("--min-donations", type=int, default=3)
221
+ p.add_argument("--p-threshold", type=float, default=0.05)
222
+ p.add_argument("--seed", type=int)
223
+ p.add_argument("--out", default="timing.json")
224
+ a = p.parse_args()
225
+
226
+ payload = analyze(
227
+ donations_path=a.donations,
228
+ donation_date_col=a.donation_date_col,
229
+ donation_amount_col=a.donation_amount_col,
230
+ donation_donor_col=a.donation_donor_col,
231
+ donation_recipient_col=a.donation_recipient_col,
232
+ contracts_path=a.contracts,
233
+ contract_date_col=a.contract_date_col,
234
+ contract_vendor_col=a.contract_vendor_col,
235
+ cross_links_path=a.cross_links,
236
+ n_permutations=a.permutations,
237
+ min_donations=a.min_donations,
238
+ p_threshold=a.p_threshold,
239
+ seed=a.seed,
240
+ out_path=a.out,
241
+ )
242
+ meta = payload["metadata"]
243
+ print(
244
+ f"Tested {meta['n_pairs_tested']} pairs ({meta['n_pairs_skipped']} skipped). "
245
+ f"Significant (p<{meta['p_threshold']}): {meta['n_significant']}. "
246
+ f"Wrote {a.out}"
247
+ )
248
+ return 0
249
+
250
+
251
+ if __name__ == "__main__":
252
+ raise SystemExit(main())
@@ -18,10 +18,11 @@ triggers:
18
18
  - "force push detected"
19
19
  - "IOC extraction"
20
20
  toolsets:
21
- - terminal
22
- - web
23
- - file
24
- - delegation
21
+ - Bash
22
+ - WebFetch
23
+ - Read
24
+ - Write
25
+ - Agent
25
26
  ---
26
27
 
27
28
  # OSS Security Forensics Skill
@@ -43,7 +44,7 @@ Read these before every investigation step. Violating them invalidates the repor
43
44
  4. **No Evidence Fabrication**: The hypothesis validator MUST mechanically check that every cited evidence ID actually exists in the evidence store before accepting a hypothesis.
44
45
  5. **Proof-Required Disproval**: A hypothesis cannot be dismissed without a specific, evidence-backed counter-argument. "No evidence found" is not sufficient to disprove—it only makes a hypothesis inconclusive.
45
46
  6. **SHA/URL Double-Verification**: Any commit SHA, URL, or external identifier cited as evidence must be independently confirmed from at least two sources before being marked as verified.
46
- 7. **Suspicious Code Rule**: Never run code found inside the investigated repository locally. Analyze statically only, or use `execute_code` in a sandboxed environment.
47
+ 7. **Suspicious Code Rule**: Never run code found inside the investigated repository locally. Analyze statically only, or use `Bash` in a sandboxed environment.
47
48
  8. **Secret Redaction**: Any API keys, tokens, or credentials discovered during investigation must be redacted in the final report. Log them internally only.
48
49
 
49
50
  ---
@@ -93,7 +94,7 @@ Read these before every investigation step. Violating them invalidates the repor
93
94
  - Provided Indicators of Compromise: commit SHAs, file paths, package names, IP addresses, domains, API keys/tokens, malicious URLs
94
95
  - Any linked vendor security reports or blog posts
95
96
 
96
- **Tools**: Reasoning only, or `execute_code` for regex extraction from large text blocks.
97
+ **Tools**: Reasoning only, or `Bash` for regex extraction from large text blocks.
97
98
 
98
99
  **Output**: Populate `iocs.md` with extracted IOCs. Each IOC must have:
99
100
  - Type (from: COMMIT_SHA, FILE_PATH, API_KEY, SECRET, IP_ADDRESS, DOMAIN, PACKAGE_NAME, ACTOR_USERNAME, MALICIOUS_URL, OTHER)
@@ -106,7 +107,7 @@ Read these before every investigation step. Violating them invalidates the repor
106
107
 
107
108
  ## Phase 2: Parallel Evidence Collection
108
109
 
109
- Spawn up to 5 specialist investigator sub-agents using `delegate_task` (batch mode, max 3 concurrent). Each investigator has a **single data source** and must not mix sources.
110
+ Spawn up to 5 specialist investigator sub-agents using `Agent` (batch mode, max 3 concurrent). Each investigator has a **single data source** and must not mix sources.
110
111
 
111
112
  > **Orchestrator note**: Pass the IOC list from Phase 1 and the investigation time window in the `context` field of each delegated task.
112
113
 
@@ -282,7 +283,7 @@ LIMIT 200
282
283
 
283
284
  **Actions**:
284
285
  - For each commit SHA: attempt recovery via direct GitHub URL (`github.com/OWNER/REPO/commit/SHA.patch`)
285
- - For each domain/IP: check passive DNS, WHOIS records (via `web_extract` on public WHOIS services)
286
+ - For each domain/IP: check passive DNS, WHOIS records (via `WebFetch` on public WHOIS services)
286
287
  - For each package name: check npm/PyPI for matching malicious package reports
287
288
  - For each actor username: check GitHub profile, contribution history, account age
288
289
  - Recover force-pushed commits using 3 methods (see [recovery-techniques.md](./references/recovery-techniques.md))
@@ -319,7 +320,7 @@ A hypothesis must:
319
320
  - Typosquatting: near-identical package name targeting misspellers
320
321
  - Credential Leak: token/key accidentally committed then force-pushed to erase
321
322
 
322
- For each hypothesis, spawn a `delegate_task` sub-agent to attempt to find disconfirming evidence before confirming.
323
+ For each hypothesis, spawn a `Agent` sub-agent to attempt to find disconfirming evidence before confirming.
323
324
 
324
325
  ---
325
326
 
@@ -0,0 +1,313 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ OSS Forensics Evidence Store Manager
4
+ Manages a JSON-based evidence store for forensic investigations.
5
+
6
+ Commands:
7
+ add - Add a piece of evidence
8
+ list - List all evidence (optionally filter by type or actor)
9
+ verify - Re-check SHA-256 hashes for integrity
10
+ query - Search evidence by keyword
11
+ export - Export evidence as a Markdown table
12
+ summary - Print investigation statistics
13
+
14
+ Usage example:
15
+ python3 evidence-store.py --store evidence.json add \
16
+ --source "git fsck output" --content "dangling commit abc123" \
17
+ --type git --actor "malicious-user" --url "https://github.com/owner/repo/commit/abc123"
18
+
19
+ python3 evidence-store.py --store evidence.json list --type git
20
+ python3 evidence-store.py --store evidence.json verify
21
+ python3 evidence-store.py --store evidence.json export > evidence-table.md
22
+ """
23
+
24
+ import json
25
+ import argparse
26
+ import os
27
+ import datetime
28
+ import hashlib
29
+ import sys
30
+
31
+ EVIDENCE_TYPES = [
32
+ "git", # Local git repository data (commits, reflog, fsck)
33
+ "gh_api", # GitHub REST API responses
34
+ "gh_archive", # GitHub Archive / BigQuery query results
35
+ "web_archive", # Wayback Machine snapshots
36
+ "ioc", # Indicator of Compromise (SHA, domain, IP, package name, etc.)
37
+ "analysis", # Derived analysis / cross-source correlation result
38
+ "manual", # Manually noted observation
39
+ "vendor_report", # External security vendor report excerpt
40
+ ]
41
+
42
+ VERIFICATION_STATES = ["unverified", "single_source", "multi_source_verified"]
43
+
44
+ IOC_TYPES = [
45
+ "COMMIT_SHA", "FILE_PATH", "API_KEY", "SECRET", "IP_ADDRESS",
46
+ "DOMAIN", "PACKAGE_NAME", "ACTOR_USERNAME", "MALICIOUS_URL",
47
+ "WORKFLOW_FILE", "BRANCH_NAME", "TAG_NAME", "RELEASE_NAME", "OTHER",
48
+ ]
49
+
50
+
51
+ def _now_iso():
52
+ return datetime.datetime.now(datetime.timezone.utc).isoformat(timespec="seconds") + "Z"
53
+
54
+
55
+ def _sha256(content: str) -> str:
56
+ return hashlib.sha256(content.encode("utf-8")).hexdigest()
57
+
58
+
59
+ class EvidenceStore:
60
+ def __init__(self, filepath: str):
61
+ self.filepath = filepath
62
+ self.data = {
63
+ "metadata": {
64
+ "version": "2.0",
65
+ "created_at": _now_iso(),
66
+ "last_updated": _now_iso(),
67
+ "investigation": "",
68
+ "target_repo": "",
69
+ },
70
+ "evidence": [],
71
+ "chain_of_custody": [],
72
+ }
73
+ if os.path.exists(filepath):
74
+ try:
75
+ with open(filepath, "r", encoding="utf-8") as f:
76
+ self.data = json.load(f)
77
+ except (json.JSONDecodeError, IOError) as e:
78
+ print(f"Error loading evidence store '{filepath}': {e}", file=sys.stderr)
79
+ print("Hint: The file might be corrupted. Check for manual edits or syntax errors.", file=sys.stderr)
80
+ sys.exit(1)
81
+
82
+ def _save(self):
83
+ self.data["metadata"]["last_updated"] = _now_iso()
84
+ with open(self.filepath, "w", encoding="utf-8") as f:
85
+ json.dump(self.data, f, indent=2, ensure_ascii=False)
86
+
87
+ def _next_id(self) -> str:
88
+ return f"EV-{len(self.data['evidence']) + 1:04d}"
89
+
90
+ def add(
91
+ self,
92
+ source: str,
93
+ content: str,
94
+ evidence_type: str,
95
+ actor: str = None,
96
+ url: str = None,
97
+ timestamp: str = None,
98
+ ioc_type: str = None,
99
+ verification: str = "unverified",
100
+ notes: str = None,
101
+ ) -> str:
102
+ evidence_id = self._next_id()
103
+ entry = {
104
+ "id": evidence_id,
105
+ "type": evidence_type,
106
+ "source": source,
107
+ "content": content,
108
+ "content_sha256": _sha256(content),
109
+ "actor": actor,
110
+ "url": url,
111
+ "event_timestamp": timestamp,
112
+ "collected_at": _now_iso(),
113
+ "ioc_type": ioc_type,
114
+ "verification": verification,
115
+ "notes": notes,
116
+ }
117
+ self.data["evidence"].append(entry)
118
+ self.data["chain_of_custody"].append({
119
+ "action": "add",
120
+ "evidence_id": evidence_id,
121
+ "timestamp": _now_iso(),
122
+ "source": source,
123
+ })
124
+ self._save()
125
+ return evidence_id
126
+
127
+ def list_evidence(self, filter_type: str = None, filter_actor: str = None):
128
+ results = self.data["evidence"]
129
+ if filter_type:
130
+ results = [e for e in results if e.get("type") == filter_type]
131
+ if filter_actor:
132
+ results = [e for e in results if e.get("actor") == filter_actor]
133
+ return results
134
+
135
+ def verify_integrity(self):
136
+ """Re-compute SHA-256 for all entries and report mismatches."""
137
+ issues = []
138
+ for entry in self.data["evidence"]:
139
+ expected = _sha256(entry["content"])
140
+ stored = entry.get("content_sha256", "")
141
+ if expected != stored:
142
+ issues.append({
143
+ "id": entry["id"],
144
+ "stored_sha256": stored,
145
+ "computed_sha256": expected,
146
+ })
147
+ return issues
148
+
149
+ def query(self, keyword: str):
150
+ """Search for keyword in content, source, actor, or url."""
151
+ keyword_lower = keyword.lower()
152
+ return [
153
+ e for e in self.data["evidence"]
154
+ if keyword_lower in (e.get("content", "") or "").lower()
155
+ or keyword_lower in (e.get("source", "") or "").lower()
156
+ or keyword_lower in (e.get("actor", "") or "").lower()
157
+ or keyword_lower in (e.get("url", "") or "").lower()
158
+ ]
159
+
160
+ def export_markdown(self) -> str:
161
+ lines = [
162
+ "# Evidence Registry",
163
+ "",
164
+ f"**Store**: `{self.filepath}`",
165
+ f"**Last Updated**: {self.data['metadata'].get('last_updated', 'N/A')}",
166
+ f"**Total Evidence Items**: {len(self.data['evidence'])}",
167
+ "",
168
+ "| ID | Type | Source | Actor | Verification | Event Timestamp | URL |",
169
+ "|----|------|--------|-------|--------------|-----------------|-----|",
170
+ ]
171
+ for e in self.data["evidence"]:
172
+ url = e.get("url") or ""
173
+ url_display = f"[link]({url})" if url else ""
174
+ lines.append(
175
+ f"| {e['id']} | {e.get('type','')} | {e.get('source','')} "
176
+ f"| {e.get('actor') or ''} | {e.get('verification','')} "
177
+ f"| {e.get('event_timestamp') or ''} | {url_display} |"
178
+ )
179
+ lines.append("")
180
+ lines.append("## Chain of Custody")
181
+ lines.append("")
182
+ lines.append("| Evidence ID | Action | Timestamp | Source |")
183
+ lines.append("|-------------|--------|-----------|--------|")
184
+ for c in self.data["chain_of_custody"]:
185
+ lines.append(
186
+ f"| {c.get('evidence_id','')} | {c.get('action','')} "
187
+ f"| {c.get('timestamp','')} | {c.get('source','')} |"
188
+ )
189
+ return "\n".join(lines)
190
+
191
+ def summary(self) -> dict:
192
+ by_type = {}
193
+ by_verification = {}
194
+ actors = set()
195
+ for e in self.data["evidence"]:
196
+ t = e.get("type", "unknown")
197
+ by_type[t] = by_type.get(t, 0) + 1
198
+ v = e.get("verification", "unverified")
199
+ by_verification[v] = by_verification.get(v, 0) + 1
200
+ if e.get("actor"):
201
+ actors.add(e["actor"])
202
+ return {
203
+ "total": len(self.data["evidence"]),
204
+ "by_type": by_type,
205
+ "by_verification": by_verification,
206
+ "unique_actors": sorted(actors),
207
+ }
208
+
209
+
210
+ def main():
211
+ parser = argparse.ArgumentParser(
212
+ description="OSS Forensics Evidence Store Manager v2.0",
213
+ formatter_class=argparse.RawDescriptionHelpFormatter,
214
+ )
215
+ parser.add_argument("--store", default="evidence.json", help="Path to evidence JSON file (default: evidence.json)")
216
+
217
+ subparsers = parser.add_subparsers(dest="command", metavar="COMMAND")
218
+
219
+ # --- add ---
220
+ add_p = subparsers.add_parser("add", help="Add a new evidence entry")
221
+ add_p.add_argument("--source", required=True, help="Where this evidence came from (e.g. 'git fsck', 'GH API /commits')")
222
+ add_p.add_argument("--content", required=True, help="The evidence content (commit SHA, API response excerpt, etc.)")
223
+ add_p.add_argument("--type", required=True, choices=EVIDENCE_TYPES, dest="evidence_type", help="Evidence type")
224
+ add_p.add_argument("--actor", help="GitHub handle or email of associated actor")
225
+ add_p.add_argument("--url", help="URL to original source")
226
+ add_p.add_argument("--timestamp", help="When the event occurred (ISO 8601)")
227
+ add_p.add_argument("--ioc-type", choices=IOC_TYPES, help="IOC subtype (for --type ioc)")
228
+ add_p.add_argument("--verification", choices=VERIFICATION_STATES, default="unverified")
229
+ add_p.add_argument("--notes", help="Additional investigator notes")
230
+ add_p.add_argument("--quiet", action="store_true", help="Suppress success message")
231
+
232
+ # --- list ---
233
+ list_p = subparsers.add_parser("list", help="List all evidence entries")
234
+ list_p.add_argument("--type", dest="filter_type", choices=EVIDENCE_TYPES, help="Filter by type")
235
+ list_p.add_argument("--actor", dest="filter_actor", help="Filter by actor")
236
+
237
+ # --- verify ---
238
+ subparsers.add_parser("verify", help="Verify SHA-256 integrity of all evidence content")
239
+
240
+ # --- query ---
241
+ query_p = subparsers.add_parser("query", help="Search evidence by keyword")
242
+ query_p.add_argument("keyword", help="Keyword to search for")
243
+
244
+ # --- export ---
245
+ subparsers.add_parser("export", help="Export evidence as a Markdown table (stdout)")
246
+
247
+ # --- summary ---
248
+ subparsers.add_parser("summary", help="Print investigation statistics")
249
+
250
+ args = parser.parse_args()
251
+
252
+ if not args.command:
253
+ parser.print_help()
254
+ sys.exit(0)
255
+
256
+ store = EvidenceStore(args.store)
257
+
258
+ if args.command == "add":
259
+ eid = store.add(
260
+ source=args.source,
261
+ content=args.content,
262
+ evidence_type=args.evidence_type,
263
+ actor=args.actor,
264
+ url=args.url,
265
+ timestamp=args.timestamp,
266
+ ioc_type=args.ioc_type,
267
+ verification=args.verification,
268
+ notes=args.notes,
269
+ )
270
+ if not getattr(args, "quiet", False):
271
+ print(f"✓ Added evidence: {eid}")
272
+
273
+ elif args.command == "list":
274
+ items = store.list_evidence(
275
+ filter_type=getattr(args, "filter_type", None),
276
+ filter_actor=getattr(args, "filter_actor", None),
277
+ )
278
+ if not items:
279
+ print("No evidence found.")
280
+ for e in items:
281
+ actor_str = f" | actor: {e['actor']}" if e.get("actor") else ""
282
+ url_str = f" | {e['url']}" if e.get("url") else ""
283
+ print(f"[{e['id']}] {e['type']:12s} | {e['verification']:20s} | {e['source']}{actor_str}{url_str}")
284
+
285
+ elif args.command == "verify":
286
+ issues = store.verify_integrity()
287
+ if not issues:
288
+ print(f"✓ All {len(store.data['evidence'])} evidence entries passed SHA-256 integrity check.")
289
+ else:
290
+ print(f"✗ {len(issues)} integrity issue(s) detected:")
291
+ for i in issues:
292
+ print(f" [{i['id']}] stored={i['stored_sha256'][:16]}... computed={i['computed_sha256'][:16]}...")
293
+ sys.exit(1)
294
+
295
+ elif args.command == "query":
296
+ results = store.query(args.keyword)
297
+ print(f"Found {len(results)} result(s) for '{args.keyword}':")
298
+ for e in results:
299
+ print(f" [{e['id']}] {e['type']} | {e['source']} | {e['content'][:80]}")
300
+
301
+ elif args.command == "export":
302
+ print(store.export_markdown())
303
+
304
+ elif args.command == "summary":
305
+ s = store.summary()
306
+ print(f"Total evidence items : {s['total']}")
307
+ print(f"By type : {json.dumps(s['by_type'], indent=2)}")
308
+ print(f"By verification : {json.dumps(s['by_verification'], indent=2)}")
309
+ print(f"Unique actors : {s['unique_actors']}")
310
+
311
+
312
+ if __name__ == "__main__":
313
+ main()
@@ -12,7 +12,7 @@ This is an optional third-party workflow, not a a core capability.
12
12
 
13
13
  Important expectations:
14
14
  - Parallel is a paid service with a free tier, not a fully free local tool.
15
- - It overlaps with native `web_search` / `web_extract`, so do not prefer it by default for ordinary lookups.
15
+ - It overlaps with native `WebSearch` / `WebFetch`, so do not prefer it by default for ordinary lookups.
16
16
  - Prefer this skill when the user mentions Parallel specifically or needs capabilities like Parallel's enrichment, FindAll, or monitor workflows.
17
17
 
18
18
  `parallel-cli` is designed for agents:
@@ -30,7 +30,7 @@ Prefer this skill when:
30
30
  - You need async deep research jobs that can be launched and polled later
31
31
  - You need structured enrichment, FindAll entity discovery, or monitoring
32
32
 
33
- Prefer native `web_search` / `web_extract` for quick one-off lookups when Parallel is not specifically requested.
33
+ Prefer native `WebSearch` / `WebFetch` for quick one-off lookups when Parallel is not specifically requested.
34
34
 
35
35
  ## Installation
36
36
 
@@ -63,7 +63,7 @@ ssh -p 443 -o StrictHostKeyChecking=no -R0:localhost:8000 "$PINGGY_TOKEN+a.pingg
63
63
 
64
64
  ## Procedure — Start a Tunnel and Get the URL
65
65
 
66
- The model SHOULD use the `terminal` tool. The tunnel must stay alive for the duration of the share, so run it as a background process and parse the public URL from stdout.
66
+ The model SHOULD use the `Bash` tool. The tunnel must stay alive for the duration of the share, so run it as a background process and parse the public URL from stdout.
67
67
 
68
68
  ### 1. Confirm a local origin is up
69
69
 
@@ -76,7 +76,7 @@ If nothing is listening yet, start it first (e.g. `python3 -m http.server 8000 -
76
76
 
77
77
  ### 2. Launch the tunnel as a background process
78
78
 
79
- Use `terminal(background=True)` and capture output to a logfile (Pinggy prints the URLs on stdout, then keeps the connection open):
79
+ Use `Bash(background=True)` and capture output to a logfile (Pinggy prints the URLs on stdout, then keeps the connection open):
80
80
 
81
81
  ```bash
82
82
  LOG=/tmp/pinggy-8000.log
@@ -127,7 +127,7 @@ kill "$(cat /tmp/pinggy-8000.pid)"
127
127
  pkill -f 'ssh -p 443 .* free@a\.pinggy\.io'
128
128
  ```
129
129
 
130
- If you have a session_id from `terminal(background=True)`, prefer `process(action='kill', session_id=...)`.
130
+ If you have a session_id from `Bash(background=True)`, prefer `process(action='kill', session_id=...)`.
131
131
 
132
132
  ## Access Control via Username Keywords
133
133