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,397 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
Domain Intelligence — Passive OSINT via Python stdlib.
|
|
4
|
+
|
|
5
|
+
Usage:
|
|
6
|
+
python domain_intel.py subdomains example.com
|
|
7
|
+
python domain_intel.py ssl example.com
|
|
8
|
+
python domain_intel.py whois example.com
|
|
9
|
+
python domain_intel.py dns example.com
|
|
10
|
+
python domain_intel.py available example.com
|
|
11
|
+
python domain_intel.py bulk example.com github.com google.com --checks ssl,dns
|
|
12
|
+
|
|
13
|
+
All output is structured JSON. No dependencies beyond Python stdlib.
|
|
14
|
+
Works on Linux, macOS, and Windows.
|
|
15
|
+
"""
|
|
16
|
+
|
|
17
|
+
import json
|
|
18
|
+
import re
|
|
19
|
+
import socket
|
|
20
|
+
import ssl
|
|
21
|
+
import sys
|
|
22
|
+
import urllib.request
|
|
23
|
+
import urllib.parse
|
|
24
|
+
from concurrent.futures import ThreadPoolExecutor, as_completed
|
|
25
|
+
from datetime import datetime, timezone
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
# ─── Subdomain Discovery (crt.sh) ──────────────────────────────────────────
|
|
29
|
+
|
|
30
|
+
def subdomains(domain, include_expired=False, limit=200):
|
|
31
|
+
"""Find subdomains via Certificate Transparency logs."""
|
|
32
|
+
url = f"https://crt.sh/?q=%25.{urllib.parse.quote(domain)}&output=json"
|
|
33
|
+
req = urllib.request.Request(url, headers={
|
|
34
|
+
"User-Agent": "domain-intel-skill/1.0", "Accept": "application/json",
|
|
35
|
+
})
|
|
36
|
+
with urllib.request.urlopen(req, timeout=15) as r:
|
|
37
|
+
entries = json.loads(r.read().decode())
|
|
38
|
+
|
|
39
|
+
seen, results = set(), []
|
|
40
|
+
now = datetime.now(timezone.utc)
|
|
41
|
+
for e in entries:
|
|
42
|
+
not_after = e.get("not_after", "")
|
|
43
|
+
if not include_expired and not_after:
|
|
44
|
+
try:
|
|
45
|
+
dt = datetime.strptime(not_after[:19], "%Y-%m-%dT%H:%M:%S").replace(tzinfo=timezone.utc)
|
|
46
|
+
if dt <= now:
|
|
47
|
+
continue
|
|
48
|
+
except ValueError:
|
|
49
|
+
pass
|
|
50
|
+
for name in e.get("name_value", "").splitlines():
|
|
51
|
+
name = name.strip().lower()
|
|
52
|
+
if name and name not in seen:
|
|
53
|
+
seen.add(name)
|
|
54
|
+
results.append({
|
|
55
|
+
"subdomain": name,
|
|
56
|
+
"issuer": e.get("issuer_name", ""),
|
|
57
|
+
"not_after": not_after,
|
|
58
|
+
})
|
|
59
|
+
|
|
60
|
+
results.sort(key=lambda r: (r["subdomain"].startswith("*"), r["subdomain"]))
|
|
61
|
+
return {"domain": domain, "count": min(len(results), limit), "subdomains": results[:limit]}
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
# ─── SSL Certificate Inspection ────────────────────────────────────────────
|
|
65
|
+
|
|
66
|
+
def check_ssl(host, port=443, timeout=10):
|
|
67
|
+
"""Inspect the TLS certificate of a host."""
|
|
68
|
+
def flat(rdns):
|
|
69
|
+
r = {}
|
|
70
|
+
for rdn in rdns:
|
|
71
|
+
for item in rdn:
|
|
72
|
+
if isinstance(item, (list, tuple)) and len(item) == 2:
|
|
73
|
+
r[item[0]] = item[1]
|
|
74
|
+
return r
|
|
75
|
+
|
|
76
|
+
def parse_date(s):
|
|
77
|
+
for fmt in ("%b %d %H:%M:%S %Y %Z", "%b %d %H:%M:%S %Y %Z"):
|
|
78
|
+
try:
|
|
79
|
+
return datetime.strptime(s, fmt).replace(tzinfo=timezone.utc)
|
|
80
|
+
except ValueError:
|
|
81
|
+
pass
|
|
82
|
+
return None
|
|
83
|
+
|
|
84
|
+
warning = None
|
|
85
|
+
try:
|
|
86
|
+
ctx = ssl.create_default_context()
|
|
87
|
+
with socket.create_connection((host, port), timeout=timeout) as sock:
|
|
88
|
+
with ctx.wrap_socket(sock, server_hostname=host) as s:
|
|
89
|
+
cert, cipher, proto = s.getpeercert(), s.cipher(), s.version()
|
|
90
|
+
except ssl.SSLCertVerificationError as e:
|
|
91
|
+
warning = str(e)
|
|
92
|
+
ctx = ssl.create_default_context()
|
|
93
|
+
ctx.check_hostname = False
|
|
94
|
+
ctx.verify_mode = ssl.CERT_NONE
|
|
95
|
+
with socket.create_connection((host, port), timeout=timeout) as sock:
|
|
96
|
+
with ctx.wrap_socket(sock, server_hostname=host) as s:
|
|
97
|
+
cert, cipher, proto = s.getpeercert(), s.cipher(), s.version()
|
|
98
|
+
|
|
99
|
+
not_after = parse_date(cert.get("notAfter", ""))
|
|
100
|
+
now = datetime.now(timezone.utc)
|
|
101
|
+
days = (not_after - now).days if not_after else None
|
|
102
|
+
is_expired = days is not None and days < 0
|
|
103
|
+
|
|
104
|
+
if is_expired:
|
|
105
|
+
status = f"EXPIRED ({abs(days)} days ago)"
|
|
106
|
+
elif days is not None and days <= 14:
|
|
107
|
+
status = f"CRITICAL — {days} day(s) left"
|
|
108
|
+
elif days is not None and days <= 30:
|
|
109
|
+
status = f"WARNING — {days} day(s) left"
|
|
110
|
+
else:
|
|
111
|
+
status = f"OK — {days} day(s) remaining" if days is not None else "unknown"
|
|
112
|
+
|
|
113
|
+
return {
|
|
114
|
+
"host": host, "port": port,
|
|
115
|
+
"subject": flat(cert.get("subject", [])),
|
|
116
|
+
"issuer": flat(cert.get("issuer", [])),
|
|
117
|
+
"subject_alt_names": [f"{t}:{v}" for t, v in cert.get("subjectAltName", [])],
|
|
118
|
+
"not_before": parse_date(cert.get("notBefore", "")).isoformat() if parse_date(cert.get("notBefore", "")) else "",
|
|
119
|
+
"not_after": not_after.isoformat() if not_after else "",
|
|
120
|
+
"days_remaining": days, "is_expired": is_expired, "expiry_status": status,
|
|
121
|
+
"tls_version": proto,
|
|
122
|
+
"cipher_suite": cipher[0] if cipher else None,
|
|
123
|
+
"serial_number": cert.get("serialNumber", ""),
|
|
124
|
+
"verification_warning": warning,
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
# ─── WHOIS Lookup ──────────────────────────────────────────────────────────
|
|
129
|
+
|
|
130
|
+
WHOIS_SERVERS = {
|
|
131
|
+
"com": "whois.verisign-grs.com", "net": "whois.verisign-grs.com",
|
|
132
|
+
"org": "whois.pir.org", "io": "whois.nic.io", "co": "whois.nic.co",
|
|
133
|
+
"ai": "whois.nic.ai", "dev": "whois.nic.google", "app": "whois.nic.google",
|
|
134
|
+
"tech": "whois.nic.tech", "shop": "whois.nic.shop", "store": "whois.nic.store",
|
|
135
|
+
"online": "whois.nic.online", "site": "whois.nic.site", "cloud": "whois.nic.cloud",
|
|
136
|
+
"digital": "whois.nic.digital", "media": "whois.nic.media", "blog": "whois.nic.blog",
|
|
137
|
+
"info": "whois.afilias.net", "biz": "whois.biz", "me": "whois.nic.me",
|
|
138
|
+
"tv": "whois.nic.tv", "cc": "whois.nic.cc", "ws": "whois.website.ws",
|
|
139
|
+
"uk": "whois.nic.uk", "co.uk": "whois.nic.uk", "de": "whois.denic.de",
|
|
140
|
+
"nl": "whois.domain-registry.nl", "fr": "whois.nic.fr", "it": "whois.nic.it",
|
|
141
|
+
"es": "whois.nic.es", "pl": "whois.dns.pl", "ru": "whois.tcinet.ru",
|
|
142
|
+
"se": "whois.iis.se", "no": "whois.norid.no", "fi": "whois.fi",
|
|
143
|
+
"ch": "whois.nic.ch", "at": "whois.nic.at", "be": "whois.dns.be",
|
|
144
|
+
"cz": "whois.nic.cz", "br": "whois.registro.br", "ca": "whois.cira.ca",
|
|
145
|
+
"mx": "whois.mx", "au": "whois.auda.org.au", "jp": "whois.jprs.jp",
|
|
146
|
+
"cn": "whois.cnnic.cn", "in": "whois.inregistry.net", "kr": "whois.kr",
|
|
147
|
+
"sg": "whois.sgnic.sg", "hk": "whois.hkirc.hk", "tr": "whois.nic.tr",
|
|
148
|
+
"ae": "whois.aeda.net.ae", "za": "whois.registry.net.za",
|
|
149
|
+
"space": "whois.nic.space", "zone": "whois.nic.zone", "ninja": "whois.nic.ninja",
|
|
150
|
+
"guru": "whois.nic.guru", "rocks": "whois.nic.rocks", "live": "whois.nic.live",
|
|
151
|
+
"game": "whois.nic.game", "games": "whois.nic.games",
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
def whois_lookup(domain):
|
|
156
|
+
"""Query WHOIS servers for domain registration info."""
|
|
157
|
+
parts = domain.split(".")
|
|
158
|
+
server = WHOIS_SERVERS.get(".".join(parts[-2:])) or WHOIS_SERVERS.get(parts[-1])
|
|
159
|
+
if not server:
|
|
160
|
+
return {"error": f"No WHOIS server for .{parts[-1]}"}
|
|
161
|
+
|
|
162
|
+
try:
|
|
163
|
+
with socket.create_connection((server, 43), timeout=10) as s:
|
|
164
|
+
s.sendall((domain + "\r\n").encode())
|
|
165
|
+
chunks = []
|
|
166
|
+
while True:
|
|
167
|
+
c = s.recv(4096)
|
|
168
|
+
if not c:
|
|
169
|
+
break
|
|
170
|
+
chunks.append(c)
|
|
171
|
+
raw = b"".join(chunks).decode("utf-8", errors="replace")
|
|
172
|
+
except Exception as e:
|
|
173
|
+
return {"error": str(e)}
|
|
174
|
+
|
|
175
|
+
patterns = {
|
|
176
|
+
"registrar": r"(?:Registrar|registrar):\s*(.+)",
|
|
177
|
+
"creation_date": r"(?:Creation Date|Created|created):\s*(.+)",
|
|
178
|
+
"expiration_date": r"(?:Registry Expiry Date|Expiration Date|Expiry Date):\s*(.+)",
|
|
179
|
+
"updated_date": r"(?:Updated Date|Last Modified):\s*(.+)",
|
|
180
|
+
"name_servers": r"(?:Name Server|nserver):\s*(.+)",
|
|
181
|
+
"status": r"(?:Domain Status|status):\s*(.+)",
|
|
182
|
+
"dnssec": r"DNSSEC:\s*(.+)",
|
|
183
|
+
}
|
|
184
|
+
result = {"domain": domain, "whois_server": server}
|
|
185
|
+
for key, pat in patterns.items():
|
|
186
|
+
matches = re.findall(pat, raw, re.IGNORECASE)
|
|
187
|
+
if matches:
|
|
188
|
+
if key in {"name_servers", "status"}:
|
|
189
|
+
result[key] = list(dict.fromkeys(m.strip().lower() for m in matches))
|
|
190
|
+
else:
|
|
191
|
+
result[key] = matches[0].strip()
|
|
192
|
+
|
|
193
|
+
for field in ("creation_date", "expiration_date", "updated_date"):
|
|
194
|
+
if field in result:
|
|
195
|
+
for fmt in ("%Y-%m-%dT%H:%M:%S", "%Y-%m-%dT%H:%M:%SZ", "%Y-%m-%d %H:%M:%S", "%Y-%m-%d"):
|
|
196
|
+
try:
|
|
197
|
+
dt = datetime.strptime(result[field][:19], fmt).replace(tzinfo=timezone.utc)
|
|
198
|
+
result[field] = dt.isoformat()
|
|
199
|
+
if field == "expiration_date":
|
|
200
|
+
days = (dt - datetime.now(timezone.utc)).days
|
|
201
|
+
result["expiration_days_remaining"] = days
|
|
202
|
+
result["is_expired"] = days < 0
|
|
203
|
+
break
|
|
204
|
+
except ValueError:
|
|
205
|
+
pass
|
|
206
|
+
return result
|
|
207
|
+
|
|
208
|
+
|
|
209
|
+
# ─── DNS Records ───────────────────────────────────────────────────────────
|
|
210
|
+
|
|
211
|
+
def dns_records(domain, types=None):
|
|
212
|
+
"""Resolve DNS records using system DNS + Google DoH."""
|
|
213
|
+
if not types:
|
|
214
|
+
types = ["A", "AAAA", "MX", "NS", "TXT", "CNAME"]
|
|
215
|
+
records = {}
|
|
216
|
+
|
|
217
|
+
for qtype in types:
|
|
218
|
+
if qtype == "A":
|
|
219
|
+
try:
|
|
220
|
+
records["A"] = list(dict.fromkeys(
|
|
221
|
+
i[4][0] for i in socket.getaddrinfo(domain, None, socket.AF_INET)
|
|
222
|
+
))
|
|
223
|
+
except Exception:
|
|
224
|
+
records["A"] = []
|
|
225
|
+
elif qtype == "AAAA":
|
|
226
|
+
try:
|
|
227
|
+
records["AAAA"] = list(dict.fromkeys(
|
|
228
|
+
i[4][0] for i in socket.getaddrinfo(domain, None, socket.AF_INET6)
|
|
229
|
+
))
|
|
230
|
+
except Exception:
|
|
231
|
+
records["AAAA"] = []
|
|
232
|
+
else:
|
|
233
|
+
url = f"https://dns.google/resolve?name={urllib.parse.quote(domain)}&type={qtype}"
|
|
234
|
+
try:
|
|
235
|
+
req = urllib.request.Request(url, headers={"User-Agent": "domain-intel-skill/1.0"})
|
|
236
|
+
with urllib.request.urlopen(req, timeout=10) as r:
|
|
237
|
+
data = json.loads(r.read())
|
|
238
|
+
records[qtype] = [
|
|
239
|
+
a.get("data", "").strip().rstrip(".")
|
|
240
|
+
for a in data.get("Answer", []) if a.get("data")
|
|
241
|
+
]
|
|
242
|
+
except Exception:
|
|
243
|
+
records[qtype] = []
|
|
244
|
+
|
|
245
|
+
return {"domain": domain, "records": records}
|
|
246
|
+
|
|
247
|
+
|
|
248
|
+
# ─── Domain Availability Check ─────────────────────────────────────────────
|
|
249
|
+
|
|
250
|
+
def check_available(domain):
|
|
251
|
+
"""Check domain availability using passive signals (DNS + WHOIS + SSL)."""
|
|
252
|
+
signals = {}
|
|
253
|
+
|
|
254
|
+
# DNS
|
|
255
|
+
try:
|
|
256
|
+
a = [i[4][0] for i in socket.getaddrinfo(domain, None, socket.AF_INET)]
|
|
257
|
+
except Exception:
|
|
258
|
+
a = []
|
|
259
|
+
|
|
260
|
+
try:
|
|
261
|
+
ns_url = f"https://dns.google/resolve?name={urllib.parse.quote(domain)}&type=NS"
|
|
262
|
+
req = urllib.request.Request(ns_url, headers={"User-Agent": "domain-intel-skill/1.0"})
|
|
263
|
+
with urllib.request.urlopen(req, timeout=10) as r:
|
|
264
|
+
ns = [x.get("data", "") for x in json.loads(r.read()).get("Answer", [])]
|
|
265
|
+
except Exception:
|
|
266
|
+
ns = []
|
|
267
|
+
|
|
268
|
+
signals["dns_a"] = a
|
|
269
|
+
signals["dns_ns"] = ns
|
|
270
|
+
dns_exists = bool(a or ns)
|
|
271
|
+
|
|
272
|
+
# SSL
|
|
273
|
+
ssl_up = False
|
|
274
|
+
try:
|
|
275
|
+
ctx = ssl.create_default_context()
|
|
276
|
+
ctx.check_hostname = False
|
|
277
|
+
ctx.verify_mode = ssl.CERT_NONE
|
|
278
|
+
with socket.create_connection((domain, 443), timeout=3) as s:
|
|
279
|
+
with ctx.wrap_socket(s, server_hostname=domain):
|
|
280
|
+
ssl_up = True
|
|
281
|
+
except Exception:
|
|
282
|
+
pass
|
|
283
|
+
signals["ssl_reachable"] = ssl_up
|
|
284
|
+
|
|
285
|
+
# WHOIS (quick check)
|
|
286
|
+
tld = domain.rsplit(".", 1)[-1]
|
|
287
|
+
server = WHOIS_SERVERS.get(tld)
|
|
288
|
+
whois_avail = None
|
|
289
|
+
whois_note = ""
|
|
290
|
+
if server:
|
|
291
|
+
try:
|
|
292
|
+
with socket.create_connection((server, 43), timeout=10) as s:
|
|
293
|
+
s.sendall((domain + "\r\n").encode())
|
|
294
|
+
raw = b""
|
|
295
|
+
while True:
|
|
296
|
+
c = s.recv(4096)
|
|
297
|
+
if not c:
|
|
298
|
+
break
|
|
299
|
+
raw += c
|
|
300
|
+
raw = raw.decode("utf-8", errors="replace").lower()
|
|
301
|
+
if any(p in raw for p in ["no match", "not found", "no data found", "status: free"]):
|
|
302
|
+
whois_avail = True
|
|
303
|
+
whois_note = "WHOIS: not found"
|
|
304
|
+
elif "registrar:" in raw or "creation date:" in raw:
|
|
305
|
+
whois_avail = False
|
|
306
|
+
whois_note = "WHOIS: registered"
|
|
307
|
+
else:
|
|
308
|
+
whois_note = "WHOIS: inconclusive"
|
|
309
|
+
except Exception as e:
|
|
310
|
+
whois_note = f"WHOIS error: {e}"
|
|
311
|
+
|
|
312
|
+
signals["whois_available"] = whois_avail
|
|
313
|
+
signals["whois_note"] = whois_note
|
|
314
|
+
|
|
315
|
+
if not dns_exists and whois_avail is True:
|
|
316
|
+
verdict, conf = "LIKELY AVAILABLE", "high"
|
|
317
|
+
elif dns_exists or whois_avail is False or ssl_up:
|
|
318
|
+
verdict, conf = "REGISTERED / IN USE", "high"
|
|
319
|
+
elif not dns_exists and whois_avail is None:
|
|
320
|
+
verdict, conf = "POSSIBLY AVAILABLE", "medium"
|
|
321
|
+
else:
|
|
322
|
+
verdict, conf = "UNCERTAIN", "low"
|
|
323
|
+
|
|
324
|
+
return {"domain": domain, "verdict": verdict, "confidence": conf, "signals": signals}
|
|
325
|
+
|
|
326
|
+
|
|
327
|
+
# ─── Bulk Analysis ─────────────────────────────────────────────────────────
|
|
328
|
+
|
|
329
|
+
COMMAND_MAP = {
|
|
330
|
+
"subdomains": subdomains,
|
|
331
|
+
"ssl": check_ssl,
|
|
332
|
+
"whois": whois_lookup,
|
|
333
|
+
"dns": dns_records,
|
|
334
|
+
"available": check_available,
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
|
|
338
|
+
def bulk_check(domains, checks=None, max_workers=5):
|
|
339
|
+
"""Run multiple checks across multiple domains in parallel."""
|
|
340
|
+
if not checks:
|
|
341
|
+
checks = ["ssl", "whois", "dns"]
|
|
342
|
+
|
|
343
|
+
def run_one(d):
|
|
344
|
+
entry = {"domain": d}
|
|
345
|
+
for check in checks:
|
|
346
|
+
fn = COMMAND_MAP.get(check)
|
|
347
|
+
if fn:
|
|
348
|
+
try:
|
|
349
|
+
entry[check] = fn(d)
|
|
350
|
+
except Exception as e:
|
|
351
|
+
entry[check] = {"error": str(e)}
|
|
352
|
+
return entry
|
|
353
|
+
|
|
354
|
+
results = []
|
|
355
|
+
with ThreadPoolExecutor(max_workers=min(max_workers, 10)) as ex:
|
|
356
|
+
futures = {ex.submit(run_one, d): d for d in domains[:20]}
|
|
357
|
+
for f in as_completed(futures):
|
|
358
|
+
results.append(f.result())
|
|
359
|
+
|
|
360
|
+
return {"total": len(results), "checks": checks, "results": results}
|
|
361
|
+
|
|
362
|
+
|
|
363
|
+
# ─── CLI Entry Point ───────────────────────────────────────────────────────
|
|
364
|
+
|
|
365
|
+
def main():
|
|
366
|
+
if len(sys.argv) < 3:
|
|
367
|
+
print(__doc__)
|
|
368
|
+
sys.exit(1)
|
|
369
|
+
|
|
370
|
+
command = sys.argv[1].lower()
|
|
371
|
+
args = sys.argv[2:]
|
|
372
|
+
|
|
373
|
+
if command == "bulk":
|
|
374
|
+
# Parse --checks flag
|
|
375
|
+
checks = None
|
|
376
|
+
domains = []
|
|
377
|
+
i = 0
|
|
378
|
+
while i < len(args):
|
|
379
|
+
if args[i] == "--checks" and i + 1 < len(args):
|
|
380
|
+
checks = [c.strip() for c in args[i + 1].split(",")]
|
|
381
|
+
i += 2
|
|
382
|
+
else:
|
|
383
|
+
domains.append(args[i])
|
|
384
|
+
i += 1
|
|
385
|
+
result = bulk_check(domains, checks)
|
|
386
|
+
elif command in COMMAND_MAP:
|
|
387
|
+
result = COMMAND_MAP[command](args[0])
|
|
388
|
+
else:
|
|
389
|
+
print(f"Unknown command: {command}")
|
|
390
|
+
print(f"Available: {', '.join(COMMAND_MAP.keys())}, bulk")
|
|
391
|
+
sys.exit(1)
|
|
392
|
+
|
|
393
|
+
print(json.dumps(result, indent=2))
|
|
394
|
+
|
|
395
|
+
|
|
396
|
+
if __name__ == "__main__":
|
|
397
|
+
main()
|
|
@@ -11,7 +11,7 @@ triggers: duckduckgo search, DDG search, web search duckduckgo, privacy search,
|
|
|
11
11
|
|
|
12
12
|
Free web search using DuckDuckGo. **No API key required.**
|
|
13
13
|
|
|
14
|
-
Preferred when `
|
|
14
|
+
Preferred when `WebSearch` is unavailable or unsuitable (for example when `FIRECRAWL_API_KEY` is not set). Can also be used as a standalone search path when DuckDuckGo results are specifically desired.
|
|
15
15
|
|
|
16
16
|
## Detection Flow
|
|
17
17
|
|
|
@@ -23,15 +23,15 @@ command -v ddgs >/dev/null && echo "DDGS_CLI=installed" || echo "DDGS_CLI=missin
|
|
|
23
23
|
```
|
|
24
24
|
|
|
25
25
|
Decision tree:
|
|
26
|
-
1. If `ddgs` CLI is installed, prefer `
|
|
27
|
-
2. If `ddgs` CLI is missing, do not assume `
|
|
26
|
+
1. If `ddgs` CLI is installed, prefer `Bash` + `ddgs`
|
|
27
|
+
2. If `ddgs` CLI is missing, do not assume `Bash` can import `ddgs`
|
|
28
28
|
3. If the user wants DuckDuckGo specifically, install `ddgs` first in the relevant environment
|
|
29
29
|
4. Otherwise fall back to built-in web/browser tools
|
|
30
30
|
|
|
31
31
|
Important runtime note:
|
|
32
|
-
- Terminal and `
|
|
33
|
-
- A successful shell install does not guarantee `
|
|
34
|
-
- Never assume third-party Python packages are preinstalled inside `
|
|
32
|
+
- Terminal and `Bash` are separate runtimes
|
|
33
|
+
- A successful shell install does not guarantee `Bash` can import `ddgs`
|
|
34
|
+
- Never assume third-party Python packages are preinstalled inside `Bash`
|
|
35
35
|
|
|
36
36
|
## Installation
|
|
37
37
|
|
|
@@ -49,7 +49,7 @@ If a workflow depends on Python imports, verify that same runtime can import `dd
|
|
|
49
49
|
|
|
50
50
|
## Method 1: CLI Search (Preferred)
|
|
51
51
|
|
|
52
|
-
Use the `ddgs` command via `
|
|
52
|
+
Use the `ddgs` command via `Bash` when it exists. This is the preferred path because it avoids assuming the `Bash` sandbox has the `ddgs` Python package installed.
|
|
53
53
|
|
|
54
54
|
```bash
|
|
55
55
|
# Text search
|
|
@@ -87,14 +87,14 @@ ddgs text -q "fastapi tutorial" -m 5 -o json
|
|
|
87
87
|
|
|
88
88
|
## Method 2: Python API (Only After Verification)
|
|
89
89
|
|
|
90
|
-
Use the `DDGS` class in `
|
|
90
|
+
Use the `DDGS` class in `Bash` or another Python runtime only after verifying that `ddgs` is installed there. Do not assume `Bash` includes third-party packages by default.
|
|
91
91
|
|
|
92
92
|
Safe wording:
|
|
93
|
-
- "Use `
|
|
93
|
+
- "Use `Bash` with `ddgs` after installing or verifying the package if needed"
|
|
94
94
|
|
|
95
95
|
Avoid saying:
|
|
96
|
-
- "`
|
|
97
|
-
- "DuckDuckGo search works by default in `
|
|
96
|
+
- "`Bash` includes `ddgs`"
|
|
97
|
+
- "DuckDuckGo search works by default in `Bash`"
|
|
98
98
|
|
|
99
99
|
**Important:** `max_results` must always be passed as a **keyword argument** — positional usage raises an error on all methods.
|
|
100
100
|
|
|
@@ -180,7 +180,7 @@ Returns: `title`, `content`, `description`, `duration`, `provider`, `published`,
|
|
|
180
180
|
|
|
181
181
|
## Workflow: Search then Extract
|
|
182
182
|
|
|
183
|
-
DuckDuckGo returns titles, URLs, and snippets — not full page content. To get full page content, search first and then extract the most relevant URL with `
|
|
183
|
+
DuckDuckGo returns titles, URLs, and snippets — not full page content. To get full page content, search first and then extract the most relevant URL with `WebFetch`, browser tools, or curl.
|
|
184
184
|
|
|
185
185
|
CLI example:
|
|
186
186
|
|
|
@@ -199,16 +199,16 @@ with DDGS() as ddgs:
|
|
|
199
199
|
print(r["title"], "->", r["href"])
|
|
200
200
|
```
|
|
201
201
|
|
|
202
|
-
Then extract the best URL with `
|
|
202
|
+
Then extract the best URL with `WebFetch` or another content-retrieval tool.
|
|
203
203
|
|
|
204
204
|
## Limitations
|
|
205
205
|
|
|
206
206
|
- **Rate limiting**: DuckDuckGo may throttle after many rapid requests. Add a short delay between searches if needed.
|
|
207
|
-
- **No content extraction**: `ddgs` returns snippets, not full page content. Use `
|
|
207
|
+
- **No content extraction**: `ddgs` returns snippets, not full page content. Use `WebFetch`, browser tools, or curl for the full article/page.
|
|
208
208
|
- **Results quality**: Generally good but less configurable than Firecrawl's search.
|
|
209
209
|
- **Availability**: DuckDuckGo may block requests from some cloud IPs. If searches return empty, try different keywords or wait a few seconds.
|
|
210
210
|
- **Field variability**: Return fields may vary between results or `ddgs` versions. Use `.get()` for optional fields to avoid `KeyError`.
|
|
211
|
-
- **Separate runtimes**: A successful `ddgs` install in terminal does not automatically mean `
|
|
211
|
+
- **Separate runtimes**: A successful `ddgs` install in terminal does not automatically mean `Bash` can import it.
|
|
212
212
|
|
|
213
213
|
## Troubleshooting
|
|
214
214
|
|
|
@@ -217,13 +217,13 @@ Then extract the best URL with `web_extract` or another content-retrieval tool.
|
|
|
217
217
|
| `ddgs: command not found` | CLI not installed in the shell environment | Install `ddgs`, or use built-in web/browser tools instead |
|
|
218
218
|
| `ModuleNotFoundError: No module named 'ddgs'` | Python runtime does not have the package installed | Do not use Python DDGS there until that runtime is prepared |
|
|
219
219
|
| Search returns nothing | Temporary rate limiting or poor query | Wait a few seconds, retry, or adjust the query |
|
|
220
|
-
| CLI works but `
|
|
220
|
+
| CLI works but `Bash` import fails | Terminal and `Bash` are different runtimes | Keep using CLI, or separately prepare the Python runtime |
|
|
221
221
|
|
|
222
222
|
## Pitfalls
|
|
223
223
|
|
|
224
224
|
- **`max_results` is keyword-only**: `ddgs.text("query", 5)` raises an error. Use `ddgs.text("query", max_results=5)`.
|
|
225
225
|
- **Do not assume the CLI exists**: Check `command -v ddgs` before using it.
|
|
226
|
-
- **Do not assume `
|
|
226
|
+
- **Do not assume `Bash` can import `ddgs`**: `from ddgs import DDGS` may fail with `ModuleNotFoundError` unless that runtime was prepared separately.
|
|
227
227
|
- **Package name**: The package is `ddgs` (previously `duckduckgo-search`). Install with `pip install ddgs`.
|
|
228
228
|
- **Don't confuse `-q` and `-m`** (CLI): `-q` is for the query, `-m` is for max results count.
|
|
229
229
|
- **Empty results**: If `ddgs` returns nothing, it may be rate-limited. Wait a few seconds and retry.
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# DuckDuckGo Search Helper Script
|
|
3
|
+
# Wrapper around ddgs CLI with sensible defaults
|
|
4
|
+
# Usage: ./duckduckgo.sh <query> [max_results]
|
|
5
|
+
|
|
6
|
+
set -e
|
|
7
|
+
|
|
8
|
+
QUERY="$1"
|
|
9
|
+
MAX_RESULTS="${2:-5}"
|
|
10
|
+
|
|
11
|
+
if [ -z "$QUERY" ]; then
|
|
12
|
+
echo "Usage: $0 <query> [max_results]"
|
|
13
|
+
echo ""
|
|
14
|
+
echo "Examples:"
|
|
15
|
+
echo " $0 'python async programming' 5"
|
|
16
|
+
echo " $0 'latest AI news' 10"
|
|
17
|
+
echo ""
|
|
18
|
+
echo "Requires: pip install ddgs"
|
|
19
|
+
exit 1
|
|
20
|
+
fi
|
|
21
|
+
|
|
22
|
+
# Check if ddgs is available
|
|
23
|
+
if ! command -v ddgs &> /dev/null; then
|
|
24
|
+
echo "Error: ddgs not found. Install with: pip install ddgs"
|
|
25
|
+
exit 1
|
|
26
|
+
fi
|
|
27
|
+
|
|
28
|
+
ddgs text -q "$QUERY" -m "$MAX_RESULTS"
|
|
@@ -28,7 +28,7 @@ This skill activates when the user is designing or implementing environment mana
|
|
|
28
28
|
- **Ephemeral Environments:** Short-lived environments created on-demand and destroyed after use. Use for: testing, demos, training, experiments. Include cost cap ($50-$200) and auto-deletion after 7 days of inactivity.
|
|
29
29
|
- **Environment Parity:** Dev, staging, and prod should be as similar as possible. Use same: container images, Terraform modules, network topology, resource sizes (scale down in non-prod, but maintain same architecture). Differ only in: data (synthetic in non-prod), scale (fewer replicas), and external integrations (use mocks in non-prod).
|
|
30
30
|
- **Environment as Code:** All environments defined via IaC (Terraform, CloudFormation, Pulumi). No manual changes in cloud console. Code should be versioned and reviewed via PRs. Use modules to ensure consistency across environments.
|
|
31
|
-
- **Configuration Drift Detection:** Use Terraform plan
|
|
31
|
+
- **Configuration Drift Detection:** Use Terraform plan or CloudFormation drift detection. Run drift detection daily and alert on any manual changes. Automatically remediate drift by reapplying IaC.
|
|
32
32
|
- **Environment Provisioning:** Self-service provisioning via CLI, API, or portal. Provisioning should: validate inputs, estimate cost, apply IaC, seed data, run smoke tests, return URL. Complete in under 10 minutes.
|
|
33
33
|
- **Environment Lifecycle:** Define stages: provisioning → active → idle → scheduled for deletion → deleted. Idle environments (no activity for 3+ days) should be flagged for review. Auto-delete after 7 days idle (with 24-hour warning).
|
|
34
34
|
- **Environment Promotion:** Promote changes from dev → staging → production. Use GitOps workflow: commit to environment-specific branch triggers deployment. Include smoke tests and rollback on failure.
|
|
@@ -69,7 +69,7 @@ git diff main...HEAD --stat
|
|
|
69
69
|
git log main..HEAD --oneline
|
|
70
70
|
```
|
|
71
71
|
|
|
72
|
-
2. **Review file by file** — use `
|
|
72
|
+
2. **Review file by file** — use `Read` on changed files for full context, and the diff to see what changed:
|
|
73
73
|
|
|
74
74
|
```bash
|
|
75
75
|
git diff main...HEAD -- src/auth/login.py
|
|
@@ -258,7 +258,7 @@ curl -s -X POST \
|
|
|
258
258
|
-d "{
|
|
259
259
|
\"commit_id\": \"$HEAD_SHA\",
|
|
260
260
|
\"event\": \"COMMENT\",
|
|
261
|
-
\"body\": \"
|
|
261
|
+
\"body\": \"Automated code review — see inline comments.\",
|
|
262
262
|
\"comments\": [
|
|
263
263
|
{\"path\": \"src/auth.py\", \"line\": 45, \"body\": \"Use parameterized queries to prevent SQL injection.\"},
|
|
264
264
|
{\"path\": \"src/models/user.py\", \"line\": 23, \"body\": \"Hash passwords with bcrypt before storing.\"},
|
|
@@ -317,7 +317,7 @@ When the user asks you to "review the code" or "check before pushing":
|
|
|
317
317
|
|
|
318
318
|
1. `git diff main...HEAD --stat` — see scope of changes
|
|
319
319
|
2. `git diff main...HEAD` — read the full diff
|
|
320
|
-
3. For each changed file, use `
|
|
320
|
+
3. For each changed file, use `Read` if you need more context
|
|
321
321
|
4. Apply the checklist above
|
|
322
322
|
5. Present findings in the structured format (Critical / Warnings / Suggestions / Looks Good)
|
|
323
323
|
6. If critical issues found, offer to fix them before the user pushes
|
|
@@ -331,7 +331,7 @@ When the user asks you to "review PR #N", "look at this PR", or gives you a PR U
|
|
|
331
331
|
### Step 1: Set up environment
|
|
332
332
|
|
|
333
333
|
```bash
|
|
334
|
-
source "${AGENT_HOME:-$HOME/.agent}/skills/github
|
|
334
|
+
source "${AGENT_HOME:-$HOME/.agent}/skills/github-auth/scripts/gh-env.sh"
|
|
335
335
|
# Or run the inline setup block from the top of this skill
|
|
336
336
|
```
|
|
337
337
|
|
|
@@ -361,7 +361,7 @@ curl -s -H "Authorization: token $GITHUB_TOKEN" \
|
|
|
361
361
|
|
|
362
362
|
### Step 3: Check out the PR locally
|
|
363
363
|
|
|
364
|
-
This gives you full access to `
|
|
364
|
+
This gives you full access to `Read`, `Grep`, and the ability to run tests.
|
|
365
365
|
|
|
366
366
|
```bash
|
|
367
367
|
git fetch origin pull/$PR_NUMBER/head:pr-$PR_NUMBER
|
|
@@ -380,7 +380,7 @@ git diff main...HEAD --name-only
|
|
|
380
380
|
git diff main...HEAD -- path/to/file.py
|
|
381
381
|
```
|
|
382
382
|
|
|
383
|
-
For each changed file, use `
|
|
383
|
+
For each changed file, use `Read` to see full context around the changes — diffs alone can miss issues visible only with surrounding code.
|
|
384
384
|
|
|
385
385
|
### Step 5: Run automated checks locally (if applicable)
|
|
386
386
|
|
|
@@ -405,7 +405,7 @@ Collect your findings and submit them as a formal review with inline comments.
|
|
|
405
405
|
**With gh:**
|
|
406
406
|
```bash
|
|
407
407
|
# If no issues — approve
|
|
408
|
-
gh pr review $PR_NUMBER --approve --body "Reviewed
|
|
408
|
+
gh pr review $PR_NUMBER --approve --body "Reviewed — no blocking issues found."
|
|
409
409
|
|
|
410
410
|
# If issues found — request changes with inline comments
|
|
411
411
|
gh pr review $PR_NUMBER --request-changes --body "Found a few issues — see inline comments."
|
|
@@ -424,7 +424,7 @@ curl -s -X POST \
|
|
|
424
424
|
-d "{
|
|
425
425
|
\"commit_id\": \"$HEAD_SHA\",
|
|
426
426
|
\"event\": \"REQUEST_CHANGES\",
|
|
427
|
-
\"body\": \"##
|
|
427
|
+
\"body\": \"## Code Review — Changes Requested\",
|
|
428
428
|
\"comments\": [
|
|
429
429
|
{\"path\": \"src/auth.py\", \"line\": 45, \"body\": \"🔴 **Critical:** User input passed directly to SQL query — use parameterized queries.\"},
|
|
430
430
|
{\"path\": \"src/models.py\", \"line\": 23, \"body\": \"⚠️ **Warning:** Password stored without hashing.\"},
|
|
@@ -458,7 +458,7 @@ gh pr comment $PR_NUMBER --body "$(cat <<'EOF'
|
|
|
458
458
|
- Good error handling in the middleware layer
|
|
459
459
|
|
|
460
460
|
---
|
|
461
|
-
*
|
|
461
|
+
*Automated code review*
|
|
462
462
|
EOF
|
|
463
463
|
)"
|
|
464
464
|
```
|