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,464 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
SubagentStart / SubagentStop hook — wicked-garden agent lifecycle tracking.
|
|
4
|
+
|
|
5
|
+
Issue #330: Track subagent start/stop events for observability and crew coordination.
|
|
6
|
+
Issue #365: Record specialist engagement for approve-command gate enforcement.
|
|
7
|
+
|
|
8
|
+
Receives the lifecycle phase as the first CLI argument ("start" or "stop").
|
|
9
|
+
Reads the hook payload from stdin (JSON with agent metadata).
|
|
10
|
+
|
|
11
|
+
Responsibilities:
|
|
12
|
+
SubagentStart:
|
|
13
|
+
- Log agent launch to ops logger
|
|
14
|
+
- Track active subagent count in session state
|
|
15
|
+
- Record agent start time for duration tracking
|
|
16
|
+
SubagentStop:
|
|
17
|
+
- Log agent completion to ops logger
|
|
18
|
+
- Decrement active subagent count
|
|
19
|
+
- Calculate and record duration
|
|
20
|
+
- Write trace entry for the subagent execution
|
|
21
|
+
- Record specialist engagement to phases/{phase}/specialist-engagement.json
|
|
22
|
+
|
|
23
|
+
Always fails open — any unhandled exception returns {"continue": true}.
|
|
24
|
+
"""
|
|
25
|
+
|
|
26
|
+
import json
|
|
27
|
+
import os
|
|
28
|
+
import sys
|
|
29
|
+
import time
|
|
30
|
+
from datetime import datetime, timezone
|
|
31
|
+
from pathlib import Path
|
|
32
|
+
|
|
33
|
+
# Add shared scripts directory to path
|
|
34
|
+
_PLUGIN_ROOT = Path(os.environ.get("CLAUDE_PLUGIN_ROOT", Path(__file__).resolve().parents[2]))
|
|
35
|
+
sys.path.insert(0, str(_PLUGIN_ROOT / "scripts"))
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
# Map from task metadata.event_type to procedure bundle injected at SubagentStart
|
|
39
|
+
_EVENT_TYPE_PROCEDURES: dict = {
|
|
40
|
+
"coding-task": (
|
|
41
|
+
"[Bulletproof Coding Standards] R1: No dead code. R2: No bare panics — "
|
|
42
|
+
"all errors handled and logged. R3: No magic values — use named constants. "
|
|
43
|
+
"R4: No swallowed errors — propagate or log with context. "
|
|
44
|
+
"R5: No unbounded ops — all loops/queries have limits. "
|
|
45
|
+
"R6: No god functions — max 50 lines, single responsibility."
|
|
46
|
+
),
|
|
47
|
+
"gate-finding": (
|
|
48
|
+
"[Gate Finding Protocol] Document the finding with: what was observed, "
|
|
49
|
+
"what standard was violated, severity (BLOCK/WARN/INFO), and suggested fix. "
|
|
50
|
+
"Reference the specific requirement or quality rule that applies."
|
|
51
|
+
),
|
|
52
|
+
"phase-transition": (
|
|
53
|
+
"[Phase Transition Protocol] Verify all gate conditions are met before "
|
|
54
|
+
"advancing. Write a transition summary: what was completed, what evidence "
|
|
55
|
+
"exists, what the next phase expects as input."
|
|
56
|
+
),
|
|
57
|
+
"subtask": (
|
|
58
|
+
"[Subtask Execution] You are executing a subtask. Scope is narrow — "
|
|
59
|
+
"complete exactly what was assigned. Report back with structured output: "
|
|
60
|
+
"what was done, what evidence exists, any blockers found."
|
|
61
|
+
),
|
|
62
|
+
"procedure-trigger": (
|
|
63
|
+
"[Procedure Execution] Follow the procedure exactly as specified. "
|
|
64
|
+
"Do not improvise or skip steps. Record each step's outcome."
|
|
65
|
+
),
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
# ---------------------------------------------------------------------------
|
|
70
|
+
# Active task event_type reader — routed via _task_reader (#596 v8-PR-2)
|
|
71
|
+
# ---------------------------------------------------------------------------
|
|
72
|
+
#
|
|
73
|
+
# WG_DAEMON_ENABLED=false (default): direct file read, bit-identical to pre-PR-2.
|
|
74
|
+
# WG_DAEMON_ENABLED=true: daemon HTTP with 45ms timeout + file fallback.
|
|
75
|
+
# WG_DAEMON_ENABLED=always: daemon HTTP only.
|
|
76
|
+
#
|
|
77
|
+
# _task_reader is stdlib-only and imported lazily so this hook remains
|
|
78
|
+
# fail-open even if the scripts/ directory is not on sys.path yet.
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
def _get_active_task_event_type(session_id: str) -> "str | None":
|
|
82
|
+
"""Return event_type of the most-recently-modified in-progress native task.
|
|
83
|
+
|
|
84
|
+
Fail-silent — never blocks the hook. Routing is delegated to
|
|
85
|
+
scripts/crew/_task_reader.py per #596.
|
|
86
|
+
"""
|
|
87
|
+
if not session_id:
|
|
88
|
+
return None
|
|
89
|
+
try:
|
|
90
|
+
from crew._task_reader import get_active_task_event_type # type: ignore[import]
|
|
91
|
+
return get_active_task_event_type(session_id)
|
|
92
|
+
except Exception:
|
|
93
|
+
return None
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
# ---------------------------------------------------------------------------
|
|
97
|
+
# Ops logger wrapper — fail-silent, never crashes the hook
|
|
98
|
+
# ---------------------------------------------------------------------------
|
|
99
|
+
|
|
100
|
+
def _log(domain, level, event, ok=True, ms=None, detail=None):
|
|
101
|
+
"""Ops logger — fail-silent, never crashes the hook."""
|
|
102
|
+
try:
|
|
103
|
+
from _logger import log
|
|
104
|
+
log(domain, level, event, ok=ok, ms=ms, detail=detail)
|
|
105
|
+
except Exception:
|
|
106
|
+
pass
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
def _now_iso() -> str:
|
|
110
|
+
return datetime.now(timezone.utc).isoformat().replace("+00:00", "Z")
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
def _sanitize_session_id(raw: str) -> str:
|
|
114
|
+
"""Strip path separators and traversal sequences from session ID."""
|
|
115
|
+
sanitized = raw.replace("/", "_").replace("\\", "_").replace("..", "_")
|
|
116
|
+
return sanitized if sanitized else "default"
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
def _get_session_id() -> str:
|
|
120
|
+
return _sanitize_session_id(os.environ.get("CLAUDE_SESSION_ID", "default"))
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
# ---------------------------------------------------------------------------
|
|
124
|
+
# Trace writer — append JSONL to session trace file
|
|
125
|
+
# ---------------------------------------------------------------------------
|
|
126
|
+
|
|
127
|
+
def _write_trace(entry: dict) -> None:
|
|
128
|
+
"""Append a trace entry to the session JSONL trace file."""
|
|
129
|
+
try:
|
|
130
|
+
import tempfile
|
|
131
|
+
session_id = _get_session_id()
|
|
132
|
+
trace_dir = Path(tempfile.gettempdir()) / "wicked-garden" / "traces"
|
|
133
|
+
trace_dir.mkdir(parents=True, exist_ok=True)
|
|
134
|
+
trace_file = trace_dir / f"{session_id}.jsonl"
|
|
135
|
+
with open(trace_file, "a") as f:
|
|
136
|
+
f.write(json.dumps(entry) + "\n")
|
|
137
|
+
except Exception:
|
|
138
|
+
pass
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
# ---------------------------------------------------------------------------
|
|
142
|
+
# Specialist engagement tracking (Issue #365)
|
|
143
|
+
# ---------------------------------------------------------------------------
|
|
144
|
+
|
|
145
|
+
def _load_specialist_domains() -> set:
|
|
146
|
+
"""Return the set of specialist domain names from specialist.json.
|
|
147
|
+
|
|
148
|
+
Reads .claude-plugin/specialist.json relative to CLAUDE_PLUGIN_ROOT.
|
|
149
|
+
Returns an empty set on any error so the hook stays fail-open.
|
|
150
|
+
"""
|
|
151
|
+
try:
|
|
152
|
+
specialist_path = _PLUGIN_ROOT / ".claude-plugin" / "specialist.json"
|
|
153
|
+
data = json.loads(specialist_path.read_text(encoding="utf-8"))
|
|
154
|
+
return {s["name"] for s in data.get("specialists", []) if "name" in s}
|
|
155
|
+
except Exception:
|
|
156
|
+
return set()
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
def _parse_specialist_from_agent_type(agent_type: str, specialist_domains: set):
|
|
160
|
+
"""Parse domain and agent name from a subagent identifier (Issue #573).
|
|
161
|
+
|
|
162
|
+
Two accepted forms:
|
|
163
|
+
|
|
164
|
+
* Fully-qualified: ``wicked-garden:{domain}:{agent-name}`` — parsed in
|
|
165
|
+
place, no resolver needed. The domain must be a known specialist
|
|
166
|
+
domain (``specialist_domains`` from ``specialist.json``) for the
|
|
167
|
+
engagement tracker to accept it.
|
|
168
|
+
* Bare role: ``requirements-analyst`` — expanded to the full form by
|
|
169
|
+
:mod:`crew.specialist_resolver`, which walks ``agents/**/*.md``
|
|
170
|
+
frontmatter. This is the path the facilitator emits by default.
|
|
171
|
+
|
|
172
|
+
Returns ``(domain, agent_name)`` on success, ``(None, None)`` when
|
|
173
|
+
the name cannot be resolved. The hook remains fail-open on any
|
|
174
|
+
resolver import / walk error (engagement tracking is best-effort).
|
|
175
|
+
"""
|
|
176
|
+
if not agent_type:
|
|
177
|
+
return None, None
|
|
178
|
+
|
|
179
|
+
if agent_type.startswith("wicked-garden:"):
|
|
180
|
+
parts = agent_type.split(":")
|
|
181
|
+
# Expect at least 3 parts: "wicked-garden", domain, agent-name
|
|
182
|
+
if len(parts) < 3:
|
|
183
|
+
return None, None
|
|
184
|
+
|
|
185
|
+
domain = parts[1]
|
|
186
|
+
agent_name = ":".join(parts[2:]) # preserve any colons in agent name
|
|
187
|
+
|
|
188
|
+
if domain not in specialist_domains:
|
|
189
|
+
return None, None
|
|
190
|
+
|
|
191
|
+
return domain, agent_name
|
|
192
|
+
|
|
193
|
+
# Bare-role path (Issue #573): resolve via agents/**/*.md frontmatter.
|
|
194
|
+
# Fail-closed to the old behavior on any resolver error — engagement
|
|
195
|
+
# tracking is best-effort and the hook must never block the agent.
|
|
196
|
+
try:
|
|
197
|
+
from crew.specialist_resolver import build_resolver, resolve_role
|
|
198
|
+
|
|
199
|
+
resolver = build_resolver(_PLUGIN_ROOT)
|
|
200
|
+
domain, subagent_type = resolve_role(agent_type, resolver)
|
|
201
|
+
if domain is None or subagent_type is None:
|
|
202
|
+
return None, None
|
|
203
|
+
if domain not in specialist_domains:
|
|
204
|
+
return None, None
|
|
205
|
+
# The tracker stores bare role as the agent_name — callers feed
|
|
206
|
+
# it straight into the engagement ledger, matching the existing
|
|
207
|
+
# wicked-garden:{domain}:{role} parsing shape.
|
|
208
|
+
return domain, agent_type
|
|
209
|
+
except Exception:
|
|
210
|
+
return None, None
|
|
211
|
+
|
|
212
|
+
|
|
213
|
+
def _record_specialist_engagement(domain: str, agent_name: str) -> None:
|
|
214
|
+
"""Append a specialist engagement entry to the active phase directory.
|
|
215
|
+
|
|
216
|
+
Writes to:
|
|
217
|
+
{project_dir}/phases/{current_phase}/specialist-engagement.jsonl
|
|
218
|
+
|
|
219
|
+
Site W9 of bus-cutover wave-2 (#746):
|
|
220
|
+
* W9a refactor (this PR): switched from JSON array (read-modify-write)
|
|
221
|
+
to JSONL (append-only). The append-only form aligns with the
|
|
222
|
+
bus-as-truth premise — events are append-only, so the on-disk
|
|
223
|
+
projection should be too. Read-modify-write the JSON array
|
|
224
|
+
contradicted that premise and was a pre-bus design choice.
|
|
225
|
+
* W9b cutover (this PR): fires ``wicked.subagent.engaged`` BEFORE
|
|
226
|
+
the JSONL append so the projector handler can replay the same
|
|
227
|
+
line. Gated on WG_BUS_AS_TRUTH_SUBAGENT_ENGAGEMENT.
|
|
228
|
+
|
|
229
|
+
Backward compatibility: legacy ``specialist-engagement.json`` files
|
|
230
|
+
in production projects are handled by the reader (see
|
|
231
|
+
``hooks/scripts/pre_tool.py``) — JSONL preferred, .json fallback on
|
|
232
|
+
miss. No migration tool needed; the next engagement append starts
|
|
233
|
+
the JSONL file fresh.
|
|
234
|
+
|
|
235
|
+
All errors are silently swallowed so the hook never blocks on I/O failures.
|
|
236
|
+
"""
|
|
237
|
+
try:
|
|
238
|
+
from _session import SessionState
|
|
239
|
+
from _paths import get_local_path
|
|
240
|
+
|
|
241
|
+
state = SessionState.load()
|
|
242
|
+
|
|
243
|
+
# Resolve current phase — prefer the cached active_project dict, fall
|
|
244
|
+
# back to loading the project state file directly.
|
|
245
|
+
current_phase: str | None = None
|
|
246
|
+
project_id: str | None = state.active_project_id
|
|
247
|
+
|
|
248
|
+
if state.active_project and isinstance(state.active_project, dict):
|
|
249
|
+
current_phase = state.active_project.get("current_phase")
|
|
250
|
+
|
|
251
|
+
if not current_phase and project_id:
|
|
252
|
+
try:
|
|
253
|
+
import re
|
|
254
|
+
if re.match(r'^[a-zA-Z0-9_-]{1,64}$', project_id):
|
|
255
|
+
base = get_local_path("wicked-crew", "projects")
|
|
256
|
+
project_json = base / project_id / "project.json"
|
|
257
|
+
if project_json.exists():
|
|
258
|
+
pdata = json.loads(project_json.read_text(encoding="utf-8"))
|
|
259
|
+
current_phase = pdata.get("current_phase")
|
|
260
|
+
except Exception:
|
|
261
|
+
pass
|
|
262
|
+
|
|
263
|
+
if not current_phase or not project_id:
|
|
264
|
+
# No active crew project — nothing to record
|
|
265
|
+
return
|
|
266
|
+
|
|
267
|
+
# Validate project_id before using it in a path
|
|
268
|
+
import re
|
|
269
|
+
if not re.match(r'^[a-zA-Z0-9_-]{1,64}$', project_id):
|
|
270
|
+
return
|
|
271
|
+
|
|
272
|
+
base = get_local_path("wicked-crew", "projects")
|
|
273
|
+
phase_dir = base / project_id / "phases" / current_phase
|
|
274
|
+
phase_dir.mkdir(parents=True, exist_ok=True)
|
|
275
|
+
engagement_file = phase_dir / "specialist-engagement.jsonl"
|
|
276
|
+
|
|
277
|
+
entry = {
|
|
278
|
+
"domain": domain,
|
|
279
|
+
"agent": agent_name,
|
|
280
|
+
"completed_at": _now_iso(),
|
|
281
|
+
}
|
|
282
|
+
line = json.dumps(entry, sort_keys=False) + "\n"
|
|
283
|
+
|
|
284
|
+
# W9b emit BEFORE the disk append so the projector can replay the
|
|
285
|
+
# same line. chain_id includes the agent_name + completed_at so
|
|
286
|
+
# multiple engagements in the same phase are uniquely identifiable
|
|
287
|
+
# downstream (per memory/bus-chain-id-must-include-uniqueness-segment-gotcha).
|
|
288
|
+
# Fail-open: bus unavailable must NOT block the append.
|
|
289
|
+
try:
|
|
290
|
+
import sys as _sys
|
|
291
|
+
from pathlib import Path as _Path
|
|
292
|
+
_scripts_root = str(_Path(__file__).resolve().parents[2] / "scripts")
|
|
293
|
+
if _scripts_root not in _sys.path:
|
|
294
|
+
_sys.path.insert(0, _scripts_root)
|
|
295
|
+
from _bus import emit_event # type: ignore[import]
|
|
296
|
+
ts_compact = "".join(ch for ch in entry["completed_at"] if ch.isdigit())[:14] or "noid"
|
|
297
|
+
emit_event(
|
|
298
|
+
"wicked.subagent.engaged",
|
|
299
|
+
{
|
|
300
|
+
"project_id": project_id,
|
|
301
|
+
"phase": current_phase,
|
|
302
|
+
"domain": domain,
|
|
303
|
+
"agent": agent_name,
|
|
304
|
+
"raw_payload": line,
|
|
305
|
+
},
|
|
306
|
+
chain_id=f"{project_id}.{current_phase}.{agent_name}-{ts_compact}",
|
|
307
|
+
)
|
|
308
|
+
except Exception: # noqa: BLE001 — fail-open per Decision #8
|
|
309
|
+
pass # bus unavailable — projector handler replays on reconnect
|
|
310
|
+
|
|
311
|
+
except Exception as exc:
|
|
312
|
+
print(f"[wicked-garden] specialist engagement record error: {exc}", file=sys.stderr)
|
|
313
|
+
|
|
314
|
+
|
|
315
|
+
# ---------------------------------------------------------------------------
|
|
316
|
+
# Handler: SubagentStart
|
|
317
|
+
# ---------------------------------------------------------------------------
|
|
318
|
+
|
|
319
|
+
def _handle_start(payload: dict) -> "str | None":
|
|
320
|
+
"""Track a subagent starting. Returns active event_type if any."""
|
|
321
|
+
agent_name = payload.get("agent_name", payload.get("subagent_type", "unknown"))
|
|
322
|
+
agent_id = payload.get("agent_id", "")
|
|
323
|
+
|
|
324
|
+
_log("subagent", "normal", "subagent.start",
|
|
325
|
+
detail={"agent": agent_name, "agent_id": agent_id})
|
|
326
|
+
|
|
327
|
+
# Track in session state
|
|
328
|
+
try:
|
|
329
|
+
from _session import SessionState
|
|
330
|
+
state = SessionState.load()
|
|
331
|
+
active_agents = state.active_subagents or {}
|
|
332
|
+
active_agents[agent_id or agent_name] = {
|
|
333
|
+
"name": agent_name,
|
|
334
|
+
"started_at": _now_iso(),
|
|
335
|
+
"started_mono": time.monotonic(),
|
|
336
|
+
}
|
|
337
|
+
active_count = state.active_subagent_count or 0
|
|
338
|
+
state.update(
|
|
339
|
+
active_subagents=active_agents,
|
|
340
|
+
active_subagent_count=active_count + 1,
|
|
341
|
+
total_subagents_launched=(state.total_subagents_launched or 0) + 1,
|
|
342
|
+
)
|
|
343
|
+
except Exception:
|
|
344
|
+
pass
|
|
345
|
+
|
|
346
|
+
session_id = _get_session_id()
|
|
347
|
+
|
|
348
|
+
# Write trace entry
|
|
349
|
+
_write_trace({
|
|
350
|
+
"event": "subagent_start",
|
|
351
|
+
"agent_name": agent_name,
|
|
352
|
+
"agent_id": agent_id,
|
|
353
|
+
"timestamp": _now_iso(),
|
|
354
|
+
"session_id": session_id,
|
|
355
|
+
})
|
|
356
|
+
|
|
357
|
+
# Get active task event_type from native on-disk task store
|
|
358
|
+
return _get_active_task_event_type(session_id)
|
|
359
|
+
|
|
360
|
+
|
|
361
|
+
# ---------------------------------------------------------------------------
|
|
362
|
+
# Handler: SubagentStop
|
|
363
|
+
# ---------------------------------------------------------------------------
|
|
364
|
+
|
|
365
|
+
def _handle_stop(payload: dict) -> None:
|
|
366
|
+
"""Track a subagent stopping."""
|
|
367
|
+
agent_name = payload.get("agent_name", payload.get("subagent_type", "unknown"))
|
|
368
|
+
agent_id = payload.get("agent_id", "")
|
|
369
|
+
|
|
370
|
+
# Calculate duration from session state
|
|
371
|
+
duration_ms = None
|
|
372
|
+
try:
|
|
373
|
+
from _session import SessionState
|
|
374
|
+
state = SessionState.load()
|
|
375
|
+
active_agents = state.active_subagents or {}
|
|
376
|
+
agent_key = agent_id or agent_name
|
|
377
|
+
|
|
378
|
+
if agent_key in active_agents:
|
|
379
|
+
started_mono = active_agents[agent_key].get("started_mono")
|
|
380
|
+
if started_mono is not None:
|
|
381
|
+
duration_ms = int((time.monotonic() - started_mono) * 1000)
|
|
382
|
+
del active_agents[agent_key]
|
|
383
|
+
|
|
384
|
+
active_count = max(0, (state.active_subagent_count or 1) - 1)
|
|
385
|
+
state.update(
|
|
386
|
+
active_subagents=active_agents,
|
|
387
|
+
active_subagent_count=active_count,
|
|
388
|
+
)
|
|
389
|
+
except Exception:
|
|
390
|
+
pass
|
|
391
|
+
|
|
392
|
+
_log("subagent", "normal", "subagent.stop",
|
|
393
|
+
ms=duration_ms,
|
|
394
|
+
detail={"agent": agent_name, "agent_id": agent_id})
|
|
395
|
+
|
|
396
|
+
# Write trace entry
|
|
397
|
+
_write_trace({
|
|
398
|
+
"event": "subagent_stop",
|
|
399
|
+
"agent_name": agent_name,
|
|
400
|
+
"agent_id": agent_id,
|
|
401
|
+
"duration_ms": duration_ms,
|
|
402
|
+
"timestamp": _now_iso(),
|
|
403
|
+
"session_id": _get_session_id(),
|
|
404
|
+
})
|
|
405
|
+
|
|
406
|
+
# Record specialist engagement (Issue #365)
|
|
407
|
+
# subagent_type is the canonical identifier; agent_name may be a display name.
|
|
408
|
+
agent_type = payload.get("subagent_type", agent_name)
|
|
409
|
+
try:
|
|
410
|
+
specialist_domains = _load_specialist_domains()
|
|
411
|
+
domain, specialist_agent = _parse_specialist_from_agent_type(agent_type, specialist_domains)
|
|
412
|
+
if domain is not None:
|
|
413
|
+
_record_specialist_engagement(domain, specialist_agent)
|
|
414
|
+
except Exception as exc:
|
|
415
|
+
print(f"[wicked-garden] specialist engagement check error: {exc}", file=sys.stderr)
|
|
416
|
+
|
|
417
|
+
|
|
418
|
+
# ---------------------------------------------------------------------------
|
|
419
|
+
# Main
|
|
420
|
+
# ---------------------------------------------------------------------------
|
|
421
|
+
|
|
422
|
+
def main():
|
|
423
|
+
# Determine phase from CLI argument
|
|
424
|
+
phase = sys.argv[1] if len(sys.argv) > 1 else "unknown"
|
|
425
|
+
|
|
426
|
+
try:
|
|
427
|
+
raw = sys.stdin.read()
|
|
428
|
+
payload = json.loads(raw) if raw.strip() else {}
|
|
429
|
+
except Exception:
|
|
430
|
+
payload = {}
|
|
431
|
+
|
|
432
|
+
event_type = None
|
|
433
|
+
try:
|
|
434
|
+
if phase == "start":
|
|
435
|
+
event_type = _handle_start(payload)
|
|
436
|
+
elif phase == "stop":
|
|
437
|
+
_handle_stop(payload)
|
|
438
|
+
else:
|
|
439
|
+
_log("subagent", "warn", "subagent.unknown_phase",
|
|
440
|
+
detail={"phase": phase})
|
|
441
|
+
except Exception as e:
|
|
442
|
+
print(f"[wicked-garden] subagent_lifecycle error: {e}", file=sys.stderr)
|
|
443
|
+
|
|
444
|
+
# Always succeed — lifecycle tracking should never block
|
|
445
|
+
output = {"continue": True}
|
|
446
|
+
|
|
447
|
+
if phase == "start":
|
|
448
|
+
tool_discovery = (
|
|
449
|
+
"[Tool Discovery] Before claiming you cannot do something, "
|
|
450
|
+
"review your available skills and tools. You have capabilities for "
|
|
451
|
+
"browser automation, visual testing, accessibility auditing, "
|
|
452
|
+
"API testing, code search, memory, and more. Use them."
|
|
453
|
+
)
|
|
454
|
+
procedure_bundle = _EVENT_TYPE_PROCEDURES.get(event_type, "") if event_type else ""
|
|
455
|
+
if procedure_bundle:
|
|
456
|
+
output["systemMessage"] = f"{tool_discovery}\n\n{procedure_bundle}"
|
|
457
|
+
else:
|
|
458
|
+
output["systemMessage"] = tool_discovery
|
|
459
|
+
|
|
460
|
+
print(json.dumps(output))
|
|
461
|
+
|
|
462
|
+
|
|
463
|
+
if __name__ == "__main__":
|
|
464
|
+
main()
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
Bus-grain subscriber: react to wicked.gate.decided events.
|
|
4
|
+
|
|
5
|
+
Issue #592 (v8 PR-8) — migrated from Claude-lifecycle pattern.
|
|
6
|
+
|
|
7
|
+
Grain: BUS-GRAIN — this handler fires on wicked.gate.decided events that may
|
|
8
|
+
have been emitted by a different session hours ago. It does NOT use Claude's
|
|
9
|
+
prompt / tool lifecycle hooks because Claude cannot see cross-session bus events.
|
|
10
|
+
|
|
11
|
+
Handler contract:
|
|
12
|
+
- Receives full event JSON on stdin.
|
|
13
|
+
- Emits {"status": "ok"|"error", "message": str, "emit_events": list} on stdout.
|
|
14
|
+
|
|
15
|
+
Responsibilities:
|
|
16
|
+
1. Validate the gate-decided event has required fields.
|
|
17
|
+
2. Log the gate decision for observability.
|
|
18
|
+
3. Optionally emit a follow-on wicked.hook.gate_decided_processed event
|
|
19
|
+
(hook chaining example).
|
|
20
|
+
|
|
21
|
+
Always fails open — any unhandled exception returns {"status": "error", ...}.
|
|
22
|
+
"""
|
|
23
|
+
|
|
24
|
+
import json
|
|
25
|
+
import sys
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def main() -> None:
|
|
29
|
+
try:
|
|
30
|
+
raw = sys.stdin.read()
|
|
31
|
+
event = json.loads(raw) if raw.strip() else {}
|
|
32
|
+
except (json.JSONDecodeError, UnicodeDecodeError) as exc:
|
|
33
|
+
sys.stdout.write(json.dumps({
|
|
34
|
+
"status": "error",
|
|
35
|
+
"message": f"Failed to parse event JSON: {exc}",
|
|
36
|
+
"emit_events": [],
|
|
37
|
+
}))
|
|
38
|
+
return
|
|
39
|
+
|
|
40
|
+
payload = event.get("payload", {})
|
|
41
|
+
project_id = payload.get("project_id") or payload.get("project") or ""
|
|
42
|
+
phase = payload.get("phase") or ""
|
|
43
|
+
verdict = payload.get("result") or payload.get("verdict") or ""
|
|
44
|
+
score = payload.get("score")
|
|
45
|
+
|
|
46
|
+
if not project_id or not phase:
|
|
47
|
+
sys.stdout.write(json.dumps({
|
|
48
|
+
"status": "error",
|
|
49
|
+
"message": f"gate.decided event missing project_id or phase: {payload!r}",
|
|
50
|
+
"emit_events": [],
|
|
51
|
+
}))
|
|
52
|
+
return
|
|
53
|
+
|
|
54
|
+
# Emit a processed event for hook chaining (optional — downstream subscribers
|
|
55
|
+
# can react to this synthetic event).
|
|
56
|
+
emit_events = [
|
|
57
|
+
{
|
|
58
|
+
"event_type": "wicked.hook.gate_decided_processed",
|
|
59
|
+
"payload": {
|
|
60
|
+
"project_id": project_id,
|
|
61
|
+
"phase": phase,
|
|
62
|
+
"verdict": verdict,
|
|
63
|
+
"score": score,
|
|
64
|
+
"source_event_id": event.get("event_id", 0),
|
|
65
|
+
},
|
|
66
|
+
}
|
|
67
|
+
]
|
|
68
|
+
|
|
69
|
+
sys.stdout.write(json.dumps({
|
|
70
|
+
"status": "ok",
|
|
71
|
+
"message": f"gate.decided processed: project={project_id} phase={phase} verdict={verdict}",
|
|
72
|
+
"emit_events": emit_events,
|
|
73
|
+
}))
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
if __name__ == "__main__":
|
|
77
|
+
try:
|
|
78
|
+
main()
|
|
79
|
+
except Exception as exc: # noqa: BLE001 — handler must never crash; always emit a result
|
|
80
|
+
sys.stdout.write(json.dumps({
|
|
81
|
+
"status": "error",
|
|
82
|
+
"message": f"Unhandled exception in on_gate_decided: {exc}",
|
|
83
|
+
"emit_events": [],
|
|
84
|
+
}))
|