@ccoalm/ccl-skills 0.1.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/LICENSE +201 -0
- package/README.md +49 -0
- package/dist/assets/marketplace/.agents/plugins/marketplace.json +12 -0
- package/dist/assets/marketplace/.claude-plugin/marketplace.json +13 -0
- package/dist/assets/marketplace/marketplace-manifest.json +12 -0
- package/dist/assets/marketplace/plugins/ccl-skills/.claude-plugin/marketplace.json +16 -0
- package/dist/assets/marketplace/plugins/ccl-skills/.claude-plugin/plugin.json +5 -0
- package/dist/assets/marketplace/plugins/ccl-skills/.codex-plugin/plugin.json +5 -0
- package/dist/assets/marketplace/plugins/ccl-skills/.worktree-only +3 -0
- package/dist/assets/marketplace/plugins/ccl-skills/agent-context/session-start.md +45 -0
- package/dist/assets/marketplace/plugins/ccl-skills/agent-context/subagent-start.md +12 -0
- package/dist/assets/marketplace/plugins/ccl-skills/hooks/AGENTS.md +19 -0
- package/dist/assets/marketplace/plugins/ccl-skills/hooks/guard-delegation-owner.sh +125 -0
- package/dist/assets/marketplace/plugins/ccl-skills/hooks/guard-edit-isolation.sh +102 -0
- package/dist/assets/marketplace/plugins/ccl-skills/hooks/guard-merge-authorization.sh +1156 -0
- package/dist/assets/marketplace/plugins/ccl-skills/hooks/hooks.json +131 -0
- package/dist/assets/marketplace/plugins/ccl-skills/hooks/merge-authorization-prompt.sh +142 -0
- package/dist/assets/marketplace/plugins/ccl-skills/hooks/owner-dispatch-guard.sh +12 -0
- package/dist/assets/marketplace/plugins/ccl-skills/hooks/owner-dispatch-stop.sh +13 -0
- package/dist/assets/marketplace/plugins/ccl-skills/hooks/remind-post-merge-cleanup.sh +144 -0
- package/dist/assets/marketplace/plugins/ccl-skills/hooks/session-context.sh +87 -0
- package/dist/assets/marketplace/plugins/ccl-skills/hooks/session-start.sh +86 -0
- package/dist/assets/marketplace/plugins/ccl-skills/hooks/skill-extraction-gate-stop.sh +69 -0
- package/dist/assets/marketplace/plugins/ccl-skills/hooks/subagent-start.sh +26 -0
- package/dist/assets/marketplace/plugins/ccl-skills/hooks/test_guard_delegation_owner.sh +329 -0
- package/dist/assets/marketplace/plugins/ccl-skills/hooks/test_guard_edit_isolation.sh +322 -0
- package/dist/assets/marketplace/plugins/ccl-skills/hooks/test_guard_merge_authorization.sh +902 -0
- package/dist/assets/marketplace/plugins/ccl-skills/hooks/test_merge_authorization_prompt.sh +178 -0
- package/dist/assets/marketplace/plugins/ccl-skills/hooks/test_remind_post_merge_cleanup.sh +121 -0
- package/dist/assets/marketplace/plugins/ccl-skills/hooks/test_session_start.sh +170 -0
- package/dist/assets/marketplace/plugins/ccl-skills/packages/opencode-plugin/AGENTS.md +17 -0
- package/dist/assets/marketplace/plugins/ccl-skills/packages/opencode-plugin/ccl-skills.ts +564 -0
- package/dist/assets/marketplace/plugins/ccl-skills/packages/opencode-plugin/commands/ccl-install-skills.md +14 -0
- package/dist/assets/marketplace/plugins/ccl-skills/packages/opencode-plugin/commands/ccl-update-skills.md +44 -0
- package/dist/assets/marketplace/plugins/ccl-skills/packages/opencode-plugin/commands/ccl-verify-skills.md +109 -0
- package/dist/assets/marketplace/plugins/ccl-skills/packages/opencode-plugin/commands/ccl-worktree-check.md +36 -0
- package/dist/assets/marketplace/plugins/ccl-skills/scripts/owner-dispatch/AGENTS.md +28 -0
- package/dist/assets/marketplace/plugins/ccl-skills/scripts/owner-dispatch/README.md +276 -0
- package/dist/assets/marketplace/plugins/ccl-skills/scripts/owner-dispatch/owner-dispatch.example.json +10 -0
- package/dist/assets/marketplace/plugins/ccl-skills/scripts/owner-dispatch/owner-dispatch.sh +1307 -0
- package/dist/assets/marketplace/plugins/ccl-skills/scripts/owner-dispatch/test.sh +941 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/agents-file-coverage-gate/SKILL.md +45 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/agents-file-coverage-gate/agents/openai.yaml +4 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/app-cross-platform-dev/SKILL.md +188 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/app-cross-platform-dev/agents/openai.yaml +4 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/app-cross-platform-dev/references/android-dev.md +92 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/app-cross-platform-dev/references/flutter-dev.md +80 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/app-cross-platform-dev/references/ios-dev.md +72 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/app-cross-platform-dev/references/kotlin-multiplatform.md +93 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/app-cross-platform-dev/references/mobile-platform-boundaries.md +77 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/app-cross-platform-dev/references/mobile-quality-release.md +77 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/app-cross-platform-dev/references/source-evidence-map.md +64 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/code-review/SKILL.md +353 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/code-review/agents/openai.yaml +4 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/code-review/references/client-routing.md +419 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/code-review/references/manual-invocation-and-prompts.md +126 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/code-review/references/staged-review-contract.md +197 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/code-review/references/timeout-auth-and-capabilities.md +179 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/code-review/scripts/AGENTS.md +98 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/code-review/scripts/classify_envelope.py +93 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/code-review/scripts/classify_timeout_exit.sh +15 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/code-review/scripts/claude_review.sh +1438 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/code-review/scripts/codex_review.sh +324 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/code-review/scripts/concern_excerpt.py +295 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/code-review/scripts/egress_schema.py +214 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/code-review/scripts/init_policy_matrix.py +642 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/code-review/scripts/kimi_packet_mcp.py +181 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/code-review/scripts/kimi_review.sh +1165 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/code-review/scripts/opencode_review.sh +1190 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/code-review/scripts/parse_cli_review.py +946 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/code-review/scripts/parse_opencode_review.py +474 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/code-review/scripts/parse_probe_result.py +1899 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/code-review/scripts/parse_review_json.py +200 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/code-review/scripts/review_gate.py +2845 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/code-review/scripts/review_gate.sh +6 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/code-review/scripts/run_claude_capture.py +71 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/code-review/scripts/runtime-surface-verification-design.md +53 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/code-review/scripts/test_classify_envelope.sh +68 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/code-review/scripts/test_claude_review_probe.sh +2311 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/code-review/scripts/test_cli_review_wrappers.sh +1832 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/code-review/scripts/test_code_review_identity.sh +73 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/code-review/scripts/test_concern_excerpt.sh +245 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/code-review/scripts/test_egress_schema.sh +177 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/code-review/scripts/test_init_policy_matrix.sh +272 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/code-review/scripts/test_kimi_packet_mcp.py +195 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/code-review/scripts/test_opencode_review_concurrency.sh +120 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/code-review/scripts/test_opencode_review_retry.sh +1005 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/code-review/scripts/test_parse_opencode_review.sh +258 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/code-review/scripts/test_parse_probe_result.sh +574 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/code-review/scripts/test_parse_review_json.sh +349 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/code-review/scripts/test_review_client_compat.py +434 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/code-review/scripts/test_review_client_order.sh +264 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/code-review/scripts/test_review_gate.sh +2412 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/code-review/scripts/verify_native_skill_binding.py +123 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/defect-diagnosis/SKILL.md +153 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/defect-diagnosis/agents/openai.yaml +4 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/defect-diagnosis/references/diagnosis-playbook.md +54 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/defect-diagnosis/references/prevention-routing.md +36 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/feature-risk-router/SKILL.md +69 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/feature-risk-router/agents/openai.yaml +4 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/feature-risk-router/references/security-review-gate.md +41 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/go-microservice-architecture/SKILL.md +165 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/go-microservice-architecture/agents/openai.yaml +4 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/go-microservice-architecture/references/api-security-boundaries.md +47 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/go-microservice-architecture/references/architecture-playbook.md +160 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/go-microservice-architecture/references/artifact-generation-architecture.md +37 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/go-microservice-architecture/references/audit-history-architecture.md +29 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/go-microservice-architecture/references/bulk-workflow-architecture.md +33 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/go-microservice-architecture/references/config-rule-routing-architecture.md +34 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/go-microservice-architecture/references/cross-cutting-concerns.md +72 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/go-microservice-architecture/references/data-modeling-and-migrations.md +79 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/go-microservice-architecture/references/data-platform-architecture.md +210 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/go-microservice-architecture/references/dependency-platform.md +105 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/go-microservice-architecture/references/developer-tooling-architecture.md +38 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/go-microservice-architecture/references/error-contract-architecture.md +36 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/go-microservice-architecture/references/event-driven-architecture.md +260 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/go-microservice-architecture/references/http-gateway-architecture.md +74 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/go-microservice-architecture/references/mq-consumer-architecture.md +38 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/go-microservice-architecture/references/multi-tenant-isolation.md +275 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/go-microservice-architecture/references/notification-architecture.md +25 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/go-microservice-architecture/references/ops-checklist.md +57 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/go-microservice-architecture/references/performance-capacity-architecture.md +38 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/go-microservice-architecture/references/protobuf-contract-architecture.md +119 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/go-microservice-architecture/references/redis-cache-coordination.md +93 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/go-microservice-architecture/references/release-runtime-readiness.md +65 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/go-microservice-architecture/references/replay-comparison-architecture.md +26 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/go-microservice-architecture/references/runtime-observability.md +94 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/go-microservice-architecture/references/service-scaffold.md +76 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/go-microservice-architecture/references/source-evidence-map.md +55 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/go-microservice-architecture/references/workflow-state-architecture.md +38 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/go-microservice-dev/SKILL.md +159 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/go-microservice-dev/agents/openai.yaml +4 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/go-microservice-dev/references/artifact-generation-patterns.md +37 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/go-microservice-dev/references/audit-history-patterns.md +28 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/go-microservice-dev/references/bulk-import-export-patterns.md +56 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/go-microservice-dev/references/config-rule-routing-patterns.md +38 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/go-microservice-dev/references/data-access-patterns.md +55 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/go-microservice-dev/references/db-schema-and-dal-patterns.md +109 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/go-microservice-dev/references/dependency-client-patterns.md +130 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/go-microservice-dev/references/developer-tooling-patterns.md +70 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/go-microservice-dev/references/domain-feature-patterns.md +78 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/go-microservice-dev/references/engineering-patterns.md +119 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/go-microservice-dev/references/error-contract-patterns.md +55 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/go-microservice-dev/references/feature-playbook.md +61 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/go-microservice-dev/references/http-gateway-client-patterns.md +76 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/go-microservice-dev/references/mq-consumer-patterns.md +55 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/go-microservice-dev/references/notification-patterns.md +42 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/go-microservice-dev/references/observability-implementation-patterns.md +101 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/go-microservice-dev/references/performance-capacity-patterns.md +44 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/go-microservice-dev/references/protobuf-contract-patterns.md +72 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/go-microservice-dev/references/public-api-integration-patterns.md +56 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/go-microservice-dev/references/quality-and-testing-patterns.md +91 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/go-microservice-dev/references/redis-cache-lock-patterns.md +123 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/go-microservice-dev/references/release-ops-patterns.md +112 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/go-microservice-dev/references/reliability-patterns.md +83 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/go-microservice-dev/references/replay-comparison-patterns.md +32 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/go-microservice-dev/references/scaffold-and-codegen.md +86 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/go-microservice-dev/references/source-evidence-map.md +54 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/go-microservice-dev/references/state-machine-task-patterns.md +45 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/grill-me/SKILL.md +80 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/grill-me/agents/openai.yaml +4 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/llm-inference-integration/SKILL.md +117 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/llm-inference-integration/agents/openai.yaml +4 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/llm-inference-integration/references/agent-approval-auto-reviewer.md +106 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/llm-inference-integration/references/agent-command-sandbox.md +441 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/llm-inference-integration/references/agent-context-freshness.md +47 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/llm-inference-integration/references/agent-credentials-auth.md +13 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/llm-inference-integration/references/agent-extensions-skills.md +13 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/llm-inference-integration/references/agent-file-edit-protocol.md +129 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/llm-inference-integration/references/agent-ide-integration.md +5 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/llm-inference-integration/references/agent-input-ingestion.md +13 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/llm-inference-integration/references/agent-instruction-composition.md +13 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/llm-inference-integration/references/agent-lifecycle-hooks.md +92 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/llm-inference-integration/references/agent-messaging.md +5 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/llm-inference-integration/references/agent-runtime-bootstrap.md +5 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/llm-inference-integration/references/agent-session-persistence.md +448 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/llm-inference-integration/references/agent-task-orchestration.md +13 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/llm-inference-integration/references/agent-tool-dispatch.md +123 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/llm-inference-integration/references/agent-turn-lifecycle.md +131 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/llm-inference-integration/references/inference-capacity-operations.md +162 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/llm-inference-integration/references/llm-client-gateway.md +156 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/llm-inference-integration/references/model-prompt-evaluation.md +146 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/llm-inference-integration/references/retrieval-agent-safety.md +273 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/miniapp-product-dev/SKILL.md +202 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/miniapp-product-dev/agents/openai.yaml +4 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/miniapp-product-dev/references/contracts-and-state.md +62 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/miniapp-product-dev/references/cross-stack-alignment.md +94 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/miniapp-product-dev/references/framework-choice.md +76 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/miniapp-product-dev/references/online-practice-uptake.md +56 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/miniapp-product-dev/references/platform-capabilities.md +91 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/miniapp-product-dev/references/product-page-checklist.md +40 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/miniapp-product-dev/references/qa-release.md +72 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/miniapp-product-dev/references/source-evidence-map.md +82 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/multi-agent-delegation/SKILL.md +103 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/multi-agent-delegation/agents/openai.yaml +5 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/multi-agent-delegation/references/multi-agent-delegation-playbook.md +100 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/multi-perspective-research/SKILL.md +70 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/multi-perspective-research/agents/openai.yaml +4 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/multi-perspective-research/references/public-data-acquisition.md +549 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/multi-perspective-research/references/public-disclosure-channels.md +97 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/multi-perspective-research/references/research-prompts.md +66 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/multi-perspective-research/scripts/AGENTS.md +32 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/multi-perspective-research/scripts/test-public-data-acquisition-recipes.sh +379 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/platform-observability/SKILL.md +244 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/platform-observability/agents/openai.yaml +4 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/platform-observability/references/alerting-and-on-call.md +76 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/platform-observability/references/framework-middleware-checklist.md +142 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/platform-observability/references/infra-component-deployment.md +268 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/platform-observability/references/log-correlation-recipe.md +124 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/platform-observability/references/log-schema-canonical.md +208 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/platform-observability/references/metrics-conventions.md +105 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/platform-observability/references/obs-stack-architecture.md +107 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/platform-observability/references/sli-slo-design.md +95 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/platform-observability/references/source-register.md +11 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/platform-release-engineering/SKILL.md +303 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/platform-release-engineering/agents/openai.yaml +4 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/platform-release-engineering/references/canary-and-rollout-strategy.md +163 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/platform-release-engineering/references/config-center-via-etcd.md +245 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/platform-release-engineering/references/custom-control-plane-boundary.md +298 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/platform-release-engineering/references/deploy-cli-concrete-recipe.md +312 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/platform-release-engineering/references/deploy-pipeline.md +165 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/platform-release-engineering/references/env-and-lane-matrix.md +126 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/platform-release-engineering/references/lane-orchestration-control-plane.md +383 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/platform-release-engineering/references/multi-region-and-cluster.md +135 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/platform-release-engineering/references/promotion-gate-and-review.md +149 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/platform-release-engineering/references/python-package-registry-release.md +462 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/platform-release-engineering/references/rollback-playbook.md +123 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/platform-release-engineering/references/secret-and-config-management.md +231 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/platform-release-engineering/references/version-authority-and-deprecation.md +21 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/platform-service-connectivity/SKILL.md +276 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/platform-service-connectivity/agents/openai.yaml +4 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/platform-service-connectivity/references/dual-sidecar-and-traffic-config-center.md +127 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/platform-service-connectivity/references/framework-middleware.md +143 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/platform-service-connectivity/references/grpc-authority-workaround.md +90 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/platform-service-connectivity/references/http-response-envelope-contract.md +24 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/platform-service-connectivity/references/mesh-architecture.md +127 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/platform-service-connectivity/references/multi-env-routing.md +192 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/platform-service-connectivity/references/protobuf-http-contract-signals.md +64 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/platform-service-connectivity/references/retry-timeout-circuit-breaker.md +124 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/platform-service-connectivity/references/rpc-framework-recipe.md +494 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/platform-service-connectivity/references/service-discovery-choice.md +113 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/platform-service-connectivity/references/service-discovery-migration-playbook.md +231 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/platform-service-connectivity/references/service-discovery-recipe.md +131 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/product-rd-workflow/SKILL.md +235 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/product-rd-workflow/agents/openai.yaml +4 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/product-rd-workflow/references/adr-convention.md +146 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/product-rd-workflow/references/algorithm-launch-checklist.md +30 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/product-rd-workflow/references/algorithm-launch-evaluation-report-template.md +25 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/product-rd-workflow/references/algorithm-launch-execution-spec.md +108 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/product-rd-workflow/references/algorithm-launch-sop.md +457 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/product-rd-workflow/references/algorithm-launch-templates.md +24 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/product-rd-workflow/references/artifact-egress-confidentiality.md +58 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/product-rd-workflow/references/code-review-checklist.md +86 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/product-rd-workflow/references/cross-repo-coordination.md +46 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/product-rd-workflow/references/delivery-lifecycle.md +192 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/product-rd-workflow/references/design-review-gate-mechanics.md +62 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/product-rd-workflow/references/design-routing-and-readiness.md +45 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/product-rd-workflow/references/diagnostic-spec-match-gate.md +36 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/product-rd-workflow/references/dispatch-owner-skills.md +35 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/product-rd-workflow/references/dormant-code-activation.md +47 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/product-rd-workflow/references/existing-project-assessment-report.md +223 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/product-rd-workflow/references/external-skill-augmentation.md +46 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/product-rd-workflow/references/feature-deprecation-cascade.md +15 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/product-rd-workflow/references/high-risk-resilience-gates.md +73 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/product-rd-workflow/references/implementation-completeness-and-minimality.md +120 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/product-rd-workflow/references/implementation-entry-reentry-gate.md +122 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/product-rd-workflow/references/modular-monolith-heuristic.md +105 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/product-rd-workflow/references/pre-final-continuation-gate.md +115 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/product-rd-workflow/references/problem-resolution-and-learning.md +62 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/product-rd-workflow/references/quality-attributes.md +112 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/product-rd-workflow/references/quality-remediation-program.md +88 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/product-rd-workflow/references/rd-standards-doc-family-checklist.md +27 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/product-rd-workflow/references/refactoring-discipline.md +52 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/product-rd-workflow/references/review-reception.md +34 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/product-rd-workflow/references/shared-gate-artifact-classification.md +76 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/product-rd-workflow/references/source-evidence-map.md +31 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/product-rd-workflow/references/status-tracker-sync.md +77 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/product-rd-workflow/references/sync-spec-repo-contract.md +25 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/product-rd-workflow/references/verify-developer-experience.md +34 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/product-rd-workflow/references/worktree-mechanics.md +55 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/product-rd-workflow/scripts/AGENTS.md +18 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/product-rd-workflow/scripts/check-agent-contract-coverage.sh +213 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/product-ui-ux-design/SKILL.md +136 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/product-ui-ux-design/agents/openai.yaml +9 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/product-ui-ux-design/references/analytics-visualization-interactions.md +206 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/product-ui-ux-design/references/behavioral-aesthetic-logic.md +108 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/product-ui-ux-design/references/complex-creation-interactions.md +194 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/product-ui-ux-design/references/design-execution-checklist.md +214 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/product-ui-ux-design/references/design-impl-naming-and-versioning.md +53 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/product-ui-ux-design/references/design-intake-and-acceptance.md +129 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/product-ui-ux-design/references/design-system-source-of-truth.md +97 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/product-ui-ux-design/references/external-ui-ux-quality-benchmarks.md +79 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/product-ui-ux-design/references/frontend-code-evidence-map.md +63 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/product-ui-ux-design/references/interaction-design-patterns.md +146 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/product-ui-ux-design/references/layout-recipes-and-screenshot-acceptance.md +250 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/product-ui-ux-design/references/multi-project-token-consistency.md +237 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/product-ui-ux-design/references/multi-stack-strategy.md +65 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/product-ui-ux-design/references/operational-processing-workflows.md +237 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/product-ui-ux-design/references/platform-mobile-patterns.md +324 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/product-ui-ux-design/references/platform-web-desktop-patterns.md +456 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/product-ui-ux-design/references/product-lifecycle-acceptance-and-iteration.md +114 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/product-ui-ux-design/references/product-surface-patterns.md +79 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/product-ui-ux-design/references/resource-management-interactions.md +113 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/product-ui-ux-design/references/scenario-community-patterns.md +133 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/product-ui-ux-design/references/source-map.md +130 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/product-ui-ux-design/references/tokens-and-components.md +47 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/product-ui-ux-design/references/trust-sensitive-ai-and-data-patterns.md +96 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/product-ui-ux-design/references/ui-ux-audit.md +106 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/product-ui-ux-design/references/ui-ux-design-development.md +176 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/product-ui-ux-design/references/visual-craft.md +111 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/python-service-architecture/SKILL.md +157 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/python-service-architecture/agents/openai.yaml +4 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/python-service-architecture/references/ai-service-integration-boundaries.md +57 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/python-service-architecture/references/api-contract-and-schema.md +62 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/python-service-architecture/references/api-security-boundaries.md +39 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/python-service-architecture/references/architecture-playbook.md +46 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/python-service-architecture/references/async-execution-model.md +24 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/python-service-architecture/references/background-jobs-and-scheduling.md +18 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/python-service-architecture/references/batch-and-pipeline-architecture.md +11 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/python-service-architecture/references/config-secrets-runtime.md +22 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/python-service-architecture/references/data-modeling-and-migrations.md +64 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/python-service-architecture/references/data-platform-architecture.md +211 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/python-service-architecture/references/event-driven-architecture.md +263 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/python-service-architecture/references/multi-tenant-isolation.md +281 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/python-service-architecture/references/observability-and-ops.md +26 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/python-service-architecture/references/packaging-runtime-readiness.md +20 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/python-service-architecture/references/redis-cache-coordination.md +41 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/python-service-architecture/references/reliability-and-error-contract.md +17 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/python-service-architecture/references/source-evidence-map.md +55 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/python-service-architecture/references/web-framework-boundaries.md +26 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/python-service-dev/SKILL.md +143 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/python-service-dev/agents/openai.yaml +4 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/python-service-dev/references/ai-service-wiring-patterns.md +16 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/python-service-dev/references/async-and-worker-patterns.md +24 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/python-service-dev/references/background-job-patterns.md +18 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/python-service-dev/references/batch-and-artifact-patterns.md +13 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/python-service-dev/references/dependency-client-patterns.md +39 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/python-service-dev/references/error-handling-patterns.md +26 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/python-service-dev/references/feature-playbook.md +43 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/python-service-dev/references/observability-implementation-patterns.md +31 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/python-service-dev/references/project-structure-and-tooling.md +24 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/python-service-dev/references/public-api-security-patterns.md +52 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/python-service-dev/references/redis-cache-lock-patterns.md +78 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/python-service-dev/references/schema-and-validation-patterns.md +23 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/python-service-dev/references/source-evidence-map.md +56 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/python-service-dev/references/sqlalchemy-and-migrations-patterns.md +99 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/python-service-dev/references/testing-and-quality-patterns.md +61 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/python-service-dev/references/web-framework-patterns.md +35 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/release-coordination/SKILL.md +91 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/release-coordination/agents/openai.yaml +4 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/release-coordination/references/config-runtime-readback.md +20 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/release-coordination/references/mr-merge-authorization.md +31 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/release-coordination/references/post-release-env-reset.md +31 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/release-coordination/references/release-closeout-evidence.md +20 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/release-coordination/references/release-scope-confirmation.md +21 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/release-coordination/references/tag-and-prod-pipeline-gate.md +20 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/release-coordination/references/test-scope-prompt.md +24 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/release-coordination/references/watcher-discipline.md +14 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/release-doc-writer/SKILL.md +64 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/release-doc-writer/agents/openai.yaml +4 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/release-doc-writer/references/comment-safe-release-doc.md +19 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/release-doc-writer/references/release-evidence-workflow.md +23 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/release-doc-writer/references/release-testing-scope-section.md +15 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/requirement-baseline/SKILL.md +87 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/requirement-baseline/agents/openai.yaml +4 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/requirement-doc-writer/SKILL.md +130 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/requirement-doc-writer/agents/openai.yaml +4 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/requirement-doc-writer/references/prd-composition-contract.md +35 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/requirement-doc-writer/references/requirement-closure-contract.md +86 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/requirement-doc-writer/references/security-four-questions.md +38 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/requirement-intent/SKILL.md +91 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/requirement-intent/agents/openai.yaml +4 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/requirement-scope/SKILL.md +88 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/requirement-scope/agents/openai.yaml +4 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/SKILL.md +337 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/agents/openai.yaml +4 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/references/analysis-parse-fix-test-challenge-replay.md +47 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/references/attribution-verification.md +69 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/references/bootstrap-slim-c3-obligation-table.md +112 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/references/coverage-exhaustion-traps.md +45 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/references/description-authoring.md +162 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/references/dual-track-review-gate.md +507 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/references/eval-routing.md +86 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/references/evidence-card-template.md +51 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/references/example-domain-preselect.md +79 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/references/external-practice-controls.md +57 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/references/extraction-lifecycle-handoff.md +65 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/references/extraction-quickstart.md +194 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/references/firing-point-placement.md +75 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/references/harness-patterns-and-eval.md +286 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/references/incident-postmortem-extraction.md +190 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/references/l0-l1-l2-routing.md +114 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/references/online-skill-review.md +47 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/references/parallel-stack-references-pattern.md +164 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/references/r0-leakage-audit.md +90 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/references/recurring-anti-patterns-checklist.md +320 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/references/resume-paused-delivery.md +16 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/references/review-feedback-mining.md +33 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/references/review-finding-standards.md +57 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/references/review-rubric.md +40 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/references/rule-consolidation.md +118 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/references/skill-listing-budget.md +19 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/references/source-register.md +254 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/references/source-to-skill-extraction.md +658 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/references/two-source-extraction-pattern.md +167 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/references/uiux-judgment-extraction.md +179 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/references/uiux-routing-map.md +51 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/references/validation-and-landing.md +180 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/scripts/AGENTS.md +18 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/scripts/check-ccl-skills.sh +1452 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/scripts/check-evidence-card-leak.sh +491 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/scripts/check-mr-target-freshness.sh +173 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/scripts/check-size-budget.sh +488 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/scripts/check-sync-pointers.sh +419 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/scripts/eval-golden-trace.rb +197 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/scripts/eval-health.rb +327 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/scripts/eval-routing-bank.rb +401 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/scripts/eval-routing.rb +248 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/scripts/generic-r0-leak-scan.sh +282 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/scripts/governing-chain-diff.py +321 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/scripts/impact-chain-gate.rb +964 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/scripts/register-firing-path-resolution.rb +708 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/scripts/skill-behavior-eval.py +540 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/scripts/source-register-lifecycle.rb +51 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/scripts/source-register-pending-status.rb +55 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/scripts/test_ai_coding_implementation_gates.sh +829 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/scripts/test_check_ccl_impact_chain_refscripts.sh +1203 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/scripts/test_check_ccl_r0_status.sh +75 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/scripts/test_check_ccl_register_pending_exclusion.sh +137 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/scripts/test_check_ccl_regressions.sh +173 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/scripts/test_check_ccl_route_drift.sh +377 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/scripts/test_check_ccl_size_budget.sh +833 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/scripts/test_check_ccl_skill_catalog.sh +491 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/scripts/test_check_ccl_source_register_lifecycle.sh +114 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/scripts/test_check_mr_target_freshness.sh +261 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/scripts/test_check_sync_pointers.sh +538 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/scripts/test_controlled_escalation_pins.sh +154 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/scripts/test_eval_routing_bank_grader_diagnostics.sh +190 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/scripts/test_eval_routing_bank_surface_binding.sh +178 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/scripts/test_eval_routing_prose_target.sh +86 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/scripts/test_generic_r0_leak_scan.sh +131 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/scripts/test_git_identity_predicate_gate.sh +243 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/scripts/test_governing_chain_diff.sh +419 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/scripts/test_impact_chain_gate_dateless_host.sh +120 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/scripts/test_register_firing_path_resolution.sh +724 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/scripts/test_register_firing_path_wiring.sh +414 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/scripts/test_regression_runner_registration.sh +34 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/scripts/test_routing_bank_integrity.sh +205 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/scripts/test_routing_pointer_integrity.sh +194 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/scripts/test_validate_skill_credential_cwd.sh +61 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/scripts/test_validate_skill_cross_refs.sh +111 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/scripts/test_validate_skill_root_depth.sh +53 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/scripts/validate-skill.sh +257 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/terminal-cli-dev/SKILL.md +98 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/terminal-cli-dev/agents/openai.yaml +4 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/terminal-cli-dev/references/input-state-machines.md +36 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/terminal-cli-dev/references/streaming-rich-output.md +130 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/terminal-cli-dev/references/terminal-side-channels.md +96 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/test-artifact-management/SKILL.md +408 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/test-artifact-management/agents/openai.yaml +4 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/test-artifact-management/references/AGENTS.md +18 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/test-artifact-management/references/bitable-setup.md +573 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/test-artifact-management/references/ci_templates/README.md +120 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/test-artifact-management/references/ci_templates/github-actions.yml +119 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/test-artifact-management/references/ci_templates/gitlab-ci.yml +76 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/test-artifact-management/references/ci_templates/jenkins.Jenkinsfile +106 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/test-artifact-management/references/classical-test-design-techniques.md +279 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/test-artifact-management/references/gen_report.py +2807 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/test-artifact-management/references/makefile-template.md +200 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/test-artifact-management/references/report-config-schema.md +272 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/test-artifact-management/references/run_pytestless.py +475 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/test-artifact-management/references/source-to-case-workflows.md +258 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/test-artifact-management/references/tc-marker-conventions.md +316 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/test-artifact-management/references/tc-review-and-prioritization.md +145 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/test-artifact-management/references/tc_helpers/AGENTS.md +16 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/test-artifact-management/references/tc_helpers/tc.dart +129 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/test-artifact-management/references/tc_helpers/tc.go +197 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/test-artifact-management/references/tc_helpers/tc.py +135 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/test-artifact-management/references/tc_helpers/tc.ts +285 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/test-artifact-management/references/test_gen_report.py +2144 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/test-artifact-management/references/update-lifecycle.md +62 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/testing-strategy/SKILL.md +212 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/testing-strategy/agents/openai.yaml +4 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/testing-strategy/references/ci-fixtures-and-flake-control.md +75 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/testing-strategy/references/client-runtime-test-matrices.md +50 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/testing-strategy/references/data-and-workflow-testing.md +34 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/testing-strategy/references/design-closed-contract-oracles.md +31 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/testing-strategy/references/e2e-real-flow-testing.md +71 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/testing-strategy/references/fitness-functions.md +240 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/testing-strategy/references/integration-contract-testing.md +235 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/testing-strategy/references/non-functional-specialized-scenarios.md +296 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/testing-strategy/references/rd-testing-standard-template.md +126 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/testing-strategy/references/run-killing-mutation-walk.md +43 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/testing-strategy/references/scenario-testing.md +136 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/testing-strategy/references/source-evidence-map.md +59 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/testing-strategy/references/structured-tc-input-translation.md +67 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/testing-strategy/references/test-code-authoring-patterns.md +392 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/testing-strategy/references/test-data-and-determinism.md +39 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/testing-strategy/references/test-topology-and-commands.md +92 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/testing-strategy/references/unit-testing.md +46 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/testing-strategy/references/vendored-contract-drift-checklist.md +64 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/testing-strategy/references/verify-enforcement-mechanisms.md +18 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/testing-strategy/scripts/AGENTS.md +17 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/testing-strategy/scripts/client-terminal-ansi-check.py +140 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/testing-strategy/scripts/client-terminal-ansi-check.test.sh +75 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/testing-strategy/scripts/lang-basics-ast-check.py +170 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/testing-strategy/scripts/lang-basics-ast-check.test.sh +87 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/testing-strategy/scripts/lang-basics-go-check.go +198 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/testing-strategy/scripts/lang-basics-go-check.test.sh +109 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/testing-strategy/scripts/test_mutation_backup_recipe.sh +237 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/tighten-doc/SKILL.md +184 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/tighten-doc/agents/openai.yaml +4 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/tighten-doc/references/comment-safe-feishu.md +93 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/tighten-doc/references/cross-model-co-review.md +3 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/tighten-doc/references/delivery-face-closeout.md +60 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/tighten-doc/references/doc-charter-first.md +17 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/tighten-doc/references/session-vantage-leakage.md +58 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/web-react-dev/SKILL.md +126 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/web-react-dev/agents/openai.yaml +4 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/web-react-dev/references/complex-workspace-patterns.md +47 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/web-react-dev/references/embedded-h5-in-host.md +87 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/web-react-dev/references/react-architecture.md +194 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/web-react-dev/references/source-evidence-map.md +60 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/web-react-dev/references/web-quality-release.md +190 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/web-react-dev/references/web-ui-quality.md +83 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/worktree-isolation/SKILL.md +179 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/worktree-isolation/agents/openai.yaml +4 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/worktree-isolation/references/shared-branch-rebase.md +25 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/worktree-isolation/scripts/AGENTS.md +23 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/worktree-isolation/scripts/test_worktree_status.sh +207 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/worktree-isolation/scripts/test_worktree_sweep.sh +481 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/worktree-isolation/scripts/worktree-status.sh +325 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/worktree-isolation/scripts/worktree-sweep.sh +245 -0
- package/dist/assets/release.json +2797 -0
- package/dist/claude-adapter.d.ts +9 -0
- package/dist/claude-adapter.js +240 -0
- package/dist/cli-worker.d.ts +1 -0
- package/dist/cli-worker.js +32 -0
- package/dist/cli.d.ts +22 -0
- package/dist/cli.js +214 -0
- package/dist/codex-host.d.ts +30 -0
- package/dist/codex-host.js +162 -0
- package/dist/fs-safe.d.ts +21 -0
- package/dist/fs-safe.js +241 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +1 -0
- package/dist/manifest.d.ts +8 -0
- package/dist/manifest.js +135 -0
- package/dist/opencode-adapter.d.ts +10 -0
- package/dist/opencode-adapter.js +416 -0
- package/dist/operations.d.ts +3 -0
- package/dist/operations.js +956 -0
- package/dist/paths.d.ts +20 -0
- package/dist/paths.js +4 -0
- package/dist/types.d.ts +58 -0
- package/dist/types.js +1 -0
- package/dist/unified.d.ts +4 -0
- package/dist/unified.js +64 -0
- package/dist/version.d.ts +2 -0
- package/dist/version.js +5 -0
- package/package.json +35 -0
|
@@ -0,0 +1,941 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# RED -> GREEN behavioral + adversarial suite for the owner-dispatch firing gate.
|
|
3
|
+
# Each case proves: WITHOUT the rule the action proceeds silently (baseline);
|
|
4
|
+
# WITH it the gate fires; and the safety invariants (fail-open, symlink-safe,
|
|
5
|
+
# per-session, no-trap, CI anti-bypass) hold.
|
|
6
|
+
set -u
|
|
7
|
+
ENGINE="$(cd "$(dirname "$0")" && pwd)/owner-dispatch.sh"
|
|
8
|
+
PASS=0; FAIL=0
|
|
9
|
+
ok() { PASS=$((PASS+1)); printf ' ok %s\n' "$1"; }
|
|
10
|
+
bad() { FAIL=$((FAIL+1)); printf ' FAIL %s\n %s\n' "$1" "${2:-}"; }
|
|
11
|
+
|
|
12
|
+
WORK=$(mktemp -d) || { echo "FATAL: mktemp -d failed (no writable TMPDIR)"; exit 1; }
|
|
13
|
+
trap 'rm -rf "$WORK"' EXIT
|
|
14
|
+
REPO="$WORK/prod"; mkdir -p "$REPO/src"
|
|
15
|
+
git -C "$REPO" init -q
|
|
16
|
+
git -C "$REPO" config user.email t@t; git -C "$REPO" config user.name t
|
|
17
|
+
echo "package x" > "$REPO/src/foo.go"; echo "# readme" > "$REPO/README.md"
|
|
18
|
+
git -C "$REPO" add -A; git -C "$REPO" commit -qm init
|
|
19
|
+
BDIR="$(git -C "$REPO" rev-parse --absolute-git-dir)/owner-dispatch"
|
|
20
|
+
|
|
21
|
+
edit() { printf '{"tool_name":"Edit","tool_input":{"file_path":"%s"},"session_id":"%s"}' "$1" "${2:-S0}"; }
|
|
22
|
+
bashj(){ printf '{"tool_name":"Bash","tool_input":{"command":"%s"}}' "$1"; }
|
|
23
|
+
bashjs(){ printf '{"tool_name":"Bash","tool_input":{"command":"%s"},"session_id":"%s"}' "$1" "$2"; }
|
|
24
|
+
stopj(){ printf '{"session_id":"%s"}' "${1:-}"; }
|
|
25
|
+
# opt-in now requires the config to be TRACKED at the git top-level, so commit it.
|
|
26
|
+
config(){ cat > "$REPO/.owner-dispatch.json"; ( cd "$REPO" && git add .owner-dispatch.json && git commit -q -m cfg -- .owner-dispatch.json ) >/dev/null 2>&1 || true; }
|
|
27
|
+
decision(){ jq -r '.hookSpecificOutput.permissionDecision // "allow"' 2>/dev/null; }
|
|
28
|
+
sdecision(){ local o; o=$(cat); [ -z "$o" ] && { echo stop; return; }; printf '%s' "$o" | jq -r '.decision // "stop"' 2>/dev/null; }
|
|
29
|
+
|
|
30
|
+
echo "owner-dispatch suite"
|
|
31
|
+
|
|
32
|
+
# 1. RED baseline: no config => silent allow.
|
|
33
|
+
out=$(edit "$REPO/src/foo.go" | bash "$ENGINE" pretool)
|
|
34
|
+
[ -z "$out" ] && ok "baseline: no config => silent allow" || bad "baseline" "got:$out"
|
|
35
|
+
|
|
36
|
+
config <<'JSON'
|
|
37
|
+
{ "enabled": true, "strict": false, "gate_bash": true,
|
|
38
|
+
"product_globs": ["src/**"], "exclude_globs": ["**/*_test.*"],
|
|
39
|
+
"owner_hint": "product-rd-workflow + the stack *-dev owner" }
|
|
40
|
+
JSON
|
|
41
|
+
|
|
42
|
+
# 2. GREEN gated edit, no boundary => ask.
|
|
43
|
+
[ "$(edit "$REPO/src/foo.go" S1 | bash "$ENGINE" pretool | decision)" = ask ] && ok "gated edit, no boundary => ask" || bad "expected ask"
|
|
44
|
+
# 3. excluded test file => allow.
|
|
45
|
+
echo x > "$REPO/src/foo_test.go"
|
|
46
|
+
[ -z "$(edit "$REPO/src/foo_test.go" | bash "$ENGINE" pretool)" ] && ok "excluded *_test.* => allow" || bad "excluded"
|
|
47
|
+
# 4. non-product => allow.
|
|
48
|
+
[ -z "$(edit "$REPO/README.md" | bash "$ENGINE" pretool)" ] && ok "non-product README => allow" || bad "README"
|
|
49
|
+
# 5. boundary recorded => allow.
|
|
50
|
+
( cd "$REPO" && bash "$ENGINE" record --owners "product-rd-workflow,go-dev" >/dev/null )
|
|
51
|
+
[ -z "$(edit "$REPO/src/foo.go" | bash "$ENGINE" pretool)" ] && ok "boundary recorded => allow" || bad "boundary allow"
|
|
52
|
+
# 5b. boundary SURVIVES a FORWARD HEAD move. Validity requires ancestry, not equality: the gate
|
|
53
|
+
# requires recording before the first gated edit, and a delivery's own commit lands
|
|
54
|
+
# after that edit — so pinning invalidated every committing delivery's own boundary and
|
|
55
|
+
# made Stop report it as "never recorded". This asserts the HEAD-independent lifetime
|
|
56
|
+
# ONLY — it does not assert anything about actor identity, which the gate does not
|
|
57
|
+
# enforce (see the residual note on boundary_valid).
|
|
58
|
+
git -C "$REPO" commit -q --allow-empty -m moved
|
|
59
|
+
out_v5=$(edit "$REPO/src/foo.go" | bash "$ENGINE" pretool); st_v5=$?
|
|
60
|
+
[ "$st_v5" = 0 ] && [ -z "$out_v5" ] \
|
|
61
|
+
&& ok "boundary survives HEAD move => allow" || bad "V5: HEAD move must not invalidate a boundary"
|
|
62
|
+
# 5b-2. …but only FORWARD. A history discontinuity (switch to an unrelated branch, or a
|
|
63
|
+
# reset onto a divergent commit) is a different piece of work and must re-fire the
|
|
64
|
+
# gate. Equality caught this incidentally; ancestry catches it on purpose.
|
|
65
|
+
_orig_branch=$(git -C "$REPO" symbolic-ref --short HEAD); _orig_head=$(git -C "$REPO" rev-parse HEAD)
|
|
66
|
+
# Build a genuine SIBLING line (fork from the commit before the current tip, then add its own
|
|
67
|
+
# commit). Simply checking out the recorded commit is not a discontinuity — it is the very
|
|
68
|
+
# point the boundary was recorded at, so ancestry legitimately still holds there.
|
|
69
|
+
git -C "$REPO" branch od-diverge "HEAD~1" >/dev/null 2>&1
|
|
70
|
+
git -C "$REPO" checkout -q od-diverge && git -C "$REPO" commit -q --allow-empty -m "divergent work"
|
|
71
|
+
git -C "$REPO" checkout -q "$_orig_branch"
|
|
72
|
+
( cd "$REPO" && bash "$ENGINE" record --owners "product-rd-workflow,go-dev" >/dev/null ) # record on THIS line
|
|
73
|
+
# POSITIVE CONTROL: prove the fresh record is actually valid HERE first. Without it, a
|
|
74
|
+
# broken/malformed record would also produce `ask` after the switch and the test would pass
|
|
75
|
+
# without demonstrating that the switch is what invalidated it.
|
|
76
|
+
[ -z "$(edit "$REPO/src/foo.go" | bash "$ENGINE" pretool)" ] \
|
|
77
|
+
&& ok "discontinuity control: fresh record valid on its own line => allow" || bad "V5b control: fresh record must be valid before the switch"
|
|
78
|
+
git -C "$REPO" checkout -q od-diverge # jump to the unrelated line
|
|
79
|
+
[ "$(edit "$REPO/src/foo.go" | bash "$ENGINE" pretool | decision)" = ask ] \
|
|
80
|
+
&& ok "boundary does NOT survive a history discontinuity => ask" || bad "V5b: divergent history must re-fire the gate"
|
|
81
|
+
# …and it is the discontinuity specifically, not a generic invalidation: the state must be
|
|
82
|
+
# reported as `discontinuous`, never collapsed into "never recorded".
|
|
83
|
+
( cd "$REPO" && bash "$ENGINE" status ) 2>/dev/null | grep -q "^boundary: discontinuous" \
|
|
84
|
+
&& ok "status: divergent-line boundary reported as discontinuous" || bad "V5b: must report discontinuous, not absent"
|
|
85
|
+
# 5b-4. A `git replace --graft` must NOT be able to manufacture the missing ancestry.
|
|
86
|
+
# merge-base honours replacement refs by default, so without GIT_NO_REPLACE_OBJECTS a
|
|
87
|
+
# graft turns this same divergent state back into "valid". Assert the real-object answer.
|
|
88
|
+
_rec_head=$(jq -r '.head' "$BDIR/boundary.json" 2>/dev/null)
|
|
89
|
+
if git -C "$REPO" replace --graft "$(git -C "$REPO" rev-parse HEAD)" "$_rec_head" >/dev/null 2>&1; then
|
|
90
|
+
[ "$(edit "$REPO/src/foo.go" | bash "$ENGINE" pretool | decision)" = ask ] \
|
|
91
|
+
&& ok "graft cannot fake ancestry (replacement refs ignored)" || bad "V5d: replace --graft bypassed the continuity check"
|
|
92
|
+
git -C "$REPO" replace -d "$(git -C "$REPO" rev-parse HEAD)" >/dev/null 2>&1
|
|
93
|
+
else
|
|
94
|
+
ok "graft fixture unavailable on this git => skipped (not a pass for the graft path)"
|
|
95
|
+
fi
|
|
96
|
+
# 5b-5. …and the LEGACY graft path too. GIT_NO_REPLACE_OBJECTS does not disable
|
|
97
|
+
# `.git/info/grafts` (verified on git 2.50) — only GIT_GRAFT_FILE does, so both are
|
|
98
|
+
# load-bearing and this fixture is what keeps the second one from being dropped.
|
|
99
|
+
_gitdir=$(git -C "$REPO" rev-parse --absolute-git-dir)
|
|
100
|
+
mkdir -p "$_gitdir/info"
|
|
101
|
+
printf '%s %s\n' "$(git -C "$REPO" rev-parse HEAD)" "$_rec_head" > "$_gitdir/info/grafts"
|
|
102
|
+
[ "$(edit "$REPO/src/foo.go" | bash "$ENGINE" pretool | decision)" = ask ] \
|
|
103
|
+
&& ok "legacy info/grafts cannot fake ancestry either" || bad "V5e: info/grafts bypassed the continuity check"
|
|
104
|
+
rm -f "$_gitdir/info/grafts"
|
|
105
|
+
git -C "$REPO" checkout -q "$_orig_branch" && git -C "$REPO" reset -q --hard "$_orig_head"
|
|
106
|
+
git -C "$REPO" branch -qD od-diverge 2>/dev/null
|
|
107
|
+
# 5b-3. The ancestry probe must FAIL CLOSED on every unusable recorded head — a gc'd or
|
|
108
|
+
# shallow-clone-missing object, a malformed value, or a missing field must re-fire the
|
|
109
|
+
# gate, never silently satisfy it. (merge-base exits non-zero for both "not an
|
|
110
|
+
# ancestor" and "bad object"; both must land on ask.)
|
|
111
|
+
( cd "$REPO" && bash "$ENGINE" record --owners "product-rd-workflow,go-dev" >/dev/null )
|
|
112
|
+
for _bad in '"0000000000000000000000000000000000000000"' '"not-a-sha"' '""' 'null'; do
|
|
113
|
+
jq ".head = $_bad" "$BDIR/boundary.json" > "$BDIR/b.tmp" && mv "$BDIR/b.tmp" "$BDIR/boundary.json"
|
|
114
|
+
[ "$(edit "$REPO/src/foo.go" | bash "$ENGINE" pretool | decision)" = ask ] \
|
|
115
|
+
|| { bad "V5c: unusable recorded head ($_bad) must fail closed"; _v5c_bad=1; }
|
|
116
|
+
done
|
|
117
|
+
[ -n "${_v5c_bad:-}" ] || ok "unusable recorded head fails closed (bad/malformed/empty/null)"
|
|
118
|
+
# 5c-2. …and it must be labelled `absent`, NOT `discontinuous`. A well-formed but nonexistent
|
|
119
|
+
# sha (all-zero, gc'd, shallow-clone-missing) is an unusable record — reporting "a
|
|
120
|
+
# branch switch moved HEAD off it" would be exactly the false diagnosis this change
|
|
121
|
+
# set exists to remove, just relocated to a new state.
|
|
122
|
+
jq '.head = "0000000000000000000000000000000000000000"' "$BDIR/boundary.json" > "$BDIR/b.tmp" && mv "$BDIR/b.tmp" "$BDIR/boundary.json"
|
|
123
|
+
( cd "$REPO" && bash "$ENGINE" status ) 2>/dev/null | grep -q "^boundary: absent" \
|
|
124
|
+
&& ok "status: nonexistent recorded commit => absent, not discontinuous" || bad "V5c2: nonexistent sha must not claim discontinuity"
|
|
125
|
+
# 5c-3. UNBORN repo fails closed. This is a deliberate change from the old equality rule,
|
|
126
|
+
# which ALLOWED here: unborn `rev-parse HEAD` prints "HEAD" on stdout and fails, so the
|
|
127
|
+
# old helper produced "HEAD\nNO_HEAD" on both sides and they compared equal. An unborn
|
|
128
|
+
# repo has no line of work to be continuous with, and orphan-branch switches must not
|
|
129
|
+
# satisfy the gate. Uses its own throwaway repo so the shared fixture is untouched.
|
|
130
|
+
UB=$(mktemp -d); git init -q "$UB"; git -C "$UB" config user.email t@t; git -C "$UB" config user.name t
|
|
131
|
+
mkdir -p "$UB/src"; echo "package main" > "$UB/src/foo.go"
|
|
132
|
+
printf '%s' '{ "enabled": true, "product_globs": ["src/**"] }' > "$UB/.owner-dispatch.json"
|
|
133
|
+
git -C "$UB" add .owner-dispatch.json >/dev/null 2>&1 # tracked-in-index, never committed
|
|
134
|
+
( cd "$UB" && bash "$ENGINE" record --owners "product-rd-workflow" >/dev/null 2>&1 )
|
|
135
|
+
[ "$(edit "$UB/src/foo.go" | ( cd "$UB" && bash "$ENGINE" pretool ) | decision)" = ask ] \
|
|
136
|
+
&& ok "unborn repo fails closed even after record (was allow under equality)" || bad "V5c3: unborn repo must fail closed"
|
|
137
|
+
rm -rf "$UB"
|
|
138
|
+
# 5c. expired boundary (TTL) => ask. TTL is now the only bound on boundary reuse at the
|
|
139
|
+
# PreToolUse layer, so it carries its own assertion. Leaves an INVALID boundary behind
|
|
140
|
+
# on purpose — case 6 (strict => deny) depends on that state.
|
|
141
|
+
( cd "$REPO" && bash "$ENGINE" record --owners "product-rd-workflow,go-dev" --ttl 0 >/dev/null )
|
|
142
|
+
[ "$(edit "$REPO/src/foo.go" | bash "$ENGINE" pretool | decision)" = ask ] && ok "boundary expired (TTL) => ask" || bad "V3: expired boundary must ask"
|
|
143
|
+
# 5d. `status` reports the real state, not a valid/not-valid collapse. It is the command an
|
|
144
|
+
# agent runs to diagnose a block, so it must separate expired from never-recorded.
|
|
145
|
+
( cd "$REPO" && bash "$ENGINE" status ) 2>/dev/null | grep -q "^boundary: expired" \
|
|
146
|
+
&& ok "status: expired boundary reported as expired" || bad "status must report expired"
|
|
147
|
+
rm -f "$BDIR/boundary.json"
|
|
148
|
+
( cd "$REPO" && bash "$ENGINE" status ) 2>/dev/null | grep -q "^boundary: absent" \
|
|
149
|
+
&& ok "status: no boundary reported as absent" || bad "status must report absent"
|
|
150
|
+
# 5e. a malformed/non-integer expiry is NOT "expired" — it is an unparseable record, so the
|
|
151
|
+
# label must stay on the conservative side rather than implying a usable record existed.
|
|
152
|
+
( cd "$REPO" && bash "$ENGINE" record --owners "x" >/dev/null )
|
|
153
|
+
jq '.expires_at = true' "$BDIR/boundary.json" > "$BDIR/b.tmp" && mv "$BDIR/b.tmp" "$BDIR/boundary.json"
|
|
154
|
+
( cd "$REPO" && bash "$ENGINE" status ) 2>/dev/null | grep -q "^boundary: absent" \
|
|
155
|
+
&& ok "status: non-integer expires_at => absent, not expired" || bad "malformed expiry must not report expired"
|
|
156
|
+
[ "$(edit "$REPO/src/foo.go" | bash "$ENGINE" pretool | decision)" = ask ] \
|
|
157
|
+
&& ok "malformed expiry: gate fails closed (ask, never allow)" || bad "malformed expiry must ask"
|
|
158
|
+
rm -f "$BDIR/boundary.json"
|
|
159
|
+
( cd "$REPO" && bash "$ENGINE" record --owners "product-rd-workflow,go-dev" --ttl 0 >/dev/null )
|
|
160
|
+
|
|
161
|
+
# 6. strict => deny.
|
|
162
|
+
config <<'JSON'
|
|
163
|
+
{ "enabled": true, "strict": true, "product_globs": ["src/**"] }
|
|
164
|
+
JSON
|
|
165
|
+
[ "$(edit "$REPO/src/foo.go" | bash "$ENGINE" pretool | decision)" = deny ] && ok "strict => deny" || bad "strict deny"
|
|
166
|
+
# 6b. strict downgrades to ask when state dir is unsafe (symlinked).
|
|
167
|
+
rm -rf "$BDIR"; ln -s /nonexistent-target "$BDIR"
|
|
168
|
+
[ "$(edit "$REPO/src/foo.go" | bash "$ENGINE" pretool | decision)" = ask ] && ok "strict + unsafe state dir => downgrade to ask (no brick)" || bad "strict downgrade"
|
|
169
|
+
rm -f "$BDIR"
|
|
170
|
+
# 6c. strict deny has an escape: a per-session waiver lets a narrow exempt edit proceed.
|
|
171
|
+
mkdir -p "$BDIR"; touch "$BDIR/s.SX.waiver"
|
|
172
|
+
[ -z "$(edit "$REPO/src/foo.go" SX | bash "$ENGINE" pretool)" ] && ok "strict + per-session waiver => allow (escape, no brick)" || bad "strict waiver escape"
|
|
173
|
+
rm -rf "$BDIR"
|
|
174
|
+
|
|
175
|
+
# 7. Bash write-heuristic is RECORD-ONLY: it records the .bashwrite activity marker
|
|
176
|
+
# and ALLOWS SILENTLY (no user `ask` popup); the Stop hook + ci are the gates.
|
|
177
|
+
config <<'JSON'
|
|
178
|
+
{ "enabled": true, "product_globs": ["src/**"], "gate_bash": true }
|
|
179
|
+
JSON
|
|
180
|
+
rm -rf "$BDIR"
|
|
181
|
+
[ -z "$( cd "$REPO" && bashjs "echo hi >> src/foo.go" S7 | bash "$ENGINE" pretool )" ] \
|
|
182
|
+
&& ok "bash write-heuristic => allow silently (no popup)" || bad "bash heuristic still prompts"
|
|
183
|
+
[ -r "$BDIR/s.S7.bashwrite" ] && ok "bash write-heuristic still records .bashwrite (Stop backstop)" || bad "bash heuristic did not record"
|
|
184
|
+
[ -z "$( cd "$REPO" && bashj "cat src/foo.go" | bash "$ENGINE" pretool )" ] && ok "bash read-only => allow" || bad "bash read"
|
|
185
|
+
rm -rf "$BDIR"
|
|
186
|
+
|
|
187
|
+
# 8. Stop per-session cap + cross-session isolation. Stop blocks only when this
|
|
188
|
+
# session actually CHANGED a gated path vs the baseline captured at first touch
|
|
189
|
+
# (PreToolUse fires BEFORE the edit, so: capture baseline THEN apply the edit).
|
|
190
|
+
rm -rf "$BDIR"
|
|
191
|
+
edit "$REPO/src/foo.go" S1 | bash "$ENGINE" pretool >/dev/null # baseline (foo.go clean)
|
|
192
|
+
echo "// real gated edit" >> "$REPO/src/foo.go" # the edit applies => dirty
|
|
193
|
+
d1=$( cd "$REPO" && stopj S1 | bash "$ENGINE" stop | sdecision )
|
|
194
|
+
d2=$( cd "$REPO" && stopj S1 | bash "$ENGINE" stop | sdecision )
|
|
195
|
+
{ [ "$d1" = block ] && [ "$d2" = stop ]; } && ok "main Stop blocks once per session (cap)" || bad "stop cap" "$d1/$d2"
|
|
196
|
+
d3=$( cd "$REPO" && stopj S2 | bash "$ENGINE" stop | sdecision )
|
|
197
|
+
[ "$d3" = stop ] && ok "fresh session not starved by another session's marker" || bad "cross-session" "$d3"
|
|
198
|
+
git -C "$REPO" checkout -q -- . 2>/dev/null
|
|
199
|
+
# 8b. No session id => fail-open (never trap).
|
|
200
|
+
d=$( cd "$REPO" && stopj "" | bash "$ENGINE" stop | sdecision )
|
|
201
|
+
[ "$d" = stop ] && ok "no session id => stop fail-open" || bad "no-session stop" "$d"
|
|
202
|
+
# 8c. session-scoped waiver => allow (even with a real changed gated file).
|
|
203
|
+
rm -rf "$BDIR"
|
|
204
|
+
edit "$REPO/src/foo.go" S3 | bash "$ENGINE" pretool >/dev/null; echo "// e" >> "$REPO/src/foo.go"
|
|
205
|
+
touch "$BDIR/s.S3.waiver"
|
|
206
|
+
[ "$( cd "$REPO" && stopj S3 | bash "$ENGINE" stop | sdecision )" = stop ] && ok "session-scoped waiver => allow" || bad "waiver"
|
|
207
|
+
git -C "$REPO" checkout -q -- . 2>/dev/null; rm -rf "$BDIR"
|
|
208
|
+
# 8d. after record, a boundary supersedes markers => gated edit ALLOWED (pretool).
|
|
209
|
+
edit "$REPO/src/foo.go" S4 | bash "$ENGINE" pretool >/dev/null
|
|
210
|
+
( cd "$REPO" && bash "$ENGINE" record --owners "product-rd-workflow" >/dev/null )
|
|
211
|
+
[ -z "$(edit "$REPO/src/foo.go" S4 | bash "$ENGINE" pretool)" ] && ok "record boundary supersedes markers => allow" || bad "record supersede"
|
|
212
|
+
rm -rf "$BDIR"
|
|
213
|
+
# 8e. OVER-FIRE FIX: read-only/dispatch-only session (heuristic match, CLEAN tree)
|
|
214
|
+
# records only the .bashwrite sentinel and must NOT block.
|
|
215
|
+
git -C "$REPO" checkout -q -- . 2>/dev/null; git -C "$REPO" clean -fdq 2>/dev/null
|
|
216
|
+
( cd "$REPO" && bashjs "cat src/foo.go | python3 -c 'print(1)'" S5 | bash "$ENGINE" pretool ) >/dev/null 2>&1
|
|
217
|
+
[ -r "$BDIR/s.S5.bashwrite" ] && [ ! -e "$BDIR/s.S5.touched" ] \
|
|
218
|
+
&& ok "read-only heuristic match records .bashwrite sentinel only" || bad "heuristic wrote wrong marker"
|
|
219
|
+
[ "$( cd "$REPO" && stopj S5 | bash "$ENGINE" stop | sdecision )" = stop ] \
|
|
220
|
+
&& ok "stop: read-only heuristic match + clean tree => allow (over-fire fix)" || bad "over-fire: clean tree blocked"
|
|
221
|
+
# 8f. heuristic session that DOES change a gated file => block.
|
|
222
|
+
echo "// real" >> "$REPO/src/foo.go"
|
|
223
|
+
[ "$( cd "$REPO" && stopj S5 | bash "$ENGINE" stop | sdecision )" = block ] \
|
|
224
|
+
&& ok "stop: heuristic session + changed gated path => block" || bad "true-positive lost"
|
|
225
|
+
git -C "$REPO" checkout -q -- . 2>/dev/null; rm -rf "$BDIR"
|
|
226
|
+
# 8g. config-shrink anti-bypass: a real gated edit still blocks even after the config
|
|
227
|
+
# is shrunk to de-classify it (baseline globs are unioned with current globs).
|
|
228
|
+
edit "$REPO/src/foo.go" SG | bash "$ENGINE" pretool >/dev/null # baseline globs incl. src/**
|
|
229
|
+
echo "// real gated edit" >> "$REPO/src/foo.go"
|
|
230
|
+
config <<'JSON'
|
|
231
|
+
{ "enabled": true, "product_globs": ["other/**"], "gate_bash": true }
|
|
232
|
+
JSON
|
|
233
|
+
[ "$( cd "$REPO" && stopj SG | bash "$ENGINE" stop | sdecision )" = block ] \
|
|
234
|
+
&& ok "stop: gated edit + config shrink => still block (baseline-glob union)" || bad "shrink false-negative"
|
|
235
|
+
git -C "$REPO" checkout -q -- . 2>/dev/null; rm -rf "$BDIR"
|
|
236
|
+
config <<'JSON'
|
|
237
|
+
{ "enabled": true, "strict": false, "gate_bash": true,
|
|
238
|
+
"product_globs": ["src/**"], "owner_hint": "product-rd-workflow + the stack *-dev owner" }
|
|
239
|
+
JSON
|
|
240
|
+
# 8h. committed-in-session gated edit (clean tree) STILL blocks (baseline HEAD diff
|
|
241
|
+
# sees the commit because `git diff <baseline-head>` compares to the work tree).
|
|
242
|
+
rm -rf "$BDIR"
|
|
243
|
+
edit "$REPO/src/foo.go" SH | bash "$ENGINE" pretool >/dev/null # baseline = pre-edit HEAD
|
|
244
|
+
echo "// committed gated edit" >> "$REPO/src/foo.go"
|
|
245
|
+
git -C "$REPO" add -A; git -C "$REPO" commit -qm "committed in-session" # tree clean, HEAD moved
|
|
246
|
+
[ "$( cd "$REPO" && stopj SH | bash "$ENGINE" stop | sdecision )" = block ] \
|
|
247
|
+
&& ok "stop: committed gated edit (clean tree) => still block (baseline HEAD diff)" || bad "commit false-pass"
|
|
248
|
+
rm -rf "$BDIR"
|
|
249
|
+
# 8h-2. Stop WORDING splits absent vs expired. Both still block; the message must not tell
|
|
250
|
+
# an actor that recorded a boundary it "never recorded" one — that wording sent
|
|
251
|
+
# diagnosis looking for a missing record when the record existed and had lapsed.
|
|
252
|
+
edit "$REPO/src/foo.go" SH2 | bash "$ENGINE" pretool >/dev/null
|
|
253
|
+
echo "// gated edit, no boundary at all" >> "$REPO/src/foo.go"
|
|
254
|
+
out_sh2=$( cd "$REPO" && stopj SH2 | bash "$ENGINE" stop 2>&1 )
|
|
255
|
+
# Assert the DECISION as well as the wording: grepping message text alone would pass on an
|
|
256
|
+
# allow response that happened to contain the same words.
|
|
257
|
+
[ "$(printf '%s' "$out_sh2" | sdecision)" = block ] \
|
|
258
|
+
&& printf '%s' "$out_sh2" | grep -q "never recorded an owner-dispatch boundary" \
|
|
259
|
+
&& ok "stop: absent boundary => block + 'never recorded' wording" || bad "S4 wording"
|
|
260
|
+
rm -rf "$BDIR"
|
|
261
|
+
edit "$REPO/src/foo.go" SH3 | bash "$ENGINE" pretool >/dev/null
|
|
262
|
+
echo "// gated edit, boundary recorded then expired" >> "$REPO/src/foo.go"
|
|
263
|
+
( cd "$REPO" && bash "$ENGINE" record --owners "product-rd-workflow" --ttl 0 >/dev/null )
|
|
264
|
+
out_sh3=$( cd "$REPO" && stopj SH3 | bash "$ENGINE" stop 2>&1 )
|
|
265
|
+
[ "$(printf '%s' "$out_sh3" | sdecision)" = block ] \
|
|
266
|
+
&& printf '%s' "$out_sh3" | grep -q "expired before this actor finished" \
|
|
267
|
+
&& ! printf '%s' "$out_sh3" | grep -q "never recorded an owner-dispatch boundary" \
|
|
268
|
+
&& ok "stop: expired boundary => block + 'expired' wording, not 'never recorded'" || bad "S5 wording"
|
|
269
|
+
rm -rf "$BDIR"
|
|
270
|
+
git -C "$REPO" checkout -q -- . 2>/dev/null
|
|
271
|
+
# 8i. rejected/undone edit => allow. PreToolUse records the marker+baseline, but the
|
|
272
|
+
# edit never applies (tree stays at baseline) => no new gated change => no false block.
|
|
273
|
+
edit "$REPO/src/foo.go" SI | bash "$ENGINE" pretool >/dev/null # marker+baseline; edit NOT applied
|
|
274
|
+
[ "$( cd "$REPO" && stopj SI | bash "$ENGINE" stop | sdecision )" = stop ] \
|
|
275
|
+
&& ok "stop: rejected/undone edit (tree at baseline) => allow (no false block)" || bad "rejected-edit false-block"
|
|
276
|
+
rm -rf "$BDIR"
|
|
277
|
+
# 8j. PRE-EXISTING dirty gated file (dirty BEFORE the session) + a heuristic match =>
|
|
278
|
+
# allow: the baseline records it as pre-existing, not this session's work.
|
|
279
|
+
echo "// pre-existing dirt" >> "$REPO/src/foo.go" # dirty BEFORE any touch
|
|
280
|
+
( cd "$REPO" && bashjs "cat src/foo.go | python3 -c 'print(1)'" SJ | bash "$ENGINE" pretool ) >/dev/null 2>&1
|
|
281
|
+
[ "$( cd "$REPO" && stopj SJ | bash "$ENGINE" stop | sdecision )" = stop ] \
|
|
282
|
+
&& ok "stop: pre-existing dirty gated file + heuristic => allow (baseline excludes it)" || bad "pre-existing-dirty false-block"
|
|
283
|
+
git -C "$REPO" checkout -q -- . 2>/dev/null; rm -rf "$BDIR"
|
|
284
|
+
# 8k. edit reverted/stashed back to baseline => allow (nothing landed).
|
|
285
|
+
edit "$REPO/src/foo.go" SK | bash "$ENGINE" pretool >/dev/null
|
|
286
|
+
echo "// will be reverted" >> "$REPO/src/foo.go"
|
|
287
|
+
git -C "$REPO" checkout -q -- "src/foo.go" # revert to baseline content
|
|
288
|
+
[ "$( cd "$REPO" && stopj SK | bash "$ENGINE" stop | sdecision )" = stop ] \
|
|
289
|
+
&& ok "stop: edit reverted to baseline => allow (nothing landed)" || bad "revert false-block"
|
|
290
|
+
rm -rf "$BDIR"
|
|
291
|
+
# 8l. pre-existing dirty gated file that is FURTHER edited this session => block
|
|
292
|
+
# (baseline records its content hash, so a re-edit is distinguishable from dirt).
|
|
293
|
+
echo "// pre-existing dirt" >> "$REPO/src/foo.go" # dirty BEFORE the session
|
|
294
|
+
edit "$REPO/src/foo.go" SL | bash "$ENGINE" pretool >/dev/null # baseline hashes foo.go as-is
|
|
295
|
+
echo "// further session edit" >> "$REPO/src/foo.go" # content now differs from baseline
|
|
296
|
+
[ "$( cd "$REPO" && stopj SL | bash "$ENGINE" stop | sdecision )" = block ] \
|
|
297
|
+
&& ok "stop: pre-existing dirty file FURTHER edited => block (content-hash baseline)" || bad "pre-existing re-edit false-pass"
|
|
298
|
+
git -C "$REPO" checkout -q -- . 2>/dev/null; rm -rf "$BDIR"
|
|
299
|
+
# 8m. exclude-widen anti-bypass: adding an exclude that covers the edited file after
|
|
300
|
+
# the first touch still blocks (baseline classification is honored).
|
|
301
|
+
edit "$REPO/src/foo.go" SM | bash "$ENGINE" pretool >/dev/null # baseline: src/** gated, no excl
|
|
302
|
+
echo "// real gated edit" >> "$REPO/src/foo.go"
|
|
303
|
+
config <<'JSON'
|
|
304
|
+
{ "enabled": true, "product_globs": ["src/**"], "exclude_globs": ["src/**"], "gate_bash": true }
|
|
305
|
+
JSON
|
|
306
|
+
[ "$( cd "$REPO" && stopj SM | bash "$ENGINE" stop | sdecision )" = block ] \
|
|
307
|
+
&& ok "stop: gated edit + exclude-widen => still block (baseline classification)" || bad "exclude-widen false-pass"
|
|
308
|
+
git -C "$REPO" checkout -q -- . 2>/dev/null; rm -rf "$BDIR"
|
|
309
|
+
config <<'JSON'
|
|
310
|
+
{ "enabled": true, "strict": false, "gate_bash": true,
|
|
311
|
+
"product_globs": ["src/**"], "owner_hint": "product-rd-workflow + the stack *-dev owner" }
|
|
312
|
+
JSON
|
|
313
|
+
|
|
314
|
+
# 9. Symlink-safe: a planted symlink state file must NOT clobber its target.
|
|
315
|
+
rm -rf "$BDIR"; mkdir -p "$BDIR"
|
|
316
|
+
SENT="$WORK/sentinel"; echo "PRECIOUS" > "$SENT"
|
|
317
|
+
ln -s "$SENT" "$BDIR/boundary.json"
|
|
318
|
+
( cd "$REPO" && bash "$ENGINE" record --owners "x" >/dev/null )
|
|
319
|
+
[ "$(cat "$SENT")" = "PRECIOUS" ] && ok "symlink-safe: record did not clobber symlink target" || bad "symlink clobber" "sentinel=$(cat "$SENT")"
|
|
320
|
+
[ ! -L "$BDIR/boundary.json" ] && ok "symlink-safe: planted symlink replaced with real file" || bad "symlink not replaced"
|
|
321
|
+
rm -rf "$BDIR"
|
|
322
|
+
|
|
323
|
+
# 9b. A leading **/ glob means "zero or more directories" and MUST gate a
|
|
324
|
+
# TOP-LEVEL (repo-root) product file too. bash `case` is not globstar-aware,
|
|
325
|
+
# so **/*.go alone only matches paths WITH a slash — a repo whose product
|
|
326
|
+
# code is top-level + ["**/*.go"] config silently gates NOTHING (observed:
|
|
327
|
+
# a real adapter repo was a complete no-op until the glob was fixed).
|
|
328
|
+
config <<'JSON'
|
|
329
|
+
{ "enabled": true, "strict": false, "gate_bash": true,
|
|
330
|
+
"product_globs": ["**/*.go"], "exclude_globs": ["**/*_test.go"] }
|
|
331
|
+
JSON
|
|
332
|
+
echo "package x" > "$REPO/root.go"
|
|
333
|
+
[ "$(edit "$REPO/root.go" S9 | bash "$ENGINE" pretool | decision)" = ask ] && ok "**/ glob gates top-level root.go (zero-or-more dirs)" || bad "top-level **/*.go NOT gated" "the no-op trap: a repo-root product file is ungated"
|
|
334
|
+
echo "package x" > "$REPO/root_test.go"
|
|
335
|
+
[ -z "$(edit "$REPO/root_test.go" | bash "$ENGINE" pretool)" ] && ok "**/ exclude still excludes top-level root_test.go" || bad "top-level **/*_test.go not excluded"
|
|
336
|
+
[ "$(edit "$REPO/src/foo.go" S9 | bash "$ENGINE" pretool | decision)" = ask ] && ok "**/ glob still gates subdir src/foo.go (no regression)" || bad "subdir regression under **/ glob"
|
|
337
|
+
rm -rf "$BDIR"
|
|
338
|
+
|
|
339
|
+
# ---- 10. CI backstop (raw config writes; commits managed explicitly per scenario) ----
|
|
340
|
+
rawcfg(){ cat > "$REPO/.owner-dispatch.json"; }
|
|
341
|
+
gc(){ git -C "$REPO" add -A; git -C "$REPO" commit -q -m "$1"; }
|
|
342
|
+
EN='{ "enabled": true, "product_globs": ["src/**"], "ci_artifact": "design/map.md" }'
|
|
343
|
+
|
|
344
|
+
# 10a. enabled, gated change, no artifact => fail.
|
|
345
|
+
printf '%s\n' "$EN" | rawcfg; gc cfg
|
|
346
|
+
base=$(git -C "$REPO" rev-parse HEAD)
|
|
347
|
+
echo "// change" >> "$REPO/src/foo.go"; gc change
|
|
348
|
+
( cd "$REPO" && bash "$ENGINE" ci --base "$base" >/dev/null 2>&1 ) && bad "ci no-artifact should fail" || ok "ci: gated change, no artifact => fail"
|
|
349
|
+
# 10b. artifact updated in the change => ok.
|
|
350
|
+
mkdir -p "$REPO/design"; echo "owners: x" > "$REPO/design/map.md"; gc map
|
|
351
|
+
( cd "$REPO" && bash "$ENGINE" ci --base "$base" >/dev/null 2>&1 ) && ok "ci: artifact updated in change => ok" || bad "ci ok"
|
|
352
|
+
# 10c. stale artifact (gated change without touching the map) => fail.
|
|
353
|
+
base2=$(git -C "$REPO" rev-parse HEAD)
|
|
354
|
+
echo "// more" >> "$REPO/src/foo.go"; gc change2
|
|
355
|
+
( cd "$REPO" && bash "$ENGINE" ci --base "$base2" >/dev/null 2>&1 ) && bad "ci stale should fail" || ok "ci: stale artifact => fail"
|
|
356
|
+
# 10d. unsafe ci_artifact path (+ gated change) => fail.
|
|
357
|
+
printf '%s\n' '{ "enabled": true, "product_globs": ["src/**"], "ci_artifact": "../evil" }' | rawcfg
|
|
358
|
+
echo "// c" >> "$REPO/src/foo.go"; gc badcfg
|
|
359
|
+
( cd "$REPO" && bash "$ENGINE" ci --base "$(git -C "$REPO" rev-parse HEAD~1)" >/dev/null 2>&1 ) && bad "ci unsafe should fail" || ok "ci: unsafe ci_artifact path => fail"
|
|
360
|
+
# 10e. shrink product_globs to dodge a gated change (base globs still apply) => fail.
|
|
361
|
+
printf '%s\n' "$EN" | rawcfg; gc reenable
|
|
362
|
+
shrinkbase=$(git -C "$REPO" rev-parse HEAD)
|
|
363
|
+
printf '%s\n' '{ "enabled": true, "product_globs": ["nonexistent/**"], "ci_artifact": "design/map.md" }' | rawcfg
|
|
364
|
+
echo "// dodge" >> "$REPO/src/foo.go"; gc shrink
|
|
365
|
+
( cd "$REPO" && bash "$ENGINE" ci --base "$shrinkbase" >/dev/null 2>&1 ) && bad "ci shrink-dodge should fail" || ok "ci: shrink product_globs to dodge => fail (base-glob union)"
|
|
366
|
+
# 10f. disable + gated change in one commit (from enabled base) => fail.
|
|
367
|
+
printf '%s\n' "$EN" | rawcfg; gc reenable2
|
|
368
|
+
enbase=$(git -C "$REPO" rev-parse HEAD)
|
|
369
|
+
printf '%s\n' '{ "enabled": false, "product_globs": ["src/**"] }' | rawcfg
|
|
370
|
+
echo "// sneaky" >> "$REPO/src/foo.go"; gc disable
|
|
371
|
+
( cd "$REPO" && bash "$ENGINE" ci --base "$enbase" >/dev/null 2>&1 ) && bad "ci disable+gated should fail" || ok "ci: disable gate + gated change => fail (anti-bypass)"
|
|
372
|
+
# 10g. clean decommit: config-only removal, no gated change => allowed (0).
|
|
373
|
+
printf '%s\n' "$EN" | rawcfg; echo "// x" >> "$REPO/src/foo.go"; gc reenable3
|
|
374
|
+
enbase2=$(git -C "$REPO" rev-parse HEAD)
|
|
375
|
+
git -C "$REPO" rm -q .owner-dispatch.json; git -C "$REPO" commit -q -m decommit
|
|
376
|
+
( cd "$REPO" && bash "$ENGINE" ci --base "$enbase2" >/dev/null 2>&1 ) && ok "ci: clean config-only decommit => allowed(0)" || bad "ci decommit"
|
|
377
|
+
# 10g2. ci_artifact pointing at product code (would self-satisfy) => fail.
|
|
378
|
+
printf '%s\n' "$EN" | rawcfg; gc reN
|
|
379
|
+
b_art=$(git -C "$REPO" rev-parse HEAD)
|
|
380
|
+
printf '%s\n' '{ "enabled": true, "product_globs": ["src/**"], "ci_artifact": "src/foo.go" }' | rawcfg
|
|
381
|
+
echo "// art" >> "$REPO/src/foo.go"; gc artbad
|
|
382
|
+
( cd "$REPO" && bash "$ENGINE" ci --base "$b_art" >/dev/null 2>&1 ) && bad "ci artifact=product should fail" || ok "ci: ci_artifact pointing at product code => fail"
|
|
383
|
+
# 10g3. enabled but schema-invalid config (product_globs not an array) => fail-closed.
|
|
384
|
+
printf '%s\n' "$EN" | rawcfg; gc reS
|
|
385
|
+
b_sch=$(git -C "$REPO" rev-parse HEAD)
|
|
386
|
+
printf '%s\n' '{ "enabled": true, "product_globs": "src/**" }' | rawcfg
|
|
387
|
+
echo "// s" >> "$REPO/src/foo.go"; gc schbad
|
|
388
|
+
( cd "$REPO" && bash "$ENGINE" ci --base "$b_sch" >/dev/null 2>&1 ) && bad "ci schema-invalid should fail" || ok "ci: enabled schema-invalid config => fail-closed"
|
|
389
|
+
# 10g5. tracked-but-malformed config + gated change (from a non-enabled base) => fail-closed.
|
|
390
|
+
git -C "$REPO" rm -q .owner-dispatch.json 2>/dev/null; gc noc
|
|
391
|
+
b_m=$(git -C "$REPO" rev-parse HEAD)
|
|
392
|
+
printf '%s' '{ bad json not closed' > "$REPO/.owner-dispatch.json"; echo "// m" >> "$REPO/src/foo.go"; gc malformed
|
|
393
|
+
( cd "$REPO" && bash "$ENGINE" ci --base "$b_m" >/dev/null 2>&1 ) && bad "ci malformed should fail" || ok "ci: tracked malformed config => fail-closed"
|
|
394
|
+
# 10g5b. tracked-but-non-object JSON is also malformed as a config => fail-closed.
|
|
395
|
+
printf '%s\n' "$EN" | rawcfg; gc reObj
|
|
396
|
+
b_obj=$(git -C "$REPO" rev-parse HEAD)
|
|
397
|
+
printf '%s\n' '[]' > "$REPO/.owner-dispatch.json"; gc nonobject
|
|
398
|
+
( cd "$REPO" && bash "$ENGINE" ci --base "$b_obj" >/dev/null 2>&1 ) && bad "ci non-object config should fail" || ok "ci: tracked non-object config => fail-closed"
|
|
399
|
+
# 10g6. ./-prefixed ci_artifact resolves to git path form => not false-failed.
|
|
400
|
+
printf '%s\n' '{ "enabled": true, "product_globs": ["src/**"], "ci_artifact": "./design/map.md" }' | rawcfg; gc reDot
|
|
401
|
+
b_dot=$(git -C "$REPO" rev-parse HEAD)
|
|
402
|
+
echo "// d" >> "$REPO/src/foo.go"; mkdir -p "$REPO/design"; echo owners > "$REPO/design/map.md"; gc dotchange
|
|
403
|
+
( cd "$REPO" && bash "$ENGINE" ci --base "$b_dot" >/dev/null 2>&1 ) && ok "ci: ./-prefixed ci_artifact matches => ok" || bad "ci dot-artifact false-fail"
|
|
404
|
+
# 10g6b. '..' inside a filename is safe; only '..' path components are unsafe.
|
|
405
|
+
printf '%s\n' '{ "enabled": true, "product_globs": ["src/**"], "ci_artifact": "design/v1..2-map.md" }' | rawcfg; gc reDotsName
|
|
406
|
+
b_dots_name=$(git -C "$REPO" rev-parse HEAD)
|
|
407
|
+
echo "// d2" >> "$REPO/src/foo.go"; mkdir -p "$REPO/design"; echo owners > "$REPO/design/v1..2-map.md"; gc dotsname
|
|
408
|
+
( cd "$REPO" && bash "$ENGINE" ci --base "$b_dots_name" >/dev/null 2>&1 ) && ok "ci: ci_artifact filename containing '..' => ok" || bad "ci dots-in-filename false-fail"
|
|
409
|
+
# 10g7. malforming an enabled config in a config-only change (no product change) => fail-closed.
|
|
410
|
+
printf '%s\n' "$EN" | rawcfg; gc reMM
|
|
411
|
+
b_mm=$(git -C "$REPO" rev-parse HEAD)
|
|
412
|
+
printf '%s' '{ bad' > "$REPO/.owner-dispatch.json"; gc malformonly
|
|
413
|
+
( cd "$REPO" && bash "$ENGINE" ci --base "$b_mm" >/dev/null 2>&1 ) && bad "malform-only should fail" || ok "ci: malform enabled config (config-only) => fail-closed (not decommit)"
|
|
414
|
+
# 10g4. a gated product path WITH A SPACE is classified correctly (no substring/split bug).
|
|
415
|
+
printf '%s\n' "$EN" | rawcfg; gc reSP
|
|
416
|
+
b_sp=$(git -C "$REPO" rev-parse HEAD)
|
|
417
|
+
echo "x" > "$REPO/src/a b.go"; gc spacefile
|
|
418
|
+
( cd "$REPO" && bash "$ENGINE" ci --base "$b_sp" >/dev/null 2>&1 ) && bad "ci space-path should fail (gated, no map)" || ok "ci: gated path with a space classified => fail"
|
|
419
|
+
# 10g8. CI fallback: a runner without jq but with python3 still verifies the same
|
|
420
|
+
# backstop semantics instead of warning forever because a shared runner lacks jq.
|
|
421
|
+
NOJQBIN="$WORK/nojqbin"; mkdir -p "$NOJQBIN"
|
|
422
|
+
for _cmd in bash git python3 dirname basename; do ln -sf "$(command -v "$_cmd")" "$NOJQBIN/$_cmd"; done
|
|
423
|
+
EN_NJ='{ "enabled": true, "product_globs": ["src/**"], "ci_artifact": "design/nojq-map.md" }'
|
|
424
|
+
printf '%s\n' "$EN_NJ" | rawcfg; gc reNJ
|
|
425
|
+
b_nj=$(git -C "$REPO" rev-parse HEAD)
|
|
426
|
+
echo "// nojq fail" >> "$REPO/src/foo.go"; gc nojqfail
|
|
427
|
+
( cd "$REPO" && PATH="$NOJQBIN" bash "$ENGINE" ci --base "$b_nj" >/dev/null 2>&1 ) \
|
|
428
|
+
&& bad "ci no-jq no-artifact should fail" || ok "ci: no-jq fallback keeps no-artifact failure"
|
|
429
|
+
mkdir -p "$REPO/design"; printf 'owners nojq\n' > "$REPO/design/nojq-map.md"; gc nojqmap
|
|
430
|
+
( cd "$REPO" && PATH="$NOJQBIN" bash "$ENGINE" ci --base "$b_nj" >/dev/null 2>&1 ) \
|
|
431
|
+
&& ok "ci: no-jq fallback accepts updated artifact" || bad "ci no-jq fallback false-fail"
|
|
432
|
+
jq_rc=0; ( cd "$REPO" && bash "$ENGINE" ci --base "$b_nj" >/dev/null 2>&1 ) || jq_rc=$?
|
|
433
|
+
py_rc=0; ( cd "$REPO" && PATH="$NOJQBIN" bash "$ENGINE" ci --base "$b_nj" >/dev/null 2>&1 ) || py_rc=$?
|
|
434
|
+
[ "$jq_rc" = "$py_rc" ] && ok "ci: jq and no-jq verdicts match on same fixture ($jq_rc)" || bad "ci jq/no-jq parity" "jq=$jq_rc py=$py_rc"
|
|
435
|
+
EN_STAR='{ "enabled": true, "product_globs": ["src/*.go"], "ci_artifact": "design/star-map.md" }'
|
|
436
|
+
printf '%s\n' "$EN_STAR" | rawcfg; gc reStar
|
|
437
|
+
b_star=$(git -C "$REPO" rev-parse HEAD)
|
|
438
|
+
mkdir -p "$REPO/src/nested" "$REPO/design"; echo "package nested" > "$REPO/src/nested/b.go"; echo star > "$REPO/design/star-map.md"; gc starglob
|
|
439
|
+
jq_rc=0; ( cd "$REPO" && bash "$ENGINE" ci --base "$b_star" >/dev/null 2>&1 ) || jq_rc=$?
|
|
440
|
+
py_rc=0; ( cd "$REPO" && PATH="$NOJQBIN" bash "$ENGINE" ci --base "$b_star" >/dev/null 2>&1 ) || py_rc=$?
|
|
441
|
+
[ "$jq_rc" = "$py_rc" ] && ok "ci: jq/no-jq parity for single-star nested path ($jq_rc)" || bad "ci single-star parity" "jq=$jq_rc py=$py_rc"
|
|
442
|
+
EN_EXCL='{ "enabled": true, "product_globs": ["src/**"], "exclude_globs": ["src/*.go"], "ci_artifact": "design/exclude-map.md" }'
|
|
443
|
+
printf '%s\n' "$EN_EXCL" | rawcfg; gc reExcl
|
|
444
|
+
b_excl=$(git -C "$REPO" rev-parse HEAD)
|
|
445
|
+
echo "package excluded" > "$REPO/src/nested/excluded.go"; gc exclglob
|
|
446
|
+
jq_rc=0; ( cd "$REPO" && bash "$ENGINE" ci --base "$b_excl" >/dev/null 2>&1 ) || jq_rc=$?
|
|
447
|
+
py_rc=0; ( cd "$REPO" && PATH="$NOJQBIN" bash "$ENGINE" ci --base "$b_excl" >/dev/null 2>&1 ) || py_rc=$?
|
|
448
|
+
[ "$jq_rc" = "$py_rc" ] && ok "ci: jq/no-jq parity for exclude single-star nested path ($jq_rc)" || bad "ci exclude-star parity" "jq=$jq_rc py=$py_rc"
|
|
449
|
+
EN_ROOTTXT='{ "enabled": true, "product_globs": ["**/*.txt"], "ci_artifact": "design/root-txt-map.md" }'
|
|
450
|
+
printf '%s\n' "$EN_ROOTTXT" | rawcfg; gc reRootTxt
|
|
451
|
+
b_root_txt=$(git -C "$REPO" rev-parse HEAD)
|
|
452
|
+
echo root > "$REPO/root.txt"; gc roottxt
|
|
453
|
+
jq_rc=0; ( cd "$REPO" && bash "$ENGINE" ci --base "$b_root_txt" >/dev/null 2>&1 ) || jq_rc=$?
|
|
454
|
+
py_rc=0; ( cd "$REPO" && PATH="$NOJQBIN" bash "$ENGINE" ci --base "$b_root_txt" >/dev/null 2>&1 ) || py_rc=$?
|
|
455
|
+
[ "$jq_rc" = "$py_rc" ] && ok "ci: jq/no-jq parity for **/ product root path ($jq_rc)" || bad "ci root **/ product parity" "jq=$jq_rc py=$py_rc"
|
|
456
|
+
EN_ROOTMD='{ "enabled": true, "product_globs": ["**/*.md"], "ci_artifact": "design/root-md-map.md" }'
|
|
457
|
+
printf '%s\n' "$EN_ROOTMD" | rawcfg; gc reRootMd
|
|
458
|
+
b_root_md=$(git -C "$REPO" rev-parse HEAD)
|
|
459
|
+
echo root > "$REPO/root.md"; gc rootmd
|
|
460
|
+
jq_rc=0; ( cd "$REPO" && bash "$ENGINE" ci --base "$b_root_md" >/dev/null 2>&1 ) || jq_rc=$?
|
|
461
|
+
py_rc=0; ( cd "$REPO" && PATH="$NOJQBIN" bash "$ENGINE" ci --base "$b_root_md" >/dev/null 2>&1 ) || py_rc=$?
|
|
462
|
+
[ "$jq_rc" = "$py_rc" ] && ok "ci: jq/no-jq parity for default **/*.md root exclude ($jq_rc)" || bad "ci root md exclude parity" "jq=$jq_rc py=$py_rc"
|
|
463
|
+
EN_EMPTY_ART='{ "enabled": true, "product_globs": ["src/**"], "ci_artifact": "" }'
|
|
464
|
+
printf '%s\n' "$EN_EMPTY_ART" | rawcfg; gc reEmptyArt
|
|
465
|
+
b_empty_art=$(git -C "$REPO" rev-parse HEAD)
|
|
466
|
+
echo "// empty art" >> "$REPO/src/foo.go"; gc emptyart
|
|
467
|
+
jq_rc=0; ( cd "$REPO" && bash "$ENGINE" ci --base "$b_empty_art" >/dev/null 2>&1 ) || jq_rc=$?
|
|
468
|
+
py_rc=0; ( cd "$REPO" && PATH="$NOJQBIN" bash "$ENGINE" ci --base "$b_empty_art" >/dev/null 2>&1 ) || py_rc=$?
|
|
469
|
+
[ "$jq_rc" = "$py_rc" ] && ok "ci: jq/no-jq parity for empty ci_artifact ($jq_rc)" || bad "ci empty artifact parity" "jq=$jq_rc py=$py_rc"
|
|
470
|
+
EN_NULL_ART='{ "enabled": true, "product_globs": ["src/**"], "ci_artifact": null }'
|
|
471
|
+
printf '%s\n' "$EN_NULL_ART" | rawcfg; gc reNullArt
|
|
472
|
+
b_null_art=$(git -C "$REPO" rev-parse HEAD)
|
|
473
|
+
echo "// null art" >> "$REPO/src/foo.go"; mkdir -p "$REPO/design"; echo owners > "$REPO/design/owner-dispatch-map.md"; gc nullart
|
|
474
|
+
jq_rc=0; ( cd "$REPO" && bash "$ENGINE" ci --base "$b_null_art" >/dev/null 2>&1 ) || jq_rc=$?
|
|
475
|
+
py_rc=0; ( cd "$REPO" && PATH="$NOJQBIN" bash "$ENGINE" ci --base "$b_null_art" >/dev/null 2>&1 ) || py_rc=$?
|
|
476
|
+
[ "$jq_rc" = "$py_rc" ] && ok "ci: jq/no-jq parity for null ci_artifact default ($jq_rc)" || bad "ci null artifact parity" "jq=$jq_rc py=$py_rc"
|
|
477
|
+
EN_STRICT='{ "enabled": true, "strict": true, "gate_bash": false, "product_globs": ["src/**"], "ci_artifact": "design/strict-map.md" }'
|
|
478
|
+
printf '%s\n' "$EN_STRICT" | rawcfg; gc reStrict
|
|
479
|
+
b_strict=$(git -C "$REPO" rev-parse HEAD)
|
|
480
|
+
echo "// strict" >> "$REPO/src/foo.go"; echo strict > "$REPO/design/strict-map.md"; gc strictci
|
|
481
|
+
jq_rc=0; ( cd "$REPO" && bash "$ENGINE" ci --base "$b_strict" >/dev/null 2>&1 ) || jq_rc=$?
|
|
482
|
+
py_rc=0; ( cd "$REPO" && PATH="$NOJQBIN" bash "$ENGINE" ci --base "$b_strict" >/dev/null 2>&1 ) || py_rc=$?
|
|
483
|
+
[ "$jq_rc" = "$py_rc" ] && ok "ci: jq/no-jq parity for strict+gate_bash schema edge ($jq_rc)" || bad "ci strict/gate_bash parity" "jq=$jq_rc py=$py_rc"
|
|
484
|
+
EN_BAD_BOOL='{ "enabled": true, "strict": 1, "gate_bash": "false", "product_globs": ["src/**"], "ci_artifact": "design/bad-bool-map.md" }'
|
|
485
|
+
printf '%s\n' "$EN_BAD_BOOL" | rawcfg; gc reBadBool
|
|
486
|
+
b_bad_bool=$(git -C "$REPO" rev-parse HEAD)
|
|
487
|
+
echo "// bad bool" >> "$REPO/src/foo.go"; gc badbool
|
|
488
|
+
jq_rc=0; ( cd "$REPO" && bash "$ENGINE" ci --base "$b_bad_bool" >/dev/null 2>&1 ) || jq_rc=$?
|
|
489
|
+
py_rc=0; ( cd "$REPO" && PATH="$NOJQBIN" bash "$ENGINE" ci --base "$b_bad_bool" >/dev/null 2>&1 ) || py_rc=$?
|
|
490
|
+
[ "$jq_rc" = "$py_rc" ] && ok "ci: jq/no-jq parity for non-boolean strict/gate_bash ($jq_rc)" || bad "ci bad bool parity" "jq=$jq_rc py=$py_rc"
|
|
491
|
+
EN_EMPTY_BRANCH='{ "enabled": true, "product_globs": ["src/**"], "ci_artifact": "design/empty-branch-map.md" }'
|
|
492
|
+
printf '%s\n' "$EN_EMPTY_BRANCH" | rawcfg; gc reEmptyBranch
|
|
493
|
+
b_empty_branch=$(git -C "$REPO" rev-parse HEAD)
|
|
494
|
+
git -C "$REPO" update-ref refs/remotes/origin/main "$b_empty_branch"
|
|
495
|
+
echo "// empty branch" >> "$REPO/src/foo.go"; echo branch > "$REPO/design/empty-branch-map.md"; gc emptybranch
|
|
496
|
+
jq_rc=0; ( cd "$REPO" && CI_DEFAULT_BRANCH="" bash "$ENGINE" ci >/dev/null 2>&1 ) || jq_rc=$?
|
|
497
|
+
py_rc=0; ( cd "$REPO" && CI_DEFAULT_BRANCH="" PATH="$NOJQBIN" bash "$ENGINE" ci >/dev/null 2>&1 ) || py_rc=$?
|
|
498
|
+
[ "$jq_rc" = "$py_rc" ] && ok "ci: jq/no-jq parity for empty CI_DEFAULT_BRANCH fallback ($jq_rc)" || bad "ci empty CI_DEFAULT_BRANCH parity" "jq=$jq_rc py=$py_rc"
|
|
499
|
+
printf '%s\n' "$EN_NJ" | rawcfg; gc reNJS
|
|
500
|
+
b_njs=$(git -C "$REPO" rev-parse HEAD)
|
|
501
|
+
printf '%s\n' '{ "enabled": true, "product_globs": "src/**", "ci_artifact": "design/nojq-map.md" }' | rawcfg
|
|
502
|
+
echo "// nojq schema" >> "$REPO/src/foo.go"; gc nojqschema
|
|
503
|
+
py_rc=0; ( cd "$REPO" && PATH="$NOJQBIN" bash "$ENGINE" ci --base "$b_njs" >/dev/null 2>&1 ) || py_rc=$?
|
|
504
|
+
[ "$py_rc" = 2 ] && ok "ci: no-jq fallback schema-invalid => fail-closed(2)" || bad "ci no-jq schema rc" "py=$py_rc"
|
|
505
|
+
printf '%s\n' "$EN_NJ" | rawcfg; gc reNJD
|
|
506
|
+
b_njd=$(git -C "$REPO" rev-parse HEAD)
|
|
507
|
+
printf '%s\n' '{ "enabled": false, "product_globs": ["src/**"], "ci_artifact": "design/nojq-map.md" }' | rawcfg
|
|
508
|
+
echo "// nojq disable" >> "$REPO/src/foo.go"; gc nojqdisable
|
|
509
|
+
py_rc=0; ( cd "$REPO" && PATH="$NOJQBIN" bash "$ENGINE" ci --base "$b_njd" >/dev/null 2>&1 ) || py_rc=$?
|
|
510
|
+
[ "$py_rc" = 1 ] && ok "ci: no-jq fallback disable+gated => fail(1)" || bad "ci no-jq disable rc" "py=$py_rc"
|
|
511
|
+
printf '%s\n' "$EN_NJ" | rawcfg; gc reNJObj
|
|
512
|
+
b_njo=$(git -C "$REPO" rev-parse HEAD)
|
|
513
|
+
printf '%s\n' '[]' > "$REPO/.owner-dispatch.json"; gc nojqnonobject
|
|
514
|
+
jq_rc=0; ( cd "$REPO" && bash "$ENGINE" ci --base "$b_njo" >/dev/null 2>&1 ) || jq_rc=$?
|
|
515
|
+
py_rc=0; ( cd "$REPO" && PATH="$NOJQBIN" bash "$ENGINE" ci --base "$b_njo" >/dev/null 2>&1 ) || py_rc=$?
|
|
516
|
+
[ "$py_rc" = 2 ] && ok "ci: no-jq fallback non-object config => fail-closed(2)" || bad "ci no-jq non-object rc" "py=$py_rc"
|
|
517
|
+
[ "$jq_rc" = "$py_rc" ] && ok "ci: jq/no-jq parity for non-object config ($jq_rc)" || bad "ci non-object parity" "jq=$jq_rc py=$py_rc"
|
|
518
|
+
# 10h. never opted in (absent at base AND head) => skip(0).
|
|
519
|
+
git -C "$REPO" rm -q .owner-dispatch.json 2>/dev/null; gc rmfinal
|
|
520
|
+
nb=$(git -C "$REPO" rev-parse HEAD)
|
|
521
|
+
echo "// z" >> "$REPO/src/foo.go"; gc more
|
|
522
|
+
( cd "$REPO" && bash "$ENGINE" ci --base "$nb" >/dev/null 2>&1 ) && ok "ci: never opted in => skip(0)" || bad "ci skip"
|
|
523
|
+
# 10i. CI fails CLOSED when it cannot determine a base (no --base, no upstream).
|
|
524
|
+
if ( cd "$REPO" && bash "$ENGINE" ci >/dev/null 2>&1 ); then bad "ci no-base should fail-closed"; else ok "ci: no base => fail-closed (non-zero)"; fi
|
|
525
|
+
|
|
526
|
+
# ---- 11. SubagentStop: agent_id-scoped enforcement (the same engine handles Stop +
|
|
527
|
+
# SubagentStop; agent_id is present only for the latter and scopes markers/cap). ----
|
|
528
|
+
rm -rf "$BDIR"
|
|
529
|
+
config <<'JSON'
|
|
530
|
+
{ "enabled": true, "strict": false, "gate_bash": true,
|
|
531
|
+
"product_globs": ["src/**"], "owner_hint": "product-rd-workflow + the stack *-dev owner" }
|
|
532
|
+
JSON
|
|
533
|
+
# pretool/stop input variants that carry agent_id (subagent context).
|
|
534
|
+
edita() { printf '{"tool_name":"Edit","tool_input":{"file_path":"%s"},"session_id":"%s","agent_id":"%s"}' "$1" "$2" "$3"; }
|
|
535
|
+
stopa() { printf '{"session_id":"%s","agent_id":"%s"}' "$1" "$2"; }
|
|
536
|
+
# Mirror the engine's injective agent_id key (jq @base64 of the raw value, base64url-ized).
|
|
537
|
+
akey() { jq -nr --arg a "$1" '$a | @base64' | tr '+/' '-_'; }
|
|
538
|
+
|
|
539
|
+
# 11a. RED baseline: WITHOUT the subagent edit there is no per-agent activity => allow.
|
|
540
|
+
[ "$( cd "$REPO" && stopa SUB A1 | bash "$ENGINE" stop | sdecision )" = stop ] \
|
|
541
|
+
&& ok "SubagentStop baseline: no per-agent activity => allow" || bad "subagent baseline"
|
|
542
|
+
# 11b. subagent edits gated code => SubagentStop blocks ONCE for that agent.
|
|
543
|
+
edita "$REPO/src/foo.go" SUB A1 | bash "$ENGINE" pretool >/dev/null # baseline + per-agent .touched
|
|
544
|
+
echo "// sub gated edit" >> "$REPO/src/foo.go"
|
|
545
|
+
s1=$( cd "$REPO" && stopa SUB A1 | bash "$ENGINE" stop | sdecision )
|
|
546
|
+
s2=$( cd "$REPO" && stopa SUB A1 | bash "$ENGINE" stop | sdecision )
|
|
547
|
+
{ [ "$s1" = block ] && [ "$s2" = stop ]; } && ok "SubagentStop: subagent gated edit => block once per agent" || bad "subagent cap" "$s1/$s2"
|
|
548
|
+
# 11c. a read-only sibling subagent (same session, no activity) is NOT starved/blocked.
|
|
549
|
+
[ "$( cd "$REPO" && stopa SUB A2 | bash "$ENGINE" stop | sdecision )" = stop ] \
|
|
550
|
+
&& ok "SubagentStop: read-only sibling subagent => allow (per-agent activity gate)" || bad "sibling subagent false-block"
|
|
551
|
+
# 11d. the MAIN Stop (no agent_id) has an INDEPENDENT cap — a subagent's block does not
|
|
552
|
+
# consume the main session's nudge (markers exist at session scope too).
|
|
553
|
+
[ "$( cd "$REPO" && stopj SUB | bash "$ENGINE" stop | sdecision )" = block ] \
|
|
554
|
+
&& ok "Stop: main session blocks independently of the subagent's cap" || bad "main cap shared with subagent"
|
|
555
|
+
git -C "$REPO" checkout -q -- . 2>/dev/null; rm -rf "$BDIR"
|
|
556
|
+
# 11e. per-subagent waiver => allow (even with a real changed gated file).
|
|
557
|
+
edita "$REPO/src/foo.go" SUB A3 | bash "$ENGINE" pretool >/dev/null
|
|
558
|
+
echo "// gated" >> "$REPO/src/foo.go"
|
|
559
|
+
touch "$BDIR/s.SUB.a.$(akey A3).waiver"
|
|
560
|
+
[ "$( cd "$REPO" && stopa SUB A3 | bash "$ENGINE" stop | sdecision )" = stop ] \
|
|
561
|
+
&& ok "SubagentStop: per-subagent waiver => allow" || bad "subagent waiver"
|
|
562
|
+
git -C "$REPO" checkout -q -- . 2>/dev/null; rm -rf "$BDIR"
|
|
563
|
+
# 11f. a session-level waiver suppresses a subagent block too (broad escape hatch).
|
|
564
|
+
edita "$REPO/src/foo.go" SUB A5 | bash "$ENGINE" pretool >/dev/null
|
|
565
|
+
echo "// gated" >> "$REPO/src/foo.go"
|
|
566
|
+
touch "$BDIR/s.SUB.waiver"
|
|
567
|
+
[ "$( cd "$REPO" && stopa SUB A5 | bash "$ENGINE" stop | sdecision )" = stop ] \
|
|
568
|
+
&& ok "SubagentStop: session-level waiver suppresses subagent block" || bad "session waiver vs subagent"
|
|
569
|
+
git -C "$REPO" checkout -q -- . 2>/dev/null; rm -rf "$BDIR"
|
|
570
|
+
# 11g. PreToolUse still nudges a subagent editing gated code (ask), and records the
|
|
571
|
+
# per-agent marker for the Stop backstop.
|
|
572
|
+
[ "$( edita "$REPO/src/foo.go" SUB A6 | bash "$ENGINE" pretool | decision )" = ask ] \
|
|
573
|
+
&& ok "PreToolUse: subagent gated edit => ask (fires in subagents)" || bad "subagent pretool ask"
|
|
574
|
+
[ -r "$BDIR/s.SUB.a.$(akey A6).touched" ] && ok "PreToolUse: subagent records per-agent .touched marker" || bad "no per-agent marker"
|
|
575
|
+
rm -rf "$BDIR"
|
|
576
|
+
# 11h. ACTOR-PRECISE attribution (the P1 fix): A1 attempts a gated edit (records a marker)
|
|
577
|
+
# but does NOT change anything; A2 changes a DIFFERENT gated file. A1's SubagentStop
|
|
578
|
+
# must ALLOW (not blamed for A2's change); A2's must BLOCK.
|
|
579
|
+
git -C "$REPO" checkout -q -- . 2>/dev/null; git -C "$REPO" clean -fdq 2>/dev/null
|
|
580
|
+
echo "package b" > "$REPO/src/b.go"; git -C "$REPO" add -A; git -C "$REPO" commit -qm addb
|
|
581
|
+
edita "$REPO/src/foo.go" SUB A1 | bash "$ENGINE" pretool >/dev/null # A1 marker on foo.go; edit NOT applied
|
|
582
|
+
edita "$REPO/src/b.go" SUB A2 | bash "$ENGINE" pretool >/dev/null # A2 marker on b.go
|
|
583
|
+
echo "// only A2's file changes" >> "$REPO/src/b.go" # only b.go is dirty
|
|
584
|
+
[ "$( cd "$REPO" && stopa SUB A1 | bash "$ENGINE" stop | sdecision )" = stop ] \
|
|
585
|
+
&& ok "SubagentStop: A1 attempted-but-unchanged, sibling A2 changed => A1 allow (no cross-blame)" || bad "cross-agent false-block (P1)"
|
|
586
|
+
[ "$( cd "$REPO" && stopa SUB A2 | bash "$ENGINE" stop | sdecision )" = block ] \
|
|
587
|
+
&& ok "SubagentStop: A2 actually changed its gated file => A2 block (true positive kept)" || bad "A2 true-positive lost"
|
|
588
|
+
git -C "$REPO" checkout -q -- . 2>/dev/null; git -C "$REPO" clean -fdq 2>/dev/null; rm -rf "$BDIR"
|
|
589
|
+
# 11i. Bash-only subagent (heuristic sentinel, no .touched path list) is not path-
|
|
590
|
+
# attributable => SubagentStop does NOT block (advisory Bash posture; session Stop/ci
|
|
591
|
+
# remain the backstop). Even with a real gated change present.
|
|
592
|
+
echo "// pre" > "$REPO/src/foo.go"; git -C "$REPO" add -A; git -C "$REPO" commit -qm pre
|
|
593
|
+
( cd "$REPO" && printf '{"tool_name":"Bash","tool_input":{"command":"echo x >> src/foo.go"},"session_id":"SUB","agent_id":"A7"}' | bash "$ENGINE" pretool ) >/dev/null 2>&1
|
|
594
|
+
echo "// real change" >> "$REPO/src/foo.go"
|
|
595
|
+
[ -r "$BDIR/s.SUB.a.$(akey A7).bashwrite" ] && [ ! -e "$BDIR/s.SUB.a.$(akey A7).touched" ] \
|
|
596
|
+
&& ok "Bash-only subagent records per-agent .bashwrite sentinel only" || bad "bash-only subagent marker shape"
|
|
597
|
+
[ "$( cd "$REPO" && stopa SUB A7 | bash "$ENGINE" stop | sdecision )" = stop ] \
|
|
598
|
+
&& ok "SubagentStop: Bash-only subagent => allow (not path-attributable, by design)" || bad "bash-only subagent blocked"
|
|
599
|
+
git -C "$REPO" checkout -q -- . 2>/dev/null; git -C "$REPO" clean -fdq 2>/dev/null; rm -rf "$BDIR"
|
|
600
|
+
# 11j. CHALLENGE FIX: baseline state lost mid-session for a subagent => NOT attributable =>
|
|
601
|
+
# allow. Must NOT fall back to the session-wide check (which would blame a sibling).
|
|
602
|
+
echo "// pre" > "$REPO/src/foo.go"; git -C "$REPO" add -A; git -C "$REPO" commit -qm prej
|
|
603
|
+
edita "$REPO/src/foo.go" SUB AJ | bash "$ENGINE" pretool >/dev/null # captures baseline + AJ marker
|
|
604
|
+
rm -f "$BDIR/s.SUB.basehead" # simulate lost/rolled state
|
|
605
|
+
echo "// a gated change exists" >> "$REPO/src/foo.go"
|
|
606
|
+
[ "$( cd "$REPO" && stopa SUB AJ | bash "$ENGINE" stop | sdecision )" = stop ] \
|
|
607
|
+
&& ok "SubagentStop: missing baseline => allow (no session-wide contamination fallback)" || bad "basehead-missing fallback contaminates"
|
|
608
|
+
git -C "$REPO" checkout -q -- . 2>/dev/null; git -C "$REPO" clean -fdq 2>/dev/null; rm -rf "$BDIR"
|
|
609
|
+
# 11k. CHALLENGE FIX: NUL-safe exact attribution — a subagent that touched a newline-
|
|
610
|
+
# containing path is NOT cross-blamed when a sibling file whose name is a line-fragment
|
|
611
|
+
# of it changes (the old grep -Fxq split the multi-line pattern and false-blocked).
|
|
612
|
+
nlpath=$'src/a\nb.go'
|
|
613
|
+
printf 'package x\n' > "$REPO/$nlpath"; printf 'package a\n' > "$REPO/src/a"
|
|
614
|
+
git -C "$REPO" add -A; git -C "$REPO" commit -qm nlfiles
|
|
615
|
+
jq -nc --arg fp "$REPO/$nlpath" '{tool_name:"Edit",tool_input:{file_path:$fp},session_id:"SUB",agent_id:"AK"}' \
|
|
616
|
+
| bash "$ENGINE" pretool >/dev/null # AK touched the newline path; not changed
|
|
617
|
+
echo "// only the line-fragment sibling changes" >> "$REPO/src/a" # src/a (a line-fragment) changes
|
|
618
|
+
[ "$( cd "$REPO" && stopa SUB AK | bash "$ENGINE" stop | sdecision )" = stop ] \
|
|
619
|
+
&& ok "SubagentStop: newline-path touch not cross-blamed for sibling 'src/a' (NUL exact match)" || bad "newline-path line-fragment cross-attribution"
|
|
620
|
+
git -C "$REPO" checkout -q -- . 2>/dev/null; git -C "$REPO" clean -fdq 2>/dev/null; rm -rf "$BDIR"
|
|
621
|
+
# 11m. CHALLENGE FIX (id collision): two agent_ids that the lossy sid_safe would collapse to
|
|
622
|
+
# the same key ("a/b" and "a:b" -> "a_b") get DISTINCT injective (percent-encoded)
|
|
623
|
+
# markers, so their .touched/.blocked/.waiver never collide.
|
|
624
|
+
edita "$REPO/src/foo.go" SUB 'a/b' | bash "$ENGINE" pretool >/dev/null
|
|
625
|
+
[ -r "$BDIR/s.SUB.a.$(akey 'a/b').touched" ] && [ ! -e "$BDIR/s.SUB.a.$(akey 'a:b').touched" ] && [ "$(akey 'a/b')" != "$(akey 'a:b')" ] \
|
|
626
|
+
&& ok "agent_id key is injective ('a/b' ≠ 'a:b'; no marker collision)" || bad "agent_id key collision (lossy sid_safe)"
|
|
627
|
+
git -C "$REPO" checkout -q -- . 2>/dev/null; rm -rf "$BDIR"
|
|
628
|
+
# 11n. CHALLENGE FIX (concurrency): O_APPEND per-agent .touched does not lose entries when
|
|
629
|
+
# the same subagent's PreToolUse fires in parallel (model emitting parallel Edits);
|
|
630
|
+
# the old read-copy-rename dropped entries and could silently miss the real changed path.
|
|
631
|
+
for i in $(seq 1 20); do echo "package p" > "$REPO/src/c$i.go"; done
|
|
632
|
+
git -C "$REPO" add -A; git -C "$REPO" commit -qm cfiles
|
|
633
|
+
edita "$REPO/src/c1.go" SUB CC | bash "$ENGINE" pretool >/dev/null # serial: capture baseline once
|
|
634
|
+
for i in $(seq 1 20); do edita "$REPO/src/c$i.go" SUB CC | bash "$ENGINE" pretool >/dev/null & done; wait
|
|
635
|
+
n=$(tr -cd '\0' < "$BDIR/s.SUB.a.$(akey CC).touched" 2>/dev/null | wc -c | tr -d ' ')
|
|
636
|
+
[ "${n:-0}" -ge 20 ] && ok "concurrent same-agent edits: all touched entries survive ($n, O_APPEND)" || bad "lost touched entries under concurrency: ${n:-0}/20"
|
|
637
|
+
git -C "$REPO" checkout -q -- . 2>/dev/null; git -C "$REPO" clean -fdq 2>/dev/null; rm -rf "$BDIR"
|
|
638
|
+
|
|
639
|
+
# ============================================================================
|
|
640
|
+
# INVOCATION EVIDENCE (name != invoke) — cross-check recorded owners against the
|
|
641
|
+
# skills actually invoked in the session transcript (backlog gate ⑥).
|
|
642
|
+
# ============================================================================
|
|
643
|
+
# Synthetic transcript: one JSONL line per invoked skill (matches the real format:
|
|
644
|
+
# message.content[] tool_use blocks with name=="Skill", input.skill=="plugin:name").
|
|
645
|
+
mktr() { # $1 out-file rest: skill invocations (plugin:name or bare)
|
|
646
|
+
local out="$1"; shift; : > "$out"
|
|
647
|
+
printf 'malformed leading line not json\n' > "$out" # BEFORE skills: must not truncate the stream
|
|
648
|
+
local s
|
|
649
|
+
for s in "$@"; do
|
|
650
|
+
printf '{"type":"assistant","message":{"content":[{"type":"tool_use","name":"Skill","input":{"skill":"%s"}}]}}\n' "$s" >> "$out"
|
|
651
|
+
done
|
|
652
|
+
# a non-Skill line + a malformed line to prove tolerance
|
|
653
|
+
printf '{"type":"user","message":{"content":[{"type":"tool_use","name":"Bash","input":{"command":"ls"}}]}}\n' >> "$out"
|
|
654
|
+
printf 'not json at all\n' >> "$out"
|
|
655
|
+
}
|
|
656
|
+
stopjt(){ printf '{"session_id":"%s","transcript_path":"%s"}' "$1" "$2"; }
|
|
657
|
+
stopjat(){
|
|
658
|
+
printf '{"session_id":"%s","agent_id":"%s","transcript_path":"%s","agent_transcript_path":"%s"}' \
|
|
659
|
+
"$1" "$2" "$3" "$4"
|
|
660
|
+
}
|
|
661
|
+
stopja_legacy(){ printf '{"session_id":"%s","agent_id":"%s","transcript_path":"%s"}' "$1" "$2" "$3"; }
|
|
662
|
+
|
|
663
|
+
TR="$BDIR.transcript.jsonl"; mkdir -p "$(dirname "$TR")"
|
|
664
|
+
|
|
665
|
+
# VI-1: subcommand — an invoked skill-shaped owner passes (exit 0).
|
|
666
|
+
mktr "$TR" "ccl-skills:testing-strategy" "ccl-skills:worktree-isolation"
|
|
667
|
+
bash "$ENGINE" verify-invocations --owners "testing-strategy,worktree-isolation" --transcript "$TR" >/dev/null
|
|
668
|
+
[ $? -eq 0 ] && ok "verify-invocations: all invoked => exit 0" || bad "VI-1"
|
|
669
|
+
|
|
670
|
+
# VI-2: subcommand — a skill-shaped owner never invoked => exit 3 and is named.
|
|
671
|
+
out=$(bash "$ENGINE" verify-invocations --owners "testing-strategy,go-microservice-dev" --transcript "$TR"); rc=$?
|
|
672
|
+
[ "$rc" = 3 ] && printf '%s' "$out" | grep -q 'go-microservice-dev' \
|
|
673
|
+
&& ! printf '%s' "$out" | grep -q 'testing-strategy' \
|
|
674
|
+
&& ok "verify-invocations: un-invoked owner flagged (exit 3)" || bad "VI-2" "rc=$rc out=$out"
|
|
675
|
+
|
|
676
|
+
# VI-3: no transcript => unverifiable => fail-open exit 0.
|
|
677
|
+
bash "$ENGINE" verify-invocations --owners "anything" --transcript "$BDIR/nope.jsonl" >/dev/null
|
|
678
|
+
[ $? -eq 0 ] && ok "verify-invocations: no transcript => fail-open exit 0" || bad "VI-3"
|
|
679
|
+
|
|
680
|
+
# VI-4: free-text (non-skill-shaped) owner never flags, even when absent.
|
|
681
|
+
out=$(bash "$ENGINE" verify-invocations --owners "then the touched owner" --transcript "$TR"); rc=$?
|
|
682
|
+
[ "$rc" = 0 ] && ok "verify-invocations: free-text owner never flags" || bad "VI-4" "rc=$rc out=$out"
|
|
683
|
+
|
|
684
|
+
# --- Stop-hook wiring: the reliable firing point (transcript_path on stdin) ---
|
|
685
|
+
git -C "$REPO" checkout -q -- . 2>/dev/null; git -C "$REPO" clean -fdq 2>/dev/null; rm -rf "$BDIR"
|
|
686
|
+
echo "package x" > "$REPO/src/foo.go"; git -C "$REPO" add -A; git -C "$REPO" commit -qm reset
|
|
687
|
+
|
|
688
|
+
# VI-5: boundary recorded with an owner that was NEVER invoked + activity + transcript => Stop BLOCKS.
|
|
689
|
+
rm -f "$BDIR/boundary.json"
|
|
690
|
+
edit "$REPO/src/foo.go" SV1 | bash "$ENGINE" pretool >/dev/null # capture baseline
|
|
691
|
+
echo "package x // SV1 change" > "$REPO/src/foo.go" # real post-baseline gated change
|
|
692
|
+
( cd "$REPO" && bash "$ENGINE" record --owners "testing-strategy,go-microservice-dev" >/dev/null )
|
|
693
|
+
mktr "$TR" "ccl-skills:testing-strategy" # only testing-strategy invoked
|
|
694
|
+
d=$( cd "$REPO" && stopjt SV1 "$TR" | bash "$ENGINE" stop | sdecision )
|
|
695
|
+
[ "$d" = block ] && ok "Stop: recorded owner never invoked => block (name≠invoke)" || bad "VI-5 expected block, got $d"
|
|
696
|
+
|
|
697
|
+
# VI-6: fresh boundary, transcript shows BOTH owners invoked => Stop allows.
|
|
698
|
+
rm -f "$BDIR/boundary.json"
|
|
699
|
+
edit "$REPO/src/foo.go" SV2 | bash "$ENGINE" pretool >/dev/null
|
|
700
|
+
echo "package x // SV2 change" > "$REPO/src/foo.go"
|
|
701
|
+
( cd "$REPO" && bash "$ENGINE" record --owners "testing-strategy,go-microservice-dev" >/dev/null )
|
|
702
|
+
mktr "$TR" "ccl-skills:testing-strategy" "ccl-skills:go-microservice-dev"
|
|
703
|
+
d=$( cd "$REPO" && stopjt SV2 "$TR" | bash "$ENGINE" stop | sdecision )
|
|
704
|
+
[ "$d" = stop ] && ok "Stop: all recorded owners invoked => allow" || bad "VI-6 expected allow, got $d"
|
|
705
|
+
|
|
706
|
+
# VI-7: boundary recorded, NO transcript_path on stdin => fail-open allow.
|
|
707
|
+
rm -f "$BDIR/boundary.json"
|
|
708
|
+
edit "$REPO/src/foo.go" SV3 | bash "$ENGINE" pretool >/dev/null
|
|
709
|
+
( cd "$REPO" && bash "$ENGINE" record --owners "go-microservice-dev" >/dev/null )
|
|
710
|
+
d=$( cd "$REPO" && stopj SV3 | bash "$ENGINE" stop | sdecision )
|
|
711
|
+
[ "$d" = stop ] && ok "Stop: boundary recorded but no transcript => fail-open allow" || bad "VI-7 expected allow, got $d"
|
|
712
|
+
|
|
713
|
+
# VI-8: block fires AT MOST ONCE per actor (same safety as the boundary-missing block).
|
|
714
|
+
rm -f "$BDIR/boundary.json"
|
|
715
|
+
edit "$REPO/src/foo.go" SV4 | bash "$ENGINE" pretool >/dev/null
|
|
716
|
+
echo "package x // SV4 change" > "$REPO/src/foo.go"
|
|
717
|
+
( cd "$REPO" && bash "$ENGINE" record --owners "go-microservice-dev" >/dev/null )
|
|
718
|
+
mktr "$TR" "ccl-skills:testing-strategy"
|
|
719
|
+
d1=$( cd "$REPO" && stopjt SV4 "$TR" | bash "$ENGINE" stop | sdecision )
|
|
720
|
+
d2=$( cd "$REPO" && stopjt SV4 "$TR" | bash "$ENGINE" stop | sdecision )
|
|
721
|
+
[ "$d1" = block ] && [ "$d2" = stop ] && ok "Stop invocation-block fires at most once per actor" || bad "VI-8 d1=$d1 d2=$d2"
|
|
722
|
+
# VI-9: boundary + un-invoked owner but the actor made NO actual gated change this session
|
|
723
|
+
# (edit then revert to baseline) => Stop must NOT block (no-trap safety preserved).
|
|
724
|
+
rm -f "$BDIR/boundary.json"
|
|
725
|
+
edit "$REPO/src/foo.go" SV5 | bash "$ENGINE" pretool >/dev/null # .touched activity...
|
|
726
|
+
git -C "$REPO" checkout -q -- src/foo.go # ...but reverted (no real change)
|
|
727
|
+
( cd "$REPO" && bash "$ENGINE" record --owners "go-microservice-dev" >/dev/null )
|
|
728
|
+
mktr "$TR" "ccl-skills:testing-strategy" # go-microservice-dev un-invoked
|
|
729
|
+
d=$( cd "$REPO" && stopjt SV5 "$TR" | bash "$ENGINE" stop | sdecision )
|
|
730
|
+
[ "$d" = stop ] && ok "Stop: un-invoked owner but NO actual gated change => allow (no-trap)" || bad "VI-9 expected allow, got $d"
|
|
731
|
+
|
|
732
|
+
# VI-10: transcript with NO Skill invocations at all (empty invoked set) => unverifiable =>
|
|
733
|
+
# fail-open, never flag every owner.
|
|
734
|
+
: > "$TR"; printf '{"message":{"content":[{"type":"tool_use","name":"Bash","input":{"command":"ls"}}]}}\n' > "$TR"
|
|
735
|
+
printf 'garbage line\n' >> "$TR"
|
|
736
|
+
out=$(bash "$ENGINE" verify-invocations --owners "go-microservice-dev,testing-strategy" --transcript "$TR"); rc=$?
|
|
737
|
+
[ "$rc" = 0 ] && ok "verify-invocations: empty invoked set => fail-open (no flags)" || bad "VI-10" "rc=$rc out=$out"
|
|
738
|
+
|
|
739
|
+
# VI-11 (challenge R1): owner recorded in FULL "ccl-skills:foo" form still matches the
|
|
740
|
+
# invoked base name (prefix normalized on both sides).
|
|
741
|
+
mktr "$TR" "ccl-skills:go-microservice-dev"
|
|
742
|
+
bash "$ENGINE" verify-invocations --owners "ccl-skills:go-microservice-dev" --transcript "$TR" >/dev/null
|
|
743
|
+
[ $? -eq 0 ] && ok "verify-invocations: full ccl-skills:owner matches invoked base" || bad "VI-11"
|
|
744
|
+
|
|
745
|
+
# VI-12 (challenge R1): a same-named skill from an UNTRUSTED plugin does NOT satisfy a
|
|
746
|
+
# CCL owner (only ccl-skills: prefix is stripped for base matching).
|
|
747
|
+
: > "$TR"; printf '{"type":"assistant","message":{"content":[{"type":"tool_use","name":"Skill","input":{"skill":"evil-plugin:go-microservice-dev"}}]}}\n' > "$TR"
|
|
748
|
+
out=$(bash "$ENGINE" verify-invocations --owners "go-microservice-dev" --transcript "$TR"); rc=$?
|
|
749
|
+
[ "$rc" = 3 ] && printf '%s' "$out" | grep -q 'go-microservice-dev' \
|
|
750
|
+
&& ok "verify-invocations: untrusted-plugin same-name does NOT satisfy CCL owner" || bad "VI-12" "rc=$rc out=$out"
|
|
751
|
+
|
|
752
|
+
# VI-13 (challenge R1): a malformed Skill.input.skill (non-string) BEFORE a valid invocation
|
|
753
|
+
# must not abort the stream — the valid invocation is still found (strings guard).
|
|
754
|
+
: > "$TR"
|
|
755
|
+
printf '{"type":"assistant","message":{"content":[{"type":"tool_use","name":"Skill","input":{"skill":123}}]}}\n' > "$TR"
|
|
756
|
+
printf '{"type":"assistant","message":{"content":[{"type":"tool_use","name":"Skill","input":{"skill":"ccl-skills:go-microservice-dev"}}]}}\n' >> "$TR"
|
|
757
|
+
bash "$ENGINE" verify-invocations --owners "go-microservice-dev" --transcript "$TR" >/dev/null
|
|
758
|
+
[ $? -eq 0 ] && ok "verify-invocations: non-string skill value skipped, later valid one found" || bad "VI-13"
|
|
759
|
+
|
|
760
|
+
# VI-14 (challenge R2): a Skill tool_use block in a NON-assistant (user-role) event must
|
|
761
|
+
# not count as a real invocation (spoof resistance). A real assistant invocation is
|
|
762
|
+
# present so the set is non-empty (not the fail-open path).
|
|
763
|
+
: > "$TR"
|
|
764
|
+
printf '{"type":"assistant","message":{"role":"assistant","content":[{"type":"tool_use","name":"Skill","input":{"skill":"ccl-skills:testing-strategy"}}]}}\n' > "$TR"
|
|
765
|
+
printf '{"type":"user","message":{"role":"user","content":[{"type":"tool_use","name":"Skill","input":{"skill":"ccl-skills:go-microservice-dev"}}]}}\n' >> "$TR"
|
|
766
|
+
out=$(bash "$ENGINE" verify-invocations --owners "go-microservice-dev,testing-strategy" --transcript "$TR"); rc=$?
|
|
767
|
+
[ "$rc" = 3 ] && printf '%s' "$out" | grep -q 'go-microservice-dev' \
|
|
768
|
+
&& ! printf '%s' "$out" | grep -q 'testing-strategy' \
|
|
769
|
+
&& ok "verify-invocations: non-assistant Skill block does not satisfy owner" || bad "VI-14" "rc=$rc out=$out"
|
|
770
|
+
|
|
771
|
+
# VI-15 (challenge R2): PROACTIVE record — owners recorded BEFORE any edit, then a real
|
|
772
|
+
# gated change, then Stop with a transcript missing an owner => still BLOCKS (the
|
|
773
|
+
# pretool now captures the activity marker even under a valid boundary).
|
|
774
|
+
rm -f "$BDIR/boundary.json"
|
|
775
|
+
( cd "$REPO" && bash "$ENGINE" record --owners "go-microservice-dev" >/dev/null ) # record FIRST
|
|
776
|
+
edit "$REPO/src/foo.go" SV6 | bash "$ENGINE" pretool >/dev/null # THEN edit (marker captured despite valid boundary)
|
|
777
|
+
echo "package x // SV6 change" > "$REPO/src/foo.go" # real gated change
|
|
778
|
+
mktr "$TR" "ccl-skills:testing-strategy" # go-microservice-dev un-invoked
|
|
779
|
+
d=$( cd "$REPO" && stopjt SV6 "$TR" | bash "$ENGINE" stop | sdecision )
|
|
780
|
+
[ "$d" = block ] && ok "Stop: proactive-record path still caught (marker captured under valid boundary)" || bad "VI-15 expected block, got $d"
|
|
781
|
+
|
|
782
|
+
# VI-16: SubagentStop must inspect the WORKER transcript. Claude supplies the main
|
|
783
|
+
# session transcript in transcript_path and the worker's own evidence in
|
|
784
|
+
# agent_transcript_path. A skill loaded only by the controller cannot satisfy the worker.
|
|
785
|
+
git -C "$REPO" checkout -q -- . 2>/dev/null; git -C "$REPO" clean -fdq 2>/dev/null; rm -rf "$BDIR"
|
|
786
|
+
MAIN_TR="$BDIR.main.jsonl"; AGENT_TR="$BDIR.agent.jsonl"
|
|
787
|
+
edita "$REPO/src/foo.go" SV7 W7 | bash "$ENGINE" pretool >/dev/null
|
|
788
|
+
echo "package x // SV7 worker change" > "$REPO/src/foo.go"
|
|
789
|
+
( cd "$REPO" && bash "$ENGINE" record --owners "go-microservice-dev" >/dev/null )
|
|
790
|
+
mktr "$MAIN_TR" "ccl-skills:go-microservice-dev" # controller loaded it
|
|
791
|
+
mktr "$AGENT_TR" "ccl-skills:testing-strategy" # worker did not
|
|
792
|
+
d=$( cd "$REPO" && stopjat SV7 W7 "$MAIN_TR" "$AGENT_TR" | bash "$ENGINE" stop | sdecision )
|
|
793
|
+
[ "$d" = block ] && ok "SubagentStop: worker transcript wins over main transcript" || bad "VI-16 expected block, got $d"
|
|
794
|
+
|
|
795
|
+
# VI-17: a worker transcript with a verifiable tool-event shape but ZERO Skill invocations is evidence
|
|
796
|
+
# of a cold worker, not transcript-format drift. Continue that worker once.
|
|
797
|
+
git -C "$REPO" checkout -q -- . 2>/dev/null; rm -rf "$BDIR"
|
|
798
|
+
edita "$REPO/src/foo.go" SV8 W8 | bash "$ENGINE" pretool >/dev/null
|
|
799
|
+
echo "package x // SV8 worker change" > "$REPO/src/foo.go"
|
|
800
|
+
( cd "$REPO" && bash "$ENGINE" record --owners "go-microservice-dev" >/dev/null )
|
|
801
|
+
mktr "$MAIN_TR" "ccl-skills:go-microservice-dev"
|
|
802
|
+
printf '{"type":"assistant","message":{"content":[{"type":"tool_use","name":"Bash","input":{"command":"go test ./..."}}]}}\n' > "$AGENT_TR"
|
|
803
|
+
d=$( cd "$REPO" && stopjat SV8 W8 "$MAIN_TR" "$AGENT_TR" | bash "$ENGINE" stop | sdecision )
|
|
804
|
+
[ "$d" = block ] && ok "SubagentStop: zero worker Skill invocations => block once" || bad "VI-17 expected block, got $d"
|
|
805
|
+
|
|
806
|
+
# VI-18/19: the standalone verifier exposes the same strict worker mode for host
|
|
807
|
+
# adapters, while malformed-only evidence remains fail-open.
|
|
808
|
+
out=$(bash "$ENGINE" verify-invocations --owners "go-microservice-dev" --transcript "$AGENT_TR" --empty-is-missing); rc=$?
|
|
809
|
+
[ "$rc" = 3 ] && printf '%s' "$out" | grep -q 'go-microservice-dev' \
|
|
810
|
+
&& ok "verify-invocations: strict empty set flags required skill" || bad "VI-18" "rc=$rc out=$out"
|
|
811
|
+
printf 'not json\nstill not json\n' > "$AGENT_TR"
|
|
812
|
+
out=$(bash "$ENGINE" verify-invocations --owners "go-microservice-dev" --transcript "$AGENT_TR" --empty-is-missing); rc=$?
|
|
813
|
+
[ "$rc" = 0 ] && ok "verify-invocations: malformed-only transcript stays fail-open" || bad "VI-19" "rc=$rc out=$out"
|
|
814
|
+
|
|
815
|
+
# VI-20: valid JSONL is not enough to prove invocation absence. If the host still emits
|
|
816
|
+
# assistant tool_use events but a Skill block's input shape drifted, strict worker
|
|
817
|
+
# verification must fail open rather than falsely claiming every owner was skipped.
|
|
818
|
+
git -C "$REPO" checkout -q -- . 2>/dev/null; rm -rf "$BDIR"
|
|
819
|
+
edita "$REPO/src/foo.go" SV9 W9 | bash "$ENGINE" pretool >/dev/null
|
|
820
|
+
echo "package x // SV9 worker change" > "$REPO/src/foo.go"
|
|
821
|
+
( cd "$REPO" && bash "$ENGINE" record --owners "go-microservice-dev" >/dev/null )
|
|
822
|
+
printf '{"type":"assistant","message":{"content":[{"type":"tool_use","name":"Skill","input":{"arguments":{"skill":"ccl-skills:go-microservice-dev"}}},{"type":"tool_use","name":"Edit","input":{"file_path":"src/foo.go"}}]}}\n' > "$AGENT_TR"
|
|
823
|
+
d=$( cd "$REPO" && stopjat SV9 W9 "$MAIN_TR" "$AGENT_TR" | bash "$ENGINE" stop | sdecision )
|
|
824
|
+
[ "$d" = stop ] && ok "SubagentStop: drifted Skill event shape stays fail-open" || bad "VI-20 expected allow, got $d"
|
|
825
|
+
|
|
826
|
+
# VI-21: an older host may omit agent_transcript_path. The main transcript fallback is
|
|
827
|
+
# orientation only and must retain legacy empty-set fail-open behavior; otherwise a
|
|
828
|
+
# controller with no Skill calls is falsely attributed to the worker.
|
|
829
|
+
git -C "$REPO" checkout -q -- . 2>/dev/null; rm -rf "$BDIR"
|
|
830
|
+
edita "$REPO/src/foo.go" SV10 W10 | bash "$ENGINE" pretool >/dev/null
|
|
831
|
+
echo "package x // SV10 worker change" > "$REPO/src/foo.go"
|
|
832
|
+
( cd "$REPO" && bash "$ENGINE" record --owners "go-microservice-dev" >/dev/null )
|
|
833
|
+
printf '{"type":"assistant","message":{"content":[{"type":"tool_use","name":"Bash","input":{"command":"git status"}}]}}\n' > "$MAIN_TR"
|
|
834
|
+
d=$( cd "$REPO" && stopja_legacy SV10 W10 "$MAIN_TR" | bash "$ENGINE" stop | sdecision )
|
|
835
|
+
[ "$d" = stop ] && ok "SubagentStop: legacy main-transcript fallback keeps empty-set fail-open" || bad "VI-21 expected allow, got $d"
|
|
836
|
+
|
|
837
|
+
git -C "$REPO" checkout -q -- . 2>/dev/null; git -C "$REPO" clean -fdq 2>/dev/null; rm -rf "$BDIR" "$TR" "$MAIN_TR" "$AGENT_TR"
|
|
838
|
+
|
|
839
|
+
# ---- WORKTREE DIMENSION (issue #5) -------------------------------------------
|
|
840
|
+
# Every fixture above builds a PLAIN repo, so none of them can cross the axis where
|
|
841
|
+
# this gate actually runs: `worktree-isolation` mandates developing in a linked
|
|
842
|
+
# worktree, while the Stop hook resolves its repo from $PWD — which the harness
|
|
843
|
+
# routinely resets back to the main checkout. Keying boundary state on
|
|
844
|
+
# `--absolute-git-dir` puts the write in `.git/worktrees/<name>/` and the read in
|
|
845
|
+
# `.git/`, so the gate reports "never recorded" on the repo's OWN standard workflow
|
|
846
|
+
# and then trains everyone to ignore it. These probes pin read/write agreement
|
|
847
|
+
# across that boundary; without the fix W1 fails.
|
|
848
|
+
echo "--- worktree dimension ---"
|
|
849
|
+
WT="$WORK/prod-wt"
|
|
850
|
+
if git -C "$REPO" worktree add -q -b od-wt "$WT" >/dev/null 2>&1; then
|
|
851
|
+
# W1: record INSIDE the worktree must be visible FROM the main checkout.
|
|
852
|
+
rm -rf "$BDIR"
|
|
853
|
+
( cd "$WT" && bash "$ENGINE" record --owners "product-rd-workflow" >/dev/null )
|
|
854
|
+
main_state=$(bash "$ENGINE" boundary-path "$REPO" 2>/dev/null)
|
|
855
|
+
wt_state=$(bash "$ENGINE" boundary-path "$WT" 2>/dev/null)
|
|
856
|
+
[ -n "$main_state" ] && [ "$main_state" = "$wt_state" ] \
|
|
857
|
+
&& ok "worktree: boundary path is identical from the worktree and the main checkout" \
|
|
858
|
+
|| bad "W1a: boundary path differs across worktrees" "main=$main_state wt=$wt_state"
|
|
859
|
+
[ -r "$main_state/boundary.json" ] \
|
|
860
|
+
&& ok "worktree: a boundary recorded in the worktree is readable from the main checkout" \
|
|
861
|
+
|| bad "W1: record-in-worktree is invisible from the main checkout (issue #5)" "looked in $main_state"
|
|
862
|
+
|
|
863
|
+
# W2: the shared path must be ABSOLUTE. `--git-common-dir` returns a RELATIVE
|
|
864
|
+
# `.git` when asked from the main checkout, so a naive swap would make the
|
|
865
|
+
# state dir depend on the caller's cwd — the same class of bug, re-introduced.
|
|
866
|
+
case "$main_state" in
|
|
867
|
+
/*) ok "worktree: boundary path is absolute from the main checkout (cwd-independent)" ;;
|
|
868
|
+
*) bad "W2: boundary path is relative => cwd-dependent state dir" "got=$main_state" ;;
|
|
869
|
+
esac
|
|
870
|
+
|
|
871
|
+
# W3: the gate itself must be satisfied — record in the worktree, Stop in the main
|
|
872
|
+
# checkout (exactly the shape the standard workflow produces).
|
|
873
|
+
rm -rf "$BDIR"
|
|
874
|
+
edit "$REPO/src/foo.go" SW1 | bash "$ENGINE" pretool >/dev/null
|
|
875
|
+
echo "package x // SW1" > "$REPO/src/foo.go"
|
|
876
|
+
( cd "$WT" && bash "$ENGINE" record --owners "product-rd-workflow" >/dev/null )
|
|
877
|
+
d=$( cd "$REPO" && stopj SW1 | bash "$ENGINE" stop | sdecision )
|
|
878
|
+
[ "$d" = stop ] && ok "worktree: record-in-worktree satisfies a Stop resolved in the main checkout" \
|
|
879
|
+
|| bad "W3: Stop still blocks after a worktree record (issue #5 end-to-end)" "got $d"
|
|
880
|
+
|
|
881
|
+
# W6: OLD GIT. `--path-format=absolute` needs git >= 2.31; without it the fallback
|
|
882
|
+
# builds the path itself, and that branch answers a LOGICAL path while git answers
|
|
883
|
+
# a PHYSICAL one. On a symlinked root (macOS /var -> /private/var, i.e. mktemp)
|
|
884
|
+
# the two disagree and the split returns — on exactly the hosts that cannot take
|
|
885
|
+
# the fast path. Shim git to reject the flag so the fallback is what runs.
|
|
886
|
+
REALGIT=$(command -v git)
|
|
887
|
+
SHIM="$WORK/shim"; mkdir -p "$SHIM"
|
|
888
|
+
cat > "$SHIM/git" <<SH
|
|
889
|
+
#!/bin/sh
|
|
890
|
+
for a in "\$@"; do
|
|
891
|
+
[ "\$a" = "--path-format=absolute" ] && { echo "error: unknown option \\\`path-format=absolute'" >&2; exit 129; }
|
|
892
|
+
done
|
|
893
|
+
exec "$REALGIT" "\$@"
|
|
894
|
+
SH
|
|
895
|
+
chmod +x "$SHIM/git"
|
|
896
|
+
old_main=$(PATH="$SHIM:$PATH" bash "$ENGINE" boundary-path "$REPO" 2>/dev/null)
|
|
897
|
+
old_wt=$(PATH="$SHIM:$PATH" bash "$ENGINE" boundary-path "$WT" 2>/dev/null)
|
|
898
|
+
[ -n "$old_main" ] && [ "$old_main" = "$old_wt" ] \
|
|
899
|
+
&& ok "worktree: path agrees across worktrees on git without --path-format (>=2.31 fallback)" \
|
|
900
|
+
|| bad "W6: fallback path differs across worktrees on old git" "main=$old_main wt=$old_wt"
|
|
901
|
+
case "$old_main" in
|
|
902
|
+
/*) ok "worktree: fallback path is absolute too" ;;
|
|
903
|
+
*) bad "W6b: fallback produced a relative path" "got=$old_main" ;;
|
|
904
|
+
esac
|
|
905
|
+
rm -rf "$SHIM"
|
|
906
|
+
|
|
907
|
+
# W4: the recording worktree is REMOVED — the normal end of a delivery, since
|
|
908
|
+
# worktree-isolation says clean up the moment it is integrated. A boundary keyed
|
|
909
|
+
# on the worktree PATH cannot survive this (the path is gone and `git -C` on it
|
|
910
|
+
# fails), which is why identity is keyed on the common git dir instead.
|
|
911
|
+
rm -rf "$BDIR"
|
|
912
|
+
( cd "$WT" && bash "$ENGINE" record --owners "product-rd-workflow" >/dev/null )
|
|
913
|
+
git -C "$REPO" worktree remove --force "$WT" >/dev/null 2>&1
|
|
914
|
+
[ -d "$WT" ] && bad "W4 fixture: worktree not actually removed" "$WT still exists"
|
|
915
|
+
[ "$(cd "$REPO" && bash "$ENGINE" status | sed -n 's/^boundary: *//p')" = valid ] \
|
|
916
|
+
&& ok "worktree: boundary survives cleanup of the worktree that recorded it" \
|
|
917
|
+
|| bad "W4: boundary lost once the recording worktree was removed" "status=$(cd "$REPO" && bash "$ENGINE" status | sed -n 's/^boundary: *//p')"
|
|
918
|
+
|
|
919
|
+
# W5: NEGATIVE — repository identity still has teeth. The path equality this change
|
|
920
|
+
# replaced was there to reject a boundary belonging to somewhere else; a boundary
|
|
921
|
+
# naming a DIFFERENT repo's git dir must still be refused, or the fix would have
|
|
922
|
+
# been a deletion wearing a replacement's clothes.
|
|
923
|
+
OTHER="$WORK/other"; mkdir -p "$OTHER"
|
|
924
|
+
git -C "$OTHER" init -q; git -C "$OTHER" config user.email t@t; git -C "$OTHER" config user.name t
|
|
925
|
+
git -C "$OTHER" commit -q --allow-empty -m init
|
|
926
|
+
other_gd=$(bash "$ENGINE" boundary-path "$OTHER")
|
|
927
|
+
jq --arg gd "$other_gd" '.repo_git_dir=$gd' "$BDIR/boundary.json" > "$BDIR/boundary.json.tmp" \
|
|
928
|
+
&& mv "$BDIR/boundary.json.tmp" "$BDIR/boundary.json"
|
|
929
|
+
[ "$(cd "$REPO" && bash "$ENGINE" status | sed -n 's/^boundary: *//p')" = absent ] \
|
|
930
|
+
&& ok "worktree: a boundary naming another repository is still refused" \
|
|
931
|
+
|| bad "W5: foreign-repo boundary accepted — identity check lost its teeth" "status=$(cd "$REPO" && bash "$ENGINE" status | sed -n 's/^boundary: *//p')"
|
|
932
|
+
rm -rf "$OTHER"
|
|
933
|
+
|
|
934
|
+
git -C "$REPO" checkout -q -- . 2>/dev/null
|
|
935
|
+
git -C "$REPO" branch -qD od-wt >/dev/null 2>&1
|
|
936
|
+
rm -rf "$BDIR"
|
|
937
|
+
else
|
|
938
|
+
bad "W0: could not create a linked worktree — the worktree dimension went untested" "git worktree add failed"
|
|
939
|
+
fi
|
|
940
|
+
|
|
941
|
+
echo "---"; echo "PASS=$PASS FAIL=$FAIL"; [ "$FAIL" -eq 0 ]
|