| name | recon-tool-integration |
| description | Adding a new tool to the recon pipeline: the enrichment-module contract and its isolated wrapper (the actual fan-out and test call path), graph completeness, and the preset catalog that silently strips unknown settings. Miss the isolated wrapper and the tool never runs in parallel; miss the catalog and AI presets drop its config. Trigger: adding a tool to the recon pipeline; a new recon/*.py or recon/main_recon_modules/*.py enrichment module; editing the execution groups in recon/main.py or the IMAGES array in recon/entrypoint.sh.
|
| license | MIT |
| metadata | {"author":"redamon","version":"1.0.0","scope":["recon"],"auto_invoke":["Adding a new tool to the recon pipeline","Editing recon execution groups, enrichment modules, or the recon image list"]} |
When to Use
- Adding a brand-new scanning/enrichment tool to the scan pipeline.
For adding AI decision-making to an existing tool, use recon-ai-enrichment.
For the graph write, use graph-db-writes. For the settings, use
project-settings-cascade. This skill is the module + pipeline wiring.
Critical Rules
- NEVER ship the enrichment module without its
_isolated wrapper.
run_<tool>_enrichment_isolated() is the actual call path for the GROUP 3b
parallel fan-out AND for every unit test; the plain run_<tool>_enrichment()
alone is never fan-out-safe. Reference:
recon/main_recon_modules/censys_enrich.py:369.
- NEVER vary the top-level result key. The module writes
combined_result["<tool>"] and the wrapper returns snapshot.get("<tool>", {})
with the same identifier used everywhere else in the pipeline
(censys_enrich.py:365).
- NEVER collect a field and not write it to the graph. Every field in the
output dict must land on a node/relationship or it is silent data loss - see
graph-db-writes.
- NEVER add a tool setting without updating BOTH preset layers. Add it to the
Zod recon-preset-schema.ts and to
RECON_PARAMETER_CATALOG in
webapp/src/app/api/presets/generate/route.ts.
Miss the Zod schema and AI-generated presets silently strip the setting;
miss the catalog and the preset LLM never knows the tool exists.
- ALWAYS prefix every
print() log [symbol][ToolName] ([*] progress,
[+] success, [-] skipped, [!] error). Recon stdout is tailed into the SSE
recon drawer; a bare print() is invisibly formatted.
- ALWAYS place a fan-out tool behind the deep-copy
_isolated wrapper and in
the correct execution group in recon/main.py; never
parallelize across a dependency boundary (a tool needing live URLs cannot run
before GROUP 4).
Enrichment-module contract (copy target)
def run_censys_enrichment(combined_result: dict, settings: dict) -> dict:
...
combined_result["censys"] = censys_data
return combined_result
def run_censys_enrichment_isolated(combined_result: dict, settings: dict) -> dict:
"""Thread-safe: does not mutate combined_result. The fan-out + test call path."""
import copy
snapshot = copy.deepcopy(combined_result)
run_censys_enrichment(snapshot, settings)
return snapshot.get("censys", {})
From recon/main_recon_modules/censys_enrich.py.
Commands
docker compose build recon
docker compose exec webapp npx prisma db push
./redamon.sh test unit
Resources