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,624 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
Stop hook — wicked-garden unified session teardown (async, 30s timeout).
|
|
4
|
+
|
|
5
|
+
Consolidates: crew stop, mem stop, session-end fact emission.
|
|
6
|
+
|
|
7
|
+
Flow:
|
|
8
|
+
1. Session outcome check (mismatch report from auto_issue_reporter state)
|
|
9
|
+
2. Automatic memory promotion from native tasks (session_fact_extractor)
|
|
10
|
+
3. Working-tier consolidation via brain compile + lint
|
|
11
|
+
4. Memory decay maintenance
|
|
12
|
+
5. Persist final SessionState
|
|
13
|
+
6. Event store retention purge
|
|
14
|
+
7. Emit memory flush reminder directive
|
|
15
|
+
|
|
16
|
+
Always fails open — any unhandled exception returns {"systemMessage": ...}.
|
|
17
|
+
Runs async so it does NOT block the user on exit.
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
import json
|
|
21
|
+
import os
|
|
22
|
+
import sys
|
|
23
|
+
import time
|
|
24
|
+
from pathlib import Path
|
|
25
|
+
from typing import Optional
|
|
26
|
+
|
|
27
|
+
# Add shared scripts directory to path
|
|
28
|
+
_PLUGIN_ROOT = Path(os.environ.get("CLAUDE_PLUGIN_ROOT", Path(__file__).resolve().parents[2]))
|
|
29
|
+
sys.path.insert(0, str(_PLUGIN_ROOT / "scripts"))
|
|
30
|
+
|
|
31
|
+
def _resolve_brain_port():
|
|
32
|
+
try:
|
|
33
|
+
from _brain_port import resolve_port
|
|
34
|
+
return resolve_port()
|
|
35
|
+
except Exception:
|
|
36
|
+
return int(os.environ.get("WICKED_BRAIN_PORT", "4242"))
|
|
37
|
+
|
|
38
|
+
# ---------------------------------------------------------------------------
|
|
39
|
+
# Ops logger wrapper — fail-silent, never crashes the hook
|
|
40
|
+
# ---------------------------------------------------------------------------
|
|
41
|
+
|
|
42
|
+
def _log(domain, level, event, ok=True, ms=None, detail=None):
|
|
43
|
+
"""Ops logger — fail-silent, never crashes the hook."""
|
|
44
|
+
try:
|
|
45
|
+
from _logger import log
|
|
46
|
+
log(domain, level, event, ok=ok, ms=ms, detail=detail)
|
|
47
|
+
except Exception:
|
|
48
|
+
pass
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
# ---------------------------------------------------------------------------
|
|
52
|
+
# Helpers
|
|
53
|
+
# ---------------------------------------------------------------------------
|
|
54
|
+
|
|
55
|
+
def _get_session_id() -> str:
|
|
56
|
+
raw = os.environ.get("CLAUDE_SESSION_ID", "default")
|
|
57
|
+
return raw.replace("/", "_").replace("\\", "_").replace("..", "_")
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def _session_dir(subdir: str) -> Path:
|
|
61
|
+
tmpdir = (os.environ.get("TMPDIR") or __import__("tempfile").gettempdir()).rstrip("/")
|
|
62
|
+
return Path(tmpdir) / subdir / _get_session_id()
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
# ---------------------------------------------------------------------------
|
|
66
|
+
# Claim sentinel (answer tier) — claim-gated at the Stop boundary.
|
|
67
|
+
# Replaces the old PostToolUse ref-watch that fired on every Bash call. Reads
|
|
68
|
+
# the turn's final assistant message from the transcript; only a real
|
|
69
|
+
# done/passing/shipped claim with no verdict for HEAD produces a nudge.
|
|
70
|
+
# ---------------------------------------------------------------------------
|
|
71
|
+
|
|
72
|
+
def _extract_text(content) -> Optional[str]:
|
|
73
|
+
"""Pull concatenated text from a transcript message's `content` — either a
|
|
74
|
+
raw string or a list of {type:'text', text:...} blocks."""
|
|
75
|
+
if isinstance(content, str):
|
|
76
|
+
return content or None
|
|
77
|
+
if isinstance(content, list):
|
|
78
|
+
parts = [b["text"] for b in content
|
|
79
|
+
if isinstance(b, dict) and b.get("type") == "text" and b.get("text")]
|
|
80
|
+
return "\n".join(parts) if parts else None
|
|
81
|
+
return None
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
def _read_final_assistant_text(transcript_path: str) -> Optional[str]:
|
|
85
|
+
"""Return the text of the LAST assistant message in the transcript JSONL,
|
|
86
|
+
or None. Fail-open — any read/parse error yields None (no claim => no fire)."""
|
|
87
|
+
try:
|
|
88
|
+
p = Path(transcript_path)
|
|
89
|
+
if not p.is_file():
|
|
90
|
+
return None
|
|
91
|
+
last = None
|
|
92
|
+
for line in p.read_text(encoding="utf-8", errors="ignore").splitlines():
|
|
93
|
+
line = line.strip()
|
|
94
|
+
if not line:
|
|
95
|
+
continue
|
|
96
|
+
try:
|
|
97
|
+
rec = json.loads(line)
|
|
98
|
+
except (json.JSONDecodeError, ValueError):
|
|
99
|
+
continue
|
|
100
|
+
if not isinstance(rec, dict):
|
|
101
|
+
continue
|
|
102
|
+
msg = rec.get("message") if isinstance(rec.get("message"), dict) else None
|
|
103
|
+
role = (msg or {}).get("role") or rec.get("role") or rec.get("type")
|
|
104
|
+
if role != "assistant":
|
|
105
|
+
continue
|
|
106
|
+
text = _extract_text((msg or {}).get("content", rec.get("content")))
|
|
107
|
+
if text:
|
|
108
|
+
last = text
|
|
109
|
+
return last
|
|
110
|
+
except Exception:
|
|
111
|
+
return None
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
def _check_claim_sentinel(input_data: dict) -> list:
|
|
115
|
+
"""If the turn's final assistant message asserts done/passing/shipped and
|
|
116
|
+
HEAD has no re-derived verdict, return a one-line nudge (debounced per sha
|
|
117
|
+
per session via SessionState). Fail-open — never breaks Stop."""
|
|
118
|
+
try:
|
|
119
|
+
transcript = input_data.get("transcript_path")
|
|
120
|
+
final_text = _read_final_assistant_text(transcript) if transcript else None
|
|
121
|
+
if not final_text:
|
|
122
|
+
return []
|
|
123
|
+
sys.path.insert(0, str(_PLUGIN_ROOT / "scripts" / "sentinel"))
|
|
124
|
+
from invariants import claim_tick, render # type: ignore
|
|
125
|
+
from _session import SessionState
|
|
126
|
+
state = SessionState.load()
|
|
127
|
+
cwd = input_data.get("cwd")
|
|
128
|
+
violation = claim_tick(
|
|
129
|
+
lambda k: getattr(state, k, None),
|
|
130
|
+
lambda k, v: state.update(**{k: v}),
|
|
131
|
+
final_message=final_text,
|
|
132
|
+
cwd=Path(cwd) if cwd else None,
|
|
133
|
+
)
|
|
134
|
+
return [render(violation)] if violation else []
|
|
135
|
+
except Exception:
|
|
136
|
+
return []
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
# ---------------------------------------------------------------------------
|
|
140
|
+
# Step 1: Session outcome check
|
|
141
|
+
# ---------------------------------------------------------------------------
|
|
142
|
+
|
|
143
|
+
def _check_session_outcome() -> list:
|
|
144
|
+
"""Return a list of outcome messages from the issue reporter state.
|
|
145
|
+
|
|
146
|
+
v9.2.12: Pre-fix, this function emitted the [Issue Reporter] banner on
|
|
147
|
+
EVERY Stop hook (i.e. every model response) as long as pending_issues.jsonl
|
|
148
|
+
or mismatches.jsonl had any content. Users saw the same banner re-fire
|
|
149
|
+
every turn until the issues were filed — chronic noise. The change-gated
|
|
150
|
+
latches (last_outcome_pending_count / last_outcome_mismatch_count on
|
|
151
|
+
SessionState) suppress re-emission unless the count has actually grown
|
|
152
|
+
since the previous emission. The first emission per session ALWAYS fires
|
|
153
|
+
(compares against default 0). Subsequent emissions only fire when new
|
|
154
|
+
issues / mismatches accumulate.
|
|
155
|
+
"""
|
|
156
|
+
messages = []
|
|
157
|
+
try:
|
|
158
|
+
# Latch state — fail-open if SessionState is unreachable.
|
|
159
|
+
try:
|
|
160
|
+
from _session import SessionState
|
|
161
|
+
session_state = SessionState.load()
|
|
162
|
+
except Exception:
|
|
163
|
+
session_state = None
|
|
164
|
+
|
|
165
|
+
sdir = _session_dir("wicked-issue-reporter")
|
|
166
|
+
pending_file = sdir / "pending_issues.jsonl"
|
|
167
|
+
mismatches_file = sdir / "mismatches.jsonl"
|
|
168
|
+
|
|
169
|
+
# Count pending issues
|
|
170
|
+
if pending_file.exists():
|
|
171
|
+
lines = [l.strip() for l in pending_file.read_text().splitlines() if l.strip()]
|
|
172
|
+
count = len(lines)
|
|
173
|
+
last_count = (
|
|
174
|
+
int(getattr(session_state, "last_outcome_pending_count", 0) or 0)
|
|
175
|
+
if session_state else 0
|
|
176
|
+
)
|
|
177
|
+
if count and count > last_count:
|
|
178
|
+
messages.append(
|
|
179
|
+
f"[Issue Reporter] {count} issue(s) queued this session. "
|
|
180
|
+
"Review with /wicked-garden:report-issue --list-unfiled."
|
|
181
|
+
)
|
|
182
|
+
if session_state is not None:
|
|
183
|
+
session_state.update(last_outcome_pending_count=count)
|
|
184
|
+
|
|
185
|
+
# Count task mismatches
|
|
186
|
+
if mismatches_file.exists():
|
|
187
|
+
lines = [l.strip() for l in mismatches_file.read_text().splitlines() if l.strip()]
|
|
188
|
+
count = len(lines)
|
|
189
|
+
last_count = (
|
|
190
|
+
int(getattr(session_state, "last_outcome_mismatch_count", 0) or 0)
|
|
191
|
+
if session_state else 0
|
|
192
|
+
)
|
|
193
|
+
if count and count > last_count:
|
|
194
|
+
signals = []
|
|
195
|
+
for line in lines[:3]:
|
|
196
|
+
try:
|
|
197
|
+
record = json.loads(line)
|
|
198
|
+
# Sanitize subject — strip control chars, truncate
|
|
199
|
+
subj = record.get("subject", "?")[:60]
|
|
200
|
+
subj = "".join(c for c in subj if c.isprintable())
|
|
201
|
+
signals.append(subj)
|
|
202
|
+
except (json.JSONDecodeError, ValueError):
|
|
203
|
+
pass
|
|
204
|
+
messages.append(
|
|
205
|
+
f"[Issue Reporter] {count} task completion mismatch(es) detected: "
|
|
206
|
+
+ "; ".join(signals)
|
|
207
|
+
)
|
|
208
|
+
if session_state is not None:
|
|
209
|
+
session_state.update(last_outcome_mismatch_count=count)
|
|
210
|
+
except Exception:
|
|
211
|
+
pass
|
|
212
|
+
return messages
|
|
213
|
+
|
|
214
|
+
|
|
215
|
+
|
|
216
|
+
|
|
217
|
+
# ---------------------------------------------------------------------------
|
|
218
|
+
# Step 2b: Session-end fact emission → wicked-brain auto-memorize
|
|
219
|
+
# ---------------------------------------------------------------------------
|
|
220
|
+
#
|
|
221
|
+
# v6: Session facts are extracted from native Claude tasks
|
|
222
|
+
# (${CLAUDE_CONFIG_DIR:-~/.claude}/tasks/{session_id}/*.json) by
|
|
223
|
+
# scripts/mem/session_fact_extractor.py. This replaces the v5 smaht
|
|
224
|
+
# FactExtractor/HistoryCondenser pipeline deleted in Gate 4 Phase 2 (#428).
|
|
225
|
+
# Emission shape is unchanged: wicked.fact.extracted events on wicked-bus,
|
|
226
|
+
# picked up by wicked-brain's auto-memorize subscriber, which re-applies its
|
|
227
|
+
# own type/length/dedup policy.
|
|
228
|
+
|
|
229
|
+
# Fact types eligible for emission — mirrors brain's auto-memorize policy.
|
|
230
|
+
# Brain will re-check these; this pre-filter keeps bus traffic sensible.
|
|
231
|
+
_EMITTABLE_FACT_TYPES = frozenset({"decision", "discovery"})
|
|
232
|
+
_MIN_FACT_CONTENT_LENGTH = 15
|
|
233
|
+
|
|
234
|
+
|
|
235
|
+
def _run_memory_promotion(session_id: str) -> list:
|
|
236
|
+
"""Emit high-value session facts as wicked.fact.extracted events on wicked-bus.
|
|
237
|
+
|
|
238
|
+
Reads native task records (TaskCreate/TaskUpdate output) via
|
|
239
|
+
scripts/mem/session_fact_extractor.py, filters to decisions + discoveries
|
|
240
|
+
over the length threshold, and emits one event per fact. Brain's
|
|
241
|
+
auto-memorize subscriber handles persistence asynchronously.
|
|
242
|
+
|
|
243
|
+
Returns a list of message strings (empty when nothing was emitted or the
|
|
244
|
+
bus is unavailable). Always fails open — exceptions are caught and logged
|
|
245
|
+
to stderr.
|
|
246
|
+
"""
|
|
247
|
+
try:
|
|
248
|
+
# scripts/ is on sys.path via the hook bootstrap; _brain_ingest is a
|
|
249
|
+
# package under scripts/ so the qualified import resolves without any
|
|
250
|
+
# additional sys.path manipulation.
|
|
251
|
+
from _brain_ingest.session_fact_extractor import extract_session_facts
|
|
252
|
+
from _bus import emit_event
|
|
253
|
+
|
|
254
|
+
facts = extract_session_facts(session_id, limit=20)
|
|
255
|
+
if not facts:
|
|
256
|
+
if os.environ.get("WICKED_DEBUG"):
|
|
257
|
+
print(
|
|
258
|
+
f"[wicked-garden] fact emit: no promotable facts in session {session_id}",
|
|
259
|
+
file=sys.stderr,
|
|
260
|
+
)
|
|
261
|
+
return []
|
|
262
|
+
|
|
263
|
+
emitted = 0
|
|
264
|
+
for fact in facts:
|
|
265
|
+
if fact.type not in _EMITTABLE_FACT_TYPES:
|
|
266
|
+
continue
|
|
267
|
+
if len(fact.content) < _MIN_FACT_CONTENT_LENGTH:
|
|
268
|
+
continue
|
|
269
|
+
emit_event(
|
|
270
|
+
"wicked.fact.extracted",
|
|
271
|
+
{
|
|
272
|
+
"type": fact.type,
|
|
273
|
+
"content": fact.content,
|
|
274
|
+
"entities": list(fact.entities)[:5] if fact.entities else [],
|
|
275
|
+
"source": fact.source or "task",
|
|
276
|
+
"session_id": session_id,
|
|
277
|
+
},
|
|
278
|
+
)
|
|
279
|
+
emitted += 1
|
|
280
|
+
|
|
281
|
+
if emitted == 0:
|
|
282
|
+
return []
|
|
283
|
+
return [f"[Memory] Emitted {emitted} fact event(s); wicked-brain will auto-memorize eligible ones."]
|
|
284
|
+
|
|
285
|
+
except Exception as e:
|
|
286
|
+
print(f"[wicked-garden] fact emit error: {e}", file=sys.stderr)
|
|
287
|
+
return []
|
|
288
|
+
|
|
289
|
+
|
|
290
|
+
# ---------------------------------------------------------------------------
|
|
291
|
+
# Step 2 & 3: Memory flush reminder + decay
|
|
292
|
+
# ---------------------------------------------------------------------------
|
|
293
|
+
|
|
294
|
+
def _brain_api(action, params=None, timeout=3):
|
|
295
|
+
"""Call brain API. Returns parsed JSON or None."""
|
|
296
|
+
try:
|
|
297
|
+
import urllib.request
|
|
298
|
+
port = _resolve_brain_port()
|
|
299
|
+
payload = json.dumps({"action": action, "params": params or {}}).encode("utf-8")
|
|
300
|
+
req = urllib.request.Request(
|
|
301
|
+
f"http://localhost:{port}/api",
|
|
302
|
+
data=payload,
|
|
303
|
+
headers={"Content-Type": "application/json"},
|
|
304
|
+
method="POST",
|
|
305
|
+
)
|
|
306
|
+
with urllib.request.urlopen(req, timeout=timeout) as resp:
|
|
307
|
+
return json.loads(resp.read().decode("utf-8"))
|
|
308
|
+
except Exception:
|
|
309
|
+
return None
|
|
310
|
+
|
|
311
|
+
|
|
312
|
+
def _run_memory_decay() -> list:
|
|
313
|
+
"""Run decay maintenance via brain lint API. Return list of result message strings."""
|
|
314
|
+
messages = []
|
|
315
|
+
try:
|
|
316
|
+
# Session-end maintenance writes — auto-start the server so a stopped
|
|
317
|
+
# server doesn't silently skip decay (fail-open, lock-safe, one
|
|
318
|
+
# spawn attempt per process).
|
|
319
|
+
try:
|
|
320
|
+
from _brain_port import ensure_server
|
|
321
|
+
ensure_server(wait_secs=2.0)
|
|
322
|
+
except Exception:
|
|
323
|
+
pass
|
|
324
|
+
result = _brain_api("lint", {}, timeout=5)
|
|
325
|
+
if result and (result.get("archived", 0) > 0 or result.get("deleted", 0) > 0):
|
|
326
|
+
messages.append(
|
|
327
|
+
f"[Memory] Decay: {result.get('archived', 0)} archived, {result.get('deleted', 0)} cleaned"
|
|
328
|
+
)
|
|
329
|
+
except Exception as e:
|
|
330
|
+
print(f"[wicked-garden] decay error: {e}", file=sys.stderr)
|
|
331
|
+
return messages
|
|
332
|
+
|
|
333
|
+
|
|
334
|
+
def _run_working_consolidation() -> list:
|
|
335
|
+
"""Consolidate working-tier memories via brain compile + lint.
|
|
336
|
+
|
|
337
|
+
Returns a list of message strings. Fails open — never blocks session end.
|
|
338
|
+
"""
|
|
339
|
+
messages = []
|
|
340
|
+
try:
|
|
341
|
+
try:
|
|
342
|
+
from _brain_port import ensure_server
|
|
343
|
+
ensure_server(wait_secs=2.0)
|
|
344
|
+
except Exception:
|
|
345
|
+
pass
|
|
346
|
+
compile_result = _brain_api("compile", {}, timeout=10)
|
|
347
|
+
lint_result = _brain_api("lint", {}, timeout=5)
|
|
348
|
+
compiled = compile_result.get("compiled", 0) if compile_result else 0
|
|
349
|
+
cleaned = lint_result.get("deleted", 0) if lint_result else 0
|
|
350
|
+
if compiled > 0 or cleaned > 0:
|
|
351
|
+
messages.append(
|
|
352
|
+
f"[Memory] Consolidation: {compiled} compiled, {cleaned} cleaned"
|
|
353
|
+
)
|
|
354
|
+
except Exception as e:
|
|
355
|
+
print(f"[wicked-garden] consolidation error: {e}", file=sys.stderr)
|
|
356
|
+
return messages
|
|
357
|
+
|
|
358
|
+
|
|
359
|
+
def _get_turn_count() -> int:
|
|
360
|
+
try:
|
|
361
|
+
from _session import SessionState
|
|
362
|
+
state = SessionState.load()
|
|
363
|
+
return state.turn_count or 0
|
|
364
|
+
except Exception:
|
|
365
|
+
return 0
|
|
366
|
+
|
|
367
|
+
|
|
368
|
+
# ---------------------------------------------------------------------------
|
|
369
|
+
# Step 6: Persist final session state
|
|
370
|
+
# ---------------------------------------------------------------------------
|
|
371
|
+
|
|
372
|
+
def _persist_session_state() -> None:
|
|
373
|
+
"""Mark session as ended in session state file."""
|
|
374
|
+
try:
|
|
375
|
+
from _session import SessionState
|
|
376
|
+
state = SessionState.load()
|
|
377
|
+
state.update(session_ended=True)
|
|
378
|
+
state.save()
|
|
379
|
+
except Exception:
|
|
380
|
+
pass
|
|
381
|
+
|
|
382
|
+
|
|
383
|
+
# ---------------------------------------------------------------------------
|
|
384
|
+
# Step 7: Event store retention purge
|
|
385
|
+
# ---------------------------------------------------------------------------
|
|
386
|
+
|
|
387
|
+
def _purge_old_events() -> None:
|
|
388
|
+
"""Purge events older than retention period (default 90 days)."""
|
|
389
|
+
try:
|
|
390
|
+
from _event_store import EventStore
|
|
391
|
+
EventStore.ensure_schema()
|
|
392
|
+
deleted = EventStore.purge_before(days=90)
|
|
393
|
+
if deleted > 0:
|
|
394
|
+
_log("stop", "debug", f"event_store.purged {deleted} events")
|
|
395
|
+
except Exception:
|
|
396
|
+
pass # fire-and-forget
|
|
397
|
+
|
|
398
|
+
|
|
399
|
+
# ---------------------------------------------------------------------------
|
|
400
|
+
# Cross-session quality telemetry (Issue #443)
|
|
401
|
+
#
|
|
402
|
+
# Captures a JSONL record of session-level quality metrics and runs drift
|
|
403
|
+
# classification against the 4-session baseline. Always fail-open — must
|
|
404
|
+
# never break Stop. Target budget: <100ms typical, <500ms worst.
|
|
405
|
+
# ---------------------------------------------------------------------------
|
|
406
|
+
|
|
407
|
+
def _run_quality_telemetry(session_id: str) -> list:
|
|
408
|
+
"""Append a timeline record + detect drift. Returns any messages."""
|
|
409
|
+
messages = []
|
|
410
|
+
try:
|
|
411
|
+
sys.path.insert(0, str(_PLUGIN_ROOT / "scripts" / "delivery"))
|
|
412
|
+
import telemetry as _telemetry
|
|
413
|
+
import drift as _drift
|
|
414
|
+
|
|
415
|
+
t_cap = time.monotonic()
|
|
416
|
+
record = _telemetry.capture_session(session_id)
|
|
417
|
+
cap_ms = int((time.monotonic() - t_cap) * 1000)
|
|
418
|
+
_log("telemetry", "debug", "telemetry.capture", ok=record is not None, ms=cap_ms)
|
|
419
|
+
if record is None:
|
|
420
|
+
return messages
|
|
421
|
+
|
|
422
|
+
project = record.get("project") or "_global"
|
|
423
|
+
records = _telemetry.read_timeline(project)
|
|
424
|
+
cls = _drift.classify(records)
|
|
425
|
+
# Emit bus event when drift actionable; fail-open when bus is absent.
|
|
426
|
+
emitted = _drift.emit_drift_event(project, cls)
|
|
427
|
+
if cls.get("drift"):
|
|
428
|
+
messages.append(
|
|
429
|
+
f"[Telemetry] Drift detected for {project}: " + _drift.summarize(cls)
|
|
430
|
+
+ (" (emitted to wicked-bus)" if emitted else "")
|
|
431
|
+
)
|
|
432
|
+
elif cls.get("zone") == "warn":
|
|
433
|
+
messages.append(
|
|
434
|
+
f"[Telemetry] Watch signal for {project}: " + _drift.summarize(cls)
|
|
435
|
+
)
|
|
436
|
+
except Exception as e:
|
|
437
|
+
print(f"[wicked-garden] telemetry error: {e}", file=sys.stderr)
|
|
438
|
+
return messages
|
|
439
|
+
|
|
440
|
+
|
|
441
|
+
# ---------------------------------------------------------------------------
|
|
442
|
+
# Step 6: Autonomous guard pipeline (Issue #448)
|
|
443
|
+
# ---------------------------------------------------------------------------
|
|
444
|
+
#
|
|
445
|
+
# Runs a tiered profile of surface-level verification at session close:
|
|
446
|
+
# * scalpel (<1s) — always runs when the pipeline is reachable
|
|
447
|
+
# * standard (~5s) — build-phase just closed, or substantial changes
|
|
448
|
+
# * deep (~30s) — release-branch sessions or explicit WG_GUARD_PROFILE=deep
|
|
449
|
+
#
|
|
450
|
+
# Always fails open — never hard-blocks session close. Findings are written
|
|
451
|
+
# to a session-scoped file that bootstrap.py can surface in the next briefing,
|
|
452
|
+
# and emitted as a `wicked.guard.findings` event on wicked-bus.
|
|
453
|
+
#
|
|
454
|
+
# Ordering: runs AFTER telemetry (#443) so both can share the end-of-session
|
|
455
|
+
# snapshot without blocking each other.
|
|
456
|
+
|
|
457
|
+
def _run_guard_pipeline() -> list:
|
|
458
|
+
"""Run the autonomous session-close guard pipeline.
|
|
459
|
+
|
|
460
|
+
Returns a list of human-readable message strings to prepend to the session
|
|
461
|
+
message. Always fails open — any error returns an empty list.
|
|
462
|
+
"""
|
|
463
|
+
try:
|
|
464
|
+
sys.path.insert(0, str(_PLUGIN_ROOT / "scripts" / "platform"))
|
|
465
|
+
from guard_pipeline import (
|
|
466
|
+
run_pipeline,
|
|
467
|
+
write_briefing_file,
|
|
468
|
+
emit_findings_event,
|
|
469
|
+
render_summary,
|
|
470
|
+
)
|
|
471
|
+
except Exception as exc:
|
|
472
|
+
print(f"[wicked-garden] guard pipeline unavailable: {exc}", file=sys.stderr)
|
|
473
|
+
return []
|
|
474
|
+
|
|
475
|
+
try:
|
|
476
|
+
# Detect whether build phase just closed — best-effort via session state
|
|
477
|
+
build_just_closed = False
|
|
478
|
+
try:
|
|
479
|
+
from _session import SessionState
|
|
480
|
+
state = SessionState.load()
|
|
481
|
+
build_just_closed = bool(
|
|
482
|
+
getattr(state, "last_phase_approved", None) == "build"
|
|
483
|
+
)
|
|
484
|
+
except Exception:
|
|
485
|
+
pass # fail open — treat unknown phase as "not just closed"
|
|
486
|
+
|
|
487
|
+
report = run_pipeline(build_phase_just_closed=build_just_closed)
|
|
488
|
+
|
|
489
|
+
# Write briefing file (next session pickup)
|
|
490
|
+
write_briefing_file(report)
|
|
491
|
+
|
|
492
|
+
# Emit bus event (fire-and-forget)
|
|
493
|
+
emit_findings_event(report)
|
|
494
|
+
|
|
495
|
+
# Only return a summary line when we actually have findings or budget blew.
|
|
496
|
+
if report.total_findings > 0 or report.status != "ok":
|
|
497
|
+
return [render_summary(report)]
|
|
498
|
+
return []
|
|
499
|
+
except Exception as exc:
|
|
500
|
+
print(f"[wicked-garden] guard pipeline error: {exc}", file=sys.stderr)
|
|
501
|
+
return []
|
|
502
|
+
|
|
503
|
+
|
|
504
|
+
# ---------------------------------------------------------------------------
|
|
505
|
+
# Main
|
|
506
|
+
# ---------------------------------------------------------------------------
|
|
507
|
+
|
|
508
|
+
def main():
|
|
509
|
+
_t0 = time.monotonic()
|
|
510
|
+
_log("session", "debug", "hook.start")
|
|
511
|
+
|
|
512
|
+
try:
|
|
513
|
+
raw = sys.stdin.read()
|
|
514
|
+
input_data = json.loads(raw) if raw.strip() else {}
|
|
515
|
+
except Exception:
|
|
516
|
+
input_data = {}
|
|
517
|
+
|
|
518
|
+
try:
|
|
519
|
+
session_id = input_data.get("session_id", os.environ.get("CLAUDE_SESSION_ID", "default"))
|
|
520
|
+
turn_count = _get_turn_count()
|
|
521
|
+
|
|
522
|
+
# 1. Session outcome check
|
|
523
|
+
outcome_messages = _check_session_outcome()
|
|
524
|
+
|
|
525
|
+
# 2b. Automatic memory promotion (fail open — never blocks session end)
|
|
526
|
+
# KEPT in stop.py per-turn — lightweight (single bus emit per fact),
|
|
527
|
+
# self-reports cleanly, and the next session's bootstrap relies on
|
|
528
|
+
# memories being current. Heavy cadence work (decay/consolidation/
|
|
529
|
+
# telemetry/guard) was extracted in v9.2.15 — see _heavy_cadence.py.
|
|
530
|
+
promotion_messages = _run_memory_promotion(session_id)
|
|
531
|
+
|
|
532
|
+
# 4. Persist session state
|
|
533
|
+
_persist_session_state()
|
|
534
|
+
|
|
535
|
+
# 5. Event store retention purge
|
|
536
|
+
_purge_old_events()
|
|
537
|
+
|
|
538
|
+
# 6. Heavy cadence (v9.2.15) — formerly per-turn, now per-session-end
|
|
539
|
+
# primary via the SessionEnd hook (hooks/scripts/session_end.py).
|
|
540
|
+
# Stop only runs the heavy work as a 60-min FALLBACK for the partial-
|
|
541
|
+
# session failure mode (CLI killed, network drop, user walked away —
|
|
542
|
+
# SessionEnd never fires). Sidecar at <local store>/wicked-garden/
|
|
543
|
+
# heavy-cadence/last_run.json gates the fallback deterministically.
|
|
544
|
+
consolidation_messages: list = []
|
|
545
|
+
decay_messages: list = []
|
|
546
|
+
telemetry_messages: list = []
|
|
547
|
+
guard_messages: list = []
|
|
548
|
+
try:
|
|
549
|
+
sys.path.insert(0, str(_PLUGIN_ROOT / "scripts"))
|
|
550
|
+
from _heavy_cadence import ( # type: ignore
|
|
551
|
+
run_heavy_cadence, should_run_fallback, TRIGGER_STOP_FALLBACK,
|
|
552
|
+
)
|
|
553
|
+
if should_run_fallback():
|
|
554
|
+
fallback_messages = run_heavy_cadence(
|
|
555
|
+
TRIGGER_STOP_FALLBACK, session_id=session_id, plugin_root=_PLUGIN_ROOT,
|
|
556
|
+
)
|
|
557
|
+
# Single combined list — semantics preserved for downstream
|
|
558
|
+
# joining; per-category split was only used by the deleted
|
|
559
|
+
# [Memory] reflection block.
|
|
560
|
+
consolidation_messages = fallback_messages
|
|
561
|
+
except Exception as e:
|
|
562
|
+
print(f"[wicked-garden] heavy cadence fallback error: {e}", file=sys.stderr)
|
|
563
|
+
|
|
564
|
+
# Read session state for task completion count (fail open)
|
|
565
|
+
tasks_completed_this_session = 0
|
|
566
|
+
try:
|
|
567
|
+
sys.path.insert(0, str(_PLUGIN_ROOT / "scripts"))
|
|
568
|
+
from _session import SessionState
|
|
569
|
+
session_state = SessionState.load()
|
|
570
|
+
tasks_completed_this_session = session_state.memory_compliance_tasks_completed or 0
|
|
571
|
+
except Exception:
|
|
572
|
+
pass
|
|
573
|
+
|
|
574
|
+
# NOTE (v9.2.15): the [Memory] reflection block was deleted.
|
|
575
|
+
# - It had a parser bug: looked for substring "Auto-extracted " but
|
|
576
|
+
# _run_memory_promotion emits "Emitted N fact event(s)" — so
|
|
577
|
+
# `promoted_count` was ALWAYS 0 and only the fallback prompt-mode
|
|
578
|
+
# branch ever fired. The "smart" branching had never executed in
|
|
579
|
+
# production.
|
|
580
|
+
# - _run_memory_promotion already self-reports when facts are
|
|
581
|
+
# auto-extracted ("[Memory] Emitted N fact event(s); wicked-brain
|
|
582
|
+
# will auto-memorize..."), so the reflection's "use wicked-brain:
|
|
583
|
+
# memory" guidance was duplicate noise.
|
|
584
|
+
# - The brainstorm in v9.2.15 chose Option A (delete) over Option B
|
|
585
|
+
# (fix the parser + re-gate) because the smart branch is dead
|
|
586
|
+
# code defending behavior no user has seen. CLAUDE.md's "Memory
|
|
587
|
+
# Management" section already tells Claude to use wicked-brain:
|
|
588
|
+
# memory for decisions; an end-of-turn reminder adds no signal.
|
|
589
|
+
# `tasks_completed_this_session` is no longer read; the variable
|
|
590
|
+
# remains in scope above for any future use without breaking the
|
|
591
|
+
# `session_state` load.
|
|
592
|
+
reflection = ""
|
|
593
|
+
# for this session (post-first-Stop) — only join with separator if both
|
|
594
|
+
# halves have content.
|
|
595
|
+
# Answer-tier claim sentinel — claim-gated, computed here (after
|
|
596
|
+
# _persist_session_state) so its debounce write is the last state write
|
|
597
|
+
# of the turn (avoids clobbering session_ended).
|
|
598
|
+
sentinel_messages = _check_claim_sentinel(input_data)
|
|
599
|
+
prepend_messages = sentinel_messages + outcome_messages + promotion_messages + consolidation_messages + telemetry_messages + guard_messages
|
|
600
|
+
if prepend_messages and reflection:
|
|
601
|
+
final_message = "\n".join(prepend_messages) + "\n\n" + reflection
|
|
602
|
+
elif prepend_messages:
|
|
603
|
+
final_message = "\n".join(prepend_messages)
|
|
604
|
+
else:
|
|
605
|
+
final_message = reflection
|
|
606
|
+
|
|
607
|
+
# Compute log file path for session summary
|
|
608
|
+
_ops_log_path = str(
|
|
609
|
+
Path(os.environ.get("TMPDIR") or __import__("tempfile").gettempdir()) / f"wicked-ops-{_get_session_id()}.jsonl"
|
|
610
|
+
)
|
|
611
|
+
_log("session", "verbose", "session.end",
|
|
612
|
+
detail={"turns": turn_count,
|
|
613
|
+
"tasks_completed": tasks_completed_this_session,
|
|
614
|
+
"log_file": _ops_log_path})
|
|
615
|
+
_log("session", "debug", "hook.end", ms=int((time.monotonic() - _t0) * 1000))
|
|
616
|
+
print(json.dumps({"systemMessage": final_message}))
|
|
617
|
+
|
|
618
|
+
except Exception as e:
|
|
619
|
+
print(f"[wicked-garden] stop hook error: {e}", file=sys.stderr)
|
|
620
|
+
print(json.dumps({"systemMessage": ""}))
|
|
621
|
+
|
|
622
|
+
|
|
623
|
+
if __name__ == "__main__":
|
|
624
|
+
main()
|