@soleur/opencode 0.0.0-stage → 3.354.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/agents.manifest.json +476 -0
- package/.claude-plugin/plugin.json +42 -0
- package/README.md +44 -2
- package/agents/community/.gitkeep +0 -0
- package/agents/engineering/cto.md +87 -0
- package/agents/engineering/design/ddd-architect.md +95 -0
- package/agents/engineering/discovery/agent-finder.md +214 -0
- package/agents/engineering/discovery/functional-discovery.md +182 -0
- package/agents/engineering/infra/infra-security.md +151 -0
- package/agents/engineering/infra/platform-strategist.md +109 -0
- package/agents/engineering/infra/terraform-architect.md +171 -0
- package/agents/engineering/prompt-engineer.md +37 -0
- package/agents/engineering/research/best-practices-researcher.md +115 -0
- package/agents/engineering/research/framework-docs-researcher.md +93 -0
- package/agents/engineering/research/git-history-analyzer.md +53 -0
- package/agents/engineering/research/learnings-researcher.md +285 -0
- package/agents/engineering/research/repo-research-analyst.md +118 -0
- package/agents/engineering/review/agent-native-reviewer.md +279 -0
- package/agents/engineering/review/architecture-strategist.md +61 -0
- package/agents/engineering/review/code-quality-analyst.md +92 -0
- package/agents/engineering/review/code-simplicity-reviewer.md +109 -0
- package/agents/engineering/review/data-integrity-guardian.md +82 -0
- package/agents/engineering/review/data-migration-expert.md +98 -0
- package/agents/engineering/review/deployment-verification-agent.md +183 -0
- package/agents/engineering/review/dhh-rails-reviewer.md +46 -0
- package/agents/engineering/review/kieran-rails-reviewer.md +87 -0
- package/agents/engineering/review/legacy-code-expert.md +55 -0
- package/agents/engineering/review/observability-coverage-reviewer.md +147 -0
- package/agents/engineering/review/pattern-recognition-specialist.md +59 -0
- package/agents/engineering/review/performance-oracle.md +130 -0
- package/agents/engineering/review/security-sentinel.md +167 -0
- package/agents/engineering/review/semgrep-sast.md +36 -0
- package/agents/engineering/review/test-design-reviewer.md +150 -0
- package/agents/engineering/review/user-impact-reviewer.md +70 -0
- package/agents/engineering/workflow/pr-comment-resolver.md +69 -0
- package/agents/finance/budget-analyst.md +29 -0
- package/agents/finance/cfo.md +44 -0
- package/agents/finance/financial-reporter.md +30 -0
- package/agents/finance/revenue-analyst.md +30 -0
- package/agents/legal/clo.md +115 -0
- package/agents/legal/legal-compliance-auditor.md +110 -0
- package/agents/legal/legal-document-generator.md +134 -0
- package/agents/marketing/analytics-analyst.md +25 -0
- package/agents/marketing/brand-architect.md +181 -0
- package/agents/marketing/cmo.md +76 -0
- package/agents/marketing/conversion-optimizer.md +19 -0
- package/agents/marketing/copywriter.md +20 -0
- package/agents/marketing/fact-checker.md +70 -0
- package/agents/marketing/growth-strategist.md +145 -0
- package/agents/marketing/paid-media-strategist.md +28 -0
- package/agents/marketing/pricing-strategist.md +17 -0
- package/agents/marketing/programmatic-seo-specialist.md +25 -0
- package/agents/marketing/retention-strategist.md +23 -0
- package/agents/marketing/seo-aeo-analyst.md +164 -0
- package/agents/operations/coo.md +50 -0
- package/agents/operations/ops-advisor.md +78 -0
- package/agents/operations/ops-provisioner.md +101 -0
- package/agents/operations/ops-research.md +52 -0
- package/agents/operations/service-automator.md +278 -0
- package/agents/product/business-validator.md +206 -0
- package/agents/product/competitive-intelligence.md +89 -0
- package/agents/product/cpo.md +63 -0
- package/agents/product/design/ux-design-lead.md +209 -0
- package/agents/product/spec-flow-analyzer.md +122 -0
- package/agents/sales/cro.md +44 -0
- package/agents/sales/deal-architect.md +29 -0
- package/agents/sales/outbound-strategist.md +29 -0
- package/agents/sales/pipeline-analyst.md +29 -0
- package/agents/support/cco.md +48 -0
- package/agents/support/community-manager.md +570 -0
- package/agents/support/ticket-triage.md +70 -0
- package/bin/soleur-opencode.js +29 -0
- package/commands/go.md +660 -0
- package/commands/help.md +273 -0
- package/commands/sync.md +977 -0
- package/commands/version.md +103 -0
- package/hooks/antigravity-hooks.json +84 -0
- package/hooks/antigravity-session-start.sh +15 -0
- package/hooks/bare-root-cwd-guard.sh +131 -0
- package/hooks/browser-snapshot-credential-guard.sh +200 -0
- package/hooks/codex-session-start.sh +9 -0
- package/hooks/compaction-state.sh +525 -0
- package/hooks/destructive-command-guard.sh +1387 -0
- package/hooks/devin-session-start.sh +90 -0
- package/hooks/ext-filter-detect.sh +171 -0
- package/hooks/hooks.json +133 -0
- package/hooks/lib/hook-tool-kind.sh +24 -0
- package/hooks/lib/log-rotation.sh +176 -0
- package/hooks/lib/shell-argv.pl +576 -0
- package/hooks/memory-backstop.sh +1114 -0
- package/hooks/operator-stage-approval.sh +391 -0
- package/hooks/stop-hook.sh +367 -0
- package/hooks/unkept-promise-hook.sh +383 -0
- package/hooks/version-banner.sh +127 -0
- package/hooks/welcome-hook.sh +50 -0
- package/install.js +29 -0
- package/lib/agent-registry.ts +154 -0
- package/lib/c4-canonical-cli.mjs +34 -0
- package/lib/c4-canonical.mjs +46 -0
- package/lib/c4-from-components.ts +554 -0
- package/lib/go-routing.ts +81 -0
- package/lib/grok-inspect-contract.ts +311 -0
- package/lib/harness-model-map.ts +101 -0
- package/lib/harness-parity.ts +726 -0
- package/lib/harness-tool-map.ts +180 -0
- package/lib/harness.ts +716 -0
- package/lib/heartbeat-live-reconcile.ts +1153 -0
- package/lib/heartbeat-manifest.ts +361 -0
- package/lib/kb-coverage.ts +252 -0
- package/lib/pr-merge-poll.ts +103 -0
- package/lib/workflow-fidelity.ts +388 -0
- package/opencode/INSTRUCTIONS.md +171 -0
- package/opencode/agents/engineering/cto.md +10 -0
- package/opencode/agents/engineering/design/ddd-architect.md +10 -0
- package/opencode/agents/engineering/discovery/agent-finder.md +10 -0
- package/opencode/agents/engineering/discovery/functional-discovery.md +10 -0
- package/opencode/agents/engineering/infra/infra-security.md +10 -0
- package/opencode/agents/engineering/infra/platform-strategist.md +10 -0
- package/opencode/agents/engineering/infra/terraform-architect.md +10 -0
- package/opencode/agents/engineering/prompt-engineer.md +10 -0
- package/opencode/agents/engineering/research/best-practices-researcher.md +10 -0
- package/opencode/agents/engineering/research/framework-docs-researcher.md +10 -0
- package/opencode/agents/engineering/research/git-history-analyzer.md +10 -0
- package/opencode/agents/engineering/research/learnings-researcher.md +10 -0
- package/opencode/agents/engineering/research/repo-research-analyst.md +10 -0
- package/opencode/agents/engineering/review/agent-native-reviewer.md +10 -0
- package/opencode/agents/engineering/review/architecture-strategist.md +10 -0
- package/opencode/agents/engineering/review/code-quality-analyst.md +10 -0
- package/opencode/agents/engineering/review/code-simplicity-reviewer.md +10 -0
- package/opencode/agents/engineering/review/data-integrity-guardian.md +10 -0
- package/opencode/agents/engineering/review/data-migration-expert.md +10 -0
- package/opencode/agents/engineering/review/deployment-verification-agent.md +10 -0
- package/opencode/agents/engineering/review/dhh-rails-reviewer.md +10 -0
- package/opencode/agents/engineering/review/kieran-rails-reviewer.md +10 -0
- package/opencode/agents/engineering/review/legacy-code-expert.md +10 -0
- package/opencode/agents/engineering/review/observability-coverage-reviewer.md +10 -0
- package/opencode/agents/engineering/review/pattern-recognition-specialist.md +10 -0
- package/opencode/agents/engineering/review/performance-oracle.md +10 -0
- package/opencode/agents/engineering/review/security-sentinel.md +10 -0
- package/opencode/agents/engineering/review/semgrep-sast.md +10 -0
- package/opencode/agents/engineering/review/test-design-reviewer.md +10 -0
- package/opencode/agents/engineering/review/user-impact-reviewer.md +10 -0
- package/opencode/agents/engineering/workflow/pr-comment-resolver.md +10 -0
- package/opencode/agents/finance/budget-analyst.md +10 -0
- package/opencode/agents/finance/cfo.md +10 -0
- package/opencode/agents/finance/financial-reporter.md +10 -0
- package/opencode/agents/finance/revenue-analyst.md +10 -0
- package/opencode/agents/legal/clo.md +10 -0
- package/opencode/agents/legal/legal-compliance-auditor.md +10 -0
- package/opencode/agents/legal/legal-document-generator.md +10 -0
- package/opencode/agents/marketing/analytics-analyst.md +10 -0
- package/opencode/agents/marketing/brand-architect.md +10 -0
- package/opencode/agents/marketing/cmo.md +10 -0
- package/opencode/agents/marketing/conversion-optimizer.md +10 -0
- package/opencode/agents/marketing/copywriter.md +10 -0
- package/opencode/agents/marketing/fact-checker.md +10 -0
- package/opencode/agents/marketing/growth-strategist.md +10 -0
- package/opencode/agents/marketing/paid-media-strategist.md +10 -0
- package/opencode/agents/marketing/pricing-strategist.md +10 -0
- package/opencode/agents/marketing/programmatic-seo-specialist.md +10 -0
- package/opencode/agents/marketing/retention-strategist.md +10 -0
- package/opencode/agents/marketing/seo-aeo-analyst.md +10 -0
- package/opencode/agents/operations/coo.md +10 -0
- package/opencode/agents/operations/ops-advisor.md +10 -0
- package/opencode/agents/operations/ops-provisioner.md +10 -0
- package/opencode/agents/operations/ops-research.md +10 -0
- package/opencode/agents/operations/service-automator.md +10 -0
- package/opencode/agents/product/business-validator.md +10 -0
- package/opencode/agents/product/competitive-intelligence.md +10 -0
- package/opencode/agents/product/cpo.md +10 -0
- package/opencode/agents/product/design/ux-design-lead.md +10 -0
- package/opencode/agents/product/spec-flow-analyzer.md +10 -0
- package/opencode/agents/sales/cro.md +10 -0
- package/opencode/agents/sales/deal-architect.md +10 -0
- package/opencode/agents/sales/outbound-strategist.md +10 -0
- package/opencode/agents/sales/pipeline-analyst.md +10 -0
- package/opencode/agents/support/cco.md +10 -0
- package/opencode/agents/support/community-manager.md +10 -0
- package/opencode/agents/support/ticket-triage.md +10 -0
- package/opencode/commands/go.md +10 -0
- package/opencode/commands/help.md +10 -0
- package/opencode/commands/sync.md +10 -0
- package/opencode/commands/version.md +11 -0
- package/opencode/opencode.json +8 -0
- package/opencode/plugin.ts +818 -0
- package/package.json +36 -4
- package/scripts/admin-merge-ready.sh +545 -0
- package/scripts/admin-merge-ready.test.sh +753 -0
- package/scripts/affected-tests.sh +908 -0
- package/scripts/affected-tests.test.sh +1797 -0
- package/scripts/alpha-metrics.sh +78 -0
- package/scripts/alpha-metrics.test.sh +115 -0
- package/scripts/ancestor-signal-helpers.baseline.txt +16 -0
- package/scripts/audit-flag-flip.sh +107 -0
- package/scripts/check-red-on-main.sh +316 -0
- package/scripts/ci-head-verdict.sh +411 -0
- package/scripts/cloud-detect.sh +193 -0
- package/scripts/delegation-verify.sh +657 -0
- package/scripts/delegation-verify.test.sh +1424 -0
- package/scripts/deploy-arm.sh +475 -0
- package/scripts/domain-model-drift.sh +419 -0
- package/scripts/emit-decision.sh +144 -0
- package/scripts/emit-decision.test.sh +144 -0
- package/scripts/ext-filter-divergence-corpus.txt +15 -0
- package/scripts/ext-filter-divergence.sh +189 -0
- package/scripts/generate-c4-from-components.ts +442 -0
- package/scripts/grok-fidelity-gate.sh +68 -0
- package/scripts/grok-pre-push-gate.sh +232 -0
- package/scripts/harness-discovery-smoke.ts +906 -0
- package/scripts/harness-parity-census.ts +92 -0
- package/scripts/inngest-luks-alert-armed-probe.ts +29 -0
- package/scripts/install-opencode-adapter.ts +509 -0
- package/scripts/lib/affected-tests/common.sh +365 -0
- package/scripts/lib/affected-tests/go.sh +157 -0
- package/scripts/lib/affected-tests/js.sh +188 -0
- package/scripts/lib/affected-tests/nx-turbo.sh +98 -0
- package/scripts/lib/affected-tests/python.sh +185 -0
- package/scripts/lib/context-sanitize.sh +49 -0
- package/scripts/lib/domain-model-lib.sh +180 -0
- package/scripts/lib/ext-filter-grammar.tsv +34 -0
- package/scripts/lib/operator-script.sh +1236 -0
- package/scripts/lib/proc.sh +580 -0
- package/scripts/lib/session-state.sh +748 -0
- package/scripts/lib/tmp-classify.sh +843 -0
- package/scripts/lib/wrapper-boundary.sh +47 -0
- package/scripts/lint-ratchet.py +1547 -0
- package/scripts/monitor-pr-checks.sh +441 -0
- package/scripts/pipeline-tally.sh +756 -0
- package/scripts/pipeline-tally.test.sh +740 -0
- package/scripts/plugin-version.sh +528 -0
- package/scripts/precommit-guard.sh +115 -0
- package/scripts/precommit-guard.test.sh +254 -0
- package/scripts/reconcile-live-heartbeats.ts +705 -0
- package/scripts/render-c4-model.sh +217 -0
- package/scripts/resolve-git-root.sh +55 -0
- package/scripts/resolve-regenerable-conflicts.sh +363 -0
- package/scripts/resolve-regenerable-conflicts.test.sh +780 -0
- package/scripts/ruff-requirements.txt +22 -0
- package/scripts/run-in-pid-namespace.sh +98 -0
- package/scripts/run-in-pid-namespace.test.sh +290 -0
- package/scripts/scan-ancestor-signal-helpers.py +556 -0
- package/scripts/scan-ancestor-signal-helpers.test.sh +670 -0
- package/scripts/setup-ralph-loop.sh +238 -0
- package/scripts/sync-cursor-name-map.ts +316 -0
- package/scripts/sync-grok-agent-compat.ts +188 -0
- package/scripts/sync-npm-package.ts +165 -0
- package/scripts/sync-opencode-adapter.ts +498 -0
- package/scripts/sync-pr-behind.sh +647 -0
- package/scripts/sync-pr-behind.test.sh +252 -0
- package/scripts/taste-profile-update.sh +180 -0
- package/scripts/taste-profile-update.test.sh +167 -0
- package/scripts/write-budget-marker.sh +23 -0
- package/scripts/write-kb-coverage.ts +113 -0
- package/skills/admin-ip-refresh/SKILL.md +81 -0
- package/skills/admin-ip-refresh/references/admin-ip-refresh-procedure.md +201 -0
- package/skills/agent-browser/SKILL.md +698 -0
- package/skills/agent-browser/scripts/playwright-mcp-profile-slot.sh +304 -0
- package/skills/agent-browser/scripts/playwright-mcp-redact-proxy.py +964 -0
- package/skills/agent-browser/scripts/redact-a11y-snapshot.py +443 -0
- package/skills/agent-browser/test/fixtures/capture-playwright-mcp-fixtures.py +217 -0
- package/skills/agent-browser/test/fixtures/fake-passthrough-proxy.py +24 -0
- package/skills/agent-browser/test/fixtures/fake-playwright-mcp.py +131 -0
- package/skills/agent-browser/test/fixtures/make-proxy-mutant.py +48 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/dialog-link-injection.json +10 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/empty-content.json +5 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/error-and-result.json +4 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/error-code-bool.json +6 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/error-code-string.json +6 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/error-message-tree.json +6 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/error-no-data.json +6 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/error-string.json +4 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/error-with-data.json +9 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/evaluate-escaped-object.json +10 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/invalid-utf8.json +4 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/link-result.json +10 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/list-two-results.json +6 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/meta-in-result.json +13 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/no-content.json +5 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/quoted-key.json +10 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/resource-block.json +18 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/result-and-method.json +11 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/result-string.json +3 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/run-code-escaped-one-row.json +10 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/run-code-escaped.json +10 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/structured-content.json +13 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/tools-list-no-tools.json +5 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/tree-no-credential.json +10 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/two-text-blocks.json +14 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/unparsable-line.json +3 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/value-contains-brace.json +10 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/value-contains-link-substring.json +10 -0
- package/skills/agent-browser/test/fixtures/playwright-mcp-0.0.78/close.json +12 -0
- package/skills/agent-browser/test/fixtures/playwright-mcp-0.0.78/evaluate.json +12 -0
- package/skills/agent-browser/test/fixtures/playwright-mcp-0.0.78/find.json +12 -0
- package/skills/agent-browser/test/fixtures/playwright-mcp-0.0.78/framing.json +6 -0
- package/skills/agent-browser/test/fixtures/playwright-mcp-0.0.78/initialize.json +14 -0
- package/skills/agent-browser/test/fixtures/playwright-mcp-0.0.78/navigate-link.json +12 -0
- package/skills/agent-browser/test/fixtures/playwright-mcp-0.0.78/navigate.json +12 -0
- package/skills/agent-browser/test/fixtures/playwright-mcp-0.0.78/roots-list-request.json +5 -0
- package/skills/agent-browser/test/fixtures/playwright-mcp-0.0.78/screenshot.json +17 -0
- package/skills/agent-browser/test/fixtures/playwright-mcp-0.0.78/snapshot-filename.json +12 -0
- package/skills/agent-browser/test/fixtures/playwright-mcp-0.0.78/snapshot-meta-json.json +12 -0
- package/skills/agent-browser/test/fixtures/playwright-mcp-0.0.78/snapshot-meta-raw.json +12 -0
- package/skills/agent-browser/test/fixtures/playwright-mcp-0.0.78/snapshot.json +12 -0
- package/skills/agent-browser/test/fixtures/playwright-mcp-0.0.78/tools-list.json +827 -0
- package/skills/agent-browser/test/fixtures/proxy-session-driver.py +138 -0
- package/skills/agent-browser/test/fixtures/session-facts.py +102 -0
- package/skills/agent-browser/test/playwright-mcp-lifetime.test.sh +1620 -0
- package/skills/agent-browser/test/playwright-mcp-redact-proxy.test.sh +1599 -0
- package/skills/agent-browser/test/redact-a11y-snapshot.test.sh +527 -0
- package/skills/agent-native-architecture/SKILL.md +479 -0
- package/skills/agent-native-architecture/references/action-parity-discipline.md +430 -0
- package/skills/agent-native-architecture/references/agent-execution-patterns.md +483 -0
- package/skills/agent-native-architecture/references/agent-native-testing.md +605 -0
- package/skills/agent-native-architecture/references/architecture-patterns.md +493 -0
- package/skills/agent-native-architecture/references/dynamic-context-injection.md +358 -0
- package/skills/agent-native-architecture/references/files-universal-interface.md +314 -0
- package/skills/agent-native-architecture/references/from-primitives-to-domain-tools.md +381 -0
- package/skills/agent-native-architecture/references/mcp-tool-design.md +524 -0
- package/skills/agent-native-architecture/references/mobile-patterns.md +897 -0
- package/skills/agent-native-architecture/references/product-implications.md +478 -0
- package/skills/agent-native-architecture/references/refactoring-to-prompt-native.md +342 -0
- package/skills/agent-native-architecture/references/self-modification.md +294 -0
- package/skills/agent-native-architecture/references/shared-workspace-architecture.md +700 -0
- package/skills/agent-native-architecture/references/system-prompt-design.md +263 -0
- package/skills/agent-native-audit/SKILL.md +300 -0
- package/skills/agent-native-audit/workflows/agent-native-audit.workflow.js +423 -0
- package/skills/andrew-kane-gem-writer/SKILL.md +189 -0
- package/skills/andrew-kane-gem-writer/references/database-adapters.md +231 -0
- package/skills/andrew-kane-gem-writer/references/module-organization.md +121 -0
- package/skills/andrew-kane-gem-writer/references/rails-integration.md +183 -0
- package/skills/andrew-kane-gem-writer/references/resources.md +126 -0
- package/skills/andrew-kane-gem-writer/references/testing-patterns.md +261 -0
- package/skills/architecture/SKILL.md +436 -0
- package/skills/architecture/references/adr-template.md +154 -0
- package/skills/architecture/references/likec4-reference.md +136 -0
- package/skills/architecture/references/nfr-reference.md +126 -0
- package/skills/archive-kb/SKILL.md +86 -0
- package/skills/archive-kb/scripts/archive-kb.sh +300 -0
- package/skills/archive-kb/test/archive-kb-partial-run.test.sh +276 -0
- package/skills/atdd-developer/SKILL.md +65 -0
- package/skills/brainstorm/SKILL.md +701 -0
- package/skills/brainstorm/references/brainstorm-brand-workshop.md +153 -0
- package/skills/brainstorm/references/brainstorm-domain-config.md +63 -0
- package/skills/brainstorm/references/brainstorm-validation-workshop.md +65 -0
- package/skills/brainstorm/references/ui-surface-terms.md +42 -0
- package/skills/brainstorm-techniques/SKILL.md +231 -0
- package/skills/brainstorm-techniques/references/decision-principles.md +150 -0
- package/skills/brainstorm-techniques/references/phase-boundaries.md +103 -0
- package/skills/brainstorm-techniques/references/standing-delegation.md +407 -0
- package/skills/brainstorm-techniques/references/technical-ruling-delegation.md +174 -0
- package/skills/campaign-calendar/SKILL.md +145 -0
- package/skills/cf-token-scope/SKILL.md +164 -0
- package/skills/cf-token-scope/references/widen-playbook.md +114 -0
- package/skills/cf-token-scope/scripts/cf-token-scope.sh +253 -0
- package/skills/changelog/SKILL.md +142 -0
- package/skills/code-to-prd/SKILL.md +66 -0
- package/skills/code-to-prd/references/banner-template.md +12 -0
- package/skills/code-to-prd/references/prd-template.md +41 -0
- package/skills/code-to-prd/scripts/code-to-prd.sh +634 -0
- package/skills/code-to-prd/test/code-to-prd.test.sh +447 -0
- package/skills/code-to-prd/test/fixture/.env.example +7 -0
- package/skills/code-to-prd/test/fixture/app/about/page.tsx +11 -0
- package/skills/code-to-prd/test/fixture/app/api/health/route.ts +10 -0
- package/skills/code-to-prd/test/fixture/app/page.tsx +14 -0
- package/skills/code-to-prd/test/fixture/next.config.mjs +3 -0
- package/skills/code-to-prd/test/fixture/package.json +6 -0
- package/skills/cohort-status/SKILL.md +62 -0
- package/skills/community/SKILL.md +210 -0
- package/skills/community/scripts/bsky-community.sh +644 -0
- package/skills/community/scripts/bsky-setup.sh +631 -0
- package/skills/community/scripts/community-router.sh +93 -0
- package/skills/community/scripts/discord-community.sh +487 -0
- package/skills/community/scripts/discord-setup.sh +784 -0
- package/skills/community/scripts/github-community.sh +706 -0
- package/skills/community/scripts/hn-community.sh +233 -0
- package/skills/community/scripts/lib/hmac-sha1-b64.sh +126 -0
- package/skills/community/scripts/linkedin-community.sh +750 -0
- package/skills/community/scripts/linkedin-setup.sh +758 -0
- package/skills/community/scripts/x-community.sh +890 -0
- package/skills/community/scripts/x-setup.sh +713 -0
- package/skills/community/test/community-argv.test.sh +2922 -0
- package/skills/community/test/github-community.test.sh +981 -0
- package/skills/competitive-analysis/SKILL.md +69 -0
- package/skills/competitive-analysis/references/peer-plugin-audit.md +218 -0
- package/skills/compound/SKILL.md +673 -0
- package/skills/compound/scripts/token-efficiency-report.sh +334 -0
- package/skills/compound/test/phase-16.test.sh +379 -0
- package/skills/compound-capture/SKILL.md +791 -0
- package/skills/compound-capture/assets/critical-pattern-template.md +37 -0
- package/skills/compound-capture/assets/resolution-template.md +116 -0
- package/skills/compound-capture/references/yaml-schema.md +67 -0
- package/skills/compound-capture/schema.yaml +181 -0
- package/skills/constraint-scaffold/SKILL.md +175 -0
- package/skills/constraint-scaffold/references/boundary-readme.template +35 -0
- package/skills/constraint-scaffold/references/constraint-gates-workflow.template +69 -0
- package/skills/constraint-scaffold/references/depcruise-config.template +230 -0
- package/skills/constraint-scaffold/references/fix-constraints-stage-a.template +240 -0
- package/skills/constraint-scaffold/references/fix-constraints-stage-b.template +313 -0
- package/skills/constraint-scaffold/references/shared-runner.template +135 -0
- package/skills/constraint-scaffold/scripts/constraint-scaffold.sh +589 -0
- package/skills/constraint-scaffold/test/bite-proof.test.sh +1338 -0
- package/skills/constraint-scaffold/test/boundary.test.sh +734 -0
- package/skills/constraint-scaffold/test/emit-fix-constraints.test.sh +193 -0
- package/skills/constraint-scaffold/test/generator.test.sh +93 -0
- package/skills/constraint-scaffold/test/parity.test.sh +285 -0
- package/skills/content-writer/SKILL.md +242 -0
- package/skills/content-writer/scripts/blog-jargon-scan.sh +42 -0
- package/skills/cron-delete/SKILL.md +56 -0
- package/skills/cron-list/SKILL.md +54 -0
- package/skills/deepen-plan/SKILL.md +937 -0
- package/skills/deepen-plan/workflows/deepen-plan.workflow.js +488 -0
- package/skills/deploy/SKILL.md +115 -0
- package/skills/deploy/references/hetzner-setup.md +67 -0
- package/skills/deploy/scripts/deploy.sh +37 -0
- package/skills/deploy-docs/SKILL.md +95 -0
- package/skills/dhh-rails-style/SKILL.md +203 -0
- package/skills/dhh-rails-style/references/architecture.md +717 -0
- package/skills/dhh-rails-style/references/controllers.md +323 -0
- package/skills/dhh-rails-style/references/frontend.md +556 -0
- package/skills/dhh-rails-style/references/gems.md +316 -0
- package/skills/dhh-rails-style/references/models.md +388 -0
- package/skills/dhh-rails-style/references/testing.md +354 -0
- package/skills/discord-content/SKILL.md +126 -0
- package/skills/docs-site/SKILL.md +214 -0
- package/skills/drain-labeled-backlog/SKILL.md +203 -0
- package/skills/drain-labeled-backlog/scripts/group-by-area.sh +208 -0
- package/skills/drain-labeled-backlog/workflows/drain-labeled-backlog.workflow.js +433 -0
- package/skills/drain-prs/SKILL.md +143 -0
- package/skills/drain-prs/scripts/triage-prs.sh +192 -0
- package/skills/drain-prs/test/argv-ceiling.test.sh +183 -0
- package/skills/dspy-ruby/SKILL.md +634 -0
- package/skills/dspy-ruby/assets/config-template.rb +359 -0
- package/skills/dspy-ruby/assets/module-template.rb +326 -0
- package/skills/dspy-ruby/assets/signature-template.rb +143 -0
- package/skills/dspy-ruby/references/core-concepts.md +268 -0
- package/skills/dspy-ruby/references/optimization.md +623 -0
- package/skills/dspy-ruby/references/providers.md +335 -0
- package/skills/eval-harness/README.md +194 -0
- package/skills/eval-harness/SKILL.md +157 -0
- package/skills/eval-harness/enums/go-routes.json +13 -0
- package/skills/eval-harness/enums/incident-threshold.json +5 -0
- package/skills/eval-harness/enums/lane.json +5 -0
- package/skills/eval-harness/enums/tool-selection.json +20 -0
- package/skills/eval-harness/enums/triage-levels.json +5 -0
- package/skills/eval-harness/gated-skills.json +34 -0
- package/skills/eval-harness/models.generated.json +5 -0
- package/skills/eval-harness/promptfooconfig-go-routing.yaml +35 -0
- package/skills/eval-harness/promptfooconfig-incident-threshold.yaml +32 -0
- package/skills/eval-harness/promptfooconfig-lane-inference.yaml +33 -0
- package/skills/eval-harness/promptfooconfig-ticket-triage.yaml +34 -0
- package/skills/eval-harness/promptfooconfig-tool-selection.yaml +33 -0
- package/skills/eval-harness/prompts/go-baseline.txt +6 -0
- package/skills/eval-harness/prompts/go-skill.txt +21 -0
- package/skills/eval-harness/prompts/incident-threshold-baseline.txt +6 -0
- package/skills/eval-harness/prompts/incident-threshold-skill.txt +12 -0
- package/skills/eval-harness/prompts/lane-inference-baseline.txt +6 -0
- package/skills/eval-harness/prompts/lane-inference-skill.txt +15 -0
- package/skills/eval-harness/prompts/tool-selection-baseline.txt +19 -0
- package/skills/eval-harness/prompts/tool-selection-skill.txt +22 -0
- package/skills/eval-harness/prompts/triage-baseline.txt +7 -0
- package/skills/eval-harness/prompts/triage-skill.txt +10 -0
- package/skills/eval-harness/scripts/eval-gate.cjs +318 -0
- package/skills/eval-harness/scripts/extract-block.cjs +87 -0
- package/skills/eval-harness/scripts/gate-classification.cjs +28 -0
- package/skills/eval-harness/scripts/gen-models.sh +41 -0
- package/skills/eval-harness/scripts/gen-skill-prompt.cjs +177 -0
- package/skills/eval-harness/scripts/measure-classification.cjs +30 -0
- package/skills/eval-harness/scripts/parse-label.cjs +93 -0
- package/skills/eval-harness/scripts/verdict.cjs +132 -0
- package/skills/eval-harness/tasks/go-routing.jsonl +8 -0
- package/skills/eval-harness/tasks/incident-threshold.jsonl +7 -0
- package/skills/eval-harness/tasks/lane-inference.jsonl +7 -0
- package/skills/eval-harness/tasks/ticket-triage.jsonl +6 -0
- package/skills/eval-harness/tasks/tool-selection.jsonl +15 -0
- package/skills/eval-harness/test/eval-gate.test.sh +132 -0
- package/skills/eval-harness/test/extract-block.test.sh +87 -0
- package/skills/eval-harness/test/gate-classification.test.sh +77 -0
- package/skills/eval-harness/test/gen-models.test.sh +75 -0
- package/skills/eval-harness/test/measure-classification.test.sh +74 -0
- package/skills/eval-harness/test/parse-label.test.sh +129 -0
- package/skills/eval-harness/test/registry-completeness.test.sh +109 -0
- package/skills/eval-harness/test/verdict.test.sh +123 -0
- package/skills/every-style-editor/SKILL.md +142 -0
- package/skills/every-style-editor/references/EVERY_WRITE_STYLE.md +529 -0
- package/skills/feature-tweet/SKILL.md +199 -0
- package/skills/feature-video/SKILL.md +412 -0
- package/skills/feature-video/scripts/check_deps.sh +281 -0
- package/skills/file-todos/SKILL.md +267 -0
- package/skills/file-todos/assets/todo-template.md +166 -0
- package/skills/fix-issue/SKILL.md +278 -0
- package/skills/fix-issue/references/agent-authored-exclusion.md +120 -0
- package/skills/fix-issue/references/exclude-label-jq-snippet.md +97 -0
- package/skills/flag-bootstrap/SETUP.md +142 -0
- package/skills/flag-create/SKILL.md +145 -0
- package/skills/flag-create/scripts/create.sh +273 -0
- package/skills/flag-delete/SKILL.md +167 -0
- package/skills/flag-delete/scripts/delete.sh +288 -0
- package/skills/flag-list/SKILL.md +99 -0
- package/skills/flag-list/scripts/list.sh +275 -0
- package/skills/flag-set-role/SKILL.md +229 -0
- package/skills/flag-set-role/scripts/flip.sh +774 -0
- package/skills/frontend-anti-slop/SKILL.md +106 -0
- package/skills/frontend-anti-slop/references/anti-patterns.md +199 -0
- package/skills/frontend-anti-slop/references/slop-rules.md +65 -0
- package/skills/frontend-anti-slop/scripts/tier1-scan.ts +525 -0
- package/skills/frontend-design/SKILL.md +77 -0
- package/skills/gdpr-gate/NOTICE +136 -0
- package/skills/gdpr-gate/SKILL.md +341 -0
- package/skills/gdpr-gate/references/fields.md +160 -0
- package/skills/gdpr-gate/references/layers/api-layer.md +355 -0
- package/skills/gdpr-gate/references/layers/auth-sessions.md +290 -0
- package/skills/gdpr-gate/references/layers/data-in-transit.md +331 -0
- package/skills/gdpr-gate/references/layers/data-lifecycle.md +341 -0
- package/skills/gdpr-gate/references/layers/frontend.md +249 -0
- package/skills/gdpr-gate/references/layers/testing-seeding.md +256 -0
- package/skills/gdpr-gate/references/leakage-vectors.md +248 -0
- package/skills/gdpr-gate/references/legacy/legal-consent-v1-prose.md +48 -0
- package/skills/gdpr-gate/references/legal-consent.md +140 -0
- package/skills/gdpr-gate/references/non-negotiables.md +60 -0
- package/skills/gdpr-gate/scripts/gdpr-gate.sh +271 -0
- package/skills/gdpr-gate/scripts/notice-frontmatter.sh +337 -0
- package/skills/gdpr-gate/scripts/path-denylist.txt +39 -0
- package/skills/gdpr-gate/scripts/repo-scan.sh +158 -0
- package/skills/gdpr-gate/scripts/vendor-drift-classify.sh +120 -0
- package/skills/gdpr-gate/scripts/vendor-pin-integrity.sh +237 -0
- package/skills/gemini-imagegen/SKILL.md +283 -0
- package/skills/gemini-imagegen/requirements.txt +5 -0
- package/skills/gemini-imagegen/scripts/_error_handling.py +146 -0
- package/skills/gemini-imagegen/scripts/compose_images.py +150 -0
- package/skills/gemini-imagegen/scripts/edit_image.py +137 -0
- package/skills/gemini-imagegen/scripts/gemini_images.py +256 -0
- package/skills/gemini-imagegen/scripts/generate_image.py +147 -0
- package/skills/gemini-imagegen/scripts/multi_turn_chat.py +223 -0
- package/skills/gemini-imagegen/scripts/test_error_handling.py +179 -0
- package/skills/git-worktree/SKILL.md +534 -0
- package/skills/git-worktree/scripts/git-repo-readiness-diag.sh +98 -0
- package/skills/git-worktree/scripts/worktree-manager.sh +4773 -0
- package/skills/git-worktree/test/create-from-origin-main.test.sh +116 -0
- package/skills/git-worktree/test/lease-protects-active.test.sh +1056 -0
- package/skills/git-worktree/test/no-repo-fail-loud.test.sh +88 -0
- package/skills/git-worktree/test/orphan-reaper-honest-count.test.sh +379 -0
- package/skills/git-worktree/test/reap-archive-persistence.test.sh +725 -0
- package/skills/git-worktree/test/stale-lock-sweep.test.sh +176 -0
- package/skills/go/SKILL.md +54 -0
- package/skills/growth/SKILL.md +164 -0
- package/skills/harvest-debt/SKILL.md +78 -0
- package/skills/harvest-debt/scripts/harvest-debt.sh +114 -0
- package/skills/heal-skill/SKILL.md +173 -0
- package/skills/help/SKILL.md +46 -0
- package/skills/incident/NOTICE +39 -0
- package/skills/incident/SKILL.md +395 -0
- package/skills/incident/scripts/dry-run.sh +448 -0
- package/skills/incident/scripts/redact-engine.py +412 -0
- package/skills/incident/scripts/redact-sentinel.sh +44 -0
- package/skills/incident/templates/pir.md +139 -0
- package/skills/incident/test/fixtures/dry-run-incident.json +26 -0
- package/skills/incident/test/fixtures/dry-run-secret-leak.json +26 -0
- package/skills/incident/test/fixtures/legacy-bash-scanner.sh +82 -0
- package/skills/incident/test/fixtures/positive-corpus.md +87 -0
- package/skills/incident/test/redact-sentinel.test.sh +1420 -0
- package/skills/invoice/SKILL.md +206 -0
- package/skills/kb-glossary/SKILL.md +71 -0
- package/skills/kb-glossary/references/glossary-format.md +111 -0
- package/skills/kb-glossary/references/rejected-request-register.md +115 -0
- package/skills/kb-search/SKILL.md +276 -0
- package/skills/kb-search/scripts/kb-search-cache.sh +123 -0
- package/skills/legal-audit/SKILL.md +161 -0
- package/skills/legal-generate/NOTICE +242 -0
- package/skills/legal-generate/SKILL.md +244 -0
- package/skills/legal-generate/references/templates/advisor-agreement/template.md +12 -0
- package/skills/legal-generate/references/templates/business-associate-agreement/template.md +112 -0
- package/skills/legal-generate/references/templates/cookie-notice/template.md +82 -0
- package/skills/legal-generate/references/templates/dpa-global/template.md +439 -0
- package/skills/legal-generate/references/templates/dpa-us/template.md +222 -0
- package/skills/legal-generate/references/templates/employee-offer-letter/template.md +75 -0
- package/skills/legal-generate/references/templates/master-services-agreement/template.md +252 -0
- package/skills/legal-generate/references/templates/mutual-nda/template.md +66 -0
- package/skills/legal-generate/references/templates/one-way-nda/template.md +38 -0
- package/skills/legal-generate/references/templates/privacy-policy-gdpr/template.md +427 -0
- package/skills/legal-generate/references/templates/privacy-policy-us/template.md +313 -0
- package/skills/legal-generate/references/templates/terms-of-use/template.md +75 -0
- package/skills/legal-generate/scripts/strip-vendor-credit.sh +96 -0
- package/skills/linear-fetch/SKILL.md +247 -0
- package/skills/linear-fetch/scripts/assert-no-linear-telemetry.sh +66 -0
- package/skills/linear-fetch/scripts/redact-linear-urls.sh +51 -0
- package/skills/linear-fetch/scripts/render-caller-template.sh +36 -0
- package/skills/linear-fetch/test/assert-no-linear-telemetry.test.sh +113 -0
- package/skills/linear-fetch/test/parity.test.sh +112 -0
- package/skills/linear-fetch/test/persist-safe-integration.test.sh +191 -0
- package/skills/linear-fetch/test/redact-linear-urls.test.sh +226 -0
- package/skills/merge-pr/SKILL.md +670 -0
- package/skills/model-launch-review/SKILL.md +255 -0
- package/skills/model-launch-review/scripts/audit-models.sh +501 -0
- package/skills/one-shot/SKILL.md +316 -0
- package/skills/one-shot/references/token-discipline.md +74 -0
- package/skills/operator-bootstrap/SKILL.md +412 -0
- package/skills/operator-bootstrap/template.sh +439 -0
- package/skills/operator-digest/SKILL.md +287 -0
- package/skills/operator-digest/assets/operator-digest.workflow.yml +175 -0
- package/skills/operator-digest/scripts/digest-scrub.sh +119 -0
- package/skills/operator-digest/scripts/provision-operator-digest-repo.sh +147 -0
- package/skills/operator-rephrase/SKILL.md +98 -0
- package/skills/pencil-setup/SKILL.md +201 -0
- package/skills/pencil-setup/scripts/check_deps.sh +556 -0
- package/skills/pencil-setup/scripts/copy_adapter.sh +80 -0
- package/skills/pencil-setup/scripts/package-lock.json +1172 -0
- package/skills/pencil-setup/scripts/package.json +14 -0
- package/skills/pencil-setup/scripts/pencil-error-enrichment.mjs +21 -0
- package/skills/pencil-setup/scripts/pencil-mcp-adapter.mjs +733 -0
- package/skills/pencil-setup/scripts/pencil-response-classify.mjs +38 -0
- package/skills/pencil-setup/scripts/pencil-save-gate.mjs +26 -0
- package/skills/pencil-setup/scripts/sanitize-filename.mjs +25 -0
- package/skills/plan/SKILL.md +1140 -0
- package/skills/plan/references/differential-migration-testing.md +185 -0
- package/skills/plan/references/plan-community-discovery.md +42 -0
- package/skills/plan/references/plan-founder-check.md +137 -0
- package/skills/plan/references/plan-functional-overlap.md +25 -0
- package/skills/plan/references/plan-host-fanout.md +51 -0
- package/skills/plan/references/plan-issue-templates.md +779 -0
- package/skills/plan/references/plan-network-outage-checklist.md +131 -0
- package/skills/plan/references/plan-scope-check.md +126 -0
- package/skills/plan/references/plan-sharp-edges.md +331 -0
- package/skills/plan/references/plan-signoff-lifecycle.md +12 -0
- package/skills/plan/references/webapp-cwv-observability.md +143 -0
- package/skills/plan-review/SKILL.md +91 -0
- package/skills/plan-review/lib/named-panel.mjs +58 -0
- package/skills/plan-review/workflows/plan-review.workflow.js +477 -0
- package/skills/postmerge/SKILL.md +642 -0
- package/skills/postmerge/references/deploy-status-debugging.md +141 -0
- package/skills/postmerge/references/graceful-degradation.md +20 -0
- package/skills/postmerge/references/sentry-error-count-delta.md +137 -0
- package/skills/preflight/SKILL.md +1553 -0
- package/skills/preflight/references/check-13-founder-check.md +286 -0
- package/skills/preflight/scripts/founder-check.py +1640 -0
- package/skills/preflight/scripts/parse-form-a.awk +107 -0
- package/skills/preflight/scripts/probe-verb-gate.sh +108 -0
- package/skills/product-roadmap/SKILL.md +357 -0
- package/skills/product-roadmap/scripts/roadmap-reconcile.sh +327 -0
- package/skills/provision-cloudflare/SKILL.md +67 -0
- package/skills/provision-cloudflare/scripts/provision-cloudflare.sh +271 -0
- package/skills/provision-doppler/SKILL.md +58 -0
- package/skills/provision-doppler/scripts/provision-doppler.sh +358 -0
- package/skills/provision-github/SKILL.md +59 -0
- package/skills/provision-github/scripts/provision-github.sh +300 -0
- package/skills/provision-hetzner/SKILL.md +76 -0
- package/skills/provision-hetzner/scripts/provision-hetzner.sh +262 -0
- package/skills/provision-hetzner/test/fixture/knowledge-base/legal/tenant-dpa-register.md +26 -0
- package/skills/provision-hetzner/test/fixture/provision-hetzner-dry-run.golden +34 -0
- package/skills/provision-hetzner/test/provision-hetzner-characterization.test.sh +227 -0
- package/skills/qa/SKILL.md +263 -0
- package/skills/qa/references/browser-preflight.md +22 -0
- package/skills/questionnaire-generate/SKILL.md +328 -0
- package/skills/questionnaire-generate/references/questionnaire.template +60 -0
- package/skills/rclone/SKILL.md +162 -0
- package/skills/rclone/scripts/check_setup.sh +63 -0
- package/skills/release-announce/SKILL.md +65 -0
- package/skills/release-docs/SKILL.md +92 -0
- package/skills/reproduce-bug/SKILL.md +358 -0
- package/skills/resolve-debt/SKILL.md +85 -0
- package/skills/resolve-debt/scripts/resolve-debt.py +584 -0
- package/skills/resolve-parallel/SKILL.md +45 -0
- package/skills/resolve-parallel/workflows/resolve-parallel.workflow.js +415 -0
- package/skills/resolve-pr-parallel/SKILL.md +68 -0
- package/skills/resolve-pr-parallel/workflows/resolve-pr-parallel.workflow.js +419 -0
- package/skills/resolve-todo-parallel/SKILL.md +57 -0
- package/skills/resolve-todo-parallel/workflows/resolve-todo-parallel.workflow.js +398 -0
- package/skills/review/SKILL.md +1620 -0
- package/skills/review/references/anti-slop-scanner-hook.md +40 -0
- package/skills/review/references/defect-classes-migrations.md +9 -0
- package/skills/review/references/generated-input-oracle-surfaces.md +15 -0
- package/skills/review/references/review-e2e-testing.md +116 -0
- package/skills/review/references/review-evidence-comment.md +36 -0
- package/skills/review/references/review-todo-structure.md +165 -0
- package/skills/review/references/risk-tier-and-fix-rounds.md +97 -0
- package/skills/review/references/semgrep-custom-rules.yaml +174 -0
- package/skills/review/references/ultrathink-phases.md +98 -0
- package/skills/review/references/wfs.md +6 -0
- package/skills/review/scripts/emit-review-trailer.sh +499 -0
- package/skills/review/scripts/ensure-semgrep.sh +99 -0
- package/skills/review/scripts/fix-round-seats.sh +197 -0
- package/skills/review/test/emit-review-trailer.test.sh +387 -0
- package/skills/review/test/ensure-semgrep.test.sh +111 -0
- package/skills/review/test/fix-round-seats.test.sh +237 -0
- package/skills/review/workflows/README.md +147 -0
- package/skills/review/workflows/review.workflow.js +667 -0
- package/skills/schedule/SKILL.md +796 -0
- package/skills/seo-aeo/SKILL.md +139 -0
- package/skills/seo-aeo/scripts/validate-csp.sh +233 -0
- package/skills/seo-aeo/scripts/validate-seo.sh +262 -0
- package/skills/ship/SKILL.md +3023 -0
- package/skills/ship/references/adr-ordinal-collision.md +47 -0
- package/skills/ship/references/affected-gate-contract.md +115 -0
- package/skills/ship/references/ci-run-diagnosis.md +29 -0
- package/skills/ship/references/ci-workflow-authoring.md +68 -0
- package/skills/ship/references/cleanup-merged-archival.md +39 -0
- package/skills/ship/references/counsel-review-clo-attestation.md +38 -0
- package/skills/ship/references/cto-ruling-armed-push.md +5 -0
- package/skills/ship/references/decision-challenges-render.md +71 -0
- package/skills/ship/references/delegated-act-authoring-form.md +7 -0
- package/skills/ship/references/detached-battery-verdict.md +13 -0
- package/skills/ship/references/epic-close-sweep.md +62 -0
- package/skills/ship/references/feature-tweet-draft.md +42 -0
- package/skills/ship/references/followthrough-issue-body-template.md +47 -0
- package/skills/ship/references/followthrough-stub-template.sh +92 -0
- package/skills/ship/references/merge-queue-dequeue.md +39 -0
- package/skills/ship/references/operator-holds.md +179 -0
- package/skills/ship/references/pipeline-tally-render.md +43 -0
- package/skills/ship/references/pr-overlap.md +153 -0
- package/skills/ship/references/queue-mode.md +7 -0
- package/skills/ship/references/ready-run-wait.md +36 -0
- package/skills/ship/references/red-on-main-quarantine.md +110 -0
- package/skills/ship/references/register-update-pr-pattern.md +88 -0
- package/skills/ship/references/settle-then-admin-merge.md +130 -0
- package/skills/ship/references/supabase-column-probe.md +13 -0
- package/skills/ship/scripts/auto-close-scan.sh +76 -0
- package/skills/ship/scripts/battery-owed.sh +403 -0
- package/skills/ship/scripts/hold-gate-eval.sh +410 -0
- package/skills/ship/scripts/net-issue-flow.sh +665 -0
- package/skills/ship/scripts/pr-overlap-preflight.sh +483 -0
- package/skills/ship/scripts/ship-pir-action-items-gate.sh +246 -0
- package/skills/ship/scripts/technical-ruling-gate.sh +444 -0
- package/skills/skill-creator/SKILL.md +299 -0
- package/skills/skill-creator/references/api-security.md +248 -0
- package/skills/skill-creator/references/authoring-levers.md +110 -0
- package/skills/skill-creator/references/be-clear-and-direct.md +587 -0
- package/skills/skill-creator/references/best-practices.md +431 -0
- package/skills/skill-creator/references/common-patterns.md +639 -0
- package/skills/skill-creator/references/core-principles.md +193 -0
- package/skills/skill-creator/references/executable-code.md +188 -0
- package/skills/skill-creator/references/iteration-and-testing.md +509 -0
- package/skills/skill-creator/references/official-spec.md +193 -0
- package/skills/skill-creator/references/recommended-structure.md +180 -0
- package/skills/skill-creator/references/skill-structure.md +396 -0
- package/skills/skill-creator/references/using-scripts.md +122 -0
- package/skills/skill-creator/references/using-templates.md +120 -0
- package/skills/skill-creator/references/workflows-and-validation.md +541 -0
- package/skills/skill-creator/scripts/init_skill.py +322 -0
- package/skills/skill-creator/scripts/package_skill.py +110 -0
- package/skills/skill-creator/scripts/quick_validate.py +64 -0
- package/skills/skill-creator/templates/router-skill.md +73 -0
- package/skills/skill-creator/templates/simple-skill.md +34 -0
- package/skills/skill-creator/workflows/add-reference.md +96 -0
- package/skills/skill-creator/workflows/add-script.md +104 -0
- package/skills/skill-creator/workflows/add-template.md +83 -0
- package/skills/skill-creator/workflows/add-workflow.md +128 -0
- package/skills/skill-creator/workflows/audit-skill.md +159 -0
- package/skills/skill-creator/workflows/create-domain-expertise-skill.md +623 -0
- package/skills/skill-creator/workflows/create-new-skill.md +207 -0
- package/skills/skill-creator/workflows/get-guidance.md +134 -0
- package/skills/skill-creator/workflows/upgrade-to-router.md +170 -0
- package/skills/skill-creator/workflows/verify-skill.md +226 -0
- package/skills/skill-security-scan/SKILL.md +145 -0
- package/skills/skill-security-scan/references/disclaimer.md +21 -0
- package/skills/skill-security-scan/references/first-party-allowlist.yaml +38 -0
- package/skills/skill-security-scan/references/override-artifact-schema.json +68 -0
- package/skills/skill-security-scan/references/override-mechanism.md +171 -0
- package/skills/skill-security-scan/references/redirect-domains.yaml +27 -0
- package/skills/skill-security-scan/references/regex-patterns.md +136 -0
- package/skills/skill-security-scan/references/rules/code-exec.yaml +70 -0
- package/skills/skill-security-scan/references/rules/filesystem-boundary.yaml +29 -0
- package/skills/skill-security-scan/references/rules/manifest.yaml +44 -0
- package/skills/skill-security-scan/references/rules/supply-chain.yaml +36 -0
- package/skills/skill-security-scan/references/scan-meta-schema.json +63 -0
- package/skills/skill-security-scan/references/test-fixtures/clean-soleur-style.skill.md +23 -0
- package/skills/skill-security-scan/references/test-fixtures/clean-third-party.skill.md +26 -0
- package/skills/skill-security-scan/references/test-fixtures/malicious-codeexec.skill.md +23 -0
- package/skills/skill-security-scan/references/test-fixtures/malicious-curl-pipe-bash.skill.md +69 -0
- package/skills/skill-security-scan/references/test-fixtures/malicious-prompt-injection.skill.md +17 -0
- package/skills/skill-security-scan/references/test-fixtures/malicious-telemetry-beacon.skill.md +23 -0
- package/skills/skill-security-scan/references/typosquat-targets.yaml +65 -0
- package/skills/skill-security-scan/scripts/check-codeexec.sh +41 -0
- package/skills/skill-security-scan/scripts/check-filesystem-boundary.sh +19 -0
- package/skills/skill-security-scan/scripts/check-prompt-injection.sh +95 -0
- package/skills/skill-security-scan/scripts/check-supply-chain.sh +219 -0
- package/skills/skill-security-scan/scripts/check-telemetry-surface.sh +126 -0
- package/skills/skill-security-scan/scripts/lib.sh +197 -0
- package/skills/skill-security-scan/scripts/parse-override.sh +231 -0
- package/skills/skill-security-scan/scripts/run-scan.sh +342 -0
- package/skills/skill-security-scan/scripts/run-self-test.sh +95 -0
- package/skills/skill-security-scan/test/argv-ceiling.test.sh +180 -0
- package/skills/skill-security-scan/test/meta-dir-reap.test.sh +411 -0
- package/skills/skill-security-scan/test/parse-override.test.sh +607 -0
- package/skills/skill-security-scan/test/redact-pii-ghs-shape.test.sh +251 -0
- package/skills/social-distribute/SKILL.md +485 -0
- package/skills/spec-templates/SKILL.md +274 -0
- package/skills/sync/SKILL.md +49 -0
- package/skills/test-browser/SKILL.md +464 -0
- package/skills/test-browser/references/feature-map.md +161 -0
- package/skills/test-fix-loop/SKILL.md +159 -0
- package/skills/test-fix-loop/references/determinism-checklist.md +154 -0
- package/skills/triage/SKILL.md +402 -0
- package/skills/trigger-cron/SKILL.md +136 -0
- package/skills/trigger-cron/scripts/trigger.sh +198 -0
- package/skills/user-set-role/SKILL.md +147 -0
- package/skills/user-set-role/scripts/set-role.sh +218 -0
- package/skills/user-story-writer/SKILL.md +77 -0
- package/skills/ux-audit/SKILL.md +251 -0
- package/skills/ux-audit/references/finding.schema.json +62 -0
- package/skills/ux-audit/references/route-list.yaml +95 -0
- package/skills/ux-audit/scripts/bot-fixture.ts +270 -0
- package/skills/ux-audit/scripts/bot-signin.ts +135 -0
- package/skills/ux-audit/scripts/dedup-hash.ts +46 -0
- package/skills/verification-scaffold/SKILL.md +73 -0
- package/skills/verification-scaffold/references/gitleaks.toml.template +13 -0
- package/skills/verification-scaffold/references/guardrail-audit.md +156 -0
- package/skills/verification-scaffold/references/guards/block-stash-hook.sh.template +72 -0
- package/skills/verification-scaffold/references/guards/commit-on-main-hook.sh.template +82 -0
- package/skills/verification-scaffold/references/guards/orphan-test-check.sh.template +102 -0
- package/skills/verification-scaffold/references/guards/precommit-guard.sh.template +115 -0
- package/skills/verification-scaffold/references/guards/secret-scan-hook.sh.template +176 -0
- package/skills/verification-scaffold/references/guards/verification-gates.yml.template +49 -0
- package/skills/verification-scaffold/references/guards/wrapper-boundary.sh.template +47 -0
- package/skills/verification-scaffold/references/guards.tsv +21 -0
- package/skills/verification-scaffold/references/verification-readme.template +55 -0
- package/skills/verification-scaffold/scripts/verification-scaffold.sh +785 -0
- package/skills/verification-scaffold/test/bite-proof.test.sh +159 -0
- package/skills/verification-scaffold/test/generator.test.sh +319 -0
- package/skills/verification-scaffold/test/manifest.test.sh +144 -0
- package/skills/work/SKILL.md +1480 -0
- package/skills/work/references/end-of-work-resume.md +7 -0
- package/skills/work/references/hook-test-main-cwd.md +24 -0
- package/skills/work/references/key-principles.md +83 -0
- package/skills/work/references/property-testing.md +122 -0
- package/skills/work/references/sql-security-definer-rpc-scaffold.sql +78 -0
- package/skills/work/references/work-agent-teams.md +97 -0
- package/skills/work/references/work-lifecycle-parallel.md +147 -0
- package/skills/work/references/work-lockfile-bumps.md +97 -0
- package/skills/work/references/work-scratch-sandboxes.md +212 -0
- package/skills/work/references/work-subagent-fanout.md +61 -0
- package/skills/work/references/work-test-harness-sharp-edges.md +73 -0
- package/skills/xcode-test/SKILL.md +360 -0
|
@@ -0,0 +1,589 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# constraint-scaffold — deterministic generator for the Layer-1 client->server-secret
|
|
3
|
+
# import-boundary gate (ADR-071, Option D). Emits a dependency-cruiser config, a
|
|
4
|
+
# shared runner, and a CI workflow into the target Next.js app, captures the
|
|
5
|
+
# known-violations baseline, PROVES the emitted gate bites on a detached worktree of
|
|
6
|
+
# HEAD (pass -> fail -> pass), then appends a README block next to the governed path
|
|
7
|
+
# and one pointer line to the repo's agent-instructions file. v1 target =
|
|
8
|
+
# apps/web-platform (Next.js-only).
|
|
9
|
+
# <!-- Inspired by mattpocock/skills/skills/in-progress/setup-ts-deep-modules/SKILL.md (MIT, Copyright (c) 2026 Matt Pocock). -->
|
|
10
|
+
#
|
|
11
|
+
# Modes:
|
|
12
|
+
# (default) detect Next.js -> require app/ components/ server/ -> emit
|
|
13
|
+
# config + runner + workflows (refuse if any already exists;
|
|
14
|
+
# NO --force) -> capture baseline -> bite-proof -> README block
|
|
15
|
+
# + instructions pointer (append-once, written LAST).
|
|
16
|
+
# --refresh-baseline clean-tree guard, then re-capture the baseline against the
|
|
17
|
+
# origin/main merge-base (so a same-PR violation is NOT
|
|
18
|
+
# grandfathered), then bite-proof. Never writes README/pointer.
|
|
19
|
+
# Agent-only; never shown to the founder.
|
|
20
|
+
#
|
|
21
|
+
# Base ref: origin/main when it exists, else the remote's default branch (origin/HEAD, e.g. a
|
|
22
|
+
# founder repo on master). Neither present -> 69 BEFORE anything is written.
|
|
23
|
+
#
|
|
24
|
+
# Exit matrix (every non-zero is a hard, fail-closed stop; every message is printed on STDOUT
|
|
25
|
+
# first — agent runtimes surface stdout and swallow stderr — then on stderr):
|
|
26
|
+
# 0 success
|
|
27
|
+
# 2 CONSTRAINT_SCAFFOLD_REPO_ROOT override is empty, "/", or relative (refused before any git call)
|
|
28
|
+
# 64 usage error (unknown argument)
|
|
29
|
+
# 65 precondition failed (target is not a Next.js app, or lacks app/ components/ server/)
|
|
30
|
+
# 66 refuse-if-exists (a non-baseline artifact already present; no --force)
|
|
31
|
+
# 67 dirty working tree (baseline capture requires a clean tree)
|
|
32
|
+
# 68 dependency-cruiser binary missing, or baseline capture failed
|
|
33
|
+
# 69 git/base-ref/worktree/temp-dir error, TMPDIR resolves inside the repository, or another
|
|
34
|
+
# scaffold run holds the run lock (<git-common-dir>/constraint-scaffold.lock, owner pid inside)
|
|
35
|
+
# 70 --refresh-baseline before generation (no .dependency-cruiser.cjs yet — run default mode first)
|
|
36
|
+
# 71 bite-proof: gate did not pass on the clean HEAD tree before the probe (config/toolchain)
|
|
37
|
+
# 72 bite-proof: gate did NOT reject the injected client->server-secret imports on their edges
|
|
38
|
+
# 73 bite-proof: gate did not return to green after the probes were removed
|
|
39
|
+
# 74 bite-proof: real client->server-secret violation(s) on HEAD newer than the baseline
|
|
40
|
+
#
|
|
41
|
+
# In default mode the self-cleanup is armed BEFORE the first artifact is written and disarmed
|
|
42
|
+
# only after the bite has passed: every failure in between (67..74, a failed `mktemp`, a
|
|
43
|
+
# `set -e` abort) REMOVES every artifact this run emitted, so a failed first install is
|
|
44
|
+
# re-runnable and never leaves a half-installed gate. The README and the pointer are written
|
|
45
|
+
# after the disarm. An INT/TERM mid-run does the same and exits 143; a runner interrupted by a
|
|
46
|
+
# terminal Ctrl-C (rc 130) is treated as an interrupt, never as a verdict. Only a SIGKILL can
|
|
47
|
+
# leave residue (the six files plus a stale `.git/worktrees` registration) — the 66 message
|
|
48
|
+
# names the recovery.
|
|
49
|
+
#
|
|
50
|
+
# Portable: POSIX tools only (no `realpath -m`, no `sed -i`) — the generator runs on founder hosts
|
|
51
|
+
# including stock macOS (bash 3.2, BSD sed). Tool errors (git worktree add, dependency-cruiser)
|
|
52
|
+
# are carried into the 68/69 message, never discarded.
|
|
53
|
+
#
|
|
54
|
+
# No test seams: this script reads no test-only environment variable. The self-tests
|
|
55
|
+
# drive every failure arm through a fixture-owned stub `depcruise` reached via the target's
|
|
56
|
+
# node_modules symlink (bite-proof.test.sh). CONSTRAINT_SCAFFOLD_REPO_ROOT (below) only
|
|
57
|
+
# re-roots the generator at a synthesized repo; it changes no branch of the logic.
|
|
58
|
+
set -euo pipefail
|
|
59
|
+
|
|
60
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
61
|
+
REF_DIR="$(cd "$SCRIPT_DIR/../references" && pwd)"
|
|
62
|
+
# REPO_ROOT defaults to the skill's own repo. CONSTRAINT_SCAFFOLD_REPO_ROOT points
|
|
63
|
+
# the generator at a synthesized fixture repo (apps/web-platform-shaped) for the
|
|
64
|
+
# hermetic generator self-tests; in normal use it is unset. Templates (REF_DIR)
|
|
65
|
+
# always come from the real skill.
|
|
66
|
+
REPO_ROOT="${CONSTRAINT_SCAFFOLD_REPO_ROOT:-$(git -C "$SCRIPT_DIR" rev-parse --show-toplevel)}"
|
|
67
|
+
# CONSTRAINT_SCAFFOLD_REPO_ROOT is caller-supplied. The `:-` default is absolute
|
|
68
|
+
# (`rev-parse --show-toplevel`), but an override is not, and every `git -C "$REPO_ROOT"` below —
|
|
69
|
+
# including a `worktree add`/`worktree remove` pair — would then resolve against CWD instead.
|
|
70
|
+
case "$REPO_ROOT" in
|
|
71
|
+
"") printf 'FATAL: REPO_ROOT is empty; git -C "" would operate on %s\n' "$PWD" >&2; exit 2 ;;
|
|
72
|
+
/|//|/.) printf 'FATAL: REPO_ROOT resolves to the filesystem root; refusing\n' >&2; exit 2 ;;
|
|
73
|
+
/*) : ;;
|
|
74
|
+
*) printf 'FATAL: REPO_ROOT %s is RELATIVE; refusing\n' "$REPO_ROOT" >&2; exit 2 ;;
|
|
75
|
+
esac
|
|
76
|
+
# physdir <dir>: the physical path of an EXISTING directory (`pwd -P`), POSIX — the generator runs
|
|
77
|
+
# on founder hosts where `realpath -m` does not exist (BSD/macOS). Prints nothing on a missing dir.
|
|
78
|
+
physdir() { ( cd -- "$1" 2>/dev/null && pwd -P ); }
|
|
79
|
+
# physpath <path>: physical path of a file that may not exist yet, via its (existing) parent.
|
|
80
|
+
physpath() { local d; d="$(physdir "$(dirname -- "$1")")" || return 1; [[ -n "$d" ]] && printf '%s/%s' "$d" "$(basename -- "$1")"; }
|
|
81
|
+
# Canonical form once (a trailing slash would defeat every `${f#"$REPO_ROOT"/}` display and the
|
|
82
|
+
# TMPDIR containment case below), re-guarded: the value now comes from a command substitution.
|
|
83
|
+
REPO_ROOT="$(physdir "$REPO_ROOT")"
|
|
84
|
+
case "$REPO_ROOT" in
|
|
85
|
+
/|//|/.) printf 'FATAL: REPO_ROOT canonicalises to the filesystem root; refusing\n' >&2; exit 2 ;;
|
|
86
|
+
/*) : ;;
|
|
87
|
+
*) printf 'FATAL: REPO_ROOT %s did not canonicalise to an absolute path; refusing\n' "$REPO_ROOT" >&2; exit 2 ;;
|
|
88
|
+
esac
|
|
89
|
+
|
|
90
|
+
# v1: the one supported target.
|
|
91
|
+
TARGET_REL="apps/web-platform"
|
|
92
|
+
TARGET="$REPO_ROOT/$TARGET_REL"
|
|
93
|
+
|
|
94
|
+
CFG="$TARGET/.dependency-cruiser.cjs"
|
|
95
|
+
RUNNER="$TARGET/scripts/constraint-gates.sh"
|
|
96
|
+
WORKFLOW="$TARGET/.github/workflows/constraint-gates.yml"
|
|
97
|
+
# Two-stage recovery dispatcher (ADR-074, #5814): an UNTRUSTED pull_request producer
|
|
98
|
+
# (Stage A) + a PRIVILEGED workflow_run consumer (Stage B). Replaces the single held
|
|
99
|
+
# issue_comment dispatcher — the privileged trigger no longer co-locates with untrusted
|
|
100
|
+
# PR-code execution.
|
|
101
|
+
FIXWORKFLOW_A="$TARGET/.github/workflows/fix-constraints-stage-a.yml"
|
|
102
|
+
FIXWORKFLOW_B="$TARGET/.github/workflows/fix-constraints-stage-b.yml"
|
|
103
|
+
BASELINE="$TARGET/.dependency-cruiser-known-violations.json"
|
|
104
|
+
DEPCRUISE="$TARGET/node_modules/.bin/depcruise"
|
|
105
|
+
README="$TARGET/server/README.md"
|
|
106
|
+
|
|
107
|
+
# The two rules the emitted config defines (bite-proof.test.sh pins these literals equal to
|
|
108
|
+
# the `name:` fields of depcruise-config.template) and the four probe paths the bite injects —
|
|
109
|
+
# top-level scalars, no array, no `$( )`.
|
|
110
|
+
RULE_DIRECT="no-client-to-server-secret"
|
|
111
|
+
RULE_TRANSITIVE="no-client-to-server-secret-transitive"
|
|
112
|
+
PROBE_DIRECT="components/__constraint_scaffold_bite_probe__/direct.tsx"
|
|
113
|
+
PROBE_HOP="components/__constraint_scaffold_bite_probe__/hop.ts"
|
|
114
|
+
PROBE_VIA_HOP="components/__constraint_scaffold_bite_probe__/via-hop.tsx"
|
|
115
|
+
PROBE_SERVER="server/__constraint_scaffold_bite_probe__.ts"
|
|
116
|
+
|
|
117
|
+
log() { printf 'constraint-scaffold: %s\n' "$*" >&2; }
|
|
118
|
+
# Agent runtimes surface stdout and swallow stderr, so anything the founder or the agent must
|
|
119
|
+
# act on is printed on STDOUT (warn/say) and only then logged. `die` is the ONE failure path:
|
|
120
|
+
# every non-zero exit prints `FAILED (<code>): <msg>` on stdout, then the message on stderr.
|
|
121
|
+
say() { printf 'constraint-scaffold: %s\n' "$*"; }
|
|
122
|
+
warn() { printf 'constraint-scaffold: WARNING: %s\n' "$*"; }
|
|
123
|
+
die() { say "FAILED (${2:-1}): $1"; log "$1"; exit "${2:-1}"; }
|
|
124
|
+
# fail_stdout <code> <msg>: kept as the named form the tests and the header cite; same path.
|
|
125
|
+
fail_stdout() { die "$2" "$1"; }
|
|
126
|
+
|
|
127
|
+
MODE="default"
|
|
128
|
+
case "${1:-}" in
|
|
129
|
+
"") MODE="default" ;;
|
|
130
|
+
--refresh-baseline) MODE="refresh" ;;
|
|
131
|
+
*) die "unknown argument: $1 (expected none or --refresh-baseline)" 64 ;;
|
|
132
|
+
esac
|
|
133
|
+
|
|
134
|
+
# --- Precondition: target is a Next.js app -----------------------------------
|
|
135
|
+
detect_nextjs() {
|
|
136
|
+
# next.config.* present AND an anchored "next": dependency key (the anchor
|
|
137
|
+
# avoids matching "next-themes" etc.).
|
|
138
|
+
compgen -G "$TARGET/next.config.*" >/dev/null 2>&1 || return 1
|
|
139
|
+
grep -qE '"next"[[:space:]]*:' "$TARGET/package.json" 2>/dev/null || return 1
|
|
140
|
+
}
|
|
141
|
+
detect_nextjs || die "target $TARGET_REL is not a Next.js app (need next.config.* + anchored \"next\": in package.json)" 65
|
|
142
|
+
|
|
143
|
+
# --- Default-mode self-cleanup ------------------------------------------------
|
|
144
|
+
# Removes every artifact a default-mode run emits and prints the list it removed. The script
|
|
145
|
+
# refuses to start when any of these exists, so at cleanup time each one present was written by
|
|
146
|
+
# THIS run. Also `rmdir`s the two `mkdir -p` directories when empty. The list below is pinned by
|
|
147
|
+
# bite-proof.test.sh against the refuse-if-exists loop: a new artifact cannot be left behind on a
|
|
148
|
+
# failed bite without also being left out of the refuse loop, and vice-versa.
|
|
149
|
+
remove_emitted_artifacts() {
|
|
150
|
+
local removed="" f
|
|
151
|
+
for f in "$CFG" "$RUNNER" "$WORKFLOW" "$FIXWORKFLOW_A" "$FIXWORKFLOW_B" "$BASELINE"; do
|
|
152
|
+
[[ -e "$f" ]] || continue
|
|
153
|
+
rm -f -- "$f"
|
|
154
|
+
removed="$removed ${f#"$REPO_ROOT"/}"
|
|
155
|
+
done
|
|
156
|
+
rmdir "$TARGET/scripts" "$TARGET/.github/workflows" "$TARGET/.github" >/dev/null 2>&1 || true
|
|
157
|
+
printf '%s' "${removed# }"
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
# --- Detached-worktree helper (the ONE trap owner, ADR-129) --------------------
|
|
161
|
+
# with_detached_worktree <ref> <fn>: creates a mktemp dir, refuses one that resolves inside the
|
|
162
|
+
# repository (the worktree and its logs must never land in the founder's tree as untracked
|
|
163
|
+
# files), installs the EXIT and INT/TERM traps BEFORE `worktree add --detach`, calls <fn> "$WT",
|
|
164
|
+
# removes the worktree, clears the traps. The signal arm clears EXIT inside itself so cleanup
|
|
165
|
+
# runs once and exits 143 (the precedent is scripts/rotate-sentry-actions-ro-token.sh; 143 for
|
|
166
|
+
# both signals because the distinction buys nothing here). Both the baseline capture and the
|
|
167
|
+
# bite-proof are callers, so there is exactly one trap owner and no ordering hazard.
|
|
168
|
+
WT=""
|
|
169
|
+
# _wt_cleanup [interrupted]: the ONE trap handler. Removes the worktree if one is open and, in
|
|
170
|
+
# default mode, every artifact this run emitted. The word "interrupted" is printed only when a
|
|
171
|
+
# signal arrived; a failed step says "run aborted".
|
|
172
|
+
_wt_cleanup() {
|
|
173
|
+
local why="${1:-run aborted}"
|
|
174
|
+
release_run_lock
|
|
175
|
+
if [[ -n "${WT:-}" ]]; then
|
|
176
|
+
git -C "$REPO_ROOT" worktree remove --force "$WT" >/dev/null 2>&1 || true
|
|
177
|
+
rm -rf -- "$WT"
|
|
178
|
+
fi
|
|
179
|
+
# Default mode: a TERM (or a die anywhere after the first write) must not leave the repo at 66.
|
|
180
|
+
if [[ "$MODE" == "default" ]]; then
|
|
181
|
+
local removed
|
|
182
|
+
removed="$(remove_emitted_artifacts)"
|
|
183
|
+
[[ -n "$removed" ]] && say "$why; removed: $removed"
|
|
184
|
+
elif [[ "$why" == "interrupted" ]]; then
|
|
185
|
+
say "interrupted (refresh mode): nothing removed; the committed baseline may already have been rewritten — review it with \`git diff\` before deciding"
|
|
186
|
+
fi
|
|
187
|
+
return 0
|
|
188
|
+
}
|
|
189
|
+
# Run lock: two scaffold runs in one repo (a default run and a --refresh-baseline, or two
|
|
190
|
+
# sessions) would each `mv` into the same baseline and one run's cleanup would delete the other's
|
|
191
|
+
# staged inputs mid-bite. One `mkdir` lock in the git common dir, holding the owner pid; a stale
|
|
192
|
+
# lock (owner gone) is taken over, a live one is a 69 with the pid named. Released by the handler.
|
|
193
|
+
RUN_LOCK=""
|
|
194
|
+
take_run_lock() {
|
|
195
|
+
local common
|
|
196
|
+
common="$(git -C "$REPO_ROOT" rev-parse --git-common-dir 2>/dev/null)" || common=".git"
|
|
197
|
+
[[ "$common" == /* ]] || common="$REPO_ROOT/$common"
|
|
198
|
+
RUN_LOCK="$common/constraint-scaffold.lock"
|
|
199
|
+
if ! mkdir "$RUN_LOCK" 2>/dev/null; then
|
|
200
|
+
local owner
|
|
201
|
+
owner="$(cat "$RUN_LOCK/pid" 2>/dev/null || true)"
|
|
202
|
+
if [[ -n "$owner" ]] && kill -0 "$owner" 2>/dev/null; then
|
|
203
|
+
RUN_LOCK=""
|
|
204
|
+
fail_stdout 69 "another constraint-scaffold run (pid $owner) is in progress in this repository; wait for it"
|
|
205
|
+
fi
|
|
206
|
+
rm -rf -- "$RUN_LOCK"
|
|
207
|
+
mkdir "$RUN_LOCK" 2>/dev/null || { RUN_LOCK=""; fail_stdout 69 "cannot take the run lock at $RUN_LOCK"; }
|
|
208
|
+
fi
|
|
209
|
+
printf '%s\n' "$$" > "$RUN_LOCK/pid"
|
|
210
|
+
}
|
|
211
|
+
release_run_lock() {
|
|
212
|
+
[[ -n "${RUN_LOCK:-}" && -d "$RUN_LOCK" ]] && rm -rf -- "$RUN_LOCK"
|
|
213
|
+
RUN_LOCK=""
|
|
214
|
+
return 0
|
|
215
|
+
}
|
|
216
|
+
# TMPDIR containment, checked before the first write (a `mktemp -d` under a TMPDIR inside the
|
|
217
|
+
# repo would land the bite worktree — and its logs — in the founder's tree as untracked files).
|
|
218
|
+
check_tmpdir_outside_repo() {
|
|
219
|
+
local t
|
|
220
|
+
t="$(physdir "${TMPDIR:-/tmp}")" || t=""
|
|
221
|
+
# A TMPDIR that does not exist cannot be inside the repo; mktemp reports it (69) at first use.
|
|
222
|
+
[[ -n "$t" ]] || return 0
|
|
223
|
+
case "$t" in
|
|
224
|
+
"$REPO_ROOT"|"$REPO_ROOT"/*)
|
|
225
|
+
fail_stdout 69 "TMPDIR ($t) resolves inside the repository; refusing to create the bite worktree there" ;;
|
|
226
|
+
esac
|
|
227
|
+
}
|
|
228
|
+
with_detached_worktree() {
|
|
229
|
+
local ref="$1" fn="$2"
|
|
230
|
+
trap '_wt_cleanup' EXIT
|
|
231
|
+
trap '_wt_cleanup interrupted; trap - EXIT; exit 143' INT TERM
|
|
232
|
+
WT="$(mktemp -d)" || fail_stdout 69 "cannot create a temp dir under TMPDIR=${TMPDIR:-/tmp}"
|
|
233
|
+
case "$(physdir "$WT")" in
|
|
234
|
+
"$REPO_ROOT"/*)
|
|
235
|
+
fail_stdout 69 "TMPDIR resolves inside the repository; refusing to create the bite worktree there" ;;
|
|
236
|
+
esac
|
|
237
|
+
# Keep git's own reason (a failing post-checkout hook, LFS, a corrupt object): a 69 whose
|
|
238
|
+
# message ends in "failed" with the cause discarded is a question the founder cannot answer.
|
|
239
|
+
local git_err
|
|
240
|
+
git_err="$(git -C "$REPO_ROOT" worktree add --detach "$WT" "$ref" 2>&1 >/dev/null)" \
|
|
241
|
+
|| fail_stdout 69 "git worktree add at ${ref:0:12} failed: $(printf '%s' "$git_err" | tail -n 3 | tr '\n' ' ')"
|
|
242
|
+
"$fn" "$WT"
|
|
243
|
+
git -C "$REPO_ROOT" worktree remove --force "$WT" >/dev/null 2>&1 || true
|
|
244
|
+
rm -rf -- "$WT"
|
|
245
|
+
WT=""
|
|
246
|
+
# Leave the handler armed while the default-mode tail owns it (CLEANUP_ARMED=1).
|
|
247
|
+
[[ "${CLEANUP_ARMED:-0}" == 1 ]] || trap - EXIT INT TERM
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
# --- Baseline capture (shared) -----------------------------------------------
|
|
251
|
+
# Captures the value-violations of the tree rooted at $1 into $BASELINE. Scans
|
|
252
|
+
# only the client dirs (app/components) that actually exist plus server/, so a
|
|
253
|
+
# single-client-dir app does not error on a missing dir.
|
|
254
|
+
capture_baseline() {
|
|
255
|
+
local app_root="$1"
|
|
256
|
+
[[ -x "$DEPCRUISE" ]] || fail_stdout 68 "dependency-cruiser not found at ${DEPCRUISE#"$REPO_ROOT"/} — run 'npm ci --ignore-scripts' in $TARGET_REL first"
|
|
257
|
+
local scan_dirs=()
|
|
258
|
+
local d
|
|
259
|
+
for d in app components server; do
|
|
260
|
+
[[ -d "$app_root/$d" ]] && scan_dirs+=("$d")
|
|
261
|
+
done
|
|
262
|
+
[[ "${#scan_dirs[@]}" -gt 0 ]] || fail_stdout 68 "no app/components/server dirs under $app_root — cannot capture baseline"
|
|
263
|
+
local tmp dc_err
|
|
264
|
+
tmp="$(mktemp)"
|
|
265
|
+
if ! dc_err="$( ( cd "$app_root" && "$DEPCRUISE" --config .dependency-cruiser.cjs --output-type baseline "${scan_dirs[@]}" ) 2>&1 > "$tmp" )"; then
|
|
266
|
+
rm -f "$tmp"
|
|
267
|
+
fail_stdout 68 "baseline capture failed — dependency-cruiser said: $(printf '%s' "$dc_err" | tail -n 5 | tr '\n' ' ') (config error, or the hoisted node_modules symlink did not resolve?)"
|
|
268
|
+
fi
|
|
269
|
+
mv "$tmp" "$BASELINE"
|
|
270
|
+
log "captured baseline: $(grep -c '"rule"' "$BASELINE" 2>/dev/null || true) known violation(s) -> ${BASELINE#"$REPO_ROOT"/}"
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
_capture_baseline_in_worktree() {
|
|
274
|
+
local wt="$1"
|
|
275
|
+
local wt_target="$wt/$TARGET_REL"
|
|
276
|
+
[[ -d "$wt_target/app" || -d "$wt_target/components" ]] \
|
|
277
|
+
|| fail_stdout 69 "base tree ($BASE_REF) has no $TARGET_REL/app|components — cannot capture baseline"
|
|
278
|
+
# The merge-base may predate the gate: ensure the current config is present, and
|
|
279
|
+
# reuse the installed node_modules (depcruise binary + resolver) via symlink.
|
|
280
|
+
cp "$CFG" "$wt_target/.dependency-cruiser.cjs"
|
|
281
|
+
[[ -e "$wt_target/node_modules" ]] || ln -s "$TARGET/node_modules" "$wt_target/node_modules"
|
|
282
|
+
capture_baseline "$wt_target"
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
# resolve_base_ref: sets BASE_REF (origin/main, else the remote's default branch via
|
|
286
|
+
# origin/HEAD) and MB (its merge-base with HEAD). Runs BEFORE the first write in both modes, so
|
|
287
|
+
# a founder repo without origin/main fails 69 with nothing to clean up. Read-only.
|
|
288
|
+
resolve_base_ref() {
|
|
289
|
+
if git -C "$REPO_ROOT" rev-parse -q --verify origin/main >/dev/null 2>&1; then
|
|
290
|
+
BASE_REF="origin/main"
|
|
291
|
+
elif BASE_REF="$(git -C "$REPO_ROOT" symbolic-ref -q --short refs/remotes/origin/HEAD 2>/dev/null)" && [[ -n "$BASE_REF" ]]; then
|
|
292
|
+
:
|
|
293
|
+
else
|
|
294
|
+
fail_stdout 69 "no origin/main and no origin/HEAD — fetch the default branch first (git fetch origin main, or git remote set-head origin -a)"
|
|
295
|
+
fi
|
|
296
|
+
if ! MB="$(git -C "$REPO_ROOT" merge-base "$BASE_REF" HEAD 2>/dev/null)"; then
|
|
297
|
+
local shallow=""
|
|
298
|
+
[[ "$(git -C "$REPO_ROOT" rev-parse --is-shallow-repository 2>/dev/null)" == "true" ]] \
|
|
299
|
+
&& shallow=" — this is a SHALLOW clone: run \`git fetch --unshallow\` first"
|
|
300
|
+
fail_stdout 69 "could not compute merge-base of $BASE_REF and HEAD (unrelated histories, or $BASE_REF not fetched?)$shallow"
|
|
301
|
+
fi
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
# Capture the baseline against the base-ref merge-base in a detached worktree,
|
|
305
|
+
# so a violation introduced in the SAME PR (branch-added) is NOT grandfathered —
|
|
306
|
+
# only violations pre-existing on the base land in the baseline. Used by BOTH modes:
|
|
307
|
+
# first adoption (default) must not grandfather a same-PR leak any more than a
|
|
308
|
+
# refresh does. Requires a clean tree (committed state == reviewable baseline).
|
|
309
|
+
# require_clean_tree <when>: 67 on a dirty tree (committed state == reviewable baseline).
|
|
310
|
+
require_clean_tree() {
|
|
311
|
+
if ! { git -C "$REPO_ROOT" diff --quiet && git -C "$REPO_ROOT" diff --cached --quiet; }; then
|
|
312
|
+
die "working tree is dirty — commit or discard changes $1" 67
|
|
313
|
+
fi
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
capture_baseline_mergebase() {
|
|
317
|
+
require_clean_tree "before capturing the baseline"
|
|
318
|
+
log "capturing baseline against $BASE_REF merge-base ${MB:0:12} (same-PR violations excluded)"
|
|
319
|
+
with_detached_worktree "$MB" _capture_baseline_in_worktree
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
# --- Bite-proof ------------------------------------------------------------------
|
|
323
|
+
# verdict_fail <code> <msg> [<log-file>] [<extra stdout lines>]: prints the verdict on STDOUT,
|
|
324
|
+
# then the last 40 lines of the captured runner log, then (default mode) removes every artifact
|
|
325
|
+
# this run emitted and says so; then dies with <code>. Refresh mode removes nothing (the
|
|
326
|
+
# artifacts are committed) and says the baseline was rewritten.
|
|
327
|
+
verdict_fail() {
|
|
328
|
+
local code="$1" msg="$2" logf="${3:-}" extra="${4:-}"
|
|
329
|
+
say "bite-proof FAILED ($code): $msg"
|
|
330
|
+
if [[ -n "$extra" ]]; then printf '%s\n' "$extra"; fi
|
|
331
|
+
if [[ -n "$logf" && -f "$logf" ]]; then
|
|
332
|
+
printf -- '--- last 40 lines of %s ---\n' "$(basename "$logf")"
|
|
333
|
+
tail -n 40 "$logf"
|
|
334
|
+
printf -- '--- end of log ---\n'
|
|
335
|
+
fi
|
|
336
|
+
if [[ "$MODE" == "default" ]]; then
|
|
337
|
+
local removed
|
|
338
|
+
removed="$(remove_emitted_artifacts)"
|
|
339
|
+
say "removed the artifacts this run emitted (${removed:-none}); the repo is as it was (a SIGKILL may leave a stale registration: \`git worktree prune\`); re-run after fixing the cause"
|
|
340
|
+
else
|
|
341
|
+
say "refresh mode: the baseline was rewritten by this run — review it with \`git diff\` before deciding; no artifact was removed"
|
|
342
|
+
fi
|
|
343
|
+
# The verdict line above IS the stdout copy; log to stderr and exit (not `die`, which would
|
|
344
|
+
# print a second FAILED line). The EXIT trap removes the worktree.
|
|
345
|
+
log "$msg"
|
|
346
|
+
exit "$code"
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
# Run the emitted runner against the worktree copy, capturing stdout+stderr to a file (so a
|
|
350
|
+
# failure can show its evidence before the worktree is removed). Sets RC; never aborts under
|
|
351
|
+
# `set -e` (a bare non-zero runner call would end the scaffold before the arm dispatch).
|
|
352
|
+
_run_gate() {
|
|
353
|
+
local wt_target="$1" logf="$2"
|
|
354
|
+
RC=0
|
|
355
|
+
CONSTRAINT_GATES_DIR="$wt_target" bash "$wt_target/scripts/constraint-gates.sh" >"$logf" 2>&1 || RC=$?
|
|
356
|
+
# A terminal Ctrl-C reaches the node child first: it exits 130 and bash never sees the
|
|
357
|
+
# signal, so without this arm the interrupted run would be dispatched as a 71/72/73 verdict.
|
|
358
|
+
if [[ "$RC" -eq 130 ]]; then
|
|
359
|
+
_wt_cleanup interrupted; trap - EXIT; exit 130
|
|
360
|
+
fi
|
|
361
|
+
# Belt and braces with the runner's NO_COLOR=1: a FORCE_COLOR environment decorates
|
|
362
|
+
# depcruise's `error <rule>:` lines and both anchors below would match nothing.
|
|
363
|
+
sed $'s/\e\\[[0-9;]*m//g' "$logf" > "$logf.plain" && mv -f "$logf.plain" "$logf"
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
_depcruise_version() {
|
|
367
|
+
local wt_target="$1"
|
|
368
|
+
node -p 'require(process.argv[1] + "/node_modules/dependency-cruiser/package.json").version' "$wt_target" 2>/dev/null \
|
|
369
|
+
|| printf 'unknown'
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
_prove_bite_in_worktree() {
|
|
373
|
+
local wt="$1"
|
|
374
|
+
local wt_target="$wt/$TARGET_REL"
|
|
375
|
+
# 1. Stage. Copy the three artifacts that may be uncommitted into the HEAD worktree. Ordering
|
|
376
|
+
# dependency: the clean-tree guard in capture_baseline_mergebase ran first, so for tracked
|
|
377
|
+
# files the working tree == HEAD and these copies are no-ops by content; the untracked case
|
|
378
|
+
# (first install) is exactly what the copy exists for. node_modules is reused via symlink,
|
|
379
|
+
# exactly as the baseline capture does.
|
|
380
|
+
mkdir -p "$wt_target/scripts"
|
|
381
|
+
cp "$CFG" "$wt_target/.dependency-cruiser.cjs"
|
|
382
|
+
cp "$RUNNER" "$wt_target/scripts/constraint-gates.sh"
|
|
383
|
+
chmod +x "$wt_target/scripts/constraint-gates.sh"
|
|
384
|
+
cp "$BASELINE" "$wt_target/.dependency-cruiser-known-violations.json"
|
|
385
|
+
[[ -e "$wt_target/node_modules" ]] || ln -s "$TARGET/node_modules" "$wt_target/node_modules"
|
|
386
|
+
local ver
|
|
387
|
+
ver="$(_depcruise_version "$wt_target" | tr -cd 'A-Za-z0-9.+-' | cut -c1-40)"
|
|
388
|
+
|
|
389
|
+
# 2. Pass on the clean tree.
|
|
390
|
+
_run_gate "$wt_target" "$wt/bite-1.log"
|
|
391
|
+
if [[ "$RC" -ne 0 ]]; then
|
|
392
|
+
local violations n
|
|
393
|
+
violations="$(grep -E '^[[:space:]]*error [^:]+: ' "$wt/bite-1.log" || true)"
|
|
394
|
+
if [[ -n "$violations" ]]; then
|
|
395
|
+
n="$(printf '%s\n' "$violations" | grep -c . || true)"
|
|
396
|
+
verdict_fail 74 "$n real client->server-secret violation(s) on HEAD newer than the merge-base baseline — the gate is live; fix the listed imports, then re-run" "$wt/bite-1.log" "$violations"
|
|
397
|
+
fi
|
|
398
|
+
verdict_fail 71 "gate did not pass on the clean tree before the probe (rc=$RC) — config or toolchain error; see the log tail" "$wt/bite-1.log"
|
|
399
|
+
fi
|
|
400
|
+
|
|
401
|
+
# 3. Inject — each rule on the edge it exists for. A symlinked server/ or components/ would
|
|
402
|
+
# route the probes OUTSIDE the worktree (a checked-out link resolves the same as in the
|
|
403
|
+
# founder's tree): refuse rather than write through it.
|
|
404
|
+
local d
|
|
405
|
+
for d in server components; do
|
|
406
|
+
[[ -L "$wt_target/$d" ]] && verdict_fail 71 "$TARGET_REL/$d is a symlink; refusing to write the bite probes through it"
|
|
407
|
+
done
|
|
408
|
+
# Each rule on the edge it exists for. direct.tsx is a "use client" module
|
|
409
|
+
# value-importing the probe server module (direct rule); hop.ts is a NON-client helper that
|
|
410
|
+
# value-imports it; via-hop.tsx is a "use client" module value-importing ./hop (transitive
|
|
411
|
+
# rule). The server module exports one string that is visibly not a secret.
|
|
412
|
+
mkdir -p "$wt_target/$(dirname "$PROBE_DIRECT")"
|
|
413
|
+
printf 'export const BITE_PROBE_MARKER = "constraint-scaffold bite probe (not a secret)";\n' > "$wt_target/$PROBE_SERVER"
|
|
414
|
+
printf '"use client";\nimport { BITE_PROBE_MARKER } from "@/server/__constraint_scaffold_bite_probe__";\nexport const Direct = () => BITE_PROBE_MARKER;\n' > "$wt_target/$PROBE_DIRECT"
|
|
415
|
+
printf 'import { BITE_PROBE_MARKER } from "@/server/__constraint_scaffold_bite_probe__";\nexport const hop = () => BITE_PROBE_MARKER;\n' > "$wt_target/$PROBE_HOP"
|
|
416
|
+
printf '"use client";\nimport { hop } from "./hop";\nexport const ViaHop = () => hop();\n' > "$wt_target/$PROBE_VIA_HOP"
|
|
417
|
+
|
|
418
|
+
# 4. Fail, naming both rules on their own edges. Anchored on depcruise's `error <rule>: `
|
|
419
|
+
# call-form on the captured stream, never a bare rule name (the runner's zero-reachability
|
|
420
|
+
# prose carries the bare transitive token, and a `warn` line must not satisfy it).
|
|
421
|
+
_run_gate "$wt_target" "$wt/bite-2.log"
|
|
422
|
+
local named=""
|
|
423
|
+
if grep -qE "^[[:space:]]*error $RULE_DIRECT: .*direct\.tsx" "$wt/bite-2.log"; then
|
|
424
|
+
named="$named $RULE_DIRECT@direct"
|
|
425
|
+
fi
|
|
426
|
+
if grep -qE "^[[:space:]]*error $RULE_TRANSITIVE: .*via-hop\.tsx" "$wt/bite-2.log"; then
|
|
427
|
+
named="$named $RULE_TRANSITIVE@via-hop"
|
|
428
|
+
fi
|
|
429
|
+
if [[ "$RC" -eq 0 || "$named" != " $RULE_DIRECT@direct $RULE_TRANSITIVE@via-hop" ]]; then
|
|
430
|
+
verdict_fail 72 "the gate did NOT reject the injected client->server-secret import (rc=$RC; depcruise=$ver; rules named on their edges:${named:- none}) — a gate that cannot fail is not a gate" "$wt/bite-2.log"
|
|
431
|
+
fi
|
|
432
|
+
|
|
433
|
+
# 5. Revert.
|
|
434
|
+
rm -f -- "$wt_target/$PROBE_DIRECT" "$wt_target/$PROBE_HOP" "$wt_target/$PROBE_VIA_HOP" "$wt_target/$PROBE_SERVER"
|
|
435
|
+
rmdir "$wt_target/$(dirname "$PROBE_DIRECT")" >/dev/null 2>&1 || true
|
|
436
|
+
|
|
437
|
+
# 6. Pass again.
|
|
438
|
+
_run_gate "$wt_target" "$wt/bite-3.log"
|
|
439
|
+
if [[ "$RC" -ne 0 ]]; then
|
|
440
|
+
verdict_fail 73 "gate did not return to green after the probes were removed (rc=$RC) — non-deterministic gate" "$wt/bite-3.log"
|
|
441
|
+
fi
|
|
442
|
+
|
|
443
|
+
# 7. One verdict line on STDOUT (ASCII arrows so an AC can grep it).
|
|
444
|
+
printf 'constraint-scaffold: bite-proof pass -> fail(%s@direct, %s@via-hop) -> pass depcruise=%s\n' "$RULE_DIRECT" "$RULE_TRANSITIVE" "$ver"
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
# prove_bite: called at the tail of BOTH modes. Runs the emitted gate on a detached worktree of
|
|
448
|
+
# HEAD through the shared helper; the helper removes the worktree afterwards.
|
|
449
|
+
prove_bite() {
|
|
450
|
+
with_detached_worktree HEAD _prove_bite_in_worktree
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
# --- README block + agent-instructions pointer (append-once, written LAST) ---------
|
|
454
|
+
# append_once <file> <marker> <content>: refuses a symlinked target first (a
|
|
455
|
+
# `CLAUDE.md -> ~/.claude/CLAUDE.md` link is a common founder shape and `>>` would write into
|
|
456
|
+
# their GLOBAL instructions — CWE-59); idempotent on <marker>; guards the trailing newline of the
|
|
457
|
+
# existing file; then appends. Returns non-zero on refusal or a failed write so the callers can
|
|
458
|
+
# warn rather than die (after a successful bite, prose is not the gate).
|
|
459
|
+
append_once() {
|
|
460
|
+
local f="$1" marker="$2" content="$3"
|
|
461
|
+
[[ -L "$f" ]] && { warn "refusing to append through a symlink: ${f#"$REPO_ROOT"/} -> $(readlink "$f")"; return 1; }
|
|
462
|
+
# A symlinked PARENT (server/ -> outside) passes `-L` on the file: require containment.
|
|
463
|
+
local phys
|
|
464
|
+
phys="$(physpath "$f")" || phys=""
|
|
465
|
+
case "$phys" in
|
|
466
|
+
"$REPO_ROOT"/*) ;;
|
|
467
|
+
*) warn "refusing to append outside the repository: ${f#"$REPO_ROOT"/} resolves to ${phys:-<unresolvable>}"; return 1 ;;
|
|
468
|
+
esac
|
|
469
|
+
grep -qF -- "$marker" "$f" 2>/dev/null && return 0
|
|
470
|
+
[[ -s "$f" && -n "$(tail -c 1 "$f")" ]] && printf '\n' >> "$f"
|
|
471
|
+
printf '%s\n' "$content" >> "$f" || return 1
|
|
472
|
+
return 0
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
emit_readme() {
|
|
476
|
+
local content
|
|
477
|
+
content="$(sed -e '1{/^<!-- Inspired by /d;}' -e "s|__TARGET_DIR__|$TARGET_REL|g" "$REF_DIR/boundary-readme.template" 2>/dev/null || true)"
|
|
478
|
+
if [[ -n "$content" ]] && append_once "$README" "<!-- constraint-scaffold:readme:start -->" "$content"; then
|
|
479
|
+
log "README block present in ${README#"$REPO_ROOT"/}"
|
|
480
|
+
else
|
|
481
|
+
warn "could not append the boundary README block to ${README#"$REPO_ROOT"/} — the gate is installed and proven; the missing doc is references/boundary-readme.template of soleur:constraint-scaffold (add it by hand)"
|
|
482
|
+
fi
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
emit_pointer() {
|
|
486
|
+
# Pointer file: repo-root CLAUDE.md if present, else AGENTS.md (created if absent). Plain,
|
|
487
|
+
# informational prose with a repo-relative path — never the `@path` import form, which would
|
|
488
|
+
# load the README into every session and promote an unpinned markdown file to instructions.
|
|
489
|
+
local f
|
|
490
|
+
if [[ -e "$REPO_ROOT/CLAUDE.md" || -L "$REPO_ROOT/CLAUDE.md" ]]; then
|
|
491
|
+
f="$REPO_ROOT/CLAUDE.md"
|
|
492
|
+
else
|
|
493
|
+
f="$REPO_ROOT/AGENTS.md"
|
|
494
|
+
fi
|
|
495
|
+
local line="The client/server import boundary and its CI gate are documented in $TARGET_REL/server/README.md (generated by soleur:constraint-scaffold). <!-- constraint-scaffold:pointer -->"
|
|
496
|
+
if append_once "$f" "<!-- constraint-scaffold:pointer -->" "$line"; then
|
|
497
|
+
log "instructions pointer present in ${f#"$REPO_ROOT"/}"
|
|
498
|
+
else
|
|
499
|
+
warn "could not append the instructions pointer to ${f#"$REPO_ROOT"/} — the gate is installed and proven; the missing line points at $TARGET_REL/server/README.md (add it by hand)"
|
|
500
|
+
fi
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
if [[ "$MODE" == "refresh" ]]; then
|
|
504
|
+
[[ -f "$CFG" ]] || die "no .dependency-cruiser.cjs at $TARGET_REL — run the default mode first to generate the gate" 70
|
|
505
|
+
require_clean_tree "before capturing the baseline"
|
|
506
|
+
resolve_base_ref
|
|
507
|
+
check_tmpdir_outside_repo
|
|
508
|
+
trap '_wt_cleanup' EXIT
|
|
509
|
+
trap '_wt_cleanup interrupted; trap - EXIT; exit 143' INT TERM
|
|
510
|
+
CLEANUP_ARMED=1
|
|
511
|
+
take_run_lock
|
|
512
|
+
capture_baseline_mergebase
|
|
513
|
+
prove_bite
|
|
514
|
+
release_run_lock
|
|
515
|
+
CLEANUP_ARMED=0
|
|
516
|
+
trap - EXIT INT TERM
|
|
517
|
+
log "refresh complete — review the baseline diff before merging."
|
|
518
|
+
exit 0
|
|
519
|
+
fi
|
|
520
|
+
|
|
521
|
+
# --- Default mode: emit artifacts (non-destructive) --------------------------
|
|
522
|
+
# Clean-tree guard FIRST — the baseline is captured against the origin/main
|
|
523
|
+
# merge-base (below), and we refuse to emit onto a dirty tree so the resulting
|
|
524
|
+
# baseline + artifact diff is reviewable and deterministic.
|
|
525
|
+
require_clean_tree "before generating the gate"
|
|
526
|
+
|
|
527
|
+
for f in "$CFG" "$RUNNER" "$WORKFLOW" "$FIXWORKFLOW_A" "$FIXWORKFLOW_B"; do
|
|
528
|
+
[[ -e "$f" ]] && die "refuse-if-exists: ${f#"$REPO_ROOT"/} already present (no --force). Committed gate: re-baseline via --refresh-baseline. Untracked leftovers of a killed first install: delete them (\`git clean -n $TARGET_REL\` lists them), run \`git worktree prune\`, re-run" 66
|
|
529
|
+
done
|
|
530
|
+
[[ -e "$BASELINE" ]] && die "refuse-if-exists: ${BASELINE#"$REPO_ROOT"/} already present (re-baseline via --refresh-baseline)" 66
|
|
531
|
+
|
|
532
|
+
# Three-dirs precondition, BEFORE anything is emitted: the emitted runner cruises all three
|
|
533
|
+
# and would fail its own CI on a target missing one; the README names the requirement.
|
|
534
|
+
for d in app components server; do
|
|
535
|
+
[[ -d "$TARGET/$d" ]] || fail_stdout 65 "target $TARGET_REL lacks $d/ (the emitted runner cruises app/ components/ server/ and would fail its own CI)"
|
|
536
|
+
done
|
|
537
|
+
|
|
538
|
+
# Base ref and temp dir, BEFORE anything is emitted: the two first-install failures a founder
|
|
539
|
+
# repo actually hits (no origin/main; an IDE TMPDIR inside the repo) must not write first.
|
|
540
|
+
resolve_base_ref
|
|
541
|
+
check_tmpdir_outside_repo
|
|
542
|
+
|
|
543
|
+
# Arm the self-cleanup before the first write (single handler: _wt_cleanup). Disarmed only
|
|
544
|
+
# after prove_bite returns — the worktree helper re-installs the same handler and leaves it
|
|
545
|
+
# armed while CLEANUP_ARMED=1. The run lock is taken inside the armed window so the handler
|
|
546
|
+
# releases it on every exit.
|
|
547
|
+
CLEANUP_ARMED=1
|
|
548
|
+
trap '_wt_cleanup' EXIT
|
|
549
|
+
trap '_wt_cleanup interrupted; trap - EXIT; exit 143' INT TERM
|
|
550
|
+
take_run_lock
|
|
551
|
+
mkdir -p "$TARGET/scripts" "$TARGET/.github/workflows"
|
|
552
|
+
|
|
553
|
+
# .dependency-cruiser.cjs — emitted verbatim (the from-set is computed at
|
|
554
|
+
# require-time, never baked in).
|
|
555
|
+
cp "$REF_DIR/depcruise-config.template" "$CFG"
|
|
556
|
+
|
|
557
|
+
# Shared runner.
|
|
558
|
+
cp "$REF_DIR/shared-runner.template" "$RUNNER"
|
|
559
|
+
chmod +x "$RUNNER"
|
|
560
|
+
|
|
561
|
+
# CI workflow — substitute the target dir (path-check glob + working-directory +
|
|
562
|
+
# runner path). sed delimiter is '|' since the value contains no '|'.
|
|
563
|
+
sed "s|__TARGET_DIR__|$TARGET_REL|g" "$REF_DIR/constraint-gates-workflow.template" > "$WORKFLOW"
|
|
564
|
+
|
|
565
|
+
# Two-stage recovery dispatcher (ADR-074): same __TARGET_DIR__ substitution. Stage A
|
|
566
|
+
# (untrusted producer) + Stage B (privileged consumer, Git Data API — no checkout/apply).
|
|
567
|
+
sed "s|__TARGET_DIR__|$TARGET_REL|g" "$REF_DIR/fix-constraints-stage-a.template" > "$FIXWORKFLOW_A"
|
|
568
|
+
sed "s|__TARGET_DIR__|$TARGET_REL|g" "$REF_DIR/fix-constraints-stage-b.template" > "$FIXWORKFLOW_B"
|
|
569
|
+
|
|
570
|
+
log "emitted: ${CFG#"$REPO_ROOT"/}, ${RUNNER#"$REPO_ROOT"/}, ${WORKFLOW#"$REPO_ROOT"/}, ${FIXWORKFLOW_A#"$REPO_ROOT"/}, ${FIXWORKFLOW_B#"$REPO_ROOT"/}"
|
|
571
|
+
|
|
572
|
+
# Capture the initial baseline against the origin/main merge-base — same path as
|
|
573
|
+
# --refresh-baseline, so a leak introduced in the SAME PR that scaffolds the gate
|
|
574
|
+
# is NOT grandfathered (only violations pre-existing on main are).
|
|
575
|
+
capture_baseline_mergebase
|
|
576
|
+
|
|
577
|
+
# Prove the gate bites on HEAD, THEN write the prose. The README block and the pointer are the
|
|
578
|
+
# last writes of the run: the clean-tree guard inside the baseline capture must never see them
|
|
579
|
+
# (a tracked CLAUDE.md or server/README.md appended earlier would exit 67 with the executables
|
|
580
|
+
# already emitted and leave the next run at 66), and a 71/72/73/74 never has to undo them.
|
|
581
|
+
prove_bite
|
|
582
|
+
release_run_lock
|
|
583
|
+
CLEANUP_ARMED=0
|
|
584
|
+
trap - EXIT INT TERM
|
|
585
|
+
emit_readme
|
|
586
|
+
emit_pointer
|
|
587
|
+
|
|
588
|
+
log "done. Verify green: (cd $TARGET_REL && bash scripts/constraint-gates.sh)"
|
|
589
|
+
exit 0
|