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,403 @@
|
|
|
1
|
+
# wicked-loom — FLOW Surface Cutover (mirror → loom-authoritative park verdict) — Implementation Plan
|
|
2
|
+
|
|
3
|
+
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
|
|
4
|
+
|
|
5
|
+
**Goal:** Promote the garden `flow` surface from a **read-only parity mirror** (which only logs `wicked.loom.parity_mismatch` and never changes behavior) to **loom-authoritative for the hard-gate park DECISION** — `approve_phase`'s `ValueError` guard fires based on loom's compiled-flow verdict (`loom flow` park-at-hard-gate semantics, re-derived through `flow_compiler` + loom's `_is_hard`), with the in-process `_HARD_GATE_PHASES` map demoted to the fail-soft fallback. `ProjectState` stays the sole source of truth for storage and one-phase-at-a-time advancement. This is the **smallest valuable, low-risk increment** of "loom authoritative for the flow surface": loom now decides *where the human stops*, but garden still *owns the state machine*.
|
|
6
|
+
|
|
7
|
+
**Architecture:** Garden's `phase_manager.approve_phase` already advances ONE phase per CLI call against a DomainStore-backed `ProjectState`; loom's `flow run` executes a WHOLE flow-def in one `while` loop and tracks its own `flowstate`. These are different state models (see "The hard design problem" below). This increment does NOT reconcile the two storage models — it delegates only the **single load-bearing decision** the parity mirror already cross-checks: *is `(archetype, phase)` a hard gate that must park for a human?* Today `_is_hard_gate` answers from the in-process `_HARD_GATE_PHASES` dict. After this increment, `_loom_confirms_hard_gate` (loom's verdict, via the compiled flow-def — which is itself derived from the same catalog + map) is **authoritative when present**, and `_HARD_GATE_PHASES` is the fallback only when loom is unavailable/uncertain. The mirror's stderr + `wicked.loom.parity_mismatch` emit is retained but re-cast as a divergence *signal* on the authoritative path. The `ValueError` hard-gate guard, the `confirmed_by`/`confirmation_evidence` requirement, and fail-closed posture are **preserved verbatim** — only the *source* of the "is this a hard gate" boolean changes.
|
|
8
|
+
|
|
9
|
+
**Tech Stack:** Python 3.9+ (stdlib only — garden's hook discipline; loom is reached as a subprocess via `scripts/_loom.py`, never imported). `pytest` (`testpaths = ["tests"]`; `tests/conftest.py` puts `scripts/` at `sys.path[0]` and `scripts/crew/` last). Tests drive the decision via the existing seams — patch `_loom.use_loom` / `phase_manager._loom_confirms_hard_gate` and stub `save_project_state` — so **no test spawns a real loom or touches the network**. The loom CLI surface this increment relies on is already shelled by `scripts/_loom.py`; the decision is computed in-process from the compiled flow-def (`flow_compiler.compile_flow`), which mirrors loom's own `_is_hard` rule (`hitl.startswith("hard:")`) — the same rule loom's `flow.py` uses to park.
|
|
10
|
+
|
|
11
|
+
**Decisions locked for this plan (override in review):**
|
|
12
|
+
- **Scope = the hard-gate PARK DECISION only.** Loom becomes authoritative for the boolean "must `approve_phase` require human confirmation here?" — nothing else. `ProjectState` storage, one-phase advancement, `start_phase`/`complete_phase`/`skip_phase`/`is_complete`, the `next_phase` resolution from `phase_plan`, and every bus emit are **unchanged**.
|
|
13
|
+
- **Fail-soft + fail-closed, both.** When loom is available and answers, loom wins. When loom is unavailable/uncertain (`_loom_confirms_hard_gate` returns `None`), the in-process `_HARD_GATE_PHASES` map answers — the exact current behavior (fail-soft, rollback-safe). Crucially, **the guard never weakens**: a phase that is hard under *either* source still requires confirmation. The authoritative source can only ADD a park (loom says hard, in-process says not) — it can never SILENTLY SKIP a park that the in-process map demands. This is the fail-closed invariant for this surface: we never regress the `ValueError`.
|
|
14
|
+
- **`_HARD_GATE_PHASES` is NOT deleted.** It stays as the fallback (loom unavailable) AND as the floor (loom must not be able to remove a park the map asserts). Deleting it is the separate **flow contract phase** (out of scope; see below).
|
|
15
|
+
- **The parity-mismatch signal is retained.** The existing `wicked.loom.parity_mismatch` stderr + bus emit stays; on the authoritative path it now means "loom and the in-process floor disagree" — still surfaced for operator visibility, but the *resolved* decision (the OR of both) drives the guard.
|
|
16
|
+
- **One feature flag, reused: `WICKED_LOOM_CUTOVER`** ∈ `{auto, on, off}`, default `auto` (the existing `_loom.use_loom()` gate). `off` / `auto`-unresolvable → loom is not consulted → the in-process map is authoritative (today's behavior). Rollback is `WICKED_LOOM_CUTOVER=off` — a single env var, no code revert.
|
|
17
|
+
- **Target repo:** garden = `~/Projects/wicked-garden` (this plan edits it). loom = `~/Projects/wicked-loom` (consumed via `scripts/_loom.py`; NOT edited here; the conduct/0.2.0 `flow` surface is its deliverable).
|
|
18
|
+
|
|
19
|
+
**Source material read before Task 1 (grounding):**
|
|
20
|
+
- `scripts/crew/phase_manager.py` — `approve_phase` (335–470), the loom parity mirror (359–377), `_is_hard_gate` (327–332), `_HARD_GATE_PHASES` (315–324), `_loom_confirms_hard_gate` (72–88), the `ValueError` hard-gate guard (380–399), and the `ProjectState` model (133–215). Garden advances ONE phase at a time via `approve_phase` → `next_phase`.
|
|
21
|
+
- `scripts/crew/flow_compiler.py` — `compile_flow` (66–105): the §3.1 archetype→flow-def compiler (already built; imports `_HARD_GATE_PHASES` so the two engines agree by construction).
|
|
22
|
+
- `scripts/_loom.py` — `use_loom()` (160–176), `run_json()` (122–151), the `WICKED_LOOM_CUTOVER` flag (154–157).
|
|
23
|
+
- `~/Projects/wicked-loom/python/loom/flow.py` — `_advance` (52–103): loom runs the WHOLE flow-def, parks at the first `hard:*` phase. `_is_hard` (36–38) is `hitl.startswith("hard:")` — the exact rule `flow_compiler` reproduces.
|
|
24
|
+
- `~/Projects/wicked-loom/python/loom/flowstate.py` — loom's own per-flow JSON state (one file per `flow_id`): a DIFFERENT state model from garden's `ProjectState`.
|
|
25
|
+
- `docs/plans/2026-06-08-wicked-loom-cutover.md` Task 3 + `2026-06-08-wicked-loom-contract.md` — the established flag-gated + parity-contract-test + fail-soft shim pattern this plan extends; the contract phase that explicitly LEFT the flow mirror intact.
|
|
26
|
+
- `tests/crew/test_loom_flow_contract.py` — the existing flow parity contract (3 tests). This plan adds to it; it does not break it.
|
|
27
|
+
|
|
28
|
+
**Out of scope (DEFERRED — do NOT do in this plan):**
|
|
29
|
+
- The **flow CONTRACT phase** — deleting the in-process flow logic. `_HARD_GATE_PHASES` and `_is_hard_gate` STAY (as fallback + floor). This increment leaves the in-process decision path in place behind the authoritative-source switch, so rollback is `WICKED_LOOM_CUTOVER=off`. Deleting them is a later plan, run only after this is proven in production.
|
|
30
|
+
- **Full `ProjectState` → loom `flowstate` migration.** Garden keeps its DomainStore `ProjectState` and its one-phase-at-a-time advancement model. Loom's whole-flow `flow run`/`flowstate` model is NOT adopted as garden's storage. That state-model reconciliation is a much larger, much riskier increment — explicitly deferred (see "The hard design problem", Decision below).
|
|
31
|
+
- **Loom autonomously driving phase advancement** (`loom flow run` executing the whole flow-def, doing gate re-derivation itself, advancing phases without the agent in the loop). This would remove the agent from the per-phase loop and is the OPPOSITE of garden's agent-driven model. Not in scope; arguably never (see Honest Assessment).
|
|
32
|
+
- **Wiring the produces-gate verdict (`loom gate`) into `approve_phase`.** The gate surface is already loom-authoritative via `vault_gate.cross_check` (contract phase done). `approve_phase` does not call the gate today and this increment does not add that call — that is a separate "gate-on-approve" feature, not a flow-surface cutover.
|
|
33
|
+
- The broader **§6 inventory** the cutover/contract did not touch (`_integration_resolver`/`_capability_resolver`/`_capability_registry`, `bootstrap` compose split, `_bus` consumer/projector, `_event_*` trio). All future increments. LEAVE ALONE.
|
|
34
|
+
|
|
35
|
+
**Bulletproof standards:** R1–R6 (no dead code — the fallback map is live, not dead; no swallowed errors — loom errors surface as `None` → fall back to the floor, never a silent skip of a park) and T1–T6 (determinism, no sleep-based sync, isolation, single-assertion focus, descriptive names, provenance). The fail-closed invariant gets the strongest coverage: a test proving loom-says-not-hard can NEVER remove a park the in-process map demands.
|
|
36
|
+
|
|
37
|
+
---
|
|
38
|
+
|
|
39
|
+
## Honest assessment: full flow cutover vs. scoped-down (READ THIS FIRST)
|
|
40
|
+
|
|
41
|
+
**A full flow cutover — loom authoritative for phase advancement — is NOT advisable as one increment. Recommend the scoped-down increment in this plan.** Reasons, plainly:
|
|
42
|
+
|
|
43
|
+
1. **The two surfaces have incompatible execution models, not just incompatible storage.** Garden's `approve_phase` advances ONE phase per call: the agent does the phase's work, calls `approve`, gets the `next_phase`, does the next phase's work, calls `approve` again. The agent is in the loop at every step. Loom's `flow run` executes the WHOLE flow-def in a single `while` loop (`flow.py:_advance`), re-deriving gates itself and parking only at the first `hard:*` phase. Adopting loom's model means the agent is NOT in the per-phase loop — loom advances autonomously between hard gates. That is a fundamental behavioral change to how garden does work, not a storage swap.
|
|
44
|
+
|
|
45
|
+
2. **The cutover plan made the flow surface read-only ON PURPOSE.** The cutover (Task 3) and the contract phase both explicitly chose a read-only parity mirror for flow and explicitly LEFT it that way ("There is no in-process re-derivation body to delete here... LEAVE the mirror"). That signal is deliberate: flow is the riskiest surface — it is the crew state machine, the thing that gates a human in the loop on `migrate.cutover` / `incident.mitigate`. A storage/execution-model migration here, done in one shot with the gate guard live, is exactly the kind of big-bang the strangler pattern exists to avoid.
|
|
46
|
+
|
|
47
|
+
3. **Two state stores would have to be reconciled.** ProjectState (`current_phase` as a phase *name*, `phases` dict keyed by name, `phase_plan` list, `extras.approvals`) vs. loom flowstate (`current_phase` as an *index*, `gate_verdicts` keyed by name, `parked`/`parked_reason`, one JSON file per `flow_id`). A full cutover must either (a) mirror loom's flowstate INTO ProjectState on every call — doubling the write path and the failure surface — or (b) move ProjectState onto loom's flowstate, breaking every existing reader (`status`, the delivery/smaht commands, the migration script). Neither is a safe single step.
|
|
48
|
+
|
|
49
|
+
4. **The valuable, low-risk decision is already isolated.** The parity mirror already computes loom's verdict for exactly ONE decision: is this phase a hard gate? Promoting that single boolean from "logged-only" to "authoritative (with the in-process map as fallback + floor)" is a 1-decision change with a trivial rollback (`WICKED_LOOM_CUTOVER=off`) and a strong, testable invariant (the park can only be ADDED, never removed). It delivers the real value of "loom decides where the human stops" without touching the state machine.
|
|
50
|
+
|
|
51
|
+
**State-model mapping decision (the hard design problem, answered):** **Keep `ProjectState` authoritative; delegate only the gate/park DECISION to loom; do NOT mirror loom's flowstate into ProjectState, and do NOT run `loom flow run` at all in this increment.** Garden does NOT shell `loom flow run` here — it computes the park decision in-process from `flow_compiler.compile_flow(archetype)` (the §3.1 seam), which reproduces loom's `_is_hard` park rule (`hitl.startswith("hard:")`) by construction. This means: (a) no second state store is created or reconciled; (b) the decision is the SAME decision loom's `flow run` would make at that phase, so when a later increment does adopt `loom flow`, the park behavior is already proven identical; (c) zero new failure modes — the only new dependency is the compiled flow-def, which already exists and is already contract-tested against `_HARD_GATE_PHASES`. The full `loom flow run` execution and any flowstate mirroring are explicitly the NEXT increment, gated on this one being proven.
|
|
52
|
+
|
|
53
|
+
---
|
|
54
|
+
|
|
55
|
+
## File Structure
|
|
56
|
+
|
|
57
|
+
```
|
|
58
|
+
wicked-garden/
|
|
59
|
+
├── scripts/
|
|
60
|
+
│ └── crew/
|
|
61
|
+
│ └── phase_manager.py # MODIFY — _is_hard_gate gains a loom-authoritative
|
|
62
|
+
│ # source (resolve_hard_gate): loom verdict wins when
|
|
63
|
+
│ # present, in-process map is fallback + floor. The
|
|
64
|
+
│ # ValueError guard, ProjectState, advancement: UNCHANGED.
|
|
65
|
+
└── tests/
|
|
66
|
+
└── crew/
|
|
67
|
+
└── test_loom_flow_contract.py # MODIFY (append) — authoritative-decision tests:
|
|
68
|
+
# loom-says-hard parks; loom-unavailable falls back to
|
|
69
|
+
# the map; loom-says-not-hard can NEVER remove a
|
|
70
|
+
# map-asserted park (the fail-closed floor); the
|
|
71
|
+
# ValueError + confirmation contract is preserved.
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
**Responsibilities (one per file, justifying the layout):**
|
|
75
|
+
- `scripts/crew/phase_manager.py` (modified) = keeps its DomainStore `ProjectState` authority and one-phase advancement. The only change is the *source* of the hard-gate boolean: a new `resolve_hard_gate(state, phase)` helper combines loom's verdict (authoritative when present) with the in-process map (fallback + floor), and `approve_phase`'s guard calls it instead of `_is_hard_gate` directly. `_is_hard_gate` and `_HARD_GATE_PHASES` remain — they are the fallback and the floor, not dead code.
|
|
76
|
+
- `tests/crew/test_loom_flow_contract.py` (modified) = extends the existing flow parity contract with the authoritative-decision behavior. The existing 3 tests (compiled-flow gate-phase parity, non-hard archetypes have no hard phase, `off` preserves the in-process `ValueError`) STAY GREEN — they still hold under the authoritative source.
|
|
77
|
+
|
|
78
|
+
Why no new file: this increment is one decision-source switch inside one function plus its helper. Adding a module would violate YAGNI. The compiler (`flow_compiler.py`) is already the loom-side decision derivation; `phase_manager` already imports the loom seam (`_loom`, `_loom_confirms_hard_gate`). The change lives where the decision is consumed.
|
|
79
|
+
|
|
80
|
+
**The decision-resolution rule this plan implements** (the heart of the increment):
|
|
81
|
+
|
|
82
|
+
```
|
|
83
|
+
resolve_hard_gate(state, phase):
|
|
84
|
+
in_process = _is_hard_gate(state, phase) # the floor (and fallback)
|
|
85
|
+
loom = _loom_confirms_hard_gate(archetype, phase) # None when loom unavailable/uncertain
|
|
86
|
+
if loom is None:
|
|
87
|
+
return in_process # fail-soft: map is authoritative
|
|
88
|
+
if loom != in_process:
|
|
89
|
+
<emit wicked.loom.parity_mismatch> # divergence signal (retained)
|
|
90
|
+
return loom or in_process # loom authoritative, but can only ADD
|
|
91
|
+
# a park, never remove the floor's park
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
`loom or in_process` is the fail-closed floor: the park is required if EITHER source says hard. Loom-authoritative means loom can turn a non-park into a park; it can never turn the in-process map's park into a non-park. That is the invariant the strongest test pins.
|
|
95
|
+
|
|
96
|
+
---
|
|
97
|
+
|
|
98
|
+
## Task 1: Promote the flow surface to loom-authoritative for the hard-gate park decision
|
|
99
|
+
|
|
100
|
+
**Files:**
|
|
101
|
+
- Modify: `~/Projects/wicked-garden/scripts/crew/phase_manager.py` (add `resolve_hard_gate`; rewire `approve_phase`'s mirror + guard. `_is_hard_gate`, `_HARD_GATE_PHASES`, `ProjectState`, advancement: unchanged.)
|
|
102
|
+
- Modify: `~/Projects/wicked-garden/tests/crew/test_loom_flow_contract.py` (append the authoritative-decision tests)
|
|
103
|
+
|
|
104
|
+
The current `approve_phase` runs a **read-only** parity mirror (lines 359–377): it computes `loom_says` and `in_proc_says`, logs a mismatch, but the guard at line 380 calls `_is_hard_gate(state, phase)` — purely the in-process map. This task makes loom authoritative by routing the guard through a new `resolve_hard_gate` that returns `loom or in_process` when loom answers (fail-closed floor), and `in_process` when loom is unavailable (fail-soft fallback). The mismatch signal is folded into `resolve_hard_gate`.
|
|
105
|
+
|
|
106
|
+
- [ ] **Step 1: Write the failing tests (append to `tests/crew/test_loom_flow_contract.py`)**
|
|
107
|
+
|
|
108
|
+
Append the following class to the existing file (keep the 3 existing tests + imports + `_EXPECTED_GATE_PHASES` intact). These tests patch `phase_manager._loom_confirms_hard_gate` (the loom-verdict seam) and stub `save_project_state` so they are hermetic — no real loom, no disk.
|
|
109
|
+
|
|
110
|
+
```python
|
|
111
|
+
class FlowAuthoritativeParkDecision(unittest.TestCase):
|
|
112
|
+
"""Flow surface cutover: loom is AUTHORITATIVE for the hard-gate park
|
|
113
|
+
decision. loom-says-hard adds a park; loom-unavailable falls back to the
|
|
114
|
+
in-process map; loom-says-not-hard can NEVER remove a map-asserted park
|
|
115
|
+
(the fail-closed floor). The ValueError + confirmation contract is preserved.
|
|
116
|
+
"""
|
|
117
|
+
|
|
118
|
+
def setUp(self):
|
|
119
|
+
os.environ["WICKED_LOOM_CUTOVER"] = "on"
|
|
120
|
+
|
|
121
|
+
def tearDown(self):
|
|
122
|
+
os.environ.pop("WICKED_LOOM_CUTOVER", None)
|
|
123
|
+
|
|
124
|
+
def _migrate_state(self, phase="cutover"):
|
|
125
|
+
return pm.ProjectState(
|
|
126
|
+
name="m1", current_phase=phase,
|
|
127
|
+
created_at=pm.get_utc_timestamp(),
|
|
128
|
+
phase_plan=["plan", "expand", "backfill", "cutover", "contract"],
|
|
129
|
+
extras={"v11_archetype": "migrate"})
|
|
130
|
+
|
|
131
|
+
def _build_state(self, phase="plan"):
|
|
132
|
+
return pm.ProjectState(
|
|
133
|
+
name="b1", current_phase=phase,
|
|
134
|
+
created_at=pm.get_utc_timestamp(),
|
|
135
|
+
phase_plan=["plan", "implement", "test", "review"],
|
|
136
|
+
extras={"v11_archetype": "build"})
|
|
137
|
+
|
|
138
|
+
def test_loom_authoritative_hard_gate_requires_confirmation(self):
|
|
139
|
+
# loom says cutover is hard; in-process map ALSO says hard. Guard fires.
|
|
140
|
+
st = self._migrate_state("cutover")
|
|
141
|
+
with patch.object(pm, "_loom_confirms_hard_gate", return_value=True), \
|
|
142
|
+
patch.object(pm, "save_project_state", lambda s: None):
|
|
143
|
+
with self.assertRaises(ValueError):
|
|
144
|
+
pm.approve_phase(st, "cutover")
|
|
145
|
+
|
|
146
|
+
def test_loom_adds_a_park_the_in_process_map_does_not_assert(self):
|
|
147
|
+
# loom says build.review is hard (it is not in _HARD_GATE_PHASES). loom is
|
|
148
|
+
# authoritative -> the guard fires even though the in-process map is silent.
|
|
149
|
+
st = self._build_state("review")
|
|
150
|
+
self.assertFalse(pm._is_hard_gate(st, "review")) # floor: not hard
|
|
151
|
+
with patch.object(pm, "_loom_confirms_hard_gate", return_value=True), \
|
|
152
|
+
patch.object(pm, "save_project_state", lambda s: None):
|
|
153
|
+
with self.assertRaises(ValueError):
|
|
154
|
+
pm.approve_phase(st, "review")
|
|
155
|
+
|
|
156
|
+
def test_loom_says_not_hard_CANNOT_remove_a_map_asserted_park(self):
|
|
157
|
+
# THE FAIL-CLOSED FLOOR: loom says cutover is NOT hard, but the in-process
|
|
158
|
+
# map asserts it IS. The park MUST still fire — loom can add, never remove.
|
|
159
|
+
st = self._migrate_state("cutover")
|
|
160
|
+
self.assertTrue(pm._is_hard_gate(st, "cutover")) # floor: hard
|
|
161
|
+
with patch.object(pm, "_loom_confirms_hard_gate", return_value=False), \
|
|
162
|
+
patch.object(pm, "save_project_state", lambda s: None):
|
|
163
|
+
with self.assertRaises(ValueError):
|
|
164
|
+
pm.approve_phase(st, "cutover")
|
|
165
|
+
|
|
166
|
+
def test_loom_unavailable_falls_back_to_in_process_map(self):
|
|
167
|
+
# loom returns None (unavailable/uncertain) -> the in-process map is
|
|
168
|
+
# authoritative (fail-soft). cutover is hard in the map -> guard fires.
|
|
169
|
+
st = self._migrate_state("cutover")
|
|
170
|
+
with patch.object(pm, "_loom_confirms_hard_gate", return_value=None), \
|
|
171
|
+
patch.object(pm, "save_project_state", lambda s: None):
|
|
172
|
+
with self.assertRaises(ValueError):
|
|
173
|
+
pm.approve_phase(st, "cutover")
|
|
174
|
+
|
|
175
|
+
def test_non_hard_phase_advances_when_both_sources_agree_not_hard(self):
|
|
176
|
+
# build.plan is not hard in either source -> no guard, normal advance.
|
|
177
|
+
st = self._build_state("plan")
|
|
178
|
+
with patch.object(pm, "_loom_confirms_hard_gate", return_value=False), \
|
|
179
|
+
patch.object(pm, "save_project_state", lambda s: None):
|
|
180
|
+
_, next_phase = pm.approve_phase(st, "plan")
|
|
181
|
+
self.assertEqual(next_phase, "implement")
|
|
182
|
+
|
|
183
|
+
def test_hard_gate_with_confirmation_advances(self):
|
|
184
|
+
# The confirmation contract is preserved: confirmed_by + evidence -> advance.
|
|
185
|
+
st = self._migrate_state("cutover")
|
|
186
|
+
with patch.object(pm, "_loom_confirms_hard_gate", return_value=True), \
|
|
187
|
+
patch.object(pm, "save_project_state", lambda s: None):
|
|
188
|
+
state, next_phase = pm.approve_phase(
|
|
189
|
+
st, "cutover", confirmed_by="oncall-jane",
|
|
190
|
+
confirmation_evidence="https://dash/rollback-drill-42")
|
|
191
|
+
self.assertEqual(next_phase, "contract")
|
|
192
|
+
self.assertEqual(state.phases["cutover"].status, "approved")
|
|
193
|
+
|
|
194
|
+
def test_resolve_hard_gate_returns_floor_when_loom_none(self):
|
|
195
|
+
st = self._migrate_state("cutover")
|
|
196
|
+
with patch.object(pm, "_loom_confirms_hard_gate", return_value=None):
|
|
197
|
+
self.assertTrue(pm.resolve_hard_gate(st, "cutover"))
|
|
198
|
+
self.assertFalse(pm.resolve_hard_gate(st, "plan"))
|
|
199
|
+
|
|
200
|
+
def test_resolve_hard_gate_is_or_of_both_sources(self):
|
|
201
|
+
st = self._build_state("review") # not hard in the map
|
|
202
|
+
with patch.object(pm, "_loom_confirms_hard_gate", return_value=True):
|
|
203
|
+
self.assertTrue(pm.resolve_hard_gate(st, "review")) # loom adds it
|
|
204
|
+
with patch.object(pm, "_loom_confirms_hard_gate", return_value=False):
|
|
205
|
+
self.assertFalse(pm.resolve_hard_gate(st, "review")) # neither
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
- [ ] **Step 2: Run the tests to verify they fail**
|
|
209
|
+
|
|
210
|
+
Run: `cd ~/Projects/wicked-garden && python3 -m pytest tests/crew/test_loom_flow_contract.py::FlowAuthoritativeParkDecision -v`
|
|
211
|
+
Expected: FAIL — `test_loom_adds_a_park_the_in_process_map_does_not_assert` raises no `ValueError` (the current guard reads only the in-process map, which is silent on `build.review`), and `test_resolve_hard_gate_*` error with `AttributeError: module 'phase_manager' has no attribute 'resolve_hard_gate'`. The floor/fallback tests may already pass against the current guard.
|
|
212
|
+
|
|
213
|
+
- [ ] **Step 3: Edit `phase_manager.py` — add `resolve_hard_gate`**
|
|
214
|
+
|
|
215
|
+
Insert this function immediately after `_is_hard_gate` (after line 332, before `approve_phase`). It folds the mismatch signal in and implements the fail-closed-floor rule:
|
|
216
|
+
|
|
217
|
+
```python
|
|
218
|
+
def resolve_hard_gate(state: ProjectState, phase: str) -> bool:
|
|
219
|
+
"""Authoritative hard-gate decision for ``(archetype, phase)`` (flow cutover).
|
|
220
|
+
|
|
221
|
+
The flow surface is now loom-AUTHORITATIVE for *where the human stops*:
|
|
222
|
+
loom's verdict (derived from the compiled flow-def, which reproduces loom's
|
|
223
|
+
own ``hitl.startswith("hard:")`` park rule) decides whether this phase is a
|
|
224
|
+
hard gate — WHEN loom is available. The in-process ``_HARD_GATE_PHASES`` map
|
|
225
|
+
is two things at once:
|
|
226
|
+
|
|
227
|
+
- the FALLBACK: when loom is unavailable/uncertain
|
|
228
|
+
(``_loom_confirms_hard_gate`` returns None — off, auto-unresolvable, or
|
|
229
|
+
a compile error), the map answers (fail-soft, rollback-safe).
|
|
230
|
+
- the FLOOR: even when loom answers, the resolved decision is
|
|
231
|
+
``loom or in_process`` — loom may ADD a park the map omits, but can
|
|
232
|
+
NEVER remove a park the map asserts. This is the fail-closed posture of
|
|
233
|
+
the flow surface: we never silently skip a human-in-the-loop stop that
|
|
234
|
+
the in-process doctrine demands. A loom that (wrongly) says "not hard"
|
|
235
|
+
for migrate.cutover cannot disarm the cutover gate.
|
|
236
|
+
|
|
237
|
+
A divergence (loom != in_process, with loom present) is surfaced as a
|
|
238
|
+
``wicked.loom.parity_mismatch`` signal — retained from the parity mirror —
|
|
239
|
+
so operators see drift even though the resolved decision is the safe OR.
|
|
240
|
+
"""
|
|
241
|
+
in_process = _is_hard_gate(state, phase)
|
|
242
|
+
archetype = (state.extras or {}).get("v11_archetype")
|
|
243
|
+
if not archetype:
|
|
244
|
+
return in_process
|
|
245
|
+
|
|
246
|
+
loom_says = _loom_confirms_hard_gate(archetype, phase)
|
|
247
|
+
if loom_says is None:
|
|
248
|
+
return in_process # fail-soft: in-process map is authoritative
|
|
249
|
+
|
|
250
|
+
if loom_says != in_process:
|
|
251
|
+
print(f"[wicked-garden] loom/in-process hard-gate parity mismatch: "
|
|
252
|
+
f"archetype={archetype} phase={phase} "
|
|
253
|
+
f"loom={loom_says} in_process={in_process}", file=sys.stderr)
|
|
254
|
+
_bus_emit_safe(
|
|
255
|
+
"wicked.loom.parity_mismatch",
|
|
256
|
+
{"project_id": state.name, "archetype": archetype,
|
|
257
|
+
"phase": phase, "loom": loom_says, "in_process": in_process,
|
|
258
|
+
"resolved": loom_says or in_process},
|
|
259
|
+
chain_id=f"{state.name}.{archetype}.{phase}.parity",
|
|
260
|
+
)
|
|
261
|
+
# loom authoritative, but fail-closed floor: a park is required if EITHER
|
|
262
|
+
# source says hard. loom can add a park; it can never remove the map's.
|
|
263
|
+
return loom_says or in_process
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
- [ ] **Step 4: Edit `approve_phase` — replace the read-only mirror block with the authoritative call**
|
|
267
|
+
|
|
268
|
+
In `approve_phase`, DELETE the read-only parity-mirror block (lines 359–377, from `# --- loom cutover mirror (flow surface) ----` through the closing `# ----`), because its mismatch-signal responsibility now lives inside `resolve_hard_gate`. Then change the guard at line 380 from `_is_hard_gate(state, phase)` to `resolve_hard_gate(state, phase)`.
|
|
269
|
+
|
|
270
|
+
Replace this (the read-only mirror, lines 359–377):
|
|
271
|
+
|
|
272
|
+
```python
|
|
273
|
+
# --- loom cutover mirror (flow surface) ----------------------------------
|
|
274
|
+
# Cross-check loom's park decision against the in-process map. A DISAGREEMENT
|
|
275
|
+
# is surfaced (stderr + bus emit) but does NOT change behavior — the
|
|
276
|
+
# in-process guard below stays authoritative during cutover (rollback-safe).
|
|
277
|
+
archetype_for_parity = (state.extras or {}).get("v11_archetype")
|
|
278
|
+
if archetype_for_parity:
|
|
279
|
+
loom_says = _loom_confirms_hard_gate(archetype_for_parity, phase)
|
|
280
|
+
in_proc_says = _is_hard_gate(state, phase)
|
|
281
|
+
if loom_says is not None and loom_says != in_proc_says:
|
|
282
|
+
print(f"[wicked-garden] loom/in-process hard-gate parity mismatch: "
|
|
283
|
+
f"archetype={archetype_for_parity} phase={phase} "
|
|
284
|
+
f"loom={loom_says} in_process={in_proc_says}", file=sys.stderr)
|
|
285
|
+
_bus_emit_safe(
|
|
286
|
+
"wicked.loom.parity_mismatch",
|
|
287
|
+
{"project_id": state.name, "archetype": archetype_for_parity,
|
|
288
|
+
"phase": phase, "loom": loom_says, "in_process": in_proc_says},
|
|
289
|
+
chain_id=f"{state.name}.{archetype_for_parity}.{phase}.parity",
|
|
290
|
+
)
|
|
291
|
+
# -------------------------------------------------------------------------
|
|
292
|
+
|
|
293
|
+
# Hard-gate guard: enforce explicit confirmation at runtime.
|
|
294
|
+
if _is_hard_gate(state, phase):
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
with this (the authoritative path — mirror responsibility moved into the helper):
|
|
298
|
+
|
|
299
|
+
```python
|
|
300
|
+
# --- loom cutover (flow surface): loom-AUTHORITATIVE park decision -------
|
|
301
|
+
# resolve_hard_gate consults loom first (authoritative when available) and
|
|
302
|
+
# falls back to the in-process map, with that map as the fail-closed floor
|
|
303
|
+
# (loom can ADD a park, never remove one). It also emits the retained
|
|
304
|
+
# wicked.loom.parity_mismatch signal on divergence. The ValueError guard,
|
|
305
|
+
# confirmation requirement, ProjectState, and advancement are UNCHANGED.
|
|
306
|
+
# -------------------------------------------------------------------------
|
|
307
|
+
|
|
308
|
+
# Hard-gate guard: enforce explicit confirmation at runtime.
|
|
309
|
+
if resolve_hard_gate(state, phase):
|
|
310
|
+
```
|
|
311
|
+
|
|
312
|
+
> Implementer note: this is the ONLY behavioral change. The `confirmed_by`/`confirmation_evidence` requirement (lines 381–399), the `approval_record`, the `next_phase` resolution from `phase_plan`, `save_project_state`, and every bus emit (`hard_gate_passed`, `advanced`, `completed`) stay exactly as they are. `_is_hard_gate` is still called — inside `resolve_hard_gate` — so it is not dead (R1). `_HARD_GATE_PHASES` is still the source for `_is_hard_gate` and for `flow_compiler` (the single source of truth the compiled flow-def is derived from), so it is not dead either. Do NOT touch `start_phase`/`complete_phase`/`skip_phase`/`is_complete` or the CLI.
|
|
313
|
+
|
|
314
|
+
- [ ] **Step 5: Run the tests to verify they pass (new + existing)**
|
|
315
|
+
|
|
316
|
+
Run: `cd ~/Projects/wicked-garden && python3 -m pytest tests/crew/test_loom_flow_contract.py -v`
|
|
317
|
+
Expected: PASS — the 8 new `FlowAuthoritativeParkDecision` tests AND the 3 existing tests (`test_compiled_flow_gate_phase_matches_in_process_map`, `test_non_hard_archetypes_compile_no_hard_phase`, `test_approve_phase_in_process_authority_unchanged_when_loom_off`). The `off` test still passes because `_loom_confirms_hard_gate` returns `None` under `off` (`_loom.use_loom()` is False), so `resolve_hard_gate` falls back to the in-process map — identical to today.
|
|
318
|
+
|
|
319
|
+
- [ ] **Step 6: Commit**
|
|
320
|
+
|
|
321
|
+
```bash
|
|
322
|
+
cd ~/Projects/wicked-garden
|
|
323
|
+
git add scripts/crew/phase_manager.py tests/crew/test_loom_flow_contract.py
|
|
324
|
+
git commit -m "feat(loom-flow-cutover): loom-authoritative hard-gate park decision (in-process map is fallback + fail-closed floor)"
|
|
325
|
+
```
|
|
326
|
+
|
|
327
|
+
---
|
|
328
|
+
|
|
329
|
+
## Task 2: Full-suite green + rollback proof + handoff note
|
|
330
|
+
|
|
331
|
+
**Files:** none (verification only).
|
|
332
|
+
|
|
333
|
+
- [ ] **Step 1: Run the full garden suite**
|
|
334
|
+
|
|
335
|
+
Run: `cd ~/Projects/wicked-garden && python3 -m pytest tests/ -q`
|
|
336
|
+
Expected: PASS — no regressions. The cutover defaults to `auto`; in CI loom is unresolvable, so `_loom_confirms_hard_gate` returns `None` and `resolve_hard_gate` falls back to the in-process map — every existing test exercises the unchanged behavior. New count: the baseline was **506** collected; this plan adds **8** tests to `test_loom_flow_contract.py` → **514** collected. Report the exact `passed` total.
|
|
337
|
+
|
|
338
|
+
- [ ] **Step 2: Prove the fail-closed floor holds (the load-bearing invariant)**
|
|
339
|
+
|
|
340
|
+
Run: `cd ~/Projects/wicked-garden && python3 -m pytest tests/crew/test_loom_flow_contract.py -k "CANNOT_remove or unavailable_falls_back or in_process_authority_unchanged" -v`
|
|
341
|
+
Expected: PASS — loom-says-not-hard cannot remove a map-asserted park; loom-unavailable falls back to the map; `off` preserves the in-process `ValueError`. The `migrate.cutover` / `incident.mitigate` human-in-the-loop guarantee never regresses.
|
|
342
|
+
|
|
343
|
+
- [ ] **Step 3: Prove rollback works**
|
|
344
|
+
|
|
345
|
+
Run: `cd ~/Projects/wicked-garden && WICKED_LOOM_CUTOVER=off python3 -m pytest tests/crew/test_loom_flow_contract.py -q`
|
|
346
|
+
Expected: PASS — with the flag off, `_loom_confirms_hard_gate` returns `None`, `resolve_hard_gate` is purely the in-process map, and the flow surface behaves exactly as before the cutover. The increment is fully reversible by a single env var (no code revert).
|
|
347
|
+
|
|
348
|
+
- [ ] **Step 4: Confirm no dead code, no signature drift**
|
|
349
|
+
|
|
350
|
+
Run: `cd ~/Projects/wicked-garden && grep -n "_is_hard_gate\|_HARD_GATE_PHASES\|resolve_hard_gate" scripts/crew/phase_manager.py scripts/crew/flow_compiler.py`
|
|
351
|
+
Expected: `_is_hard_gate` is called inside `resolve_hard_gate` (live); `_HARD_GATE_PHASES` is read by `_is_hard_gate` and imported by `flow_compiler` (live); `resolve_hard_gate` is called by `approve_phase` (live). No orphan.
|
|
352
|
+
|
|
353
|
+
- [ ] **Step 5: Report (no autonomous push)**
|
|
354
|
+
|
|
355
|
+
Report to the operator: the flow surface is now loom-AUTHORITATIVE for the hard-gate park decision, behind the `WICKED_LOOM_CUTOVER` flag, with the in-process `_HARD_GATE_PHASES` map as the fail-soft fallback AND the fail-closed floor (loom can add a park, never remove one). `ProjectState`, one-phase advancement, and the `ValueError`/confirmation contract are unchanged. Rollback = `WICKED_LOOM_CUTOVER=off`. The flow CONTRACT phase (deleting the in-process map) and the full `ProjectState`→loom-`flowstate` migration are DEFERRED — run them only after this is proven in production. Do NOT run `npm publish`, `/wg-release`, or delete `_HARD_GATE_PHASES` / `_is_hard_gate` in this plan.
|
|
356
|
+
|
|
357
|
+
---
|
|
358
|
+
|
|
359
|
+
## Self-Review
|
|
360
|
+
|
|
361
|
+
**1. Spec coverage** — checked against the prompt's deliverables:
|
|
362
|
+
|
|
363
|
+
| Requirement | Where realized | Status |
|
|
364
|
+
|---|---|---|
|
|
365
|
+
| Honest assessment: full vs scoped-down, recommend smallest valuable low-risk increment | "Honest assessment" section — full cutover NOT advisable; recommend the park-decision-only increment | ✓ |
|
|
366
|
+
| State-model mapping decision (ProjectState authoritative? mirror loom's flowstate? delegate only the decision?) | "State-model mapping decision" — ProjectState stays authoritative; delegate ONLY the park decision; do NOT mirror flowstate; do NOT run `loom flow run`; compute the decision in-process from `flow_compiler` | ✓ |
|
|
367
|
+
| Flag-gated | `WICKED_LOOM_CUTOVER` reused via `_loom.use_loom()` inside `_loom_confirms_hard_gate`; `off` → fallback to in-process | ✓ |
|
|
368
|
+
| Parity-contract-test | Existing 3 tests retained + 8 added; `test_compiled_flow_gate_phase_matches_in_process_map` is the parity contract | ✓ |
|
|
369
|
+
| Fail-soft (in-process stays as fallback) | `resolve_hard_gate` returns `in_process` when `_loom_confirms_hard_gate` is `None` | ✓ |
|
|
370
|
+
| In-process NOT deleted (separate contract phase) | `_HARD_GATE_PHASES` + `_is_hard_gate` retained as fallback + floor; deletion explicitly out of scope | ✓ |
|
|
371
|
+
| Preserve hard-gate guarantee (ValueError on unapproved hard gate must not regress) | Guard unchanged except its boolean source; `test_loom_says_not_hard_CANNOT_remove_a_map_asserted_park` + `test_loom_unavailable_falls_back` + the existing `off` test pin it | ✓ |
|
|
372
|
+
| Fail-closed posture | `loom or in_process` floor — a park is required if EITHER says hard; loom can only ADD | ✓ |
|
|
373
|
+
| Out of scope stated: contract phase, full ProjectState→flowstate migration, broader §6 | "Out of scope" section enumerates all three explicitly | ✓ |
|
|
374
|
+
| Bite-sized TDD with complete code + exact pytest commands + expected output | Task 1 steps 1–6, Task 2 steps 1–5 | ✓ |
|
|
375
|
+
| Self-Review + Execution Handoff | this section + below | ✓ |
|
|
376
|
+
|
|
377
|
+
**2. Placeholder scan** — No `TBD`/`TODO`/"add error handling"/"similar to Task N". Every code step shows complete, runnable code (the full `resolve_hard_gate`, the exact old→new `approve_phase` block, all 8 test methods); every run step shows the exact `python3 -m pytest …` command + expected pass/fail with named tests. ✓
|
|
378
|
+
|
|
379
|
+
**3. Type consistency** —
|
|
380
|
+
- `resolve_hard_gate(state: ProjectState, phase: str) -> bool` — consumed by `approve_phase`'s guard (`if resolve_hard_gate(state, phase):`) and asserted directly in `test_resolve_hard_gate_*`. ✓
|
|
381
|
+
- `_loom_confirms_hard_gate(archetype: str, phase: str) -> Optional[bool]` — already exists (lines 72–88); `resolve_hard_gate` reads `None` (fallback) vs `True`/`False` (authoritative). Patched in tests via `patch.object(pm, "_loom_confirms_hard_gate", ...)`. ✓
|
|
382
|
+
- `_is_hard_gate(state: ProjectState, phase: str) -> bool` — already exists (327–332); called by `resolve_hard_gate` and directly in tests (`pm._is_hard_gate(st, "review")`). ✓
|
|
383
|
+
- `approve_phase(...) -> Tuple[ProjectState, Optional[str]]` — signature and return UNCHANGED; tests read `_, next_phase = pm.approve_phase(...)` and `state.phases[...].status`. ✓
|
|
384
|
+
- `_bus_emit_safe(event_type, payload, *, chain_id)` — reused verbatim inside `resolve_hard_gate` with the same kwargs as the deleted mirror. ✓
|
|
385
|
+
|
|
386
|
+
**One self-review note (no fix needed):** the existing read-only mirror emitted `wicked.loom.parity_mismatch` with payload keys `{project_id, archetype, phase, loom, in_process}`; `resolve_hard_gate` keeps those and ADDS `resolved` (the OR). This is additive — no downstream consumer breaks (the bus is fire-and-forget, schema-tolerant), and it makes the authoritative decision auditable. Retained intentionally.
|
|
387
|
+
|
|
388
|
+
---
|
|
389
|
+
|
|
390
|
+
## Execution Handoff
|
|
391
|
+
|
|
392
|
+
Plan complete and saved to `docs/plans/2026-06-08-wicked-loom-flow-cutover.md`. Two execution options:
|
|
393
|
+
|
|
394
|
+
1. **Subagent-Driven (recommended)** — fresh subagent per task, two-stage review between tasks. REQUIRED SUB-SKILL: `superpowers:subagent-driven-development`. This is a 2-task plan (1 implementation + 1 verification); a single subagent per task is appropriate.
|
|
395
|
+
2. **Inline Execution** — execute in this session with checkpoints. REQUIRED SUB-SKILL: `superpowers:executing-plans`.
|
|
396
|
+
|
|
397
|
+
Notes for the executor:
|
|
398
|
+
- Execution happens in **wicked-garden** (`~/Projects/wicked-garden`), editing `scripts/crew/phase_manager.py` and `tests/crew/test_loom_flow_contract.py` only. The in-process `_HARD_GATE_PHASES` map and `_is_hard_gate` are **left in place** as the fallback + floor — do NOT delete them; that is the flow contract phase.
|
|
399
|
+
- No prerequisite on a published loom: the decision is computed in-process from `flow_compiler.compile_flow` (already built and contract-tested). Garden does NOT shell `loom flow run` in this increment, so `wicked-loom@0.2.0` is not required for the tests (the existing `_loom.use_loom()` gate still governs whether loom's verdict is consulted at all — under `auto` in CI, loom is unresolvable → fallback).
|
|
400
|
+
- Rollback during transition is a single env var: `WICKED_LOOM_CUTOVER=off` returns the flow surface to the pure in-process decision. No code revert needed.
|
|
401
|
+
- The flow CONTRACT phase (deleting `_HARD_GATE_PHASES`/`_is_hard_gate`) and the full `ProjectState`→loom-`flowstate` migration (adopting loom's whole-flow execution model) are the **next** plans — run them only after this park-decision cutover is proven in production.
|
|
402
|
+
|
|
403
|
+
**Which approach?**
|