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.
- package/.agent/mindforge/wf-orchestrate-review.md +35 -0
- package/.agent/mindforge/wf-verification-loop.md +45 -0
- package/.agent/mindforge/wf-workflow-optimizer.md +51 -0
- package/.agent/skills/article-illustrator/SKILL.md +7 -7
- package/.agent/skills/arxiv/SKILL.md +6 -6
- package/.agent/skills/code-wiki/SKILL.md +11 -11
- package/.agent/skills/concept-diagrams/SKILL.md +6 -6
- package/.agent/skills/concept-diagrams/examples/apartment-floor-plan-conversion.md +244 -0
- package/.agent/skills/concept-diagrams/examples/automated-password-reset-flow.md +276 -0
- package/.agent/skills/concept-diagrams/examples/autonomous-llm-research-agent-flow.md +240 -0
- package/.agent/skills/concept-diagrams/examples/banana-journey-tree-to-smoothie.md +161 -0
- package/.agent/skills/concept-diagrams/examples/commercial-aircraft-structure.md +209 -0
- package/.agent/skills/concept-diagrams/examples/cpu-ooo-microarchitecture.md +236 -0
- package/.agent/skills/concept-diagrams/examples/electricity-grid-flow.md +182 -0
- package/.agent/skills/concept-diagrams/examples/feature-film-production-pipeline.md +172 -0
- package/.agent/skills/concept-diagrams/examples/hospital-emergency-department-flow.md +165 -0
- package/.agent/skills/concept-diagrams/examples/ml-benchmark-grouped-bar-chart.md +114 -0
- package/.agent/skills/concept-diagrams/examples/place-order-uml-sequence.md +325 -0
- package/.agent/skills/concept-diagrams/examples/smart-city-infrastructure.md +173 -0
- package/.agent/skills/concept-diagrams/examples/smartphone-layer-anatomy.md +154 -0
- package/.agent/skills/concept-diagrams/examples/sn2-reaction-mechanism.md +247 -0
- package/.agent/skills/concept-diagrams/examples/wind-turbine-structure.md +338 -0
- package/.agent/skills/concept-diagrams/templates/template.html +174 -0
- package/.agent/skills/domain-intel/SKILL.md +7 -7
- package/.agent/skills/duckduckgo-search/SKILL.md +17 -17
- package/.agent/skills/github-auth/scripts/gh-env.sh +66 -0
- package/.agent/skills/github-code-review/SKILL.md +9 -9
- package/.agent/skills/github-pr-workflow/SKILL.md +3 -3
- package/.agent/skills/godmode/SKILL.md +8 -8
- package/.agent/skills/jupyter-live-kernel/SKILL.md +3 -3
- package/.agent/skills/kanban-orchestrator/SKILL.md +10 -10
- package/.agent/skills/kanban-worker/SKILL.md +6 -6
- package/.agent/skills/llm-wiki/SKILL.md +7 -7
- package/.agent/skills/mindforge-autonomous/SKILL.md +1 -1
- package/.agent/skills/mindforge-complete-milestone/SKILL.md +1 -1
- package/.agent/skills/mindforge-discuss-phase/SKILL.md +1 -1
- package/.agent/skills/mindforge-do/SKILL.md +1 -1
- package/.agent/skills/mindforge-execute-phase/SKILL.md +1 -1
- package/.agent/skills/mindforge-list-workspaces/SKILL.md +1 -1
- package/.agent/skills/mindforge-manager/SKILL.md +1 -1
- package/.agent/skills/mindforge-neural-orchestrator/SKILL.md +1 -1
- package/.agent/skills/mindforge-new-milestone/SKILL.md +4 -4
- package/.agent/skills/mindforge-new-project/SKILL.md +4 -4
- package/.agent/skills/mindforge-new-workspace/SKILL.md +1 -1
- package/.agent/skills/mindforge-note/SKILL.md +1 -1
- package/.agent/skills/mindforge-plan-phase/SKILL.md +1 -1
- package/.agent/skills/mindforge-profile-user/SKILL.md +1 -1
- package/.agent/skills/mindforge-remove-workspace/SKILL.md +1 -1
- package/.agent/skills/mindforge-research-phase/SKILL.md +1 -1
- package/.agent/skills/mindforge-ui-phase/SKILL.md +1 -1
- package/.agent/skills/mindforge-ui-review/SKILL.md +1 -1
- package/.agent/skills/mindforge-verify-work/SKILL.md +1 -1
- package/.agent/skills/mindforge-workspace-isolated/SKILL.md +1 -1
- package/.agent/skills/node-inspect-debugger/SKILL.md +1 -1
- package/.agent/skills/obsidian/SKILL.md +15 -15
- package/.agent/skills/osint-investigation/SKILL.md +3 -2
- package/.agent/skills/osint-investigation/references/sources/courtlistener.md +98 -0
- package/.agent/skills/osint-investigation/references/sources/gdelt.md +104 -0
- package/.agent/skills/osint-investigation/references/sources/icij-offshore.md +104 -0
- package/.agent/skills/osint-investigation/references/sources/nyc-acris.md +90 -0
- package/.agent/skills/osint-investigation/references/sources/ofac-sdn.md +92 -0
- package/.agent/skills/osint-investigation/references/sources/opencorporates.md +103 -0
- package/.agent/skills/osint-investigation/references/sources/sec-edgar.md +83 -0
- package/.agent/skills/osint-investigation/references/sources/senate-ld.md +89 -0
- package/.agent/skills/osint-investigation/references/sources/usaspending.md +97 -0
- package/.agent/skills/osint-investigation/references/sources/wayback.md +93 -0
- package/.agent/skills/osint-investigation/references/sources/wikipedia.md +107 -0
- package/.agent/skills/osint-investigation/scripts/_http.py +82 -0
- package/.agent/skills/osint-investigation/scripts/_normalize.py +67 -0
- package/.agent/skills/osint-investigation/scripts/build_findings.py +221 -0
- package/.agent/skills/osint-investigation/scripts/entity_resolution.py +228 -0
- package/.agent/skills/osint-investigation/scripts/fetch_courtlistener.py +149 -0
- package/.agent/skills/osint-investigation/scripts/fetch_gdelt.py +161 -0
- package/.agent/skills/osint-investigation/scripts/fetch_icij_offshore.py +234 -0
- package/.agent/skills/osint-investigation/scripts/fetch_nyc_acris.py +203 -0
- package/.agent/skills/osint-investigation/scripts/fetch_ofac_sdn.py +175 -0
- package/.agent/skills/osint-investigation/scripts/fetch_opencorporates.py +191 -0
- package/.agent/skills/osint-investigation/scripts/fetch_sec_edgar.py +184 -0
- package/.agent/skills/osint-investigation/scripts/fetch_senate_ld.py +146 -0
- package/.agent/skills/osint-investigation/scripts/fetch_usaspending.py +170 -0
- package/.agent/skills/osint-investigation/scripts/fetch_wayback.py +142 -0
- package/.agent/skills/osint-investigation/scripts/fetch_wikipedia.py +266 -0
- package/.agent/skills/osint-investigation/scripts/timing_analysis.py +252 -0
- package/.agent/skills/oss-forensics/SKILL.md +10 -9
- package/.agent/skills/oss-forensics/scripts/evidence-store.py +313 -0
- package/.agent/skills/parallel-cli/SKILL.md +2 -2
- package/.agent/skills/pinggy-tunnel/SKILL.md +3 -3
- package/.agent/skills/pixel-art/SKILL.md +2 -2
- package/.agent/skills/plan/SKILL.md +10 -10
- package/.agent/skills/requesting-code-review/SKILL.md +4 -6
- package/.agent/skills/research-paper-writing/SKILL.md +32 -32
- package/.agent/skills/rest-graphql-debug/SKILL.md +31 -32
- package/.agent/skills/s6-container-supervision/SKILL.md +1 -1
- package/.agent/skills/scrapling/SKILL.md +1 -1
- package/.agent/skills/sherlock/SKILL.md +1 -1
- package/.agent/skills/simplify-code/SKILL.md +5 -7
- package/.agent/skills/skill-authoring/SKILL.md +4 -4
- package/.agent/skills/spike/SKILL.md +11 -13
- package/.agent/skills/subagent-driven-development/SKILL.md +7 -11
- package/.agent/skills/systematic-debugging/SKILL.md +13 -14
- package/.agent/skills/test-driven-development/SKILL.md +6 -7
- package/.agent/skills/video-orchestrator/SKILL.md +1 -1
- package/.agent/skills/web-pentest/SKILL.md +7 -7
- package/.mindforge/config.json +3 -2
- package/.mindforge/dynamic-workflows/REGISTRY.md +4 -1
- package/.mindforge/dynamic-workflows/index.json +910 -840
- package/.mindforge/dynamic-workflows/scripts/accessibility-audit.js +88 -90
- package/.mindforge/dynamic-workflows/scripts/ai-model-eval.js +59 -61
- package/.mindforge/dynamic-workflows/scripts/api-contract-test.js +87 -85
- package/.mindforge/dynamic-workflows/scripts/api-migration.js +120 -122
- package/.mindforge/dynamic-workflows/scripts/architecture-modernization.js +84 -86
- package/.mindforge/dynamic-workflows/scripts/code-audit.js +75 -77
- package/.mindforge/dynamic-workflows/scripts/code-explainer.js +99 -101
- package/.mindforge/dynamic-workflows/scripts/competitive-analysis.js +62 -64
- package/.mindforge/dynamic-workflows/scripts/competitive-teardown.js +106 -108
- package/.mindforge/dynamic-workflows/scripts/cost-analysis.js +78 -80
- package/.mindforge/dynamic-workflows/scripts/data-pipeline-validate.js +47 -49
- package/.mindforge/dynamic-workflows/scripts/database-migration.js +85 -87
- package/.mindforge/dynamic-workflows/scripts/debug-detective.js +97 -99
- package/.mindforge/dynamic-workflows/scripts/dependency-health.js +81 -83
- package/.mindforge/dynamic-workflows/scripts/design-system-audit.js +84 -86
- package/.mindforge/dynamic-workflows/scripts/documentation-gen.js +65 -67
- package/.mindforge/dynamic-workflows/scripts/feature-planner.js +78 -80
- package/.mindforge/dynamic-workflows/scripts/incident-response.js +81 -83
- package/.mindforge/dynamic-workflows/scripts/multi-repo-sync.js +49 -51
- package/.mindforge/dynamic-workflows/scripts/mutation-testing.js +113 -115
- package/.mindforge/dynamic-workflows/scripts/onboard-codebase.js +79 -81
- package/.mindforge/dynamic-workflows/scripts/orchestrate-review.js +115 -0
- package/.mindforge/dynamic-workflows/scripts/perf-optimize.js +97 -99
- package/.mindforge/dynamic-workflows/scripts/pr-review.js +61 -63
- package/.mindforge/dynamic-workflows/scripts/refactor-plan.js +88 -90
- package/.mindforge/dynamic-workflows/scripts/release-prep.js +79 -81
- package/.mindforge/dynamic-workflows/scripts/security-hardening.js +117 -119
- package/.mindforge/dynamic-workflows/scripts/security-threat-model.js +119 -121
- package/.mindforge/dynamic-workflows/scripts/tdd-sprint.js +80 -82
- package/.mindforge/dynamic-workflows/scripts/tech-evaluation.js +50 -52
- package/.mindforge/dynamic-workflows/scripts/test-coverage-gap.js +68 -70
- package/.mindforge/dynamic-workflows/scripts/ux-heuristic-audit.js +89 -91
- package/.mindforge/dynamic-workflows/scripts/verification-loop.js +138 -0
- package/.mindforge/dynamic-workflows/scripts/workflow-optimizer.js +136 -0
- package/.mindforge/dynamic-workflows/scripts/writer-reviewer.js +63 -65
- package/.mindforge/memory/sync-manifest.json +1 -1
- package/.mindforge/personas/advisor-researcher.md +2 -2
- package/.mindforge/personas/api-load-tester.md +1 -1
- package/.mindforge/personas/authentication-architect.md +1 -1
- package/.mindforge/personas/backup-recovery-specialist.md +1 -1
- package/.mindforge/personas/build-optimizer.md +1 -1
- package/.mindforge/personas/caching-strategist.md +1 -1
- package/.mindforge/personas/chaos-engineer.md +1 -1
- package/.mindforge/personas/compliance-auditor.md +1 -1
- package/.mindforge/personas/config-management-expert.md +1 -1
- package/.mindforge/personas/coverage-specialist.md +1 -1
- package/.mindforge/personas/debug-specialist.md +2 -2
- package/.mindforge/personas/debugger.md +2 -2
- package/.mindforge/personas/dependency-auditor.md +1 -1
- package/.mindforge/personas/developer.md +1 -1
- package/.mindforge/personas/devops-engineer.md +1 -1
- package/.mindforge/personas/executor.md +1 -1
- package/.mindforge/personas/go-specialist.md +1 -1
- package/.mindforge/personas/incident-commander.md +1 -1
- package/.mindforge/personas/java-specialist.md +1 -1
- package/.mindforge/personas/kubernetes-debugger.md +1 -1
- package/.mindforge/personas/logging-architect.md +1 -1
- package/.mindforge/personas/mf-planner.md +1 -1
- package/.mindforge/personas/mf-researcher.md +1 -1
- package/.mindforge/personas/mf-reviewer.md +1 -1
- package/.mindforge/personas/nyquist-auditor.md +1 -1
- package/.mindforge/personas/observability-engineer.md +1 -1
- package/.mindforge/personas/performance-optimizer.md +1 -1
- package/.mindforge/personas/phase-researcher.md +5 -5
- package/.mindforge/personas/planner.md +1 -1
- package/.mindforge/personas/project-researcher.md +2 -2
- package/.mindforge/personas/python-specialist.md +1 -1
- package/.mindforge/personas/qa-engineer.md +1 -1
- package/.mindforge/personas/release-manager.md +1 -1
- package/.mindforge/personas/research-agent.md +4 -4
- package/.mindforge/personas/roadmapper-extend.md +1 -1
- package/.mindforge/personas/rust-specialist.md +1 -1
- package/.mindforge/personas/security-reviewer.md +1 -1
- package/.mindforge/personas/tech-writer.md +1 -1
- package/.mindforge/personas/typescript-wizard.md +1 -1
- package/.mindforge/personas/ui-researcher.md +1 -1
- package/.mindforge/skills/accessibility/SKILL.md +3 -3
- package/.mindforge/skills/agent-architecture-audit/SKILL.md +11 -0
- package/.mindforge/skills/agent-loops/SKILL.md +1 -1
- package/.mindforge/skills/arxiv/SKILL.md +6 -6
- package/.mindforge/skills/arxiv/scripts/search_arxiv.py +114 -0
- package/.mindforge/skills/code-tour/SKILL.md +2 -2
- package/.mindforge/skills/code-wiki/SKILL.md +11 -11
- package/.mindforge/skills/code-wiki/templates/README.md +31 -0
- package/.mindforge/skills/code-wiki/templates/architecture.md +30 -0
- package/.mindforge/skills/code-wiki/templates/getting-started.md +47 -0
- package/.mindforge/skills/code-wiki/templates/module.md +38 -0
- package/.mindforge/skills/concept-diagrams/SKILL.md +6 -6
- package/.mindforge/skills/concept-diagrams/examples/apartment-floor-plan-conversion.md +244 -0
- package/.mindforge/skills/concept-diagrams/examples/automated-password-reset-flow.md +276 -0
- package/.mindforge/skills/concept-diagrams/examples/autonomous-llm-research-agent-flow.md +240 -0
- package/.mindforge/skills/concept-diagrams/examples/banana-journey-tree-to-smoothie.md +161 -0
- package/.mindforge/skills/concept-diagrams/examples/commercial-aircraft-structure.md +209 -0
- package/.mindforge/skills/concept-diagrams/examples/cpu-ooo-microarchitecture.md +236 -0
- package/.mindforge/skills/concept-diagrams/examples/electricity-grid-flow.md +182 -0
- package/.mindforge/skills/concept-diagrams/examples/feature-film-production-pipeline.md +172 -0
- package/.mindforge/skills/concept-diagrams/examples/hospital-emergency-department-flow.md +165 -0
- package/.mindforge/skills/concept-diagrams/examples/ml-benchmark-grouped-bar-chart.md +114 -0
- package/.mindforge/skills/concept-diagrams/examples/place-order-uml-sequence.md +325 -0
- package/.mindforge/skills/concept-diagrams/examples/smart-city-infrastructure.md +173 -0
- package/.mindforge/skills/concept-diagrams/examples/smartphone-layer-anatomy.md +154 -0
- package/.mindforge/skills/concept-diagrams/examples/sn2-reaction-mechanism.md +247 -0
- package/.mindforge/skills/concept-diagrams/examples/wind-turbine-structure.md +338 -0
- package/.mindforge/skills/concept-diagrams/references/dashboard-patterns.md +43 -0
- package/.mindforge/skills/concept-diagrams/references/infrastructure-patterns.md +144 -0
- package/.mindforge/skills/concept-diagrams/references/physical-shape-cookbook.md +42 -0
- package/.mindforge/skills/concept-diagrams/templates/template.html +174 -0
- package/.mindforge/skills/creative-ideation/references/full-prompt-library.md +110 -0
- package/.mindforge/skills/documentation/SKILL.md +1 -1
- package/.mindforge/skills/domain-intel/SKILL.md +7 -7
- package/.mindforge/skills/domain-intel/scripts/domain_intel.py +397 -0
- package/.mindforge/skills/duckduckgo-search/SKILL.md +17 -17
- package/.mindforge/skills/duckduckgo-search/scripts/duckduckgo.sh +28 -0
- package/.mindforge/skills/environment-management/SKILL.md +1 -1
- package/.mindforge/skills/github-code-review/SKILL.md +9 -9
- package/.mindforge/skills/github-code-review/references/review-output-template.md +74 -0
- package/.mindforge/skills/github-issues/templates/bug-report.md +35 -0
- package/.mindforge/skills/github-issues/templates/feature-request.md +31 -0
- package/.mindforge/skills/github-pr-workflow/SKILL.md +3 -3
- package/.mindforge/skills/github-pr-workflow/references/ci-troubleshooting.md +183 -0
- package/.mindforge/skills/github-pr-workflow/references/conventional-commits.md +71 -0
- package/.mindforge/skills/github-pr-workflow/templates/pr-body-bugfix.md +35 -0
- package/.mindforge/skills/github-pr-workflow/templates/pr-body-feature.md +33 -0
- package/.mindforge/skills/incident-response/SKILL.md +1 -1
- package/.mindforge/skills/jupyter-live-kernel/SKILL.md +3 -3
- package/.mindforge/skills/kanban-orchestrator/SKILL.md +10 -10
- package/.mindforge/skills/kanban-worker/SKILL.md +6 -6
- package/.mindforge/skills/meme-generation/SKILL.md +1 -1
- package/.mindforge/skills/meme-generation/scripts/generate_meme.py +470 -0
- package/.mindforge/skills/meme-generation/scripts/templates.json +97 -0
- package/.mindforge/skills/obsidian/SKILL.md +15 -15
- package/.mindforge/skills/orch-pipeline/SKILL.md +2 -2
- package/.mindforge/skills/osint-investigation/SKILL.md +3 -2
- package/.mindforge/skills/osint-investigation/references/sources/courtlistener.md +98 -0
- package/.mindforge/skills/osint-investigation/references/sources/gdelt.md +104 -0
- package/.mindforge/skills/osint-investigation/references/sources/icij-offshore.md +104 -0
- package/.mindforge/skills/osint-investigation/references/sources/nyc-acris.md +90 -0
- package/.mindforge/skills/osint-investigation/references/sources/ofac-sdn.md +92 -0
- package/.mindforge/skills/osint-investigation/references/sources/opencorporates.md +103 -0
- package/.mindforge/skills/osint-investigation/references/sources/sec-edgar.md +83 -0
- package/.mindforge/skills/osint-investigation/references/sources/senate-ld.md +89 -0
- package/.mindforge/skills/osint-investigation/references/sources/usaspending.md +97 -0
- package/.mindforge/skills/osint-investigation/references/sources/wayback.md +93 -0
- package/.mindforge/skills/osint-investigation/references/sources/wikipedia.md +107 -0
- package/.mindforge/skills/osint-investigation/scripts/_http.py +82 -0
- package/.mindforge/skills/osint-investigation/scripts/_normalize.py +67 -0
- package/.mindforge/skills/osint-investigation/scripts/build_findings.py +221 -0
- package/.mindforge/skills/osint-investigation/scripts/entity_resolution.py +228 -0
- package/.mindforge/skills/osint-investigation/scripts/fetch_courtlistener.py +149 -0
- package/.mindforge/skills/osint-investigation/scripts/fetch_gdelt.py +161 -0
- package/.mindforge/skills/osint-investigation/scripts/fetch_icij_offshore.py +234 -0
- package/.mindforge/skills/osint-investigation/scripts/fetch_nyc_acris.py +203 -0
- package/.mindforge/skills/osint-investigation/scripts/fetch_ofac_sdn.py +175 -0
- package/.mindforge/skills/osint-investigation/scripts/fetch_opencorporates.py +191 -0
- package/.mindforge/skills/osint-investigation/scripts/fetch_sec_edgar.py +184 -0
- package/.mindforge/skills/osint-investigation/scripts/fetch_senate_ld.py +146 -0
- package/.mindforge/skills/osint-investigation/scripts/fetch_usaspending.py +170 -0
- package/.mindforge/skills/osint-investigation/scripts/fetch_wayback.py +142 -0
- package/.mindforge/skills/osint-investigation/scripts/fetch_wikipedia.py +266 -0
- package/.mindforge/skills/osint-investigation/scripts/timing_analysis.py +252 -0
- package/.mindforge/skills/osint-investigation/templates/source-template.md +59 -0
- package/.mindforge/skills/oss-forensics/SKILL.md +6 -6
- package/.mindforge/skills/oss-forensics/references/evidence-types.md +89 -0
- package/.mindforge/skills/oss-forensics/references/github-archive-guide.md +184 -0
- package/.mindforge/skills/oss-forensics/references/investigation-templates.md +131 -0
- package/.mindforge/skills/oss-forensics/references/recovery-techniques.md +164 -0
- package/.mindforge/skills/oss-forensics/scripts/evidence-store.py +313 -0
- package/.mindforge/skills/oss-forensics/templates/forensic-report.md +151 -0
- package/.mindforge/skills/oss-forensics/templates/malicious-package-report.md +43 -0
- package/.mindforge/skills/pixel-art/SKILL.md +2 -2
- package/.mindforge/skills/pixel-art/references/palettes.md +49 -0
- package/.mindforge/skills/plan/SKILL.md +10 -10
- package/.mindforge/skills/requesting-code-review/SKILL.md +4 -6
- package/.mindforge/skills/research-paper-writing/SKILL.md +32 -32
- package/.mindforge/skills/research-paper-writing/references/autoreason-methodology.md +394 -0
- package/.mindforge/skills/research-paper-writing/references/checklists.md +434 -0
- package/.mindforge/skills/research-paper-writing/references/citation-workflow.md +563 -0
- package/.mindforge/skills/research-paper-writing/references/experiment-patterns.md +728 -0
- package/.mindforge/skills/research-paper-writing/references/human-evaluation.md +476 -0
- package/.mindforge/skills/research-paper-writing/references/paper-types.md +481 -0
- package/.mindforge/skills/research-paper-writing/references/reviewer-guidelines.md +433 -0
- package/.mindforge/skills/research-paper-writing/references/sources.md +191 -0
- package/.mindforge/skills/research-paper-writing/references/writing-guide.md +474 -0
- package/.mindforge/skills/research-paper-writing/templates/README.md +251 -0
- package/.mindforge/skills/scrapling/SKILL.md +1 -1
- package/.mindforge/skills/security-review/SKILL.md +1 -1
- package/.mindforge/skills/sherlock/SKILL.md +1 -1
- package/.mindforge/skills/simplify-code/SKILL.md +5 -7
- package/.mindforge/skills/spike/SKILL.md +11 -13
- package/.mindforge/skills/subagent-driven-development/SKILL.md +7 -11
- package/.mindforge/skills/subagent-driven-development/references/context-budget-discipline.md +53 -0
- package/.mindforge/skills/subagent-driven-development/references/gates-taxonomy.md +93 -0
- package/.mindforge/skills/systematic-debugging/SKILL.md +13 -14
- package/.mindforge/skills/test-driven-development/SKILL.md +7 -8
- package/.mindforge/skills/testing-standards/SKILL.md +1 -1
- package/.mindforge/skills/web-pentest/SKILL.md +2 -2
- package/.mindforge/skills/web-pentest/references/bypass-techniques.md +133 -0
- package/.mindforge/skills/web-pentest/references/exploitation-techniques.md +204 -0
- package/.mindforge/skills/web-pentest/references/scope-enforcement.md +110 -0
- package/.mindforge/skills/web-pentest/references/vuln-taxonomy.md +81 -0
- package/.mindforge/skills/web-pentest/templates/authorization.md +69 -0
- package/.mindforge/skills/web-pentest/templates/pentest-report.md +178 -0
- package/.mindforge/skills/writing-skills/SKILL.md +4 -3
- package/CHANGELOG.md +35 -0
- package/MINDFORGE.md +3 -3
- package/README.md +9 -7
- package/RELEASENOTES.md +65 -2
- package/SECURITY.md +5 -3
- package/bin/autonomous/auto-runner.js +5 -2
- package/bin/engine/skill-loader.js +4 -0
- package/bin/governance/rbac.js +4 -0
- package/bin/memory/eis-client.js +1 -0
- package/bin/mindforge-cli.js +5 -0
- package/bin/models/bedrock-provider.js +192 -0
- package/bin/models/model-client.js +19 -0
- package/bin/spawn-agent.js +9 -2
- package/docs/commands-reference.md +68 -6
- package/docs/faq.md +38 -1
- package/docs/getting-started.md +27 -12
- package/docs/sdk-reference.md +36 -3
- package/docs/troubleshooting.md +59 -1
- package/docs/user-guide.md +7 -4
- package/package.json +3 -3
- package/.claude/commands/mindforge/skill-tdd.md +0 -53
- package/.claude/commands/mindforge/skills-index.md +0 -118
- package/.claude/commands/mindforge/systematic-debug.md +0 -60
- package/.claude/commands/mindforge/wf-accessibility-audit.md +0 -31
- package/.claude/commands/mindforge/wf-ai-model-eval.md +0 -31
- package/.claude/commands/mindforge/wf-api-migration.md +0 -31
- package/.claude/commands/mindforge/wf-architecture-modernization.md +0 -32
- package/.claude/commands/mindforge/wf-catalog.md +0 -59
- package/.claude/commands/mindforge/wf-code-audit.md +0 -31
- package/.claude/commands/mindforge/wf-code-explainer.md +0 -31
- package/.claude/commands/mindforge/wf-competitive-analysis.md +0 -31
- package/.claude/commands/mindforge/wf-competitive-teardown.md +0 -31
- package/.claude/commands/mindforge/wf-cost-analysis.md +0 -31
- package/.claude/commands/mindforge/wf-data-pipeline-validate.md +0 -31
- package/.claude/commands/mindforge/wf-database-migration.md +0 -31
- package/.claude/commands/mindforge/wf-debug-detective.md +0 -32
- package/.claude/commands/mindforge/wf-design-system-audit.md +0 -31
- package/.claude/commands/mindforge/wf-documentation-gen.md +0 -31
- package/.claude/commands/mindforge/wf-feature-planner.md +0 -31
- package/.claude/commands/mindforge/wf-incident-response.md +0 -31
- package/.claude/commands/mindforge/wf-multi-repo-sync.md +0 -31
- package/.claude/commands/mindforge/wf-mutation-testing.md +0 -31
- package/.claude/commands/mindforge/wf-onboard-codebase.md +0 -31
- package/.claude/commands/mindforge/wf-perf-optimize.md +0 -31
- package/.claude/commands/mindforge/wf-pr-review.md +0 -31
- package/.claude/commands/mindforge/wf-refactor-plan.md +0 -31
- package/.claude/commands/mindforge/wf-release-prep.md +0 -31
- package/.claude/commands/mindforge/wf-security-threat-model.md +0 -31
- package/.claude/commands/mindforge/wf-tdd-sprint.md +0 -31
- package/.claude/commands/mindforge/wf-tech-evaluation.md +0 -31
- package/.claude/commands/mindforge/wf-ux-heuristic-audit.md +0 -31
- 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())
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# <Source Name>
|
|
2
|
+
|
|
3
|
+
## 1. Summary
|
|
4
|
+
|
|
5
|
+
What this data source is, who publishes it, why it matters for investigations.
|
|
6
|
+
|
|
7
|
+
## 2. Access Methods
|
|
8
|
+
|
|
9
|
+
- API endpoint(s)
|
|
10
|
+
- Bulk download URLs
|
|
11
|
+
- Auth requirements (none / API key / OAuth)
|
|
12
|
+
- Rate limits
|
|
13
|
+
|
|
14
|
+
## 3. Data Schema
|
|
15
|
+
|
|
16
|
+
Key fields, record types, table relationships. List the columns the fetch
|
|
17
|
+
script emits.
|
|
18
|
+
|
|
19
|
+
## 4. Coverage
|
|
20
|
+
|
|
21
|
+
- Jurisdiction
|
|
22
|
+
- Time range
|
|
23
|
+
- Update frequency
|
|
24
|
+
- Data volume (rows / GB)
|
|
25
|
+
|
|
26
|
+
## 5. Cross-Reference Potential
|
|
27
|
+
|
|
28
|
+
Which other sources can be joined and on what keys. Be explicit:
|
|
29
|
+
|
|
30
|
+
- `<source>` ↔ `<column>` (join key: <normalized entity name / EIN / CIK / etc.>)
|
|
31
|
+
|
|
32
|
+
## 6. Data Quality
|
|
33
|
+
|
|
34
|
+
Known issues — formatting inconsistencies, missing fields, duplicates,
|
|
35
|
+
historical gaps, redaction.
|
|
36
|
+
|
|
37
|
+
## 7. Acquisition Script
|
|
38
|
+
|
|
39
|
+
Path: `scripts/fetch_<source>.py`
|
|
40
|
+
|
|
41
|
+
Example:
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
python3 SKILL_DIR/scripts/fetch_<source>.py --<filter> <value> --out data/<source>.csv
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
Output CSV columns: `<col1>, <col2>, ...`
|
|
48
|
+
|
|
49
|
+
## 8. Legal & Licensing
|
|
50
|
+
|
|
51
|
+
- Public records law / FOIA basis
|
|
52
|
+
- Terms of use / acceptable use
|
|
53
|
+
- Attribution requirements (if any)
|
|
54
|
+
|
|
55
|
+
## 9. References
|
|
56
|
+
|
|
57
|
+
- Official docs: <url>
|
|
58
|
+
- Data dictionary: <url>
|
|
59
|
+
- Related coverage / journalism: <url>
|
|
@@ -26,7 +26,7 @@ Read these before every investigation step. Violating them invalidates the repor
|
|
|
26
26
|
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.
|
|
27
27
|
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.
|
|
28
28
|
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.
|
|
29
|
-
7. **Suspicious Code Rule**: Never run code found inside the investigated repository locally. Analyze statically only, or use `
|
|
29
|
+
7. **Suspicious Code Rule**: Never run code found inside the investigated repository locally. Analyze statically only, or use `Bash` in a sandboxed environment.
|
|
30
30
|
8. **Secret Redaction**: Any API keys, tokens, or credentials discovered during investigation must be redacted in the final report. Log them internally only.
|
|
31
31
|
|
|
32
32
|
---
|
|
@@ -41,7 +41,7 @@ Read these before every investigation step. Violating them invalidates the repor
|
|
|
41
41
|
|
|
42
42
|
> **Path convention**: Throughout this skill, `SKILL_DIR` refers to the root of this skill's
|
|
43
43
|
> installation directory (the folder containing this `SKILL.md`). When the skill is loaded,
|
|
44
|
-
> resolve `SKILL_DIR` to the actual path — e.g. `~/.
|
|
44
|
+
> resolve `SKILL_DIR` to the actual path — e.g. `~/.mindforge/skills/oss-forensics/`
|
|
45
45
|
> or the `optional-skills/` equivalent. All script and template references are relative to it.
|
|
46
46
|
|
|
47
47
|
## Phase 0: Initialization
|
|
@@ -76,7 +76,7 @@ Read these before every investigation step. Violating them invalidates the repor
|
|
|
76
76
|
- Provided Indicators of Compromise: commit SHAs, file paths, package names, IP addresses, domains, API keys/tokens, malicious URLs
|
|
77
77
|
- Any linked vendor security reports or blog posts
|
|
78
78
|
|
|
79
|
-
**Tools**: Reasoning only, or `
|
|
79
|
+
**Tools**: Reasoning only, or `Bash` for regex extraction from large text blocks.
|
|
80
80
|
|
|
81
81
|
**Output**: Populate `iocs.md` with extracted IOCs. Each IOC must have:
|
|
82
82
|
- Type (from: COMMIT_SHA, FILE_PATH, API_KEY, SECRET, IP_ADDRESS, DOMAIN, PACKAGE_NAME, ACTOR_USERNAME, MALICIOUS_URL, OTHER)
|
|
@@ -89,7 +89,7 @@ Read these before every investigation step. Violating them invalidates the repor
|
|
|
89
89
|
|
|
90
90
|
## Phase 2: Parallel Evidence Collection
|
|
91
91
|
|
|
92
|
-
Spawn up to 5 specialist investigator sub-agents using `
|
|
92
|
+
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.
|
|
93
93
|
|
|
94
94
|
> **Orchestrator note**: Pass the IOC list from Phase 1 and the investigation time window in the `context` field of each delegated task.
|
|
95
95
|
|
|
@@ -265,7 +265,7 @@ LIMIT 200
|
|
|
265
265
|
|
|
266
266
|
**Actions**:
|
|
267
267
|
- For each commit SHA: attempt recovery via direct GitHub URL (`github.com/OWNER/REPO/commit/SHA.patch`)
|
|
268
|
-
- For each domain/IP: check passive DNS, WHOIS records (via `
|
|
268
|
+
- For each domain/IP: check passive DNS, WHOIS records (via `WebFetch` on public WHOIS services)
|
|
269
269
|
- For each package name: check npm/PyPI for matching malicious package reports
|
|
270
270
|
- For each actor username: check GitHub profile, contribution history, account age
|
|
271
271
|
- Recover force-pushed commits using 3 methods (see [recovery-techniques.md](./references/recovery-techniques.md))
|
|
@@ -302,7 +302,7 @@ A hypothesis must:
|
|
|
302
302
|
- Typosquatting: near-identical package name targeting misspellers
|
|
303
303
|
- Credential Leak: token/key accidentally committed then force-pushed to erase
|
|
304
304
|
|
|
305
|
-
For each hypothesis, spawn a `
|
|
305
|
+
For each hypothesis, spawn a `Agent` sub-agent to attempt to find disconfirming evidence before confirming.
|
|
306
306
|
|
|
307
307
|
---
|
|
308
308
|
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
# Evidence Types Reference
|
|
2
|
+
|
|
3
|
+
Taxonomy of all evidence types, IOC types, GitHub event types, and observation types
|
|
4
|
+
used in OSS forensic investigations.
|
|
5
|
+
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Evidence Source Types
|
|
9
|
+
|
|
10
|
+
| Type | Description | Example Sources |
|
|
11
|
+
|------|-------------|-----------------|
|
|
12
|
+
| `git` | Data from local git repository analysis | `git log`, `git fsck`, `git reflog`, `git blame` |
|
|
13
|
+
| `gh_api` | Data from GitHub REST API responses | `/repos/.../commits`, `/repos/.../pulls`, `/repos/.../events` |
|
|
14
|
+
| `gh_archive` | Data from GitHub Archive (BigQuery) | `githubarchive.month.*` BigQuery tables |
|
|
15
|
+
| `web_archive` | Archived web pages from Wayback Machine | CDX API results, `web.archive.org/web/...` snapshots |
|
|
16
|
+
| `ioc` | Indicator of Compromise from any source | Extracted from vendor reports, git history, network traces |
|
|
17
|
+
| `analysis` | Derived insight from cross-source correlation | "SHA present in archive but absent from API" |
|
|
18
|
+
| `vendor_report` | External security vendor or researcher report | CVE advisories, blog posts, NVD records |
|
|
19
|
+
| `manual` | Manually recorded observation by investigator | Notes on behavioral patterns, timeline gaps |
|
|
20
|
+
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
## IOC Types
|
|
24
|
+
|
|
25
|
+
| Type | Description | Example |
|
|
26
|
+
|------|-------------|---------|
|
|
27
|
+
| `COMMIT_SHA` | A git commit hash linked to malicious activity | `abc123def456...` |
|
|
28
|
+
| `FILE_PATH` | A suspicious file inside the repository | `src/utils/crypto.js`, `dist/index.min.js` |
|
|
29
|
+
| `API_KEY` | An API key accidentally committed | `AKIA...` (AWS), `ghp_...` (GitHub PAT) |
|
|
30
|
+
| `SECRET` | A generic secret / credential | Database password, private key blob |
|
|
31
|
+
| `IP_ADDRESS` | A C2 server or attacker IP | `192.0.2.1` |
|
|
32
|
+
| `DOMAIN` | A malicious or suspicious domain | `evil-cdn.io`, typosquatted package registry domain |
|
|
33
|
+
| `PACKAGE_NAME` | A malicious or squatted package name | `colo-rs` (typosquatting `color`), `lodash-utils` |
|
|
34
|
+
| `ACTOR_USERNAME` | A GitHub handle linked to the attack | `malicious-bot-account` |
|
|
35
|
+
| `MALICIOUS_URL` | A URL to a malicious resource | `https://evil.example.com/payload.sh` |
|
|
36
|
+
| `WORKFLOW_FILE` | A suspicious CI/CD workflow file | `.github/workflows/release.yml` |
|
|
37
|
+
| `BRANCH_NAME` | A suspicious branch | `refs/heads/temp-fix-do-not-merge` |
|
|
38
|
+
| `TAG_NAME` | A suspicious git tag | `v1.0.0-security-patch` |
|
|
39
|
+
| `RELEASE_NAME` | A suspicious release | Release with no associated tag or changelog |
|
|
40
|
+
| `OTHER` | Catch-all for unclassified IOCs | — |
|
|
41
|
+
|
|
42
|
+
---
|
|
43
|
+
|
|
44
|
+
## GitHub Archive Event Types (12 Types)
|
|
45
|
+
|
|
46
|
+
| Event Type | Forensic Relevance |
|
|
47
|
+
|------------|-------------------|
|
|
48
|
+
| `PushEvent` | Core: `payload.distinct_size=0` with `payload.size>0` → force push. `payload.before`/`payload.head` shows rewritten history. |
|
|
49
|
+
| `PullRequestEvent` | Detects deleted PRs, rapid open→close patterns, PRs from new accounts |
|
|
50
|
+
| `IssueEvent` | Detects deleted issues, coordinated labeling, rapid closure of vulnerability reports |
|
|
51
|
+
| `IssueCommentEvent` | Deleted comments, rapid activity bursts |
|
|
52
|
+
| `WatchEvent` | Star-farming campaigns (coordinated starring from new accounts) |
|
|
53
|
+
| `ForkEvent` | Unusual fork patterns before malicious commit |
|
|
54
|
+
| `CreateEvent` | Branch/tag creation: signals new release or code injection point |
|
|
55
|
+
| `DeleteEvent` | Branch/tag deletion: critical — often used to hide traces |
|
|
56
|
+
| `ReleaseEvent` | Unauthorized releases, release artifacts modified post-publish |
|
|
57
|
+
| `MemberEvent` | Collaborator added/removed: maintainer compromise indicator |
|
|
58
|
+
| `PublicEvent` | Repository made public (sometimes to drop malicious code briefly) |
|
|
59
|
+
| `WorkflowRunEvent` | CI/CD pipeline executions: workflow injection, secret exfiltration |
|
|
60
|
+
|
|
61
|
+
---
|
|
62
|
+
|
|
63
|
+
## Evidence Verification States
|
|
64
|
+
|
|
65
|
+
| State | Meaning |
|
|
66
|
+
|-------|---------|
|
|
67
|
+
| `unverified` | Collected from a single source, not cross-referenced |
|
|
68
|
+
| `single_source` | The primary source has been confirmed directly (e.g., SHA resolves on GitHub), but no second source |
|
|
69
|
+
| `multi_source_verified` | Confirmed from 2+ independent sources (e.g., GH Archive AND GitHub API both show the same event) |
|
|
70
|
+
|
|
71
|
+
Only `multi_source_verified` evidence may be cited as fact in validated hypotheses.
|
|
72
|
+
`unverified` and `single_source` evidence must be labeled `[UNVERIFIED]` or `[SINGLE-SOURCE]`.
|
|
73
|
+
|
|
74
|
+
---
|
|
75
|
+
|
|
76
|
+
## Observation Types (Patterned after RAPTOR)
|
|
77
|
+
|
|
78
|
+
| Type | Description |
|
|
79
|
+
|------|-------------|
|
|
80
|
+
| `CommitObservation` | Specific commit SHA with metadata (author, date, files changed) |
|
|
81
|
+
| `ForceWashObservation` | Evidence that commits were force-erased from a branch |
|
|
82
|
+
| `DanglingCommitObservation` | SHA present in git object store but unreachable from any ref |
|
|
83
|
+
| `IssueObservation` | A GitHub issue (current or archived) with title, body, timestamp |
|
|
84
|
+
| `PRObservation` | A GitHub PR (current or archived) with diff summary, reviewers |
|
|
85
|
+
| `IOC` | A single Indicator of Compromise with context |
|
|
86
|
+
| `TimelineGap` | A period with unusual absence of expected activity |
|
|
87
|
+
| `ActorAnomalyObservation` | Behavioral anomaly for a specific GitHub actor |
|
|
88
|
+
| `WorkflowAnomalyObservation` | Suspicious CI/CD workflow change or unexpected run |
|
|
89
|
+
| `CrossSourceDiscrepancy` | Item present in one source but absent in another (strong deletion indicator) |
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
# GitHub Archive Query Guide (BigQuery)
|
|
2
|
+
|
|
3
|
+
GitHub Archive records every public event on GitHub as immutable JSON records. This data is accessible via Google BigQuery and is the most reliable source for forensic investigation — events cannot be deleted or modified after recording.
|
|
4
|
+
|
|
5
|
+
## Public Dataset
|
|
6
|
+
|
|
7
|
+
- **Project**: `githubarchive`
|
|
8
|
+
- **Tables**: `day.YYYYMMDD`, `month.YYYYMM`, `year.YYYY`
|
|
9
|
+
- **Cost**: $6.25 per TiB scanned. Always run dry runs first.
|
|
10
|
+
- **Access**: Requires a Google Cloud account with BigQuery enabled. Free tier includes 1 TiB/month of queries.
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
## The 12 GitHub Event Types
|
|
15
|
+
|
|
16
|
+
| Event Type | What It Records | Forensic Value |
|
|
17
|
+
|------------|-----------------|----------------|
|
|
18
|
+
| `PushEvent` | Commits pushed to a branch | Force-push detection, commit timeline, author attribution |
|
|
19
|
+
| `PullRequestEvent` | PR opened, closed, merged, reopened | Deleted PR recovery, review timeline |
|
|
20
|
+
| `IssuesEvent` | Issue opened, closed, reopened, labeled | Deleted issue recovery, social engineering traces |
|
|
21
|
+
| `IssueCommentEvent` | Comments on issues and PRs | Deleted comment recovery, communication patterns |
|
|
22
|
+
| `CreateEvent` | Branch, tag, or repository creation | Suspicious branch creation, tag timing |
|
|
23
|
+
| `DeleteEvent` | Branch or tag deletion | Evidence of cleanup after compromise |
|
|
24
|
+
| `MemberEvent` | Collaborator added or removed | Permission changes, access escalation |
|
|
25
|
+
| `PublicEvent` | Repository made public | Accidental exposure of private repos |
|
|
26
|
+
| `WatchEvent` | User stars a repository | Actor reconnaissance patterns |
|
|
27
|
+
| `ForkEvent` | Repository forked | Exfiltration of code before cleanup |
|
|
28
|
+
| `ReleaseEvent` | Release published, edited, deleted | Malicious release injection, deleted release recovery |
|
|
29
|
+
| `WorkflowRunEvent` | GitHub Actions workflow triggered | CI/CD abuse, unauthorized workflow runs |
|
|
30
|
+
|
|
31
|
+
---
|
|
32
|
+
|
|
33
|
+
## Query Templates
|
|
34
|
+
|
|
35
|
+
### Basic: All Events for a Repository
|
|
36
|
+
|
|
37
|
+
```sql
|
|
38
|
+
SELECT
|
|
39
|
+
created_at,
|
|
40
|
+
type,
|
|
41
|
+
actor.login,
|
|
42
|
+
repo.name,
|
|
43
|
+
payload
|
|
44
|
+
FROM
|
|
45
|
+
`githubarchive.day.20240101` -- Adjust date
|
|
46
|
+
WHERE
|
|
47
|
+
repo.name = 'owner/repo'
|
|
48
|
+
AND type IN ('PushEvent', 'DeleteEvent', 'MemberEvent')
|
|
49
|
+
ORDER BY
|
|
50
|
+
created_at ASC
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
### Force-Push Detection
|
|
54
|
+
|
|
55
|
+
Force-pushes produce PushEvents where commits are overwritten. Key indicators:
|
|
56
|
+
- `payload.distinct_size = 0` with `payload.size > 0` → commits were erased
|
|
57
|
+
- `payload.before` contains the SHA before the rewrite (recoverable)
|
|
58
|
+
|
|
59
|
+
```sql
|
|
60
|
+
SELECT
|
|
61
|
+
created_at,
|
|
62
|
+
actor.login,
|
|
63
|
+
JSON_EXTRACT_SCALAR(payload, '$.before') AS before_sha,
|
|
64
|
+
JSON_EXTRACT_SCALAR(payload, '$.head') AS after_sha,
|
|
65
|
+
JSON_EXTRACT_SCALAR(payload, '$.size') AS total_commits,
|
|
66
|
+
JSON_EXTRACT_SCALAR(payload, '$.distinct_size') AS distinct_commits,
|
|
67
|
+
JSON_EXTRACT_SCALAR(payload, '$.ref') AS branch_ref
|
|
68
|
+
FROM
|
|
69
|
+
`githubarchive.month.*`
|
|
70
|
+
WHERE
|
|
71
|
+
_TABLE_SUFFIX BETWEEN '202401' AND '202403'
|
|
72
|
+
AND type = 'PushEvent'
|
|
73
|
+
AND repo.name = 'owner/repo'
|
|
74
|
+
AND CAST(JSON_EXTRACT_SCALAR(payload, '$.distinct_size') AS INT64) = 0
|
|
75
|
+
ORDER BY
|
|
76
|
+
created_at ASC
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### Deleted Branch/Tag Detection
|
|
80
|
+
|
|
81
|
+
```sql
|
|
82
|
+
SELECT
|
|
83
|
+
created_at,
|
|
84
|
+
actor.login,
|
|
85
|
+
JSON_EXTRACT_SCALAR(payload, '$.ref') AS deleted_ref,
|
|
86
|
+
JSON_EXTRACT_SCALAR(payload, '$.ref_type') AS ref_type
|
|
87
|
+
FROM
|
|
88
|
+
`githubarchive.month.*`
|
|
89
|
+
WHERE
|
|
90
|
+
_TABLE_SUFFIX BETWEEN '202401' AND '202403'
|
|
91
|
+
AND type = 'DeleteEvent'
|
|
92
|
+
AND repo.name = 'owner/repo'
|
|
93
|
+
ORDER BY
|
|
94
|
+
created_at ASC
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
### Collaborator Permission Changes
|
|
98
|
+
|
|
99
|
+
```sql
|
|
100
|
+
SELECT
|
|
101
|
+
created_at,
|
|
102
|
+
actor.login,
|
|
103
|
+
JSON_EXTRACT_SCALAR(payload, '$.action') AS action,
|
|
104
|
+
JSON_EXTRACT_SCALAR(payload, '$.member.login') AS member
|
|
105
|
+
FROM
|
|
106
|
+
`githubarchive.month.*`
|
|
107
|
+
WHERE
|
|
108
|
+
_TABLE_SUFFIX BETWEEN '202401' AND '202403'
|
|
109
|
+
AND type = 'MemberEvent'
|
|
110
|
+
AND repo.name = 'owner/repo'
|
|
111
|
+
ORDER BY
|
|
112
|
+
created_at ASC
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
### CI/CD Workflow Activity
|
|
116
|
+
|
|
117
|
+
```sql
|
|
118
|
+
SELECT
|
|
119
|
+
created_at,
|
|
120
|
+
actor.login,
|
|
121
|
+
JSON_EXTRACT_SCALAR(payload, '$.action') AS action,
|
|
122
|
+
JSON_EXTRACT_SCALAR(payload, '$.workflow_run.name') AS workflow_name,
|
|
123
|
+
JSON_EXTRACT_SCALAR(payload, '$.workflow_run.conclusion') AS conclusion,
|
|
124
|
+
JSON_EXTRACT_SCALAR(payload, '$.workflow_run.head_sha') AS head_sha
|
|
125
|
+
FROM
|
|
126
|
+
`githubarchive.month.*`
|
|
127
|
+
WHERE
|
|
128
|
+
_TABLE_SUFFIX BETWEEN '202401' AND '202403'
|
|
129
|
+
AND type = 'WorkflowRunEvent'
|
|
130
|
+
AND repo.name = 'owner/repo'
|
|
131
|
+
ORDER BY
|
|
132
|
+
created_at ASC
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
### Actor Activity Profiling
|
|
136
|
+
|
|
137
|
+
```sql
|
|
138
|
+
SELECT
|
|
139
|
+
type,
|
|
140
|
+
COUNT(*) AS event_count,
|
|
141
|
+
MIN(created_at) AS first_event,
|
|
142
|
+
MAX(created_at) AS last_event
|
|
143
|
+
FROM
|
|
144
|
+
`githubarchive.month.*`
|
|
145
|
+
WHERE
|
|
146
|
+
_TABLE_SUFFIX BETWEEN '202301' AND '202412'
|
|
147
|
+
AND actor.login = 'suspicious-username'
|
|
148
|
+
GROUP BY type
|
|
149
|
+
ORDER BY event_count DESC
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
---
|
|
153
|
+
|
|
154
|
+
## Cost Optimization (MANDATORY)
|
|
155
|
+
|
|
156
|
+
1. **Always dry run first**: Add `--dry_run` flag to `bq query` to see estimated bytes scanned before executing.
|
|
157
|
+
2. **Use `_TABLE_SUFFIX`**: Narrow the date range as much as possible. `day.*` tables are cheapest for narrow windows; `month.*` for broader sweeps.
|
|
158
|
+
3. **Select only needed columns**: Avoid `SELECT *`. The `payload` column is large — only select specific JSON paths.
|
|
159
|
+
4. **Add LIMIT**: Use `LIMIT 1000` during exploration. Remove only for final exhaustive queries.
|
|
160
|
+
5. **Column filtering in WHERE**: Filter on indexed columns (`type`, `repo.name`, `actor.login`) before payload extraction.
|
|
161
|
+
|
|
162
|
+
**Cost estimation**: A single month of GH Archive data is ~1-2 TiB uncompressed. Querying a specific repo + event type with `_TABLE_SUFFIX` typically scans 1-10 GiB ($0.006-$0.06).
|
|
163
|
+
|
|
164
|
+
---
|
|
165
|
+
|
|
166
|
+
## Accessing via the agent
|
|
167
|
+
|
|
168
|
+
**Option A: BigQuery CLI** (if `gcloud` is installed)
|
|
169
|
+
```bash
|
|
170
|
+
bq query --use_legacy_sql=false --format=json "YOUR QUERY"
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
**Option B: Python** (via `execute_code`)
|
|
174
|
+
```python
|
|
175
|
+
from google.cloud import bigquery
|
|
176
|
+
client = bigquery.Client()
|
|
177
|
+
query = "YOUR QUERY"
|
|
178
|
+
results = client.query(query).result()
|
|
179
|
+
for row in results:
|
|
180
|
+
print(dict(row))
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
**Option C: No GCP credentials available**
|
|
184
|
+
If BigQuery is unavailable, document this limitation in the report. Use the other 4 investigators (Git, GitHub API, Wayback Machine, IOC Enrichment) — they cover most investigation needs without BigQuery.
|