wicked-garden 12.27.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/.claude-plugin/archetypes.json +166 -0
- package/.claude-plugin/components.json +75 -0
- package/.claude-plugin/marketplace.json +15 -0
- package/.claude-plugin/plugin.json +174 -0
- package/.claude-plugin/specialist.json +48 -0
- package/.claude-plugin/stack-registry.json +96 -0
- package/AGENTS.md +13 -0
- package/CHANGELOG.md +712 -0
- package/CONTRIBUTING.md +99 -0
- package/ETHOS.md +83 -0
- package/LICENSE +21 -0
- package/README.md +115 -0
- package/WICKED_GARDEN_BUS_EVENTS.md +149 -0
- package/agents/agentic/architect.md +449 -0
- package/agents/agentic/performance-analyst.md +702 -0
- package/agents/agentic/safety-reviewer.md +662 -0
- package/agents/crew/implementer.md +163 -0
- package/agents/crew/researcher.md +94 -0
- package/agents/crew/reviewer.md +184 -0
- package/agents/data/data-engineer.md +227 -0
- package/agents/engineering/api-documentarian.md +440 -0
- package/agents/engineering/migration-engineer.md +301 -0
- package/agents/engineering/solution-architect.md +208 -0
- package/agents/jam/brainstorm-facilitator.md +297 -0
- package/agents/jam/council.md +322 -0
- package/agents/jam/quick-facilitator.md +85 -0
- package/agents/persona/persona-agent.md +121 -0
- package/agents/platform/compliance-officer.md +266 -0
- package/agents/platform/privacy-expert.md +496 -0
- package/agents/platform/security-engineer.md +287 -0
- package/agents/product/a11y-expert.md +323 -0
- package/agents/product/requirements-analyst.md +238 -0
- package/agents/product/ui-reviewer.md +180 -0
- package/agents/product/ux-designer.md +199 -0
- package/agents/product/value-strategist.md +269 -0
- package/agents/qe/semantic-reviewer.md +78 -0
- package/commands/agentic/audit.md +24 -0
- package/commands/agentic/design.md +24 -0
- package/commands/agentic/frameworks.md +25 -0
- package/commands/agentic/review.md +27 -0
- package/commands/archetype/build.md +12 -0
- package/commands/archetype/decide.md +12 -0
- package/commands/archetype/explore.md +12 -0
- package/commands/archetype/incident.md +12 -0
- package/commands/archetype/migrate.md +12 -0
- package/commands/archetype/modernize.md +12 -0
- package/commands/archetype/review.md +14 -0
- package/commands/archetype/ship.md +12 -0
- package/commands/archetype/specify.md +12 -0
- package/commands/archetype/triage.md +12 -0
- package/commands/compile.md +37 -0
- package/commands/data/analyze.md +18 -0
- package/commands/data/data.md +21 -0
- package/commands/data/ml.md +18 -0
- package/commands/data/ontology.md +22 -0
- package/commands/data/pipeline.md +17 -0
- package/commands/deliberate.md +181 -0
- package/commands/engineering/add-field.md +77 -0
- package/commands/engineering/apply.md +58 -0
- package/commands/engineering/arch.md +26 -0
- package/commands/engineering/debug.md +27 -0
- package/commands/engineering/docs.md +27 -0
- package/commands/engineering/new-generator.md +257 -0
- package/commands/engineering/patch-plan.md +59 -0
- package/commands/engineering/plan.md +29 -0
- package/commands/engineering/remove.md +48 -0
- package/commands/engineering/rename.md +44 -0
- package/commands/engineering/review.md +32 -0
- package/commands/help.md +128 -0
- package/commands/install.md +118 -0
- package/commands/intent.md +54 -0
- package/commands/jam/brainstorm.md +37 -0
- package/commands/jam/council.md +49 -0
- package/commands/jam/quick.md +21 -0
- package/commands/jam/revisit.md +79 -0
- package/commands/persona/as.md +136 -0
- package/commands/persona/define.md +24 -0
- package/commands/persona/list.md +118 -0
- package/commands/platform/actions.md +20 -0
- package/commands/platform/assert.md +18 -0
- package/commands/platform/audit.md +23 -0
- package/commands/platform/compliance.md +20 -0
- package/commands/platform/gh.md +22 -0
- package/commands/platform/health.md +22 -0
- package/commands/platform/incident.md +23 -0
- package/commands/platform/infra.md +24 -0
- package/commands/platform/peer-health.md +103 -0
- package/commands/platform/plugin-health.md +58 -0
- package/commands/platform/security.md +38 -0
- package/commands/platform/toolchain.md +96 -0
- package/commands/platform/traces.md +20 -0
- package/commands/product/a11y.md +19 -0
- package/commands/product/acceptance.md +19 -0
- package/commands/product/align.md +20 -0
- package/commands/product/analyze.md +23 -0
- package/commands/product/elicit.md +19 -0
- package/commands/product/listen.md +24 -0
- package/commands/product/mockup.md +20 -0
- package/commands/product/screenshot.md +19 -0
- package/commands/product/strategy.md +40 -0
- package/commands/product/synthesize.md +23 -0
- package/commands/product/ux-review.md +42 -0
- package/commands/product/ux.md +20 -0
- package/commands/product/visual-direction.md +34 -0
- package/commands/prove.md +47 -0
- package/commands/report-issue.md +243 -0
- package/commands/reset.md +144 -0
- package/commands/search/blast-radius.md +58 -0
- package/commands/search/hotspots.md +55 -0
- package/commands/search/index.md +38 -0
- package/commands/search/lineage.md +47 -0
- package/commands/search/service-map.md +79 -0
- package/commands/setup.md +363 -0
- package/commands/smaht/briefing.md +200 -0
- package/commands/smaht/events-import.md +95 -0
- package/commands/smaht/state.md +19 -0
- package/commands/where-am-i.md +58 -0
- package/docs/README.md +32 -0
- package/docs/adr/0001-code-relationship-graph-engine.md +116 -0
- package/docs/adr/0002-major-cleanup-keep-cut.md +91 -0
- package/docs/adr/0003-peers-gate-required-layers-optin.md +41 -0
- package/docs/adr/0004-code-graph-moves-to-wicked-brain.md +47 -0
- package/docs/brain-chunk-format.md +135 -0
- package/docs/compiler.md +95 -0
- package/docs/daemon-api.md +70 -0
- package/docs/domains.md +197 -0
- package/docs/getting-started.md +208 -0
- package/docs/plans/2026-06-08-wicked-loom-conduct.md +1337 -0
- package/docs/plans/2026-06-08-wicked-loom-contract.md +638 -0
- package/docs/plans/2026-06-08-wicked-loom-cutover.md +1300 -0
- package/docs/plans/2026-06-08-wicked-loom-expand-compose.md +843 -0
- package/docs/plans/2026-06-08-wicked-loom-flow-cutover.md +403 -0
- package/docs/plans/2026-06-10-codegraph-to-brain-phase1a-graph-core.md +838 -0
- package/docs/plans/2026-06-10-codegraph-to-brain-phase1b-injected-edges.md +44 -0
- package/docs/required-peers.md +60 -0
- package/docs/specs/2026-06-08-wicked-loom-extraction.md +225 -0
- package/docs/specs/2026-06-10-codegraph-to-brain-migration.md +168 -0
- package/docs/v11/archetypes.md +231 -0
- package/hooks/hooks.json +275 -0
- package/hooks/scripts/bootstrap.py +1797 -0
- package/hooks/scripts/invoke.py +62 -0
- package/hooks/scripts/notification.py +166 -0
- package/hooks/scripts/permission_request.py +223 -0
- package/hooks/scripts/post_tool.py +1374 -0
- package/hooks/scripts/pre_compact.py +272 -0
- package/hooks/scripts/pre_tool.py +1278 -0
- package/hooks/scripts/prompt_submit.py +1109 -0
- package/hooks/scripts/session_end.py +95 -0
- package/hooks/scripts/stop.py +624 -0
- package/hooks/scripts/subagent_lifecycle.py +464 -0
- package/hooks/scripts/subscribers/on_gate_decided.py +84 -0
- package/hooks/scripts/task_completed.py +322 -0
- package/hooks/scripts/worktree_guard.py +148 -0
- package/hooks/subscriptions/on_gate_decided.json +9 -0
- package/install.mjs +128 -0
- package/package.json +41 -0
- package/pyproject.toml +59 -0
- package/schemas/README.md +32 -0
- package/schemas/assert_contracts.json +37 -0
- package/schemas/health_probe.json +46 -0
- package/schemas/plugin_status.json +37 -0
- package/scripts/_adapters/__init__.py +166 -0
- package/scripts/_adapters/jira_adapter.py +18 -0
- package/scripts/_adapters/linear_adapter.py +18 -0
- package/scripts/_adapters/miro_adapter.py +18 -0
- package/scripts/_adapters/notion_adapter.py +18 -0
- package/scripts/_agents.py +357 -0
- package/scripts/_brain_ingest/__init__.py +2 -0
- package/scripts/_brain_ingest/session_fact_extractor.py +341 -0
- package/scripts/_brain_port.py +163 -0
- package/scripts/_bus.py +1081 -0
- package/scripts/_bus_catalog_gen.py +93 -0
- package/scripts/_bus_consumers.json +46 -0
- package/scripts/_bus_emit.py +43 -0
- package/scripts/_capability_registry.py +334 -0
- package/scripts/_capability_resolver.py +322 -0
- package/scripts/_domain_store.py +559 -0
- package/scripts/_event_log_reader.py +154 -0
- package/scripts/_event_schema.py +305 -0
- package/scripts/_event_store.py +397 -0
- package/scripts/_heavy_cadence.py +324 -0
- package/scripts/_integration_resolver.py +321 -0
- package/scripts/_logger.py +151 -0
- package/scripts/_loom.py +482 -0
- package/scripts/_paths.py +133 -0
- package/scripts/_python.sh +22 -0
- package/scripts/_run.py +137 -0
- package/scripts/_session.py +502 -0
- package/scripts/_validate_registry.py +1042 -0
- package/scripts/_wicked_testing_probe.py +277 -0
- package/scripts/agentic/analyze_agents.py +391 -0
- package/scripts/agentic/detect_framework.py +420 -0
- package/scripts/agentic/issue_taxonomy.py +357 -0
- package/scripts/agentic/pattern_scorer.py +434 -0
- package/scripts/classify/persist.py +169 -0
- package/scripts/compiler/compile.py +552 -0
- package/scripts/compiler/phase0/VERDICT.md +60 -0
- package/scripts/compiler/phase0/detect.py +292 -0
- package/scripts/compiler/phase0/emit.py +228 -0
- package/scripts/compiler/phase0/evidence/Enterprise-AISDLC.bindings.json +30 -0
- package/scripts/compiler/phase0/evidence/Enterprise-AISDLC.lint-output.txt +17 -0
- package/scripts/compiler/phase0/evidence/Enterprise-AISDLC.stage/.wg/evidence/failing-tests.txt +4 -0
- package/scripts/compiler/phase0/evidence/Enterprise-AISDLC.stage/.wg/evidence/honest-tests.txt +2 -0
- package/scripts/compiler/phase0/evidence/Enterprise-AISDLC.stage/fab-fail.build.md +8 -0
- package/scripts/compiler/phase0/evidence/Enterprise-AISDLC.stage/fab-missing.build.md +8 -0
- package/scripts/compiler/phase0/evidence/Enterprise-AISDLC.stage/honest.build.md +8 -0
- package/scripts/compiler/phase0/evidence/Enterprise-AISDLC.stage/wg_check_claims.py +174 -0
- package/scripts/compiler/phase0/evidence/command_iq.bindings.json +45 -0
- package/scripts/compiler/phase0/evidence/command_iq.lint-output.txt +17 -0
- package/scripts/compiler/phase0/evidence/command_iq.stage/.projects/evidence-domain/phase-1-clarify/evidence/failing-tests.txt +4 -0
- package/scripts/compiler/phase0/evidence/command_iq.stage/.projects/evidence-domain/phase-1-clarify/evidence/honest-tests.txt +3 -0
- package/scripts/compiler/phase0/evidence/command_iq.stage/fab-fail.build.md +8 -0
- package/scripts/compiler/phase0/evidence/command_iq.stage/fab-missing.build.md +8 -0
- package/scripts/compiler/phase0/evidence/command_iq.stage/honest.build.md +8 -0
- package/scripts/compiler/phase0/evidence/command_iq.stage/wg_check_claims.py +174 -0
- package/scripts/compiler/phase0/evidence/memos.bindings.json +28 -0
- package/scripts/compiler/phase0/evidence/memos.lint-output.txt +17 -0
- package/scripts/compiler/phase0/evidence/memos.stage/.wg/evidence/failing-tests.txt +4 -0
- package/scripts/compiler/phase0/evidence/memos.stage/.wg/evidence/honest-tests.txt +2 -0
- package/scripts/compiler/phase0/evidence/memos.stage/fab-fail.build.md +8 -0
- package/scripts/compiler/phase0/evidence/memos.stage/fab-missing.build.md +8 -0
- package/scripts/compiler/phase0/evidence/memos.stage/honest.build.md +8 -0
- package/scripts/compiler/phase0/evidence/memos.stage/wg_check_claims.py +174 -0
- package/scripts/compiler/phase0/evidence/verdict.json +104 -0
- package/scripts/compiler/phase0/evidence/wicked-bus.bindings.json +29 -0
- package/scripts/compiler/phase0/evidence/wicked-bus.lint-output.txt +17 -0
- package/scripts/compiler/phase0/evidence/wicked-bus.stage/coverage/failing-tests.txt +4 -0
- package/scripts/compiler/phase0/evidence/wicked-bus.stage/coverage/honest-tests.txt +3 -0
- package/scripts/compiler/phase0/evidence/wicked-bus.stage/fab-fail.build.md +8 -0
- package/scripts/compiler/phase0/evidence/wicked-bus.stage/fab-missing.build.md +8 -0
- package/scripts/compiler/phase0/evidence/wicked-bus.stage/honest.build.md +8 -0
- package/scripts/compiler/phase0/evidence/wicked-bus.stage/wg_check_claims.py +174 -0
- package/scripts/compiler/phase0/evidence/wire-vault-transcript.txt +60 -0
- package/scripts/compiler/phase0/run_probe.py +234 -0
- package/scripts/compiler/phase0/wire_vault.py +310 -0
- package/scripts/crew/__init__.py +0 -0
- package/scripts/crew/_task_audit_writer.py +243 -0
- package/scripts/crew/_task_reader.py +389 -0
- package/scripts/crew/archetypes_v11.py +348 -0
- package/scripts/crew/detectors/__init__.py +12 -0
- package/scripts/crew/flow_compiler.py +121 -0
- package/scripts/crew/phase_manager.py +703 -0
- package/scripts/crew/scope_delta.py +264 -0
- package/scripts/crew/specialist_resolver.py +218 -0
- package/scripts/crew/stack_registry.py +189 -0
- package/scripts/data/data_profiler.py +271 -0
- package/scripts/data/ontology_recommender.py +231 -0
- package/scripts/data/schema_validator.py +267 -0
- package/scripts/delivery/drift.py +739 -0
- package/scripts/delivery/telemetry.py +614 -0
- package/scripts/engineering/patch/codegraph_db.py +125 -0
- package/scripts/engineering/patch/generators/__init__.py +56 -0
- package/scripts/engineering/patch/generators/base.py +373 -0
- package/scripts/engineering/patch/generators/csharp_generator.py +494 -0
- package/scripts/engineering/patch/generators/go_generator.py +430 -0
- package/scripts/engineering/patch/generators/java_generator.py +928 -0
- package/scripts/engineering/patch/generators/jsp_generator.py +454 -0
- package/scripts/engineering/patch/generators/kotlin_generator.py +561 -0
- package/scripts/engineering/patch/generators/perl_generator.py +510 -0
- package/scripts/engineering/patch/generators/php_generator.py +644 -0
- package/scripts/engineering/patch/generators/propagation_engine.py +929 -0
- package/scripts/engineering/patch/generators/python_generator.py +487 -0
- package/scripts/engineering/patch/generators/ruby_generator.py +463 -0
- package/scripts/engineering/patch/generators/rust_generator.py +400 -0
- package/scripts/engineering/patch/generators/sql_generator.py +594 -0
- package/scripts/engineering/patch/generators/typescript_generator.py +439 -0
- package/scripts/engineering/patch/patch.py +800 -0
- package/scripts/engineering/patch/safety.py +429 -0
- package/scripts/jam/__init__.py +0 -0
- package/scripts/jam/_bus_consumers.py +271 -0
- package/scripts/jam/agentic_cli_registry.py +703 -0
- package/scripts/jam/consensus.py +737 -0
- package/scripts/jam/detect_clis.py +409 -0
- package/scripts/jam/jam.py +283 -0
- package/scripts/jam/save_transcript.py +171 -0
- package/scripts/loom/__init__.py +22 -0
- package/scripts/loom/cli.py +170 -0
- package/scripts/loom/compose.py +180 -0
- package/scripts/loom/gate.py +120 -0
- package/scripts/loom/manifest.py +140 -0
- package/scripts/loom/resolve.py +59 -0
- package/scripts/persona/__init__.py +0 -0
- package/scripts/persona/registry.py +688 -0
- package/scripts/platform/guard_pipeline.py +1214 -0
- package/scripts/platform/guard_profiles.py +216 -0
- package/scripts/platform/observability/assert_contracts.py +434 -0
- package/scripts/platform/observability/health_probe.py +915 -0
- package/scripts/platform/observability/ops_log_viewer.py +209 -0
- package/scripts/platform/prereq_doctor.py +567 -0
- package/scripts/qe/conditions_manifest.py +260 -0
- package/scripts/qe/content_sanitizer.py +160 -0
- package/scripts/qe/coverage_tracker.py +535 -0
- package/scripts/qe/discover_scenarios.py +243 -0
- package/scripts/qe/evidence_tracker.py +232 -0
- package/scripts/qe/prove.py +196 -0
- package/scripts/qe/registry_lookup.py +80 -0
- package/scripts/qe/registry_store.py +176 -0
- package/scripts/qe/semantic_review.py +1005 -0
- package/scripts/qe/vault_gate.py +382 -0
- package/scripts/qe/verdict_audit.py +175 -0
- package/scripts/qe/verdict_schema.py +335 -0
- package/scripts/reset.py +220 -0
- package/scripts/resolve_path.py +22 -0
- package/scripts/sentinel/invariants.py +402 -0
- package/scripts/sentinel/pre_push.py +73 -0
- package/scripts/setup/__init__.py +1 -0
- package/scripts/setup/detect_state.py +114 -0
- package/scripts/setup/migrate_legacy.py +67 -0
- package/scripts/setup/migrate_v6_projects.py +232 -0
- package/scripts/setup/onboarding.py +114 -0
- package/scripts/smaht/_bus_consumers.py +98 -0
- package/scripts/smaht/adapters/__init__.py +83 -0
- package/scripts/smaht/adapters/brain_adapter.py +254 -0
- package/scripts/smaht/adapters/context7_adapter.py +438 -0
- package/scripts/smaht/adapters/delegation_adapter.py +104 -0
- package/scripts/smaht/adapters/domain_adapter.py +206 -0
- package/scripts/smaht/adapters/events_adapter.py +231 -0
- package/scripts/smaht/adapters/tools_adapter.py +49 -0
- package/scripts/smaht/cheatsheet_store.py +236 -0
- package/scripts/smaht/context_package.py +386 -0
- package/scripts/smaht/knowledge_graph.py +395 -0
- package/scripts/smaht/propose_skills.py +856 -0
- package/scripts/smaht/test_cheatsheet_store.py +428 -0
- package/scripts/statusline.py +151 -0
- package/scripts/where_am_i.py +236 -0
- package/skills/agentic/agentic-patterns/SKILL.md +91 -0
- package/skills/agentic/agentic-patterns/refs/anti-patterns-design.md +283 -0
- package/skills/agentic/agentic-patterns/refs/anti-patterns-operational.md +216 -0
- package/skills/agentic/agentic-patterns/refs/pattern-catalog.md +329 -0
- package/skills/agentic/context-engineering/SKILL.md +142 -0
- package/skills/agentic/context-engineering/refs/caching-and-optimization.md +251 -0
- package/skills/agentic/context-engineering/refs/compression-techniques.md +171 -0
- package/skills/agentic/context-engineering/refs/cost-calculation-budget.md +250 -0
- package/skills/agentic/context-engineering/refs/cost-optimization-reporting.md +300 -0
- package/skills/agentic/context-engineering/refs/selective-loading.md +179 -0
- package/skills/agentic/frameworks/SKILL.md +191 -0
- package/skills/agentic/frameworks/refs/framework-profiles-1.md +209 -0
- package/skills/agentic/frameworks/refs/framework-profiles-2.md +214 -0
- package/skills/agentic/frameworks/refs/migration-patterns-paths.md +267 -0
- package/skills/agentic/frameworks/refs/migration-patterns-testing.md +208 -0
- package/skills/agentic/refs/audit.md +134 -0
- package/skills/agentic/refs/design.md +137 -0
- package/skills/agentic/refs/frameworks.md +102 -0
- package/skills/agentic/refs/review.md +160 -0
- package/skills/agentic/review-methodology/SKILL.md +186 -0
- package/skills/agentic/review-methodology/refs/deliverable-templates.md +246 -0
- package/skills/agentic/review-methodology/refs/issue-taxonomy-quality-testing.md +277 -0
- package/skills/agentic/review-methodology/refs/issue-taxonomy-reliability-safety.md +253 -0
- package/skills/agentic/trust-and-safety/SKILL.md +177 -0
- package/skills/agentic/trust-and-safety/refs/guardrails-actions.md +246 -0
- package/skills/agentic/trust-and-safety/refs/guardrails-input-output.md +238 -0
- package/skills/agentic/trust-and-safety/refs/guardrails-resources.md +209 -0
- package/skills/agentic/trust-and-safety/refs/safety-checklist-advanced.md +209 -0
- package/skills/agentic/trust-and-safety/refs/safety-checklist-core.md +215 -0
- package/skills/archetype/SKILL.md +104 -0
- package/skills/archetype/refs/build.md +142 -0
- package/skills/archetype/refs/decide.md +117 -0
- package/skills/archetype/refs/explore.md +66 -0
- package/skills/archetype/refs/incident.md +149 -0
- package/skills/archetype/refs/migrate.md +170 -0
- package/skills/archetype/refs/modernize.md +187 -0
- package/skills/archetype/refs/review.md +145 -0
- package/skills/archetype/refs/ship.md +117 -0
- package/skills/archetype/refs/specify.md +108 -0
- package/skills/archetype/refs/triage.md +62 -0
- package/skills/classify/SKILL.md +157 -0
- package/skills/data/analysis/SKILL.md +125 -0
- package/skills/data/analysis/refs/templates.md +170 -0
- package/skills/data/data/SKILL.md +118 -0
- package/skills/data/data/refs/examples.md +235 -0
- package/skills/data/ml/SKILL.md +125 -0
- package/skills/data/ml/refs/templates.md +172 -0
- package/skills/data/pipeline/SKILL.md +136 -0
- package/skills/data/pipeline/refs/templates.md +175 -0
- package/skills/data/refs/analyze.md +123 -0
- package/skills/data/refs/data.md +95 -0
- package/skills/data/refs/ml.md +118 -0
- package/skills/data/refs/pipeline.md +92 -0
- package/skills/deliberate/SKILL.md +125 -0
- package/skills/deliberate/refs/architecture-lens.md +37 -0
- package/skills/deliberate/refs/assumptions-lens.md +43 -0
- package/skills/deliberate/refs/code-lens.md +38 -0
- package/skills/deliberate/refs/content-lens.md +37 -0
- package/skills/deliberate/refs/data-lens.md +43 -0
- package/skills/deliberate/refs/design-lens.md +37 -0
- package/skills/deliberate/refs/opportunity-patterns.md +107 -0
- package/skills/deliberate/refs/ops-lens.md +43 -0
- package/skills/deliberate/refs/product-lens.md +46 -0
- package/skills/deliberate/refs/rethink-framework.md +77 -0
- package/skills/deliberate/refs/security-lens.md +47 -0
- package/skills/deliberate/refs/testing-lens.md +45 -0
- package/skills/deliberate/refs/timing-lens.md +42 -0
- package/skills/engineering/architecture/SKILL.md +177 -0
- package/skills/engineering/architecture/refs/adr-template.md +268 -0
- package/skills/engineering/architecture/refs/architecture-template-deployment.md +176 -0
- package/skills/engineering/architecture/refs/architecture-template-design.md +300 -0
- package/skills/engineering/architecture/refs/examples-ecommerce-analytics.md +299 -0
- package/skills/engineering/architecture/refs/examples-saas-trading.md +291 -0
- package/skills/engineering/architecture/refs/patterns-advanced.md +238 -0
- package/skills/engineering/architecture/refs/patterns-structural.md +303 -0
- package/skills/engineering/backend/SKILL.md +102 -0
- package/skills/engineering/backend/refs/checklists.md +146 -0
- package/skills/engineering/backend/refs/patterns.md +181 -0
- package/skills/engineering/debugging/SKILL.md +99 -0
- package/skills/engineering/debugging/refs/patterns.md +248 -0
- package/skills/engineering/debugging/refs/process.md +203 -0
- package/skills/engineering/docs/SKILL.md +97 -0
- package/skills/engineering/engineering/SKILL.md +88 -0
- package/skills/engineering/engineering/refs/checklists.md +91 -0
- package/skills/engineering/engineering/refs/templates.md +71 -0
- package/skills/engineering/frontend/SKILL.md +92 -0
- package/skills/engineering/frontend/refs/checklists.md +96 -0
- package/skills/engineering/frontend/refs/patterns.md +167 -0
- package/skills/engineering/integration/SKILL.md +183 -0
- package/skills/engineering/integration/refs/error-handling-best-practices.md +139 -0
- package/skills/engineering/integration/refs/error-handling-error-classes-typescript.md +212 -0
- package/skills/engineering/integration/refs/error-handling-error-response-format.md +301 -0
- package/skills/engineering/integration/refs/error-handling-retry-strategies.md +190 -0
- package/skills/engineering/integration/refs/event-schemas-best-practices.md +225 -0
- package/skills/engineering/integration/refs/event-schemas-event-naming-conventions.md +303 -0
- package/skills/engineering/integration/refs/event-schemas-event-structure.md +288 -0
- package/skills/engineering/integration/refs/graphql-best-practices.md +138 -0
- package/skills/engineering/integration/refs/graphql-error-handling.md +198 -0
- package/skills/engineering/integration/refs/graphql-graphql-basics.md +197 -0
- package/skills/engineering/integration/refs/graphql-query-examples.md +226 -0
- package/skills/engineering/integration/refs/graphql-schema-design-patterns.md +280 -0
- package/skills/engineering/integration/refs/grpc-grpc-overview.md +246 -0
- package/skills/engineering/integration/refs/grpc-implementation-examples.md +269 -0
- package/skills/engineering/integration/refs/grpc-metadata-headers.md +304 -0
- package/skills/engineering/integration/refs/grpc-testing.md +49 -0
- package/skills/engineering/integration/refs/openapi-template.yaml +682 -0
- package/skills/engineering/integration/refs/resilience-best-practices.md +109 -0
- package/skills/engineering/integration/refs/resilience-circuit-breaker-pattern.md +302 -0
- package/skills/engineering/integration/refs/resilience-rate-limiting.md +245 -0
- package/skills/engineering/integration/refs/resilience-timeout-pattern.md +212 -0
- package/skills/engineering/integration/refs/rest-api-fundamentals.md +299 -0
- package/skills/engineering/integration/refs/rest-api-responses-security.md +302 -0
- package/skills/engineering/integration/refs/versioning-breaking-changes.md +237 -0
- package/skills/engineering/integration/refs/versioning-migration-strategies.md +257 -0
- package/skills/engineering/integration/refs/versioning-versioning-strategies.md +296 -0
- package/skills/engineering/large-scale-migration/SKILL.md +65 -0
- package/skills/engineering/patch/SKILL.md +184 -0
- package/skills/engineering/refs/arch.md +126 -0
- package/skills/engineering/refs/debug.md +142 -0
- package/skills/engineering/refs/docs.md +190 -0
- package/skills/engineering/refs/plan.md +109 -0
- package/skills/engineering/refs/review.md +138 -0
- package/skills/engineering/system-design/SKILL.md +154 -0
- package/skills/engineering/system-design/refs/anti-patterns-big-ball-of-mud.md +254 -0
- package/skills/engineering/system-design/refs/anti-patterns-circular-dependencies.md +241 -0
- package/skills/engineering/system-design/refs/anti-patterns-feature-envy.md +168 -0
- package/skills/engineering/system-design/refs/anti-patterns-god-object.md +247 -0
- package/skills/engineering/system-design/refs/component-template-lifecycle.md +210 -0
- package/skills/engineering/system-design/refs/component-template-maintenance.md +219 -0
- package/skills/engineering/system-design/refs/component-template-structure.md +276 -0
- package/skills/engineering/system-design/refs/dependencies-best-practices.md +260 -0
- package/skills/engineering/system-design/refs/dependencies-dependency-principles.md +295 -0
- package/skills/engineering/system-design/refs/dependencies-dependency-tracking.md +261 -0
- package/skills/engineering/system-design/refs/interface-template-lifecycle.md +211 -0
- package/skills/engineering/system-design/refs/interface-template-maintenance.md +212 -0
- package/skills/engineering/system-design/refs/interface-template-structure.md +269 -0
- package/skills/engineering/system-design/refs/patterns-dependency-injection.md +151 -0
- package/skills/engineering/system-design/refs/patterns-facade-pattern.md +257 -0
- package/skills/engineering/system-design/refs/patterns-layered-pattern.md +204 -0
- package/skills/engineering/system-design/refs/patterns-plugin-architecture.md +229 -0
- package/skills/engineering/unit-test-quality/SKILL.md +194 -0
- package/skills/ground/SKILL.md +130 -0
- package/skills/integration-discovery/SKILL.md +168 -0
- package/skills/integration-discovery/refs/capabilities.md +282 -0
- package/skills/integration-discovery/refs/cli-detection.md +295 -0
- package/skills/integration-discovery/refs/discovery-sources.md +233 -0
- package/skills/integration-discovery/refs/task-patterns.md +206 -0
- package/skills/jam/SKILL.md +45 -0
- package/skills/jam/refs/facilitation-patterns.md +125 -0
- package/skills/jam/refs/quick.md +64 -0
- package/skills/jam/refs/synthesis-patterns.md +114 -0
- package/skills/multi-model/SKILL.md +168 -0
- package/skills/multi-model/refs/aichat.md +119 -0
- package/skills/multi-model/refs/aider.md +100 -0
- package/skills/multi-model/refs/auditability.md +238 -0
- package/skills/multi-model/refs/codex.md +169 -0
- package/skills/multi-model/refs/context.md +306 -0
- package/skills/multi-model/refs/copilot.md +161 -0
- package/skills/multi-model/refs/examples.md +224 -0
- package/skills/multi-model/refs/gemini.md +185 -0
- package/skills/multi-model/refs/goose.md +112 -0
- package/skills/multi-model/refs/llm.md +124 -0
- package/skills/multi-model/refs/opencode.md +196 -0
- package/skills/multi-model/refs/orchestration.md +188 -0
- package/skills/multi-model/refs/pi.md +208 -0
- package/skills/persona/SKILL.md +144 -0
- package/skills/persona/refs/define.md +133 -0
- package/skills/platform/actions/refs/actions.md +114 -0
- package/skills/platform/audit/SKILL.md +174 -0
- package/skills/platform/audit/refs/audit.md +145 -0
- package/skills/platform/audit/refs/checklists-evidence-operations.md +144 -0
- package/skills/platform/audit/refs/checklists-gdpr-pci-evidence.md +213 -0
- package/skills/platform/audit/refs/checklists-soc2-hipaa.md +120 -0
- package/skills/platform/audit/refs/frameworks-gdpr-pci.md +225 -0
- package/skills/platform/audit/refs/frameworks-soc2-hipaa.md +228 -0
- package/skills/platform/compliance/SKILL.md +169 -0
- package/skills/platform/compliance/refs/checklists.md +303 -0
- package/skills/platform/compliance/refs/compliance.md +117 -0
- package/skills/platform/compliance/refs/frameworks.md +282 -0
- package/skills/platform/errors/SKILL.md +183 -0
- package/skills/platform/errors/refs/patterns.md +271 -0
- package/skills/platform/errors/refs/severity.md +264 -0
- package/skills/platform/gate-benchmark-rebaseline/SKILL.md +108 -0
- package/skills/platform/gh/refs/gh.md +105 -0
- package/skills/platform/gh-cli/SKILL.md +120 -0
- package/skills/platform/gh-cli/refs/automation.md +63 -0
- package/skills/platform/gh-cli/refs/gh-ops.md +103 -0
- package/skills/platform/gh-cli/refs/patterns.md +132 -0
- package/skills/platform/gh-cli/scripts/gh_ops.py +454 -0
- package/skills/platform/github-actions/SKILL.md +159 -0
- package/skills/platform/github-actions/refs/security.md +150 -0
- package/skills/platform/github-actions/refs/templates.md +230 -0
- package/skills/platform/github-actions/refs/troubleshooting.md +174 -0
- package/skills/platform/github-actions/scripts/workflow_gen.py +215 -0
- package/skills/platform/gitlab-ci/SKILL.md +140 -0
- package/skills/platform/gitlab-ci/refs/templates.md +223 -0
- package/skills/platform/gitlab-ci/refs/troubleshooting.md +213 -0
- package/skills/platform/glab-cli/SKILL.md +133 -0
- package/skills/platform/glab-cli/refs/ci-debugging.md +95 -0
- package/skills/platform/glab-cli/refs/glab-ops.md +78 -0
- package/skills/platform/glab-cli/refs/patterns.md +131 -0
- package/skills/platform/glab-cli/scripts/glab_ops.py +313 -0
- package/skills/platform/health/SKILL.md +177 -0
- package/skills/platform/health/refs/health.md +72 -0
- package/skills/platform/health/refs/sources.md +302 -0
- package/skills/platform/incident/refs/incident.md +136 -0
- package/skills/platform/infra/refs/infra.md +104 -0
- package/skills/platform/observability/SKILL.md +128 -0
- package/skills/platform/observability/refs/toolchain-discovery.md +243 -0
- package/skills/platform/prereq-doctor/SKILL.md +57 -0
- package/skills/platform/prereq-doctor/refs/tool-registry.md +58 -0
- package/skills/platform/traces/refs/traces.md +101 -0
- package/skills/product/acceptance-criteria/SKILL.md +193 -0
- package/skills/product/acceptance-criteria/refs/ac-anti-patterns.md +291 -0
- package/skills/product/acceptance-criteria/refs/ac-examples.md +277 -0
- package/skills/product/accessibility/SKILL.md +197 -0
- package/skills/product/accessibility/refs/aria-patterns-basics.md +250 -0
- package/skills/product/accessibility/refs/aria-patterns-dynamic.md +187 -0
- package/skills/product/accessibility/refs/aria-patterns-interactive.md +246 -0
- package/skills/product/accessibility/refs/audit-report-findings.md +248 -0
- package/skills/product/accessibility/refs/audit-report-results.md +276 -0
- package/skills/product/accessibility/refs/common-violations-html-css.md +270 -0
- package/skills/product/accessibility/refs/common-violations-interactive.md +303 -0
- package/skills/product/accessibility/refs/keyboard-testing-basics.md +222 -0
- package/skills/product/accessibility/refs/keyboard-testing-patterns.md +173 -0
- package/skills/product/accessibility/refs/screen-reader-testing-advanced.md +294 -0
- package/skills/product/accessibility/refs/screen-reader-testing-commands.md +255 -0
- package/skills/product/accessibility/refs/wcag-checklist.md +262 -0
- package/skills/product/analyze/SKILL.md +164 -0
- package/skills/product/analyze/refs/algorithms.md +238 -0
- package/skills/product/analyze/refs/sentiment-patterns.md +180 -0
- package/skills/product/imagery/SKILL.md +97 -0
- package/skills/product/imagery/alter/SKILL.md +105 -0
- package/skills/product/imagery/alter/refs/editing-reference.md +146 -0
- package/skills/product/imagery/create/SKILL.md +109 -0
- package/skills/product/imagery/create/refs/prompt-engineering.md +112 -0
- package/skills/product/imagery/create/refs/provider-reference.md +219 -0
- package/skills/product/imagery/review/SKILL.md +101 -0
- package/skills/product/imagery/review/refs/analysis-lenses.md +136 -0
- package/skills/product/imagery/review/refs/quality-gates.md +153 -0
- package/skills/product/imagery/scripts/analyze.sh +23 -0
- package/skills/product/imagery/scripts/edit.sh +14 -0
- package/skills/product/imagery/scripts/generate.sh +13 -0
- package/skills/product/imagery/scripts/provider.py +787 -0
- package/skills/product/listen/SKILL.md +175 -0
- package/skills/product/listen/refs/channels.md +220 -0
- package/skills/product/mockup/SKILL.md +106 -0
- package/skills/product/mockup/refs/templates.md +95 -0
- package/skills/product/refs/a11y.md +109 -0
- package/skills/product/refs/acceptance.md +79 -0
- package/skills/product/refs/align.md +67 -0
- package/skills/product/refs/analyze.md +77 -0
- package/skills/product/refs/elicit.md +67 -0
- package/skills/product/refs/listen.md +58 -0
- package/skills/product/refs/mockup.md +77 -0
- package/skills/product/refs/screenshot.md +59 -0
- package/skills/product/refs/strategy.md +77 -0
- package/skills/product/refs/synthesize.md +54 -0
- package/skills/product/refs/ux-review.md +68 -0
- package/skills/product/refs/ux.md +101 -0
- package/skills/product/requirements-analysis/SKILL.md +136 -0
- package/skills/product/requirements-analysis/refs/requirements-example-auth.md +264 -0
- package/skills/product/requirements-analysis/refs/requirements-example-export-integration.md +88 -0
- package/skills/product/requirements-analysis/refs/requirements-output-format-template.md +247 -0
- package/skills/product/requirements-analysis/refs/user-story-guide.md +296 -0
- package/skills/product/requirements-graph/SKILL.md +155 -0
- package/skills/product/requirements-graph/refs/examples.md +223 -0
- package/skills/product/requirements-graph/refs/schema.md +162 -0
- package/skills/product/requirements-migrate/SKILL.md +90 -0
- package/skills/product/requirements-navigate/SKILL.md +141 -0
- package/skills/product/requirements-navigate/refs/meta-templates.md +141 -0
- package/skills/product/screenshot/SKILL.md +147 -0
- package/skills/product/strategy/SKILL.md +198 -0
- package/skills/product/strategy/refs/frameworks.md +295 -0
- package/skills/product/strategy/refs/templates-competitive-market.md +299 -0
- package/skills/product/strategy/refs/templates-roi-value.md +207 -0
- package/skills/product/synthesize/SKILL.md +116 -0
- package/skills/product/synthesize/refs/journey-mapping.md +212 -0
- package/skills/product/synthesize/refs/prioritization.md +193 -0
- package/skills/product/ux-review/SKILL.md +164 -0
- package/skills/product/visual-direction/SKILL.md +137 -0
- package/skills/product/visual-review/SKILL.md +131 -0
- package/skills/runtime-exec/SKILL.md +138 -0
- package/skills/search/codebase-narrator/SKILL.md +131 -0
- package/skills/search/codebase-narrator/refs/output-template.md +100 -0
- package/skills/smaht/SKILL.md +72 -0
- package/skills/smaht/discovery/SKILL.md +65 -0
- package/skills/smaht/intent/SKILL.md +89 -0
- package/skills/smaht/propose-skills/SKILL.md +142 -0
- package/skills/smaht/refs/state.md +76 -0
- package/skills/swarm/SKILL.md +132 -0
- package/skills/swarm/refs/fan-out.md +104 -0
- package/skills/swarm/refs/independent-verification.md +86 -0
- package/skills/swarm/refs/receipts-and-evidence.md +69 -0
- package/skills/swarm/refs/recon-synthesis.md +87 -0
- package/skills/swarm/refs/ship-discipline.md +90 -0
- package/skills/wickedizer/SKILL.md +147 -0
- package/skills/wickedizer/refs/artifact-types.md +238 -0
- package/skills/wickedizer/refs/complexity.md +278 -0
- package/skills/wickedizer/refs/de-ai-pass.md +140 -0
- package/skills/wickedizer/refs/failure-modes.md +249 -0
- package/skills/wickedizer/refs/patterns.md +282 -0
- package/skills/wickedizer/refs/review.md +221 -0
- package/skills/wickedizer/refs/structure.md +282 -0
- package/skills/wickedizer/refs/voice-profile.md +125 -0
- package/skills/workflow/SKILL.md +132 -0
- package/skills/workflow/refs/archetype-adjustments.md +205 -0
- package/skills/workflow/refs/evidence.md +58 -0
- package/skills/workflow/refs/integration.md +130 -0
- package/skills/workflow/refs/risk-dimension-signals.md +260 -0
- package/skills/workflow/refs/scoring-rubric.md +49 -0
- package/skills/workflow/refs/signal-keywords.md +176 -0
- package/skills/workflow/refs/specialist-routing-rules.md +159 -0
- package/skills/worktrees/SKILL.md +87 -0
- package/skills/worktrees/refs/recipes.md +96 -0
|
@@ -0,0 +1,838 @@
|
|
|
1
|
+
# Codegraph → Brain, Phase 1a: Graph Core — Implementation Plan
|
|
2
|
+
|
|
3
|
+
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
|
|
4
|
+
|
|
5
|
+
**Goal:** Make `wicked-brain` answer code-relationship queries (blast-radius, callers, lineage) from a codegraph-built static graph it owns — with zero `wicked-garden` dependency.
|
|
6
|
+
|
|
7
|
+
**Architecture:** Brain shells the external `@colbymchenry/codegraph` CLI to *build* a per-repo SQLite graph at `<source>/.codegraph/codegraph.db`, then reads that DB **directly** via `better-sqlite3` (no query-time subprocess) to serve new `graph-*` API actions, exposed through a new `wicked-brain:graph` skill. Freshness is lazy: every query carries a "N commits behind HEAD" staleness stamp and rebuilds on demand — never coupled to the file watcher (Decision D5).
|
|
8
|
+
|
|
9
|
+
**Tech Stack:** Node ≥18 ESM (`.mjs`), `better-sqlite3` v12 (read codegraph DB), `node:child_process` (shell codegraph CLI), `node:test` + `node:assert/strict`. The codegraph CLI itself requires **Node ≥22.5** (`node:sqlite`); brain runs on Node 26.
|
|
10
|
+
|
|
11
|
+
**Repo:** `/Users/michael.parcewski/Projects/wicked-brain` (server source under `server/`). This plan does NOT touch wicked-garden.
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## Subsequent plans (sequenced after this one)
|
|
16
|
+
|
|
17
|
+
- **Phase 1b — injected edges + extractor framework** (brain): built-in extractors (bus producer→consumer, command→agent, hooks, agent→tool) + the drop-in extractor registry (Decision D3). Enriches this plan's graph; independently testable.
|
|
18
|
+
- **Phase 2 — garden-side** (wicked-garden): repoint wicked-patch to brain's DB, ship the archetype extractor as a drop-in, alias/remove `search:*` commands, amend ADR 0001, update CLAUDE.md.
|
|
19
|
+
|
|
20
|
+
Reference spec: `wicked-garden/docs/specs/2026-06-10-codegraph-to-brain-migration.md` (Decisions D1–D6).
|
|
21
|
+
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
## File structure
|
|
25
|
+
|
|
26
|
+
| File | New/Mod | Responsibility |
|
|
27
|
+
|---|---|---|
|
|
28
|
+
| `server/lib/codegraph-resolver.mjs` | Create | Resolve the codegraph CLI argv (env → brain config → PATH → node_modules → npx); kill-switch. Port of garden's `_codegraph.py::resolve_codegraph`. |
|
|
29
|
+
| `server/lib/codegraph-index.mjs` | Create | `dbPath(source)`, `staleness(source)` (commits-behind HEAD), `runIndex(source)` (spawn `codegraph index`). |
|
|
30
|
+
| `server/lib/codegraph-client.mjs` | Create | Open `.codegraph/codegraph.db` readonly; `blastRadius`, `callers`, `lineage` via BFS over the `edges` table; attaches staleness to every result. |
|
|
31
|
+
| `server/bin/wicked-brain-server.mjs` | Modify (actions object ~L135–306) | Register `graph-index`, `graph-blast-radius`, `graph-callers`, `graph-lineage`; add the write one to `WRITE_ACTIONS`. |
|
|
32
|
+
| `skills/wicked-brain-graph/SKILL.md` | Create | New `wicked-brain:graph` skill documenting the graph queries. |
|
|
33
|
+
| `skills/wicked-brain-lsp/SKILL.md` | Modify (frontmatter) | Remove "blast radius" / "architecture map" trigger phrases (they were never implemented in LSP; they move here). |
|
|
34
|
+
| `server/test/codegraph-resolver.test.mjs` | Create | Resolver ladder + kill-switch. |
|
|
35
|
+
| `server/test/codegraph-index.test.mjs` | Create | dbPath + staleness (present/absent/behind). |
|
|
36
|
+
| `server/test/codegraph-client.test.mjs` | Create | blastRadius/callers/lineage over a hand-built fixture DB. |
|
|
37
|
+
| `docs/codegraph-contract.md` | Create (Task 1) | Pinned codegraph schema + edge-direction findings the client relies on. |
|
|
38
|
+
|
|
39
|
+
**Edge-direction constant:** the client centralizes the dependents-traversal direction in ONE constant (`DEPENDENTS_BY`), set from Task 1's empirical finding, so a wrong guess is a one-line flip, not a rewrite.
|
|
40
|
+
|
|
41
|
+
---
|
|
42
|
+
|
|
43
|
+
## Task 1: Characterization spike — pin codegraph's schema + edge direction
|
|
44
|
+
|
|
45
|
+
**Why:** Garden's `_codegraph.py` says the `nodes`/`edges` schema is `nodes(id,kind,name,qualified_name,file_path,language,start_line,end_line,start_column,end_column,updated_at,signature)` and `edges(source,target,kind,metadata,provenance)`, but its `inject_edges.py` comment is self-contradictory about blast-radius edge direction ("walk incoming edges" vs. an inserted producer→consumer edge that only resolves walking *outgoing*). We must observe the real behavior before writing traversal SQL.
|
|
46
|
+
|
|
47
|
+
**Files:**
|
|
48
|
+
- Create: `docs/codegraph-contract.md`
|
|
49
|
+
|
|
50
|
+
- [ ] **Step 1: Build a graph on a tiny fixture**
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
cd /tmp && rm -rf cg-spike && mkdir cg-spike && cd cg-spike
|
|
54
|
+
git init -q && printf '%s\n' "def base(): pass" > a.py
|
|
55
|
+
printf '%s\n' "from a import base" "def caller(): return base()" > b.py
|
|
56
|
+
git add -A && git commit -qm init
|
|
57
|
+
npx -y @colbymchenry/codegraph index .
|
|
58
|
+
```
|
|
59
|
+
Expected: `.codegraph/codegraph.db` created; output reports nodes/edges counts.
|
|
60
|
+
|
|
61
|
+
- [ ] **Step 2: Dump the real schema**
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
cd /tmp/cg-spike
|
|
65
|
+
sqlite3 .codegraph/codegraph.db ".schema nodes" ".schema edges"
|
|
66
|
+
sqlite3 .codegraph/codegraph.db "SELECT id,kind,name,file_path FROM nodes;"
|
|
67
|
+
sqlite3 .codegraph/codegraph.db "SELECT source,target,kind FROM edges;"
|
|
68
|
+
```
|
|
69
|
+
Record the exact column lists for `nodes` and `edges`.
|
|
70
|
+
|
|
71
|
+
- [ ] **Step 3: Determine blast-radius edge direction empirically**
|
|
72
|
+
|
|
73
|
+
`b.py::caller` calls/imports `a.py::base`. So `base`'s dependents (blast radius) must include `caller`. Inspect the edge row for that relationship:
|
|
74
|
+
- If the edge is `(source=<caller/b.py>, target=<base/a.py>)` → **dependents-of-X = rows WHERE target=X, collect `source`** → set `DEPENDENTS_BY = "target"`.
|
|
75
|
+
- If reversed → `DEPENDENTS_BY = "source"`.
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
sqlite3 .codegraph/codegraph.db \
|
|
79
|
+
"SELECT source,target,kind FROM edges WHERE kind IN ('calls','imports','references');"
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
- [ ] **Step 4: Capture the index CLI contract**
|
|
83
|
+
|
|
84
|
+
```bash
|
|
85
|
+
npx -y @colbymchenry/codegraph index --help 2>&1 | head -40
|
|
86
|
+
```
|
|
87
|
+
Record: exact subcommand + flags for indexing a directory, and whether it accepts a path arg or uses cwd. (Used by `runIndex` in Task 3.)
|
|
88
|
+
|
|
89
|
+
- [ ] **Step 5: Write the contract doc**
|
|
90
|
+
|
|
91
|
+
Create `docs/codegraph-contract.md` with: the `nodes` columns, the `edges` columns, the resolved `DEPENDENTS_BY` value (with the evidence row), the index command form, and the codegraph version (`npx -y @colbymchenry/codegraph --version`). This is the single reference Tasks 3–4 cite.
|
|
92
|
+
|
|
93
|
+
- [ ] **Step 6: Commit**
|
|
94
|
+
|
|
95
|
+
```bash
|
|
96
|
+
cd /Users/michael.parcewski/Projects/wicked-brain
|
|
97
|
+
git add docs/codegraph-contract.md
|
|
98
|
+
git commit -m "docs(codegraph): pin schema + blast-radius edge direction from spike"
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
---
|
|
102
|
+
|
|
103
|
+
## Task 2: `codegraph-resolver.mjs` — resolve the CLI
|
|
104
|
+
|
|
105
|
+
**Files:**
|
|
106
|
+
- Create: `server/lib/codegraph-resolver.mjs`
|
|
107
|
+
- Test: `server/test/codegraph-resolver.test.mjs`
|
|
108
|
+
|
|
109
|
+
- [ ] **Step 1: Write the failing test**
|
|
110
|
+
|
|
111
|
+
```javascript
|
|
112
|
+
// server/test/codegraph-resolver.test.mjs
|
|
113
|
+
import { test } from "node:test";
|
|
114
|
+
import assert from "node:assert/strict";
|
|
115
|
+
import { mkdtempSync, mkdirSync, writeFileSync, rmSync } from "node:fs";
|
|
116
|
+
import { tmpdir } from "node:os";
|
|
117
|
+
import { join } from "node:path";
|
|
118
|
+
import { resolveCodegraph } from "../lib/codegraph-resolver.mjs";
|
|
119
|
+
|
|
120
|
+
test("env override wins and is split into argv", () => {
|
|
121
|
+
const argv = resolveCodegraph({ env: { WICKED_CODEGRAPH_BIN: "/opt/cg" } });
|
|
122
|
+
assert.deepEqual(argv, ["/opt/cg"]);
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
test("a .mjs/.js env target is invoked via node", () => {
|
|
126
|
+
const argv = resolveCodegraph({ env: { WICKED_CODEGRAPH_BIN: "/x/cg.mjs" } });
|
|
127
|
+
assert.deepEqual(argv, ["node", "/x/cg.mjs"]);
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
test("set-but-empty env is the kill switch -> null", () => {
|
|
131
|
+
assert.equal(resolveCodegraph({ env: { WICKED_CODEGRAPH_BIN: "" } }), null);
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
test("brain config _meta/codegraph.json bin is honored", () => {
|
|
135
|
+
const brain = mkdtempSync(join(tmpdir(), "cg-cfg-"));
|
|
136
|
+
mkdirSync(join(brain, "_meta"), { recursive: true });
|
|
137
|
+
writeFileSync(join(brain, "_meta", "codegraph.json"), JSON.stringify({ bin: "/cfg/cg" }));
|
|
138
|
+
try {
|
|
139
|
+
const argv = resolveCodegraph({ env: {}, brainPath: brain, which: () => null });
|
|
140
|
+
assert.deepEqual(argv, ["/cfg/cg"]);
|
|
141
|
+
} finally {
|
|
142
|
+
rmSync(brain, { recursive: true, force: true });
|
|
143
|
+
}
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
test("falls back to npx when nothing else resolves", () => {
|
|
147
|
+
const argv = resolveCodegraph({ env: {}, which: (c) => (c === "npx" ? "/usr/bin/npx" : null) });
|
|
148
|
+
assert.deepEqual(argv, ["npx", "-y", "@colbymchenry/codegraph"]);
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
test("no npx and nothing resolves -> null", () => {
|
|
152
|
+
assert.equal(resolveCodegraph({ env: {}, which: () => null }), null);
|
|
153
|
+
});
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
- [ ] **Step 2: Run it, verify failure**
|
|
157
|
+
|
|
158
|
+
Run: `cd /Users/michael.parcewski/Projects/wicked-brain/server && node --test test/codegraph-resolver.test.mjs`
|
|
159
|
+
Expected: FAIL — `Cannot find module '../lib/codegraph-resolver.mjs'`.
|
|
160
|
+
|
|
161
|
+
- [ ] **Step 3: Implement**
|
|
162
|
+
|
|
163
|
+
```javascript
|
|
164
|
+
// server/lib/codegraph-resolver.mjs
|
|
165
|
+
import { execFileSync } from "node:child_process";
|
|
166
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
167
|
+
import { join } from "node:path";
|
|
168
|
+
import { platform } from "node:os";
|
|
169
|
+
|
|
170
|
+
const PACKAGE = "@colbymchenry/codegraph";
|
|
171
|
+
|
|
172
|
+
function argvFor(target) {
|
|
173
|
+
// A .mjs/.js path is a script -> invoke via node; else run directly.
|
|
174
|
+
return /\.(mjs|js)$/.test(target) ? ["node", target] : [target];
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
function whichDefault(command) {
|
|
178
|
+
try {
|
|
179
|
+
const cmd = platform() === "win32" ? "where" : "which";
|
|
180
|
+
const out = execFileSync(cmd, [command], { encoding: "utf-8", timeout: 5000,
|
|
181
|
+
stdio: ["pipe", "pipe", "pipe"] });
|
|
182
|
+
return out.trim().split("\n")[0] || null;
|
|
183
|
+
} catch {
|
|
184
|
+
return null;
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
function configBin(brainPath) {
|
|
189
|
+
if (!brainPath) return null;
|
|
190
|
+
try {
|
|
191
|
+
const cfg = JSON.parse(readFileSync(join(brainPath, "_meta", "codegraph.json"), "utf-8"));
|
|
192
|
+
return typeof cfg.bin === "string" && cfg.bin.trim() ? cfg.bin.trim() : null;
|
|
193
|
+
} catch {
|
|
194
|
+
return null;
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
/**
|
|
199
|
+
* Resolve the argv prefix that invokes codegraph, or null.
|
|
200
|
+
* Ladder: WICKED_CODEGRAPH_BIN (set-but-empty = kill switch) -> brain
|
|
201
|
+
* _meta/codegraph.json {bin} -> PATH -> source node_modules/.bin -> `npx`.
|
|
202
|
+
* @param {{env?:object, brainPath?:string, sourcePath?:string, which?:Function, allowNpx?:boolean}} opts
|
|
203
|
+
*/
|
|
204
|
+
export function resolveCodegraph(opts = {}) {
|
|
205
|
+
const { env = process.env, brainPath, sourcePath, which = whichDefault,
|
|
206
|
+
allowNpx = true } = opts;
|
|
207
|
+
|
|
208
|
+
if (Object.prototype.hasOwnProperty.call(env, "WICKED_CODEGRAPH_BIN")) {
|
|
209
|
+
const v = (env.WICKED_CODEGRAPH_BIN || "").trim();
|
|
210
|
+
return v ? argvFor(v) : null; // empty == kill switch
|
|
211
|
+
}
|
|
212
|
+
const cfg = configBin(brainPath);
|
|
213
|
+
if (cfg) return argvFor(cfg);
|
|
214
|
+
|
|
215
|
+
const onPath = which("codegraph");
|
|
216
|
+
if (onPath) return [onPath];
|
|
217
|
+
|
|
218
|
+
if (sourcePath) {
|
|
219
|
+
const local = join(sourcePath, "node_modules", ".bin", "codegraph");
|
|
220
|
+
if (existsSync(local)) return [local];
|
|
221
|
+
}
|
|
222
|
+
if (allowNpx && which("npx")) return ["npx", "-y", PACKAGE];
|
|
223
|
+
return null;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
/** True iff a CONCRETE install resolves (not the npx last resort). */
|
|
227
|
+
export function codegraphAvailable(opts = {}) {
|
|
228
|
+
return resolveCodegraph({ ...opts, allowNpx: false }) !== null;
|
|
229
|
+
}
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
- [ ] **Step 4: Run, verify pass**
|
|
233
|
+
|
|
234
|
+
Run: `node --test test/codegraph-resolver.test.mjs`
|
|
235
|
+
Expected: PASS (6 tests).
|
|
236
|
+
|
|
237
|
+
- [ ] **Step 5: Commit**
|
|
238
|
+
|
|
239
|
+
```bash
|
|
240
|
+
git add server/lib/codegraph-resolver.mjs server/test/codegraph-resolver.test.mjs
|
|
241
|
+
git commit -m "feat(codegraph): CLI resolution ladder + kill switch"
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
---
|
|
245
|
+
|
|
246
|
+
## Task 3: `codegraph-index.mjs` — dbPath, staleness, runIndex
|
|
247
|
+
|
|
248
|
+
**Files:**
|
|
249
|
+
- Create: `server/lib/codegraph-index.mjs`
|
|
250
|
+
- Test: `server/test/codegraph-index.test.mjs`
|
|
251
|
+
|
|
252
|
+
- [ ] **Step 1: Write the failing test**
|
|
253
|
+
|
|
254
|
+
```javascript
|
|
255
|
+
// server/test/codegraph-index.test.mjs
|
|
256
|
+
import { test } from "node:test";
|
|
257
|
+
import assert from "node:assert/strict";
|
|
258
|
+
import { mkdtempSync, mkdirSync, writeFileSync, rmSync, utimesSync } from "node:fs";
|
|
259
|
+
import { tmpdir } from "node:os";
|
|
260
|
+
import { join } from "node:path";
|
|
261
|
+
import { execFileSync } from "node:child_process";
|
|
262
|
+
import { dbPath, staleness } from "../lib/codegraph-index.mjs";
|
|
263
|
+
|
|
264
|
+
test("dbPath points at <source>/.codegraph/codegraph.db", () => {
|
|
265
|
+
assert.equal(dbPath("/repo"), join("/repo", ".codegraph", "codegraph.db"));
|
|
266
|
+
});
|
|
267
|
+
|
|
268
|
+
test("staleness reports not-present when db is missing", () => {
|
|
269
|
+
const s = staleness("/no/such/repo");
|
|
270
|
+
assert.equal(s.present, false);
|
|
271
|
+
assert.equal(s.stale, null);
|
|
272
|
+
});
|
|
273
|
+
|
|
274
|
+
test("staleness reports commits behind HEAD", () => {
|
|
275
|
+
const repo = mkdtempSync(join(tmpdir(), "cg-stale-"));
|
|
276
|
+
try {
|
|
277
|
+
const git = (...a) => execFileSync("git", ["-C", repo, ...a], { stdio: "pipe" });
|
|
278
|
+
git("init"); git("config", "user.email", "t@t"); git("config", "user.name", "t");
|
|
279
|
+
writeFileSync(join(repo, "f.txt"), "1"); git("add", "-A"); git("commit", "-m", "c1");
|
|
280
|
+
// build the db, then backdate it before a second commit
|
|
281
|
+
mkdirSync(join(repo, ".codegraph"), { recursive: true });
|
|
282
|
+
const db = join(repo, ".codegraph", "codegraph.db");
|
|
283
|
+
writeFileSync(db, "x");
|
|
284
|
+
const past = new Date(Date.now() - 60_000);
|
|
285
|
+
utimesSync(db, past, past);
|
|
286
|
+
writeFileSync(join(repo, "g.txt"), "2"); git("add", "-A"); git("commit", "-m", "c2");
|
|
287
|
+
|
|
288
|
+
const s = staleness(repo);
|
|
289
|
+
assert.equal(s.present, true);
|
|
290
|
+
assert.equal(s.stale, true);
|
|
291
|
+
assert.ok(s.commits_behind >= 1);
|
|
292
|
+
} finally {
|
|
293
|
+
rmSync(repo, { recursive: true, force: true });
|
|
294
|
+
}
|
|
295
|
+
});
|
|
296
|
+
```
|
|
297
|
+
|
|
298
|
+
- [ ] **Step 2: Run, verify failure**
|
|
299
|
+
|
|
300
|
+
Run: `node --test test/codegraph-index.test.mjs`
|
|
301
|
+
Expected: FAIL — module not found.
|
|
302
|
+
|
|
303
|
+
- [ ] **Step 3: Implement**
|
|
304
|
+
|
|
305
|
+
```javascript
|
|
306
|
+
// server/lib/codegraph-index.mjs
|
|
307
|
+
import { execFileSync, spawn } from "node:child_process";
|
|
308
|
+
import { existsSync, statSync } from "node:fs";
|
|
309
|
+
import { join } from "node:path";
|
|
310
|
+
import { resolveCodegraph } from "./codegraph-resolver.mjs";
|
|
311
|
+
|
|
312
|
+
export function dbPath(sourcePath) {
|
|
313
|
+
return join(sourcePath, ".codegraph", "codegraph.db");
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
/**
|
|
317
|
+
* How far the graph has drifted from HEAD. Fail-open: errors report
|
|
318
|
+
* present-but-unknown, never throw. Port of garden _codegraph.py::staleness.
|
|
319
|
+
* @returns {{present:boolean, stale:boolean|null, commits_behind:number|null, indexed_at:string|null}}
|
|
320
|
+
*/
|
|
321
|
+
export function staleness(sourcePath) {
|
|
322
|
+
const db = dbPath(sourcePath);
|
|
323
|
+
if (!existsSync(db)) {
|
|
324
|
+
return { present: false, stale: null, commits_behind: null, indexed_at: null };
|
|
325
|
+
}
|
|
326
|
+
try {
|
|
327
|
+
const mtimeMs = statSync(db).mtimeMs;
|
|
328
|
+
const iso = new Date(mtimeMs).toISOString();
|
|
329
|
+
const out = execFileSync("git",
|
|
330
|
+
["-C", sourcePath, "rev-list", "--count", `--since=${iso}`, "HEAD"],
|
|
331
|
+
{ encoding: "utf-8", timeout: 10_000, stdio: ["pipe", "pipe", "pipe"] }).trim();
|
|
332
|
+
const behind = out ? parseInt(out, 10) : 0;
|
|
333
|
+
return { present: true, stale: behind > 0, commits_behind: behind, indexed_at: iso };
|
|
334
|
+
} catch {
|
|
335
|
+
return { present: true, stale: null, commits_behind: null, indexed_at: null };
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
/**
|
|
340
|
+
* Build/refresh the graph by shelling `codegraph index`. Resolves nothing ->
|
|
341
|
+
* returns {ok:false, error}. Never throws.
|
|
342
|
+
* NOTE: the index subcommand/flags are pinned in docs/codegraph-contract.md (Task 1).
|
|
343
|
+
*/
|
|
344
|
+
export function runIndex(sourcePath, opts = {}) {
|
|
345
|
+
return new Promise((resolve) => {
|
|
346
|
+
const argv = resolveCodegraph({ ...opts, sourcePath });
|
|
347
|
+
if (!argv) { resolve({ ok: false, error: "codegraph not resolvable" }); return; }
|
|
348
|
+
const [cmd, ...prefix] = argv;
|
|
349
|
+
const proc = spawn(cmd, [...prefix, "index", "."], {
|
|
350
|
+
cwd: sourcePath, stdio: ["ignore", "pipe", "pipe"],
|
|
351
|
+
});
|
|
352
|
+
let stderr = "";
|
|
353
|
+
proc.stderr.on("data", (d) => { stderr += d.toString(); });
|
|
354
|
+
proc.on("error", (e) => resolve({ ok: false, error: e.message }));
|
|
355
|
+
proc.on("close", (code) =>
|
|
356
|
+
resolve(code === 0 ? { ok: true } : { ok: false, error: stderr.trim() || `exit ${code}` }));
|
|
357
|
+
});
|
|
358
|
+
}
|
|
359
|
+
```
|
|
360
|
+
|
|
361
|
+
- [ ] **Step 4: Run, verify pass**
|
|
362
|
+
|
|
363
|
+
Run: `node --test test/codegraph-index.test.mjs`
|
|
364
|
+
Expected: PASS (3 tests).
|
|
365
|
+
|
|
366
|
+
- [ ] **Step 5: Commit**
|
|
367
|
+
|
|
368
|
+
```bash
|
|
369
|
+
git add server/lib/codegraph-index.mjs server/test/codegraph-index.test.mjs
|
|
370
|
+
git commit -m "feat(codegraph): dbPath + staleness stamp + index runner"
|
|
371
|
+
```
|
|
372
|
+
|
|
373
|
+
---
|
|
374
|
+
|
|
375
|
+
## Task 4: `codegraph-client.mjs` — blast-radius / callers / lineage
|
|
376
|
+
|
|
377
|
+
**Files:**
|
|
378
|
+
- Create: `server/lib/codegraph-client.mjs`
|
|
379
|
+
- Test: `server/test/codegraph-client.test.mjs`
|
|
380
|
+
|
|
381
|
+
> The client reads codegraph's DB directly (no query-time subprocess). Schema from Task 1: `nodes(id,kind,name,qualified_name,file_path,language,start_line,end_line,start_column,end_column,updated_at,signature)`, `edges(source,target,kind,metadata,provenance)`. `DEPENDENTS_BY` is set from Task 1, Step 3 (default `"target"` — dependents of X are edge rows WHERE target=X, collecting `source`).
|
|
382
|
+
|
|
383
|
+
- [ ] **Step 1: Write the failing test (hand-built fixture DB)**
|
|
384
|
+
|
|
385
|
+
```javascript
|
|
386
|
+
// server/test/codegraph-client.test.mjs
|
|
387
|
+
import { test } from "node:test";
|
|
388
|
+
import assert from "node:assert/strict";
|
|
389
|
+
import { mkdtempSync, mkdirSync, rmSync } from "node:fs";
|
|
390
|
+
import { tmpdir } from "node:os";
|
|
391
|
+
import { join } from "node:path";
|
|
392
|
+
import Database from "better-sqlite3";
|
|
393
|
+
import { CodegraphClient } from "../lib/codegraph-client.mjs";
|
|
394
|
+
|
|
395
|
+
function makeRepo() {
|
|
396
|
+
const repo = mkdtempSync(join(tmpdir(), "cg-client-"));
|
|
397
|
+
mkdirSync(join(repo, ".codegraph"), { recursive: true });
|
|
398
|
+
const db = new Database(join(repo, ".codegraph", "codegraph.db"));
|
|
399
|
+
db.exec(`
|
|
400
|
+
CREATE TABLE nodes (id TEXT PRIMARY KEY, kind TEXT, name TEXT, qualified_name TEXT,
|
|
401
|
+
file_path TEXT, language TEXT, start_line INT, end_line INT,
|
|
402
|
+
start_column INT, end_column INT, updated_at INT, signature TEXT);
|
|
403
|
+
CREATE TABLE edges (source TEXT, target TEXT, kind TEXT, metadata TEXT, provenance TEXT);
|
|
404
|
+
`);
|
|
405
|
+
const n = db.prepare(`INSERT INTO nodes
|
|
406
|
+
(id,kind,name,qualified_name,file_path,language,start_line,end_line,start_column,end_column,updated_at,signature)
|
|
407
|
+
VALUES (?,?,?,?,?,?,?,?,0,0,0,?)`);
|
|
408
|
+
n.run("file:a.py", "file", "a.py", "a.py", "a.py", "python", 1, 1, null);
|
|
409
|
+
n.run("file:b.py", "file", "b.py", "b.py", "b.py", "python", 1, 2, null);
|
|
410
|
+
n.run("file:c.py", "file", "c.py", "c.py", "c.py", "python", 1, 2, null);
|
|
411
|
+
// b and c depend on a (edge source=dependent, target=dependency)
|
|
412
|
+
const e = db.prepare("INSERT INTO edges (source,target,kind,metadata,provenance) VALUES (?,?,?,?,?)");
|
|
413
|
+
e.run("file:b.py", "file:a.py", "imports", null, "static");
|
|
414
|
+
e.run("file:c.py", "file:b.py", "calls", null, "static");
|
|
415
|
+
db.close();
|
|
416
|
+
return repo;
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
test("blastRadius returns transitive dependents of a node", () => {
|
|
420
|
+
const repo = makeRepo();
|
|
421
|
+
try {
|
|
422
|
+
const c = new CodegraphClient(repo);
|
|
423
|
+
const r = c.blastRadius({ node: "file:a.py" });
|
|
424
|
+
const ids = r.dependents.map((d) => d.id).sort();
|
|
425
|
+
assert.deepEqual(ids, ["file:b.py", "file:c.py"]); // c depends on b depends on a
|
|
426
|
+
assert.equal(r.staleness.present, true);
|
|
427
|
+
c.close();
|
|
428
|
+
} finally {
|
|
429
|
+
rmSync(repo, { recursive: true, force: true });
|
|
430
|
+
}
|
|
431
|
+
});
|
|
432
|
+
|
|
433
|
+
test("callers returns direct dependents only", () => {
|
|
434
|
+
const repo = makeRepo();
|
|
435
|
+
try {
|
|
436
|
+
const c = new CodegraphClient(repo);
|
|
437
|
+
const r = c.callers({ node: "file:a.py" });
|
|
438
|
+
assert.deepEqual(r.callers.map((d) => d.id), ["file:b.py"]);
|
|
439
|
+
c.close();
|
|
440
|
+
} finally {
|
|
441
|
+
rmSync(repo, { recursive: true, force: true });
|
|
442
|
+
}
|
|
443
|
+
});
|
|
444
|
+
|
|
445
|
+
test("lineage returns transitive dependencies (downstream)", () => {
|
|
446
|
+
const repo = makeRepo();
|
|
447
|
+
try {
|
|
448
|
+
const c = new CodegraphClient(repo);
|
|
449
|
+
const r = c.lineage({ node: "file:c.py" });
|
|
450
|
+
const ids = r.dependencies.map((d) => d.id).sort();
|
|
451
|
+
assert.deepEqual(ids, ["file:a.py", "file:b.py"]);
|
|
452
|
+
c.close();
|
|
453
|
+
} finally {
|
|
454
|
+
rmSync(repo, { recursive: true, force: true });
|
|
455
|
+
}
|
|
456
|
+
});
|
|
457
|
+
|
|
458
|
+
test("missing db -> engine unavailable, not an empty graph", () => {
|
|
459
|
+
const repo = mkdtempSync(join(tmpdir(), "cg-empty-"));
|
|
460
|
+
try {
|
|
461
|
+
const c = new CodegraphClient(repo);
|
|
462
|
+
const r = c.blastRadius({ node: "file:a.py" });
|
|
463
|
+
assert.equal(r.engine, "unavailable");
|
|
464
|
+
c.close();
|
|
465
|
+
} finally {
|
|
466
|
+
rmSync(repo, { recursive: true, force: true });
|
|
467
|
+
}
|
|
468
|
+
});
|
|
469
|
+
```
|
|
470
|
+
|
|
471
|
+
- [ ] **Step 2: Run, verify failure**
|
|
472
|
+
|
|
473
|
+
Run: `node --test test/codegraph-client.test.mjs`
|
|
474
|
+
Expected: FAIL — module not found.
|
|
475
|
+
|
|
476
|
+
- [ ] **Step 3: Implement**
|
|
477
|
+
|
|
478
|
+
```javascript
|
|
479
|
+
// server/lib/codegraph-client.mjs
|
|
480
|
+
import { existsSync } from "node:fs";
|
|
481
|
+
import Database from "better-sqlite3";
|
|
482
|
+
import { dbPath, staleness } from "./codegraph-index.mjs";
|
|
483
|
+
|
|
484
|
+
// Set from Task 1, Step 3. "target": dependents-of-X are edges WHERE target=X
|
|
485
|
+
// (collect `source`); dependencies-of-X are edges WHERE source=X (collect `target`).
|
|
486
|
+
const DEPENDENTS_BY = "target";
|
|
487
|
+
const DEPENDENCIES_BY = DEPENDENTS_BY === "target" ? "source" : "target";
|
|
488
|
+
|
|
489
|
+
export class CodegraphClient {
|
|
490
|
+
#sourcePath;
|
|
491
|
+
#db = null;
|
|
492
|
+
|
|
493
|
+
constructor(sourcePath) { this.#sourcePath = sourcePath; }
|
|
494
|
+
|
|
495
|
+
#open() {
|
|
496
|
+
if (this.#db) return this.#db;
|
|
497
|
+
const p = dbPath(this.#sourcePath);
|
|
498
|
+
if (!existsSync(p)) return null;
|
|
499
|
+
this.#db = new Database(p, { readonly: true });
|
|
500
|
+
return this.#db;
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
close() { if (this.#db) { this.#db.close(); this.#db = null; } }
|
|
504
|
+
|
|
505
|
+
#nodeRows(ids) {
|
|
506
|
+
if (ids.length === 0) return [];
|
|
507
|
+
const db = this.#db;
|
|
508
|
+
const ph = ids.map(() => "?").join(",");
|
|
509
|
+
return db.prepare(
|
|
510
|
+
`SELECT id, kind, name, file_path, start_line, end_line FROM nodes WHERE id IN (${ph})`
|
|
511
|
+
).all(...ids);
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
// Generic BFS over edges. fromCol = the column we match the frontier on;
|
|
515
|
+
// toCol = the column we collect as the next frontier.
|
|
516
|
+
#walk(start, { fromCol, toCol, maxDepth }) {
|
|
517
|
+
const db = this.#db;
|
|
518
|
+
const stmt = db.prepare(`SELECT DISTINCT ${toCol} AS next FROM edges WHERE ${fromCol} = ?`);
|
|
519
|
+
const seen = new Set();
|
|
520
|
+
let frontier = [start];
|
|
521
|
+
let depth = 0;
|
|
522
|
+
while (frontier.length && depth < maxDepth) {
|
|
523
|
+
const nextFrontier = [];
|
|
524
|
+
for (const node of frontier) {
|
|
525
|
+
for (const row of stmt.all(node)) {
|
|
526
|
+
if (row.next && row.next !== start && !seen.has(row.next)) {
|
|
527
|
+
seen.add(row.next);
|
|
528
|
+
nextFrontier.push(row.next);
|
|
529
|
+
}
|
|
530
|
+
}
|
|
531
|
+
}
|
|
532
|
+
frontier = nextFrontier;
|
|
533
|
+
depth += 1;
|
|
534
|
+
}
|
|
535
|
+
return [...seen];
|
|
536
|
+
}
|
|
537
|
+
|
|
538
|
+
#unavailable() {
|
|
539
|
+
return { engine: "unavailable", reason: `no graph at ${dbPath(this.#sourcePath)} — run graph-index`,
|
|
540
|
+
staleness: staleness(this.#sourcePath) };
|
|
541
|
+
}
|
|
542
|
+
|
|
543
|
+
/** Transitive dependents of a node — "what breaks if I change X". */
|
|
544
|
+
blastRadius({ node, maxDepth = 25 }) {
|
|
545
|
+
if (!this.#open()) return this.#unavailable();
|
|
546
|
+
const ids = this.#walk(node, { fromCol: DEPENDENTS_BY,
|
|
547
|
+
toCol: DEPENDENTS_BY === "target" ? "source" : "target", maxDepth });
|
|
548
|
+
return { node, dependents: this.#nodeRows(ids), staleness: staleness(this.#sourcePath) };
|
|
549
|
+
}
|
|
550
|
+
|
|
551
|
+
/** Direct dependents only (depth 1). */
|
|
552
|
+
callers({ node }) {
|
|
553
|
+
if (!this.#open()) return this.#unavailable();
|
|
554
|
+
const ids = this.#walk(node, { fromCol: DEPENDENTS_BY,
|
|
555
|
+
toCol: DEPENDENTS_BY === "target" ? "source" : "target", maxDepth: 1 });
|
|
556
|
+
return { node, callers: this.#nodeRows(ids), staleness: staleness(this.#sourcePath) };
|
|
557
|
+
}
|
|
558
|
+
|
|
559
|
+
/** Transitive dependencies of a node — downstream lineage. */
|
|
560
|
+
lineage({ node, maxDepth = 25 }) {
|
|
561
|
+
if (!this.#open()) return this.#unavailable();
|
|
562
|
+
const ids = this.#walk(node, { fromCol: DEPENDENCIES_BY,
|
|
563
|
+
toCol: DEPENDENCIES_BY === "target" ? "source" : "target", maxDepth });
|
|
564
|
+
return { node, dependencies: this.#nodeRows(ids), staleness: staleness(this.#sourcePath) };
|
|
565
|
+
}
|
|
566
|
+
}
|
|
567
|
+
```
|
|
568
|
+
|
|
569
|
+
> Note for the implementer: `#walk`'s `toCol` is derived inline so dependents collect the opposite column from the one matched. If Task 1 flips `DEPENDENTS_BY` to `"source"`, the derivations follow automatically — no other change needed.
|
|
570
|
+
|
|
571
|
+
- [ ] **Step 4: Run, verify pass**
|
|
572
|
+
|
|
573
|
+
Run: `node --test test/codegraph-client.test.mjs`
|
|
574
|
+
Expected: PASS (4 tests).
|
|
575
|
+
|
|
576
|
+
- [ ] **Step 5: Commit**
|
|
577
|
+
|
|
578
|
+
```bash
|
|
579
|
+
git add server/lib/codegraph-client.mjs server/test/codegraph-client.test.mjs
|
|
580
|
+
git commit -m "feat(codegraph): graph client — blast-radius/callers/lineage over edges"
|
|
581
|
+
```
|
|
582
|
+
|
|
583
|
+
---
|
|
584
|
+
|
|
585
|
+
## Task 5: Wire the `graph-*` server actions
|
|
586
|
+
|
|
587
|
+
**Files:**
|
|
588
|
+
- Modify: `server/bin/wicked-brain-server.mjs` (the `actions` object ~L135–306; `WRITE_ACTIONS` set ~L311–321)
|
|
589
|
+
- Test: `server/test/codegraph-actions.test.mjs` (Create)
|
|
590
|
+
|
|
591
|
+
> The server constructs collaborators once at startup (`db`, `lsp`) from `brainPath`/`sourcePath`. Add a codegraph client + index runner the same way and register four actions. `graph-index` mutates → add to `WRITE_ACTIONS`.
|
|
592
|
+
|
|
593
|
+
- [ ] **Step 1: Write the failing test (handlers are pure functions of params)**
|
|
594
|
+
|
|
595
|
+
```javascript
|
|
596
|
+
// server/test/codegraph-actions.test.mjs
|
|
597
|
+
import { test } from "node:test";
|
|
598
|
+
import assert from "node:assert/strict";
|
|
599
|
+
import { mkdtempSync, mkdirSync, rmSync } from "node:fs";
|
|
600
|
+
import { tmpdir } from "node:os";
|
|
601
|
+
import { join } from "node:path";
|
|
602
|
+
import Database from "better-sqlite3";
|
|
603
|
+
import { makeGraphActions } from "../lib/codegraph-actions.mjs";
|
|
604
|
+
|
|
605
|
+
function repoWithGraph() {
|
|
606
|
+
const repo = mkdtempSync(join(tmpdir(), "cg-act-"));
|
|
607
|
+
mkdirSync(join(repo, ".codegraph"), { recursive: true });
|
|
608
|
+
const db = new Database(join(repo, ".codegraph", "codegraph.db"));
|
|
609
|
+
db.exec(`CREATE TABLE nodes (id TEXT PRIMARY KEY, kind TEXT, name TEXT, qualified_name TEXT,
|
|
610
|
+
file_path TEXT, language TEXT, start_line INT, end_line INT, start_column INT,
|
|
611
|
+
end_column INT, updated_at INT, signature TEXT);
|
|
612
|
+
CREATE TABLE edges (source TEXT, target TEXT, kind TEXT, metadata TEXT, provenance TEXT);`);
|
|
613
|
+
db.prepare(`INSERT INTO nodes (id,kind,name,qualified_name,file_path,language,start_line,end_line,start_column,end_column,updated_at,signature)
|
|
614
|
+
VALUES (?,?,?,?,?,?,1,1,0,0,0,NULL)`).run("file:a.py","file","a.py","a.py","a.py","python");
|
|
615
|
+
db.prepare(`INSERT INTO nodes (id,kind,name,qualified_name,file_path,language,start_line,end_line,start_column,end_column,updated_at,signature)
|
|
616
|
+
VALUES (?,?,?,?,?,?,1,1,0,0,0,NULL)`).run("file:b.py","file","b.py","b.py","b.py","python");
|
|
617
|
+
db.prepare("INSERT INTO edges (source,target,kind,metadata,provenance) VALUES (?,?,?,?,?)")
|
|
618
|
+
.run("file:b.py","file:a.py","imports",null,"static");
|
|
619
|
+
db.close();
|
|
620
|
+
return repo;
|
|
621
|
+
}
|
|
622
|
+
|
|
623
|
+
test("graph-blast-radius action returns dependents", () => {
|
|
624
|
+
const repo = repoWithGraph();
|
|
625
|
+
try {
|
|
626
|
+
const actions = makeGraphActions({ sourcePath: repo });
|
|
627
|
+
const r = actions["graph-blast-radius"]({ node: "file:a.py" });
|
|
628
|
+
assert.deepEqual(r.dependents.map((d) => d.id), ["file:b.py"]);
|
|
629
|
+
} finally {
|
|
630
|
+
rmSync(repo, { recursive: true, force: true });
|
|
631
|
+
}
|
|
632
|
+
});
|
|
633
|
+
|
|
634
|
+
test("graph-blast-radius on a graphless repo reports unavailable", () => {
|
|
635
|
+
const repo = mkdtempSync(join(tmpdir(), "cg-none-"));
|
|
636
|
+
try {
|
|
637
|
+
const actions = makeGraphActions({ sourcePath: repo });
|
|
638
|
+
assert.equal(actions["graph-blast-radius"]({ node: "x" }).engine, "unavailable");
|
|
639
|
+
} finally {
|
|
640
|
+
rmSync(repo, { recursive: true, force: true });
|
|
641
|
+
}
|
|
642
|
+
});
|
|
643
|
+
```
|
|
644
|
+
|
|
645
|
+
- [ ] **Step 2: Run, verify failure**
|
|
646
|
+
|
|
647
|
+
Run: `node --test test/codegraph-actions.test.mjs`
|
|
648
|
+
Expected: FAIL — `Cannot find module '../lib/codegraph-actions.mjs'`.
|
|
649
|
+
|
|
650
|
+
- [ ] **Step 3: Implement the action factory**
|
|
651
|
+
|
|
652
|
+
```javascript
|
|
653
|
+
// server/lib/codegraph-actions.mjs
|
|
654
|
+
import { CodegraphClient } from "./codegraph-client.mjs";
|
|
655
|
+
import { runIndex, staleness } from "./codegraph-index.mjs";
|
|
656
|
+
|
|
657
|
+
/**
|
|
658
|
+
* Build the graph-* action handlers bound to a source repo. A fresh client per
|
|
659
|
+
* call keeps the readonly DB handle short-lived and always reopens after a rebuild.
|
|
660
|
+
*/
|
|
661
|
+
export function makeGraphActions({ sourcePath, brainPath } = {}) {
|
|
662
|
+
const withClient = (fn) => {
|
|
663
|
+
const c = new CodegraphClient(sourcePath);
|
|
664
|
+
try { return fn(c); } finally { c.close(); }
|
|
665
|
+
};
|
|
666
|
+
return {
|
|
667
|
+
"graph-blast-radius": (p = {}) => withClient((c) => c.blastRadius({ node: p.node, maxDepth: p.maxDepth })),
|
|
668
|
+
"graph-callers": (p = {}) => withClient((c) => c.callers({ node: p.node })),
|
|
669
|
+
"graph-lineage": (p = {}) => withClient((c) => c.lineage({ node: p.node, maxDepth: p.maxDepth })),
|
|
670
|
+
"graph-index": async () => {
|
|
671
|
+
const r = await runIndex(sourcePath, { brainPath, sourcePath });
|
|
672
|
+
return { ...r, staleness: staleness(sourcePath) };
|
|
673
|
+
},
|
|
674
|
+
};
|
|
675
|
+
}
|
|
676
|
+
```
|
|
677
|
+
|
|
678
|
+
- [ ] **Step 4: Run, verify pass**
|
|
679
|
+
|
|
680
|
+
Run: `node --test test/codegraph-actions.test.mjs`
|
|
681
|
+
Expected: PASS (2 tests).
|
|
682
|
+
|
|
683
|
+
- [ ] **Step 5: Register actions in the server**
|
|
684
|
+
|
|
685
|
+
In `server/bin/wicked-brain-server.mjs`, near where `lsp`/`db` are constructed, add:
|
|
686
|
+
|
|
687
|
+
```javascript
|
|
688
|
+
import { makeGraphActions } from "../lib/codegraph-actions.mjs";
|
|
689
|
+
// ... after sourcePath/brainPath are known:
|
|
690
|
+
const graphActions = makeGraphActions({ sourcePath, brainPath });
|
|
691
|
+
```
|
|
692
|
+
|
|
693
|
+
Then spread the handlers into the `actions` object (alongside the `lsp-*` block ~L238–248):
|
|
694
|
+
|
|
695
|
+
```javascript
|
|
696
|
+
...graphActions, // graph-index, graph-blast-radius, graph-callers, graph-lineage
|
|
697
|
+
```
|
|
698
|
+
|
|
699
|
+
And add the mutating one to the `WRITE_ACTIONS` set (~L311–321):
|
|
700
|
+
|
|
701
|
+
```javascript
|
|
702
|
+
const WRITE_ACTIONS = new Set([
|
|
703
|
+
/* ...existing... */
|
|
704
|
+
"graph-index",
|
|
705
|
+
]);
|
|
706
|
+
```
|
|
707
|
+
|
|
708
|
+
- [ ] **Step 6: Smoke the live server action**
|
|
709
|
+
|
|
710
|
+
```bash
|
|
711
|
+
cd /Users/michael.parcewski/Projects/wicked-brain/server
|
|
712
|
+
# in repo /tmp/cg-spike from Task 1, with .codegraph already built:
|
|
713
|
+
node bin/wicked-brain-server.mjs --brain /tmp/cg-spike-brain --port 4399 --source /tmp/cg-spike &
|
|
714
|
+
SRV=$!; sleep 1
|
|
715
|
+
curl -s -XPOST localhost:4399/api -H 'content-type: application/json' \
|
|
716
|
+
-d '{"action":"graph-blast-radius","params":{"node":"file:a.py"}}'
|
|
717
|
+
kill $SRV
|
|
718
|
+
```
|
|
719
|
+
Expected: JSON with a `dependents` array containing `file:b.py` and a `staleness` object.
|
|
720
|
+
|
|
721
|
+
- [ ] **Step 7: Commit**
|
|
722
|
+
|
|
723
|
+
```bash
|
|
724
|
+
git add server/lib/codegraph-actions.mjs server/test/codegraph-actions.test.mjs server/bin/wicked-brain-server.mjs
|
|
725
|
+
git commit -m "feat(codegraph): register graph-* server actions"
|
|
726
|
+
```
|
|
727
|
+
|
|
728
|
+
---
|
|
729
|
+
|
|
730
|
+
## Task 6: `wicked-brain:graph` skill + trim the LSP skill
|
|
731
|
+
|
|
732
|
+
**Files:**
|
|
733
|
+
- Create: `skills/wicked-brain-graph/SKILL.md`
|
|
734
|
+
- Modify: `skills/wicked-brain-lsp/SKILL.md` (frontmatter description only)
|
|
735
|
+
|
|
736
|
+
- [ ] **Step 1: Create the graph skill**
|
|
737
|
+
|
|
738
|
+
```markdown
|
|
739
|
+
---
|
|
740
|
+
name: wicked-brain:graph
|
|
741
|
+
description: |
|
|
742
|
+
Code-relationship graph queries — blast radius, callers, and lineage — backed
|
|
743
|
+
by a codegraph static graph the brain owns. Answers "what breaks if I change X",
|
|
744
|
+
"who calls X", and "what does X depend on" across the whole repo, including
|
|
745
|
+
relationships a grep or single-file LSP lookup cannot see.
|
|
746
|
+
|
|
747
|
+
Use when: "blast radius", "what breaks if I change", "impact of changing X",
|
|
748
|
+
"who calls X", "what depends on X", "lineage", "what does X depend on",
|
|
749
|
+
"architecture map", "code relationship graph".
|
|
750
|
+
---
|
|
751
|
+
|
|
752
|
+
# wicked-brain:graph
|
|
753
|
+
|
|
754
|
+
Relationship-graph intelligence over a codegraph-built SQLite graph. Distinct from
|
|
755
|
+
`wicked-brain:lsp` (live, single-symbol def/ref/hover/diagnostics) — this is the
|
|
756
|
+
whole-repo relationship graph and the home of blast-radius / lineage.
|
|
757
|
+
|
|
758
|
+
## Queries (via `npx wicked-brain-call`)
|
|
759
|
+
|
|
760
|
+
- `graph-index` — build/refresh the graph (`codegraph index .`). Run once per repo,
|
|
761
|
+
then on demand when results report they are stale.
|
|
762
|
+
- `graph-blast-radius {node}` — transitive dependents of `node` ("what breaks if I change it").
|
|
763
|
+
- `graph-callers {node}` — direct dependents only.
|
|
764
|
+
- `graph-lineage {node}` — transitive dependencies (downstream).
|
|
765
|
+
|
|
766
|
+
`node` ids follow codegraph's convention (e.g. `file:src/app.py`, or a symbol id).
|
|
767
|
+
Every result carries a `staleness` stamp (`commits_behind`, `indexed_at`); if
|
|
768
|
+
`stale` is true, re-run `graph-index`.
|
|
769
|
+
|
|
770
|
+
## Freshness
|
|
771
|
+
|
|
772
|
+
Lazy by design — the graph is never auto-rebuilt by a file watcher. Results tell you
|
|
773
|
+
when they are behind HEAD; rebuild with `graph-index` (or wire the optional commit hook).
|
|
774
|
+
```
|
|
775
|
+
|
|
776
|
+
- [ ] **Step 2: Trim the LSP skill description**
|
|
777
|
+
|
|
778
|
+
In `skills/wicked-brain-lsp/SKILL.md` frontmatter, remove the `"blast radius"` and `"architecture map"` trigger phrases from the `Use when:` line (they were never implemented in LSP and now live in `wicked-brain:graph`). Add a one-line pointer in the body:
|
|
779
|
+
|
|
780
|
+
```markdown
|
|
781
|
+
> For blast-radius / lineage / architecture (whole-repo relationships), use `wicked-brain:graph`.
|
|
782
|
+
```
|
|
783
|
+
|
|
784
|
+
- [ ] **Step 3: Verify install picks up the new skill**
|
|
785
|
+
|
|
786
|
+
```bash
|
|
787
|
+
cd /Users/michael.parcewski/Projects/wicked-brain
|
|
788
|
+
node install.mjs 2>&1 | grep -i "skills installed"
|
|
789
|
+
ls ~/.claude/skills/wicked-brain-graph/SKILL.md
|
|
790
|
+
```
|
|
791
|
+
Expected: install reports the skill count incremented by one; the file exists.
|
|
792
|
+
|
|
793
|
+
- [ ] **Step 4: Commit**
|
|
794
|
+
|
|
795
|
+
```bash
|
|
796
|
+
git add skills/wicked-brain-graph/SKILL.md skills/wicked-brain-lsp/SKILL.md
|
|
797
|
+
git commit -m "feat(codegraph): wicked-brain:graph skill; move blast-radius off lsp skill"
|
|
798
|
+
```
|
|
799
|
+
|
|
800
|
+
---
|
|
801
|
+
|
|
802
|
+
## Task 7: End-to-end verification
|
|
803
|
+
|
|
804
|
+
**Files:** none (verification only)
|
|
805
|
+
|
|
806
|
+
- [ ] **Step 1: Full suite green**
|
|
807
|
+
|
|
808
|
+
Run: `cd /Users/michael.parcewski/Projects/wicked-brain/server && npm test`
|
|
809
|
+
Expected: all tests pass, including the four new files.
|
|
810
|
+
|
|
811
|
+
- [ ] **Step 2: Real-repo blast-radius**
|
|
812
|
+
|
|
813
|
+
```bash
|
|
814
|
+
# Point at a real repo (e.g. wicked-brain itself), build, query.
|
|
815
|
+
cd /Users/michael.parcewski/Projects/wicked-brain
|
|
816
|
+
npx -y @colbymchenry/codegraph index .
|
|
817
|
+
node server/bin/wicked-brain-server.mjs --brain ~/.wicked-brain/projects/cg-e2e --port 4398 --source "$PWD" &
|
|
818
|
+
SRV=$!; sleep 1
|
|
819
|
+
curl -s -XPOST localhost:4398/api -H 'content-type: application/json' \
|
|
820
|
+
-d '{"action":"graph-callers","params":{"node":"file:server/lib/sqlite-search.mjs"}}' | head -c 400
|
|
821
|
+
kill $SRV
|
|
822
|
+
```
|
|
823
|
+
Expected: a `callers` array (non-empty if anything imports that module) + a `staleness` stamp with `stale:false` right after indexing.
|
|
824
|
+
|
|
825
|
+
- [ ] **Step 3: Commit (if any doc tweaks)**
|
|
826
|
+
|
|
827
|
+
```bash
|
|
828
|
+
git add -A && git commit -m "test(codegraph): phase-1a e2e verification notes" || echo "nothing to commit"
|
|
829
|
+
```
|
|
830
|
+
|
|
831
|
+
---
|
|
832
|
+
|
|
833
|
+
## Self-review (done at write time)
|
|
834
|
+
|
|
835
|
+
- **Spec coverage:** D1 (brain owns queries) → Tasks 4–6. D2 (zero garden dep) → all code is brain-native `.mjs`, imports nothing from garden. D4 (codegraph=graph of record, LSP=live) → Task 6 moves blast-radius off LSP. D5 (lazy staleness, no watcher) → Task 3 staleness + Task 5 `graph-index` on demand, watcher untouched. D6 (DB stays codegraph-native) → `dbPath` = `<source>/.codegraph/codegraph.db`, opened readonly. D3 (extractor registry) + injected edges are **Phase 1b** — explicitly out of this plan.
|
|
836
|
+
- **Placeholder scan:** none — every step has runnable code/commands. The one empirical unknown (edge direction) is isolated to Task 1 + the `DEPENDENTS_BY` constant.
|
|
837
|
+
- **Type consistency:** `resolveCodegraph`, `dbPath`, `staleness`, `runIndex`, `CodegraphClient.{blastRadius,callers,lineage,close}`, `makeGraphActions` names are consistent across tasks and tests. Result shapes (`{dependents|callers|dependencies, staleness}` / `{engine:"unavailable"}`) match between client, actions, and their tests.
|
|
838
|
+
- **Scope:** single shippable subsystem (graph-core); injected edges and garden-side work deferred to named follow-on plans.
|