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,559 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
_domain_store.py — DomainStore: per-domain local JSON storage with integration-discovery routing.
|
|
4
|
+
|
|
5
|
+
The standard storage interface for all domain scripts.
|
|
6
|
+
Local JSON is the canonical store. External tools (Linear MCP, Jira MCP, Notion MCP, etc.)
|
|
7
|
+
are resolved via integration-discovery and used when configured and authenticated.
|
|
8
|
+
|
|
9
|
+
Storage paths:
|
|
10
|
+
Local: ~/.something-wicked/wicked-garden/local/{domain}/{source}/{id}.json
|
|
11
|
+
|
|
12
|
+
Usage:
|
|
13
|
+
from _domain_store import DomainStore
|
|
14
|
+
|
|
15
|
+
ds = DomainStore("wicked-garden:mem")
|
|
16
|
+
items = ds.list("memories", project="my-project")
|
|
17
|
+
item = ds.get("memories", "abc123")
|
|
18
|
+
new = ds.create("memories", {"title": "...", "content": "..."})
|
|
19
|
+
ds.update("memories", "abc123", {"title": "new title"})
|
|
20
|
+
ds.delete("memories", "abc123")
|
|
21
|
+
|
|
22
|
+
# For truly ephemeral files (caches, temp session state) only:
|
|
23
|
+
from _domain_store import get_local_path
|
|
24
|
+
cache_dir = get_local_path("wicked-smaht", "cache", "context7")
|
|
25
|
+
|
|
26
|
+
hook_mode=True:
|
|
27
|
+
When True, skips integration-discovery entirely and operates local-only.
|
|
28
|
+
Use this from hook scripts to stay within the 5s timing budget.
|
|
29
|
+
|
|
30
|
+
_skip_discovery=True:
|
|
31
|
+
When True, skips integration-discovery. Used internally by the integration
|
|
32
|
+
resolver when it writes preferences via MemoryStore to avoid circular init.
|
|
33
|
+
"""
|
|
34
|
+
from __future__ import annotations
|
|
35
|
+
|
|
36
|
+
import json
|
|
37
|
+
import os
|
|
38
|
+
import sys
|
|
39
|
+
import uuid
|
|
40
|
+
from datetime import datetime, timezone
|
|
41
|
+
from pathlib import Path
|
|
42
|
+
from typing import Any
|
|
43
|
+
|
|
44
|
+
# ---------------------------------------------------------------------------
|
|
45
|
+
# Paths (shared with _storage.py — same local JSON location)
|
|
46
|
+
# ---------------------------------------------------------------------------
|
|
47
|
+
|
|
48
|
+
try:
|
|
49
|
+
from _paths import get_project_root
|
|
50
|
+
_LOCAL_ROOT = get_project_root()
|
|
51
|
+
except ImportError:
|
|
52
|
+
_LOCAL_ROOT = Path.home() / ".something-wicked" / "wicked-garden" / "local"
|
|
53
|
+
|
|
54
|
+
# ---------------------------------------------------------------------------
|
|
55
|
+
# Domain MCP Pattern Registry
|
|
56
|
+
#
|
|
57
|
+
# Maps domain names to keyword patterns that identify compatible MCP servers.
|
|
58
|
+
# Used by integration-discovery to find external tools for each domain.
|
|
59
|
+
# Matching is case-insensitive substring search.
|
|
60
|
+
# Domains not listed here skip discovery and go directly to local JSON.
|
|
61
|
+
# ---------------------------------------------------------------------------
|
|
62
|
+
|
|
63
|
+
DOMAIN_MCP_PATTERNS: dict[str, list[str]] = {
|
|
64
|
+
"wicked-garden:mem": [
|
|
65
|
+
"notion", "confluence", "obsidian", "memory",
|
|
66
|
+
"knowledge", "wiki", "coda",
|
|
67
|
+
],
|
|
68
|
+
"wicked-jam": [
|
|
69
|
+
"miro", "figjam", "mural", "whiteboard",
|
|
70
|
+
"figma", "brainstorm",
|
|
71
|
+
],
|
|
72
|
+
"wicked-crew": ["jira", "linear", "github", "rally", "ado", "azure-devops", "project"],
|
|
73
|
+
"wicked-garden:search": ["elasticsearch", "algolia", "typesense", "search"],
|
|
74
|
+
# wicked-smaht, wicked-qe, wicked-patch: local-only (no MCP patterns)
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
# ---------------------------------------------------------------------------
|
|
79
|
+
# Public path helpers — delegate to _paths.py
|
|
80
|
+
# ---------------------------------------------------------------------------
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
def get_local_path(domain: str, *subpath: str) -> Path:
|
|
84
|
+
"""Delegate to _paths.get_local_path — see _paths.py for docs.
|
|
85
|
+
|
|
86
|
+
Returns a directory path under the wicked-garden local root,
|
|
87
|
+
creating it if it does not exist.
|
|
88
|
+
|
|
89
|
+
Example:
|
|
90
|
+
get_local_path("wicked-crew", "projects")
|
|
91
|
+
# → ~/.something-wicked/wicked-garden/local/wicked-crew/projects/
|
|
92
|
+
"""
|
|
93
|
+
try:
|
|
94
|
+
sys.path.insert(0, str(Path(__file__).parent))
|
|
95
|
+
from _paths import get_local_path as _glp
|
|
96
|
+
return _glp(domain, *subpath)
|
|
97
|
+
except ImportError:
|
|
98
|
+
# Inline fallback if _paths.py is not present
|
|
99
|
+
p = _LOCAL_ROOT / domain
|
|
100
|
+
for part in subpath:
|
|
101
|
+
p = p / part
|
|
102
|
+
p.mkdir(parents=True, exist_ok=True)
|
|
103
|
+
return p
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
def get_local_file(domain: str, *subpath: str) -> Path:
|
|
107
|
+
"""Delegate to _paths.get_local_file — see _paths.py for docs.
|
|
108
|
+
|
|
109
|
+
Returns a file path under the wicked-garden local root.
|
|
110
|
+
Parent directories are created automatically. Does not create the file.
|
|
111
|
+
|
|
112
|
+
Example:
|
|
113
|
+
get_local_file("wicked-garden:search", "unified_search.db")
|
|
114
|
+
# → ~/.something-wicked/wicked-garden/local/wicked-garden:search/unified_search.db
|
|
115
|
+
"""
|
|
116
|
+
try:
|
|
117
|
+
sys.path.insert(0, str(Path(__file__).parent))
|
|
118
|
+
from _paths import get_local_file as _glf
|
|
119
|
+
return _glf(domain, *subpath)
|
|
120
|
+
except ImportError:
|
|
121
|
+
# Inline fallback if _paths.py is not present
|
|
122
|
+
p = _LOCAL_ROOT / domain
|
|
123
|
+
for part in subpath:
|
|
124
|
+
p = p / part
|
|
125
|
+
p.parent.mkdir(parents=True, exist_ok=True)
|
|
126
|
+
return p
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
# ---------------------------------------------------------------------------
|
|
130
|
+
# DomainStore
|
|
131
|
+
# ---------------------------------------------------------------------------
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
class DomainStore:
|
|
135
|
+
"""Per-domain local JSON storage with integration-discovery routing.
|
|
136
|
+
|
|
137
|
+
Initialization (once per domain per script invocation):
|
|
138
|
+
1. Load cached tool selection from SessionState.integration_tools[domain]
|
|
139
|
+
2. If no cache: run _init_routing() to discover + resolve external tool
|
|
140
|
+
3. Store result back to SessionState for the session lifetime
|
|
141
|
+
|
|
142
|
+
CRUD API:
|
|
143
|
+
list(source, **params) -> list[dict]
|
|
144
|
+
get(source, id) -> dict | None
|
|
145
|
+
create(source, payload) -> dict
|
|
146
|
+
update(source, id, diff) -> dict | None
|
|
147
|
+
delete(source, id) -> bool
|
|
148
|
+
search(source, q, **params) -> list[dict] (delegates to list with q in params)
|
|
149
|
+
|
|
150
|
+
Routing:
|
|
151
|
+
- If an external tool is resolved: delegate to ExternalToolAdapter first,
|
|
152
|
+
fall back to local JSON on None return.
|
|
153
|
+
- hook_mode=True or _skip_discovery=True: local JSON only, no discovery.
|
|
154
|
+
- Domains not in DOMAIN_MCP_PATTERNS: local JSON only.
|
|
155
|
+
"""
|
|
156
|
+
|
|
157
|
+
def __init__(
|
|
158
|
+
self,
|
|
159
|
+
domain: str,
|
|
160
|
+
*,
|
|
161
|
+
hook_mode: bool = False,
|
|
162
|
+
_skip_discovery: bool = False,
|
|
163
|
+
) -> None:
|
|
164
|
+
"""
|
|
165
|
+
Args:
|
|
166
|
+
domain: Plugin domain, e.g. "wicked-garden:mem", "wicked-crew".
|
|
167
|
+
hook_mode: Pass True from hook scripts. Skips integration-discovery
|
|
168
|
+
to stay within the 5s hook timing budget.
|
|
169
|
+
_skip_discovery: Internal flag. Pass True from integration resolver when
|
|
170
|
+
creating a MemoryStore to prevent circular initialization.
|
|
171
|
+
"""
|
|
172
|
+
self._domain = domain
|
|
173
|
+
self._hook_mode = hook_mode
|
|
174
|
+
self._skip_discovery = _skip_discovery
|
|
175
|
+
self._external: Any | None = None # ExternalToolAdapter, wired in Task 1.4
|
|
176
|
+
self._init_routing()
|
|
177
|
+
|
|
178
|
+
# ------------------------------------------------------------------
|
|
179
|
+
# Routing initialization
|
|
180
|
+
# ------------------------------------------------------------------
|
|
181
|
+
|
|
182
|
+
def _init_routing(self) -> None:
|
|
183
|
+
"""Load or discover the external tool for this domain.
|
|
184
|
+
|
|
185
|
+
1. Skip entirely when hook_mode or _skip_discovery is True.
|
|
186
|
+
2. Check SessionState.integration_tools[domain] cache first (<5ms).
|
|
187
|
+
3. If cache miss: call resolve_tool() — runs discovery.
|
|
188
|
+
4. Cache the result in SessionState for the session lifetime.
|
|
189
|
+
5. If resolved tool != "local" and != None: instantiate adapter via
|
|
190
|
+
from_tool_name() and assign to self._external.
|
|
191
|
+
|
|
192
|
+
Imports are lazy (inside this method) to avoid circular imports at
|
|
193
|
+
module load time. Any import failure causes silent local-only fallback.
|
|
194
|
+
"""
|
|
195
|
+
# hooks and circular-init callers always go local
|
|
196
|
+
if self._hook_mode or self._skip_discovery:
|
|
197
|
+
return
|
|
198
|
+
|
|
199
|
+
# Domains not in the pattern registry skip discovery entirely
|
|
200
|
+
if self._domain not in DOMAIN_MCP_PATTERNS:
|
|
201
|
+
return
|
|
202
|
+
|
|
203
|
+
tool_name: str | None = None
|
|
204
|
+
|
|
205
|
+
# ── Step 1: check session cache ──────────────────────────────────────
|
|
206
|
+
try:
|
|
207
|
+
sys.path.insert(0, str(Path(__file__).parent))
|
|
208
|
+
from _session import SessionState
|
|
209
|
+
|
|
210
|
+
state = SessionState.load()
|
|
211
|
+
cached = (state.integration_tools or {}).get(self._domain)
|
|
212
|
+
if cached is not None:
|
|
213
|
+
# Cache hit — use the stored value directly
|
|
214
|
+
tool_name = cached if cached != "local" else None
|
|
215
|
+
else:
|
|
216
|
+
# ── Step 2: cache miss — run discovery ───────────────────────
|
|
217
|
+
tool_name = self._discover_tool()
|
|
218
|
+
|
|
219
|
+
# ── Step 3: cache in SessionState ────────────────────────────
|
|
220
|
+
tools = dict(state.integration_tools or {})
|
|
221
|
+
tools[self._domain] = tool_name if tool_name else "local"
|
|
222
|
+
state.update(integration_tools=tools)
|
|
223
|
+
except Exception:
|
|
224
|
+
# SessionState unavailable (e.g. no TMPDIR, corrupted file) —
|
|
225
|
+
# run discovery without caching; fail open on any error.
|
|
226
|
+
try:
|
|
227
|
+
tool_name = self._discover_tool()
|
|
228
|
+
except Exception:
|
|
229
|
+
tool_name = None
|
|
230
|
+
|
|
231
|
+
# ── Step 4: instantiate adapter ──────────────────────────────────────
|
|
232
|
+
if tool_name and tool_name != "local":
|
|
233
|
+
try:
|
|
234
|
+
from _adapters import from_tool_name
|
|
235
|
+
|
|
236
|
+
self._external = from_tool_name(tool_name)
|
|
237
|
+
except Exception:
|
|
238
|
+
self._external = None # import failure → local only
|
|
239
|
+
|
|
240
|
+
def _discover_tool(self) -> str | None:
|
|
241
|
+
"""Run integration-resolver discovery for this domain.
|
|
242
|
+
|
|
243
|
+
Returns the tool name string or None for local-only. Imported lazily
|
|
244
|
+
to avoid circular imports (_integration_resolver imports _domain_store).
|
|
245
|
+
"""
|
|
246
|
+
try:
|
|
247
|
+
from _integration_resolver import resolve_tool
|
|
248
|
+
|
|
249
|
+
return resolve_tool(self._domain, hook_mode=False)
|
|
250
|
+
except Exception:
|
|
251
|
+
return None
|
|
252
|
+
|
|
253
|
+
# ------------------------------------------------------------------
|
|
254
|
+
# Read operations
|
|
255
|
+
# ------------------------------------------------------------------
|
|
256
|
+
|
|
257
|
+
def list(self, source: str, **params) -> list[dict]:
|
|
258
|
+
"""List records for a source, with optional filter params.
|
|
259
|
+
|
|
260
|
+
Returns:
|
|
261
|
+
List of record dicts. Empty list on any error.
|
|
262
|
+
|
|
263
|
+
Delegates to external tool first (when resolved); falls back to local JSON.
|
|
264
|
+
"""
|
|
265
|
+
if self._external is not None:
|
|
266
|
+
try:
|
|
267
|
+
result = self._external.list(source, **params)
|
|
268
|
+
if result is not None:
|
|
269
|
+
return result
|
|
270
|
+
except Exception:
|
|
271
|
+
pass # fall through to local
|
|
272
|
+
|
|
273
|
+
return self._local_list(source, params)
|
|
274
|
+
|
|
275
|
+
def search(self, source: str, q: str, **params) -> list[dict]:
|
|
276
|
+
"""Search records — delegates to list() with q in params.
|
|
277
|
+
|
|
278
|
+
Falls back to local token-based search (title, content, summary, description).
|
|
279
|
+
|
|
280
|
+
Args:
|
|
281
|
+
source: Source name (e.g. "memories")
|
|
282
|
+
q: Search query string
|
|
283
|
+
**params: Additional filter params (type, project, etc.)
|
|
284
|
+
"""
|
|
285
|
+
return self.list(source, q=q, **params)
|
|
286
|
+
|
|
287
|
+
def get(self, source: str, id: str) -> dict | None:
|
|
288
|
+
"""Fetch a single record by ID.
|
|
289
|
+
|
|
290
|
+
Returns:
|
|
291
|
+
Record dict, or None if not found.
|
|
292
|
+
"""
|
|
293
|
+
if self._external is not None:
|
|
294
|
+
try:
|
|
295
|
+
result = self._external.get(source, id)
|
|
296
|
+
if result is not None:
|
|
297
|
+
return result
|
|
298
|
+
except Exception:
|
|
299
|
+
pass # fall through to local
|
|
300
|
+
|
|
301
|
+
return self._local_get(source, id)
|
|
302
|
+
|
|
303
|
+
# ------------------------------------------------------------------
|
|
304
|
+
# Event emission (fire-and-forget)
|
|
305
|
+
# ------------------------------------------------------------------
|
|
306
|
+
|
|
307
|
+
def _emit_event(self, action: str, source: str, record_id: str | None = None,
|
|
308
|
+
payload: dict | None = None, tags: list[str] | None = None) -> None:
|
|
309
|
+
"""Emit an event to the unified event log. Never raises.
|
|
310
|
+
|
|
311
|
+
Emits only safe metadata (id, timestamps, action) — not the full record
|
|
312
|
+
payload, to avoid replicating sensitive data into the FTS-indexed event log.
|
|
313
|
+
Callers needing full payload in events should call EventStore.append() directly.
|
|
314
|
+
"""
|
|
315
|
+
try:
|
|
316
|
+
from _event_store import EventStore
|
|
317
|
+
EventStore.ensure_schema()
|
|
318
|
+
|
|
319
|
+
# Auto-resolve project_id from session state
|
|
320
|
+
project_id = None
|
|
321
|
+
try:
|
|
322
|
+
from _session import SessionState
|
|
323
|
+
state = SessionState.load()
|
|
324
|
+
project_id = getattr(state, "active_project", None)
|
|
325
|
+
except Exception:
|
|
326
|
+
pass # fail open
|
|
327
|
+
|
|
328
|
+
# Emit safe metadata only — strip sensitive fields from payload
|
|
329
|
+
safe_payload = None
|
|
330
|
+
if payload is not None:
|
|
331
|
+
safe_payload = {
|
|
332
|
+
k: v for k, v in payload.items()
|
|
333
|
+
if k in ("id", "name", "title", "type", "status", "phase",
|
|
334
|
+
"created_at", "updated_at", "deleted_at", "tags",
|
|
335
|
+
"complexity_score", "signals_detected")
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
EventStore.append(
|
|
339
|
+
domain=self._domain,
|
|
340
|
+
action=f"{source}.{action}",
|
|
341
|
+
source=source,
|
|
342
|
+
record_id=record_id,
|
|
343
|
+
payload=safe_payload if safe_payload else None,
|
|
344
|
+
project_id=project_id,
|
|
345
|
+
tags=tags,
|
|
346
|
+
)
|
|
347
|
+
except Exception:
|
|
348
|
+
pass # fire-and-forget — never break domain operations
|
|
349
|
+
|
|
350
|
+
# ------------------------------------------------------------------
|
|
351
|
+
# Write operations
|
|
352
|
+
# ------------------------------------------------------------------
|
|
353
|
+
|
|
354
|
+
def create(self, source: str, payload: dict) -> dict | None:
|
|
355
|
+
"""Create a new record.
|
|
356
|
+
|
|
357
|
+
Returns:
|
|
358
|
+
Created record dict, or None on failure.
|
|
359
|
+
|
|
360
|
+
When an external tool is resolved, delegates to it first. On success,
|
|
361
|
+
also writes to local JSON (external tool is the ID authority when used).
|
|
362
|
+
Falls back to local JSON with auto-generated UUID on any failure.
|
|
363
|
+
"""
|
|
364
|
+
record = dict(payload)
|
|
365
|
+
record.setdefault("created_at", _now())
|
|
366
|
+
record.setdefault("updated_at", _now())
|
|
367
|
+
|
|
368
|
+
if self._external is not None:
|
|
369
|
+
try:
|
|
370
|
+
result = self._external.create(source, record)
|
|
371
|
+
if result is not None:
|
|
372
|
+
# Use external-tool-assigned ID as canonical ID
|
|
373
|
+
if result.get("id"):
|
|
374
|
+
record["id"] = result["id"]
|
|
375
|
+
elif "id" not in record:
|
|
376
|
+
record["id"] = str(uuid.uuid4())
|
|
377
|
+
self._local_write(source, record["id"], record)
|
|
378
|
+
self._emit_event("created", source, record["id"], record)
|
|
379
|
+
return record
|
|
380
|
+
except Exception:
|
|
381
|
+
pass # fall through to local
|
|
382
|
+
|
|
383
|
+
# Local path: generate UUID and write
|
|
384
|
+
if "id" not in record:
|
|
385
|
+
record["id"] = str(uuid.uuid4())
|
|
386
|
+
self._local_write(source, record["id"], record)
|
|
387
|
+
self._emit_event("created", source, record["id"], record)
|
|
388
|
+
return record
|
|
389
|
+
|
|
390
|
+
def update(self, source: str, id: str, diff: dict) -> dict | None:
|
|
391
|
+
"""Patch an existing record with the fields in diff.
|
|
392
|
+
|
|
393
|
+
Returns:
|
|
394
|
+
Updated record dict, or None if not found.
|
|
395
|
+
"""
|
|
396
|
+
if self._external is not None:
|
|
397
|
+
try:
|
|
398
|
+
result = self._external.update(source, id, diff)
|
|
399
|
+
if result is not None:
|
|
400
|
+
# Also update local copy
|
|
401
|
+
existing = self._local_get(source, id)
|
|
402
|
+
if existing:
|
|
403
|
+
existing.update(diff)
|
|
404
|
+
existing["updated_at"] = _now()
|
|
405
|
+
self._local_write(source, id, existing)
|
|
406
|
+
return result
|
|
407
|
+
except Exception:
|
|
408
|
+
pass # fall through to local
|
|
409
|
+
|
|
410
|
+
# Local path: read-modify-write
|
|
411
|
+
existing = self._local_get(source, id)
|
|
412
|
+
if existing is None:
|
|
413
|
+
return None
|
|
414
|
+
|
|
415
|
+
existing.update(diff)
|
|
416
|
+
existing["updated_at"] = _now()
|
|
417
|
+
self._local_write(source, id, existing)
|
|
418
|
+
self._emit_event("updated", source, id, diff)
|
|
419
|
+
return existing
|
|
420
|
+
|
|
421
|
+
def delete(self, source: str, id: str) -> bool:
|
|
422
|
+
"""Delete a record (soft-delete: sets deleted=True locally).
|
|
423
|
+
|
|
424
|
+
Returns:
|
|
425
|
+
True if the record was found and removed/marked deleted.
|
|
426
|
+
"""
|
|
427
|
+
if self._external is not None:
|
|
428
|
+
try:
|
|
429
|
+
result = self._external.delete(source, id)
|
|
430
|
+
if result is not None:
|
|
431
|
+
# Also soft-delete locally
|
|
432
|
+
existing = self._local_get(source, id)
|
|
433
|
+
if existing:
|
|
434
|
+
existing["deleted"] = True
|
|
435
|
+
existing["deleted_at"] = _now()
|
|
436
|
+
self._local_write(source, id, existing)
|
|
437
|
+
return bool(result)
|
|
438
|
+
except Exception:
|
|
439
|
+
pass # fall through to local
|
|
440
|
+
|
|
441
|
+
# Local path: soft-delete
|
|
442
|
+
existing = self._local_get(source, id)
|
|
443
|
+
if existing is None:
|
|
444
|
+
return False
|
|
445
|
+
|
|
446
|
+
existing["deleted"] = True
|
|
447
|
+
existing["deleted_at"] = _now()
|
|
448
|
+
self._local_write(source, id, existing)
|
|
449
|
+
self._emit_event("deleted", source, id)
|
|
450
|
+
return True
|
|
451
|
+
|
|
452
|
+
# ------------------------------------------------------------------
|
|
453
|
+
# Private: local file operations
|
|
454
|
+
# (local file operations)
|
|
455
|
+
# ------------------------------------------------------------------
|
|
456
|
+
|
|
457
|
+
def _local_dir(self, source: str) -> Path:
|
|
458
|
+
return _LOCAL_ROOT / self._domain / source
|
|
459
|
+
|
|
460
|
+
def _local_file(self, source: str, id: str) -> Path:
|
|
461
|
+
return self._local_dir(source) / f"{id}.json"
|
|
462
|
+
|
|
463
|
+
def _local_list(self, source: str, params: dict) -> list[dict]:
|
|
464
|
+
"""Scan local JSON files and return non-deleted records matching params."""
|
|
465
|
+
source_dir = self._local_dir(source)
|
|
466
|
+
if not source_dir.exists():
|
|
467
|
+
return []
|
|
468
|
+
|
|
469
|
+
records: list[dict] = []
|
|
470
|
+
for json_file in sorted(source_dir.glob("*.json")):
|
|
471
|
+
try:
|
|
472
|
+
record = json.loads(json_file.read_text(encoding="utf-8"))
|
|
473
|
+
except (json.JSONDecodeError, OSError):
|
|
474
|
+
continue
|
|
475
|
+
|
|
476
|
+
# Skip soft-deleted records
|
|
477
|
+
if record.get("deleted"):
|
|
478
|
+
continue
|
|
479
|
+
|
|
480
|
+
# Apply simple equality filters from params
|
|
481
|
+
if not _matches_params(record, params):
|
|
482
|
+
continue
|
|
483
|
+
|
|
484
|
+
records.append(record)
|
|
485
|
+
|
|
486
|
+
return records
|
|
487
|
+
|
|
488
|
+
def _local_get(self, source: str, id: str) -> dict | None:
|
|
489
|
+
"""Read a single local JSON file by ID."""
|
|
490
|
+
path = self._local_file(source, id)
|
|
491
|
+
|
|
492
|
+
if path.exists():
|
|
493
|
+
try:
|
|
494
|
+
record = json.loads(path.read_text(encoding="utf-8"))
|
|
495
|
+
if record.get("deleted"):
|
|
496
|
+
return None
|
|
497
|
+
return record
|
|
498
|
+
except (json.JSONDecodeError, OSError):
|
|
499
|
+
return None
|
|
500
|
+
|
|
501
|
+
return None
|
|
502
|
+
|
|
503
|
+
def _local_write(self, source: str, id: str, record: dict) -> None:
|
|
504
|
+
"""Atomically write a record to its local JSON file."""
|
|
505
|
+
path = self._local_file(source, id)
|
|
506
|
+
path.parent.mkdir(parents=True, exist_ok=True)
|
|
507
|
+
tmp = path.with_suffix(".tmp")
|
|
508
|
+
try:
|
|
509
|
+
tmp.write_text(json.dumps(record, indent=2), encoding="utf-8")
|
|
510
|
+
os.replace(tmp, path)
|
|
511
|
+
except OSError as exc:
|
|
512
|
+
print(
|
|
513
|
+
f"[wicked-garden] Local write failed for {source}/{id}: {exc}",
|
|
514
|
+
file=sys.stderr,
|
|
515
|
+
)
|
|
516
|
+
|
|
517
|
+
|
|
518
|
+
# ---------------------------------------------------------------------------
|
|
519
|
+
# Helpers
|
|
520
|
+
# ---------------------------------------------------------------------------
|
|
521
|
+
|
|
522
|
+
|
|
523
|
+
def _matches_params(record: dict, params: dict) -> bool:
|
|
524
|
+
"""Filter for local list queries.
|
|
525
|
+
|
|
526
|
+
Supports exact equality for most fields plus substring search for the
|
|
527
|
+
special ``q`` parameter (searches across title, content, summary,
|
|
528
|
+
description).
|
|
529
|
+
|
|
530
|
+
Copied from _storage.py to avoid import dependency.
|
|
531
|
+
"""
|
|
532
|
+
for key, value in params.items():
|
|
533
|
+
if key == "q":
|
|
534
|
+
# Token-based search across text fields (all tokens must match)
|
|
535
|
+
text_fields = [
|
|
536
|
+
str(record.get(f, ""))
|
|
537
|
+
for f in ("title", "content", "summary", "description")
|
|
538
|
+
]
|
|
539
|
+
# Include tags (may be a list)
|
|
540
|
+
tags_val = record.get("tags", [])
|
|
541
|
+
if isinstance(tags_val, list):
|
|
542
|
+
text_fields.append(" ".join(str(t) for t in tags_val))
|
|
543
|
+
elif tags_val:
|
|
544
|
+
text_fields.append(str(tags_val))
|
|
545
|
+
# Include search_tags if present
|
|
546
|
+
search_tags_val = record.get("search_tags", "")
|
|
547
|
+
if search_tags_val:
|
|
548
|
+
text_fields.append(str(search_tags_val))
|
|
549
|
+
searchable = " ".join(text_fields).lower()
|
|
550
|
+
tokens = str(value).lower().split()
|
|
551
|
+
if not all(tok in searchable for tok in tokens):
|
|
552
|
+
return False
|
|
553
|
+
elif record.get(key) != value:
|
|
554
|
+
return False
|
|
555
|
+
return True
|
|
556
|
+
|
|
557
|
+
|
|
558
|
+
def _now() -> str:
|
|
559
|
+
return datetime.now(timezone.utc).isoformat()
|