@soleur/opencode 0.0.0-stage → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/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 +659 -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 +108 -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 +342 -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 +152 -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 +493 -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 +363 -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 +520 -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 +113 -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 +178 -0
- package/scripts/sync-opencode-adapter.ts +479 -0
- package/scripts/sync-pr-behind.sh +534 -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 +65 -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 +142 -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 +118 -0
- package/skills/fix-issue/references/exclude-label-jq-snippet.md +96 -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 +668 -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 +325 -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 +138 -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 +1621 -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-todo-structure.md +165 -0
- package/skills/review/references/risk-tier-and-fix-rounds.md +95 -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 +3022 -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/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/detached-battery-verdict.md +13 -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 +149 -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/work/SKILL.md +1479 -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,34 @@
|
|
|
1
|
+
|
|
2
|
+
=== DRY RUN — No changes will be made ===
|
|
3
|
+
|
|
4
|
+
--- Console guidance ---
|
|
5
|
+
1. Log in to the tenant's Hetzner Cloud Console
|
|
6
|
+
2. Create a sub-project named 'tenant-fixture-tenant-prd'
|
|
7
|
+
3. Inside the sub-project, go to Security → API Tokens
|
|
8
|
+
4. Create a project-scoped API token with Read+Write permissions
|
|
9
|
+
5. Copy the token (shown only once)
|
|
10
|
+
|
|
11
|
+
--- Smoke-test commands (run after token creation) ---
|
|
12
|
+
read -rs -p 'Hetzner token: ' HCLOUD_TOKEN; echo
|
|
13
|
+
(
|
|
14
|
+
export HCLOUD_TOKEN
|
|
15
|
+
hcloud server create --name 'probe-provision-fixture-tenant' --type cx11 --image ubuntu-22.04 --location nbg1
|
|
16
|
+
hcloud server delete 'probe-provision-fixture-tenant'
|
|
17
|
+
)
|
|
18
|
+
unset HCLOUD_TOKEN
|
|
19
|
+
|
|
20
|
+
--- Teardown ---
|
|
21
|
+
Delete sub-project via Console: Projects → tenant-fixture-tenant-prd → Delete
|
|
22
|
+
Revoke the API token: Security → API Tokens → Revoke
|
|
23
|
+
|
|
24
|
+
Next step: type /soleur:provision-cloudflare fixture-tenant <zone-id> <account-id> yourself (user-invoked; Soleur cannot run it, ADR-236)
|
|
25
|
+
|
|
26
|
+
=== Teardown commands (resources created during this run) ===
|
|
27
|
+
(no resources were created)
|
|
28
|
+
|
|
29
|
+
If the probe server 'probe-provision-fixture-tenant' was not cleaned up:
|
|
30
|
+
hcloud server delete 'probe-provision-fixture-tenant'
|
|
31
|
+
|
|
32
|
+
To tear down the Hetzner sub-project:
|
|
33
|
+
Delete via Hetzner Console → Projects → tenant-fixture-tenant-prd → Delete
|
|
34
|
+
(CLI does not support project deletion)
|
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Characterization suite for provision-hetzner.sh (#8287 Phase 1).
|
|
3
|
+
#
|
|
4
|
+
# This is the SAFETY NET for the Phase 4 library refactor: it pins today's
|
|
5
|
+
# observable `--dry-run` behaviour byte-for-byte so the refactor can be proven
|
|
6
|
+
# behaviour-preserving rather than asserted to be.
|
|
7
|
+
#
|
|
8
|
+
# Three things this suite exists to pin, each of which the refactor could
|
|
9
|
+
# silently change:
|
|
10
|
+
# 1. the `--dry-run` stdout, byte-for-byte;
|
|
11
|
+
# 2. that a SUCCESSFUL `--dry-run` still emits the teardown block (the EXIT
|
|
12
|
+
# trap fires after `exit 0`) — the "duplicate teardown" the plan names;
|
|
13
|
+
# 3. that `--help` and bad-argument exits print NO teardown, while DPA-gate
|
|
14
|
+
# exits (rc 3) DO.
|
|
15
|
+
#
|
|
16
|
+
# Runs with cwd OUTSIDE the repository (the DPA gate reads a path relative to
|
|
17
|
+
# cwd), against a synthesized fixture register.
|
|
18
|
+
set -uo pipefail
|
|
19
|
+
|
|
20
|
+
export TMPDIR="${TMPDIR:-/var/tmp}"
|
|
21
|
+
|
|
22
|
+
SUITE_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
23
|
+
SCRIPT="${SUITE_DIR}/../scripts/provision-hetzner.sh"
|
|
24
|
+
FIXTURE_KB="${SUITE_DIR}/fixture/knowledge-base"
|
|
25
|
+
|
|
26
|
+
# ONE counter per outcome: the self-test, the anti-vacuity floor and the verdict
|
|
27
|
+
# all read these two names (review P1-5 — a shadow `fails` beside `FAIL_COUNT`
|
|
28
|
+
# let a dropped increment print [FAIL] and exit 0).
|
|
29
|
+
PASS_COUNT=0
|
|
30
|
+
FAIL_COUNT=0
|
|
31
|
+
|
|
32
|
+
pass() { PASS_COUNT=$((PASS_COUNT + 1)); echo " [ok] $1"; }
|
|
33
|
+
fail() { FAIL_COUNT=$((FAIL_COUNT + 1)); echo " [FAIL] $1" >&2; }
|
|
34
|
+
|
|
35
|
+
# Instrument self-test (ADR-193): drive both helpers once each and refuse to
|
|
36
|
+
# continue unless both counters moved. A battery whose helpers are neutered
|
|
37
|
+
# reports a clean run, so this must run BEFORE any real assertion. Reported via
|
|
38
|
+
# printf + exit, never via the helpers under test.
|
|
39
|
+
_st_p=$PASS_COUNT; _st_f=$FAIL_COUNT
|
|
40
|
+
pass "instrument self-test: pass() reached" >/dev/null
|
|
41
|
+
fail "instrument self-test: fail() reached (expected, not a real failure)" 2>/dev/null
|
|
42
|
+
if [[ "$PASS_COUNT" -ne $((_st_p + 1)) || "$FAIL_COUNT" -ne $((_st_f + 1)) ]]; then
|
|
43
|
+
printf 'INSTRUMENT SELF-TEST FAILED: pass/fail helpers did not both move (pass %s->%s, fail %s->%s)\n' \
|
|
44
|
+
"$_st_p" "$PASS_COUNT" "$_st_f" "$FAIL_COUNT" >&2
|
|
45
|
+
exit 2
|
|
46
|
+
fi
|
|
47
|
+
# Unwind the accounting the self-test perturbed; count the self-test itself once.
|
|
48
|
+
PASS_COUNT=1; FAIL_COUNT=0
|
|
49
|
+
echo " [ok] instrument self-test: both helpers dispatch"
|
|
50
|
+
|
|
51
|
+
[[ -f "$SCRIPT" ]] || { printf 'HARNESS: script not found at %s\n' "$SCRIPT" >&2; exit 2; }
|
|
52
|
+
[[ -d "$FIXTURE_KB" ]] || { printf 'HARNESS: fixture register not found at %s\n' "$FIXTURE_KB" >&2; exit 2; }
|
|
53
|
+
|
|
54
|
+
SB="$(mktemp -d -t hetzner-char.XXXXXXXX)" || { printf 'HARNESS: mktemp failed\n' >&2; exit 2; }
|
|
55
|
+
trap 'rm -rf "$SB"' EXIT
|
|
56
|
+
mkdir -p "$SB/bin" "$SB/run" || { printf 'HARNESS: mkdir failed\n' >&2; exit 2; }
|
|
57
|
+
cp -r "$FIXTURE_KB" "$SB/run/" || { printf 'HARNESS: fixture copy failed\n' >&2; exit 2; }
|
|
58
|
+
|
|
59
|
+
# `hcloud` only has to EXIST for the pre-check; --dry-run never invokes it.
|
|
60
|
+
# Exit 64 on any invocation so an accidental network call is loud, not silent.
|
|
61
|
+
printf '#!/usr/bin/env bash\necho "STUB hcloud invoked: $*" >&2\nexit 64\n' > "$SB/bin/hcloud"
|
|
62
|
+
chmod +x "$SB/bin/hcloud"
|
|
63
|
+
|
|
64
|
+
run_script() {
|
|
65
|
+
# Always from $SB/run — OUTSIDE the repository (task 1.8).
|
|
66
|
+
( cd "$SB/run" && PATH="$SB/bin:$PATH" bash "$SCRIPT" "$@" 2>&1 )
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
echo "== provision-hetzner characterization =="
|
|
70
|
+
|
|
71
|
+
# --- 5 (arm 1). Snapshot the LIVE skill tree before any run --------------------
|
|
72
|
+
# §5 below asserts the runs wrote nothing into plugins/soleur/skills/provision-
|
|
73
|
+
# hetzner/. A snapshot of `git status` over that tree, taken before the first
|
|
74
|
+
# run and compared after the last, is what makes that a real observation
|
|
75
|
+
# (review P2-24: the old §5 checked a file the harness itself had copied). The
|
|
76
|
+
# snapshot names untracked files individually so a new ledger beside the script
|
|
77
|
+
# shows up as its own row.
|
|
78
|
+
SKILL_TREE="$(cd "${SUITE_DIR}/.." && pwd)"
|
|
79
|
+
live_tree_status() {
|
|
80
|
+
git -C "$SKILL_TREE" status --porcelain --untracked-files=all -- . 2>/dev/null || echo "NOT-A-GIT-TREE"
|
|
81
|
+
}
|
|
82
|
+
status_before="$(live_tree_status)"
|
|
83
|
+
|
|
84
|
+
# --- 1. Golden --dry-run stdout, byte-for-byte -------------------------------
|
|
85
|
+
GOLDEN="${SUITE_DIR}/fixture/provision-hetzner-dry-run.golden"
|
|
86
|
+
actual="$(run_script fixture-tenant --dry-run)"; rc=$?
|
|
87
|
+
if [[ "$rc" -eq 0 ]]; then
|
|
88
|
+
pass "--dry-run exits 0"
|
|
89
|
+
else
|
|
90
|
+
fail "--dry-run exits 0 (got $rc)"
|
|
91
|
+
fi
|
|
92
|
+
|
|
93
|
+
if [[ -f "$GOLDEN" ]]; then
|
|
94
|
+
if diff -u "$GOLDEN" <(printf '%s\n' "$actual") > "$SB/diff.txt" 2>&1; then
|
|
95
|
+
pass "--dry-run stdout is byte-identical to the golden"
|
|
96
|
+
else
|
|
97
|
+
fail "--dry-run stdout DIFFERS from the golden:"
|
|
98
|
+
sed -n '1,40p' "$SB/diff.txt" >&2
|
|
99
|
+
fi
|
|
100
|
+
else
|
|
101
|
+
fail "golden file missing at $GOLDEN"
|
|
102
|
+
fi
|
|
103
|
+
|
|
104
|
+
# --- 2. A successful --dry-run STILL emits the teardown block ----------------
|
|
105
|
+
# The EXIT trap fires after `exit 0`, so the dry-run prints its own guidance
|
|
106
|
+
# AND the trap's teardown. Pinning this stops the refactor from "tidying" it.
|
|
107
|
+
if grep -qF '=== Teardown commands (resources created during this run) ===' <<<"$actual"; then
|
|
108
|
+
pass "successful --dry-run emits the teardown block (EXIT trap after exit 0)"
|
|
109
|
+
else
|
|
110
|
+
fail "successful --dry-run no longer emits the teardown block"
|
|
111
|
+
fi
|
|
112
|
+
if grep -qF '(no resources were created)' <<<"$actual"; then
|
|
113
|
+
pass "teardown block reports no resources created on a dry run"
|
|
114
|
+
else
|
|
115
|
+
fail "teardown block lost its empty-resources arm"
|
|
116
|
+
fi
|
|
117
|
+
|
|
118
|
+
# --- 3. --help and bad arguments print NO teardown --------------------------
|
|
119
|
+
help_out="$(run_script --help)"; help_rc=$?
|
|
120
|
+
if [[ "$help_rc" -eq 1 ]]; then
|
|
121
|
+
pass "--help exits 1"
|
|
122
|
+
else
|
|
123
|
+
fail "--help exits 1 (got $help_rc)"
|
|
124
|
+
fi
|
|
125
|
+
if grep -qF 'Teardown commands' <<<"$help_out"; then
|
|
126
|
+
fail "--help printed a teardown block (it must not)"
|
|
127
|
+
else
|
|
128
|
+
pass "--help prints no teardown block"
|
|
129
|
+
fi
|
|
130
|
+
|
|
131
|
+
bad_out="$(run_script --nope)"; bad_rc=$?
|
|
132
|
+
if [[ "$bad_rc" -eq 1 ]]; then
|
|
133
|
+
pass "unknown flag exits 1"
|
|
134
|
+
else
|
|
135
|
+
fail "unknown flag exits 1 (got $bad_rc)"
|
|
136
|
+
fi
|
|
137
|
+
if grep -qF 'Teardown commands' <<<"$bad_out"; then
|
|
138
|
+
fail "unknown flag printed a teardown block (it must not)"
|
|
139
|
+
else
|
|
140
|
+
pass "unknown flag prints no teardown block"
|
|
141
|
+
fi
|
|
142
|
+
|
|
143
|
+
noslug_out="$(run_script)"; noslug_rc=$?
|
|
144
|
+
if [[ "$noslug_rc" -eq 1 ]]; then
|
|
145
|
+
pass "missing slug exits 1"
|
|
146
|
+
else
|
|
147
|
+
fail "missing slug exits 1 (got $noslug_rc)"
|
|
148
|
+
fi
|
|
149
|
+
if grep -qF 'Teardown commands' <<<"$noslug_out"; then
|
|
150
|
+
fail "missing slug printed a teardown block (it must not)"
|
|
151
|
+
else
|
|
152
|
+
pass "missing slug prints no teardown block"
|
|
153
|
+
fi
|
|
154
|
+
|
|
155
|
+
# --- 4. DPA-gate exits (rc 3) DO print teardown ------------------------------
|
|
156
|
+
# Bidirectional by construction: the fixture carries a `terminated` row that
|
|
157
|
+
# must NOT pass the gate, and an absent slug that also must not. Asserting only
|
|
158
|
+
# the passing direction would not detect a gate that accepts everything.
|
|
159
|
+
# `fixture-offboarded` carries a historical `dpa-signed` row FOLLOWED by a
|
|
160
|
+
# `terminated` row: the register is append-only, so the LAST row for a slug is
|
|
161
|
+
# the tenant's state, and a gate that latched on the first match admitted every
|
|
162
|
+
# offboarded tenant (review P2-9).
|
|
163
|
+
for blocked in fixture-revoked fixture-offboarded absent-slug; do
|
|
164
|
+
gate_out="$(run_script "$blocked" --dry-run)"; gate_rc=$?
|
|
165
|
+
if [[ "$gate_rc" -eq 3 ]]; then
|
|
166
|
+
pass "DPA gate blocks '$blocked' with rc 3"
|
|
167
|
+
else
|
|
168
|
+
fail "DPA gate blocks '$blocked' with rc 3 (got $gate_rc)"
|
|
169
|
+
fi
|
|
170
|
+
if grep -qF 'Teardown commands' <<<"$gate_out"; then
|
|
171
|
+
pass "DPA-gate exit for '$blocked' prints the teardown block"
|
|
172
|
+
else
|
|
173
|
+
fail "DPA-gate exit for '$blocked' lost its teardown block"
|
|
174
|
+
fi
|
|
175
|
+
done
|
|
176
|
+
|
|
177
|
+
# The in-progress row must pass — a gate that accepted only `dpa-signed` would
|
|
178
|
+
# be a silent narrowing, and the one-row fixture could not see it.
|
|
179
|
+
inflight_out="$(run_script fixture-inflight --dry-run)"; inflight_rc=$?
|
|
180
|
+
if [[ "$inflight_rc" -eq 0 ]]; then
|
|
181
|
+
pass "DPA gate admits a 'provisioning-in-progress' row"
|
|
182
|
+
else
|
|
183
|
+
fail "DPA gate admits a 'provisioning-in-progress' row (got $inflight_rc)"
|
|
184
|
+
fi
|
|
185
|
+
if grep -qF "tenant-fixture-inflight-prd" <<<"$inflight_out"; then
|
|
186
|
+
pass "slug is interpolated into the sub-project name"
|
|
187
|
+
else
|
|
188
|
+
fail "slug is not interpolated into the sub-project name"
|
|
189
|
+
fi
|
|
190
|
+
|
|
191
|
+
# --- 5. No live-repo write (task 1.8) ---------------------------------------
|
|
192
|
+
if [[ -e "$SB/run/knowledge-base/legal/tenant-dpa-register.md" ]]; then
|
|
193
|
+
pass "suite read its own fixture register, not the live one"
|
|
194
|
+
else
|
|
195
|
+
fail "fixture register missing from the sandbox"
|
|
196
|
+
fi
|
|
197
|
+
status_after="$(live_tree_status)"
|
|
198
|
+
if [[ "$status_before" == "NOT-A-GIT-TREE" ]]; then
|
|
199
|
+
fail "no live-repo write: the skill tree is not inside a git work tree, so the snapshot cannot observe a write"
|
|
200
|
+
elif [[ "$status_before" == "$status_after" ]]; then
|
|
201
|
+
pass "no live-repo write: git status over the live skill tree is identical before and after every run"
|
|
202
|
+
else
|
|
203
|
+
fail "no live-repo write: the runs changed the live skill tree:
|
|
204
|
+
$(diff <(printf '%s\n' "$status_before") <(printf '%s\n' "$status_after") | sed 's/^/ /')"
|
|
205
|
+
fi
|
|
206
|
+
|
|
207
|
+
# --- Anti-vacuity floor -----------------------------------------------------
|
|
208
|
+
# REPORTS DIRECTLY (printf + exit 1), never by incrementing FAIL_COUNT (ADR-193)
|
|
209
|
+
# — a floor dispatched through the suite's own pass()/fail() is disarmed by the
|
|
210
|
+
# same one-line edit that disarms every assertion it backstops. This suite is
|
|
211
|
+
# PROMOTED into guard-vacuity-floor's covered scope, which mutation-tests this
|
|
212
|
+
# shape, so the direct form is what keeps the promotion honest.
|
|
213
|
+
ASSERT_TOTAL=$((PASS_COUNT + FAIL_COUNT))
|
|
214
|
+
FLOOR=21
|
|
215
|
+
if [[ "$ASSERT_TOTAL" -lt "$FLOOR" ]]; then
|
|
216
|
+
printf ' [FAIL] anti-vacuity floor: only %s assertions ran, floor is %s\n' "$ASSERT_TOTAL" "$FLOOR" >&2
|
|
217
|
+
printf 'Total: %s assertions, %s failed\n' "$ASSERT_TOTAL" "$((FAIL_COUNT + 1))"
|
|
218
|
+
exit 1
|
|
219
|
+
fi
|
|
220
|
+
# Conservation: pass + fail must account for every assertion the run made.
|
|
221
|
+
if [[ "$ASSERT_TOTAL" -ne $((PASS_COUNT + FAIL_COUNT)) ]]; then
|
|
222
|
+
printf ' [FAIL] accounting: pass=%s fail=%s do not reconcile to %s\n' "$PASS_COUNT" "$FAIL_COUNT" "$ASSERT_TOTAL" >&2
|
|
223
|
+
exit 1
|
|
224
|
+
fi
|
|
225
|
+
|
|
226
|
+
echo "Total: $((PASS_COUNT + FAIL_COUNT)) assertions, ${FAIL_COUNT} failed"
|
|
227
|
+
[[ "$FAIL_COUNT" -eq 0 ]]
|
|
@@ -0,0 +1,263 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: qa
|
|
3
|
+
description: "This skill should be used when running functional QA before merge."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
<!-- soleur-cloud-mode:start -->
|
|
7
|
+
**Cloud Mode (Devin):** before pipeline work run `bash "${CLAUDE_PLUGIN_ROOT}/scripts/cloud-detect.sh"`. If `CLAUDE_PLUGIN_ROOT` is unset (cloud exec shells do not export it), resolve the root by IDENTITY, never by script basename: for `d` in `"$HOME/.local/share/devin/cli/plugins/cache"` and `/opt/.devin/plugins`, skip unless `[ -d "$d" ]`, then `MANIFEST="$(find "$d" -path '*/.claude-plugin/plugin.json' -exec grep -l '"name"[[:space:]]*:[[:space:]]*"soleur"' {} + 2>/dev/null | head -1)"`, `ROOT="${MANIFEST%/.claude-plugin/plugin.json}"` — one resolution, two consumers: `$ROOT/scripts/cloud-detect.sh` and `$ROOT/scripts/precommit-guard.sh`. (Shape check, not authentication: a planted `{"name":"soleur"}` dir passes — ADR-179 A11.) `local` or `not-local:no-devin-env` proceeds normally; any other `not-local:<reason>` applies `<plugin-root>/devin/INSTRUCTIONS.md` §Cloud Mode: emit the `--banner`, fan out sequentially with `Reviewed-Coverage: sequential-fallback` disclosure (never claim an independent review ran), `message_user` ack before any secrets read or production mutation, and run `precommit-guard.sh` before any `git commit` — hooks do not fire in cloud.
|
|
8
|
+
<!-- soleur-cloud-mode:end -->
|
|
9
|
+
|
|
10
|
+
<!-- grok-harness-invoke:start -->
|
|
11
|
+
**Grok Build (`plugins/soleur/lib/harness.ts` `invokeSkill()`):** Read this SKILL.md in this process and run it to completion. A one-segment `soleur:<name>` in this document names a SKILL — on Grok Build, Read `plugins/soleur/skills/<name>/SKILL.md` in this process; it is not a nested tool_use. A multi-segment id such as `soleur:<domain>:<name>` names an AGENT: spawn it, never Read it, and on Grok Build spawn_subagent takes the id with its colons replaced by hyphens (`agentIdToGrokSubagentType`). **Claude Code:** Skill tool for a skill (`soleur:<name>`), Task tool with `subagent_type` for an agent. Forbidden is executing a subset, not the Read.
|
|
12
|
+
<!-- grok-harness-invoke:end -->
|
|
13
|
+
|
|
14
|
+
<!-- lifecycle-handoff-protocol:start -->
|
|
15
|
+
**Lifecycle handoff (standalone `soleur:qa`):** When no parent orchestrator (`one-shot`, `work`) owns the pipeline, invoke `soleur:compound` then `soleur:ship` after the QA report — do not end at the report. A PASS is a checkpoint, not completion. If a recorded operator ruling already authorizes shipping (a scope ruling in `session-state.md`, an explicit instruction), proceed under `wg-verified-work-ships-without-asking` rather than pausing to re-confirm — held scope that was never implemented has no files to carry along and is not a reason to halt.
|
|
16
|
+
<!-- lifecycle-handoff-protocol:end -->
|
|
17
|
+
|
|
18
|
+
# Functional QA
|
|
19
|
+
|
|
20
|
+
Verify that features actually work before merge -- not just that pages render, but that forms submit correctly, external services receive the right data, and data integrity holds across system boundaries.
|
|
21
|
+
|
|
22
|
+
**Scope boundary with `soleur:test-browser`:** This skill verifies functional correctness (user flows + external service state). `soleur:test-browser` verifies visual rendering, layout regressions, and console errors. They coexist in the pipeline.
|
|
23
|
+
|
|
24
|
+
## Prerequisites
|
|
25
|
+
|
|
26
|
+
- Local development server running OR a `dev` script in the project's `package.json` (auto-started if not running)
|
|
27
|
+
- Playwright MCP available (for browser scenarios)
|
|
28
|
+
- Doppler CLI installed and configured (for API verification scenarios)
|
|
29
|
+
|
|
30
|
+
## Usage
|
|
31
|
+
|
|
32
|
+
**Claude:** Skill tool. **Grok:** Read this SKILL.md in this process (`soleur:qa`); slash names the skill.
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
skill: soleur:qa, args: "<plan_file_path>" # Claude Skill tool
|
|
36
|
+
soleur:qa <plan_file_path> # Grok slash (then Read this SKILL.md)
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
The skill reads the plan file's `## Test Scenarios` section and executes each scenario.
|
|
40
|
+
|
|
41
|
+
## Workflow
|
|
42
|
+
|
|
43
|
+
### Step 1: Read Plan and Extract Test Scenarios
|
|
44
|
+
|
|
45
|
+
Read the plan file passed as `$ARGUMENTS`. Find the `## Test Scenarios` section.
|
|
46
|
+
|
|
47
|
+
**If no Test Scenarios section exists:** Output "No test scenarios found in plan — skipping QA" and stop. Do not block the pipeline.
|
|
48
|
+
|
|
49
|
+
**If Test Scenarios section is empty:** Same as above — warn and skip.
|
|
50
|
+
|
|
51
|
+
**If Test Scenarios contains only Given/When/Then prose with no `Browser:`, `API verify:`, or `Cleanup:` prefixed steps:** Output "Test Scenarios are integration-level Given/When/Then prose (no executable Browser:/API verify: steps) — covered by unit test suite + manual Phase 6 cross-check. Skipping automated QA." and stop. Do not start the dev server. This case is common for plans whose QA gate is explicitly manual (e.g., requires a real Anthropic key + live Supabase apply); a dev-server smoke would not add coverage beyond what the typecheck + unit suite already validate. Never block the pipeline on a confirmation prompt for the dev server in a test environment — auto-skip silently.
|
|
52
|
+
|
|
53
|
+
### Step 1.5: Ensure Dev Server is Running
|
|
54
|
+
|
|
55
|
+
Before executing any browser scenarios, check whether the dev server is reachable. If not, attempt to start it automatically.
|
|
56
|
+
|
|
57
|
+
1. **Check if already running:** `curl -sf --max-time 3 http://localhost:3000/ >/dev/null 2>&1`. If reachable, skip to Step 2 — no action needed. Record that the server was NOT started by QA (so cleanup skips it).
|
|
58
|
+
|
|
59
|
+
2. **Detect the dev command:** Read `apps/web-platform/package.json` and extract the `scripts.dev` field. If no `dev` script exists, warn: "No dev script found in package.json — cannot auto-start server. Skipping browser scenarios." Continue to API verification steps (do not block the pipeline).
|
|
60
|
+
|
|
61
|
+
3. **Start the server:** Change to the `apps/web-platform/` directory first (the dev command must run from the app root). Check if Doppler is available (`command -v doppler`). If available, start via `doppler run -p soleur -c dev -- <dev-command> > "$QA_LOG" 2>&1 &` (after `QA_LOG=$(mktemp -p "$(mktemp -d -t soleur-run.$$.XXXXXXXX)" qa-dev-server.XXXXXXXX.log)`). If Doppler is unavailable, start via `<dev-command> > "$QA_LOG" 2>&1 &`. Record the background PID **and echo `QA_LOG=$QA_LOG`** — a later Bash call does not inherit the variable, so the path must be recoverable from the transcript. A fixed name would collide with any concurrent QA session. Remove it at QA teardown (`rm -f` on the echoed `QA_LOG=` path plus `rmdir` on its parent — a later Bash call does not inherit the variable) — it is scratch, and a count-shaped `/tmp` leak is real (#10017).
|
|
62
|
+
|
|
63
|
+
4. **Poll for readiness (30s timeout):** Poll `http://localhost:3000/` until it responds or 30 seconds have elapsed, whichever comes first. If the server responds, proceed to Step 2. If the timeout elapses:
|
|
64
|
+
- Kill the background process by PID
|
|
65
|
+
- Include the last 20 lines of `"$QA_LOG"` in the failure report
|
|
66
|
+
- Report: "Dev server failed to start within 30s. See server output above."
|
|
67
|
+
- Continue to API verification steps (do not block the pipeline)
|
|
68
|
+
|
|
69
|
+
- When `doppler run` starts the dev server but Supabase env vars (`NEXT_PUBLIC_SUPABASE_URL`, `NEXT_PUBLIC_SUPABASE_ANON_KEY`) are missing from the Doppler config, the server starts but crashes on first request. Check the server log for "Your project's URL and Key are required" before declaring the server ready.
|
|
70
|
+
|
|
71
|
+
### Step 2: Detect Environment
|
|
72
|
+
|
|
73
|
+
Determine the Doppler config to use:
|
|
74
|
+
|
|
75
|
+
```bash
|
|
76
|
+
# Check if DEPLOY_URL is set (indicates production context)
|
|
77
|
+
echo "${DEPLOY_URL:-not_set}"
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
- If `DEPLOY_URL` is set: use Doppler config `prd`
|
|
81
|
+
- If `DEPLOY_URL` is not set: use Doppler config `dev`
|
|
82
|
+
|
|
83
|
+
Store the config name for use in subsequent `doppler` commands.
|
|
84
|
+
|
|
85
|
+
### Step 2.6: Structural-UI Visual-Regression Gate (#4834 / ADR-049)
|
|
86
|
+
|
|
87
|
+
This is the gate's semantic home. Run it when the diff (`git diff --name-only origin/main...HEAD` — the branch-vs-main merge-base diff; do NOT use `origin/<branch>...HEAD`, which only sees unpushed commits and returns 0 files once the branch is pushed, silently skipping the gate) touches `apps/web-platform/app/(dashboard)/**`, `apps/web-platform/components/dashboard/**`, or any `layout.tsx`. Skip silently otherwise.
|
|
88
|
+
|
|
89
|
+
**Why this exists:** jsdom (vitest) renders no CSS, so `md:w-14` / `hidden md:block` / `flex-wrap` / `display:none` regressions ship green through the unit suite (the #4810 class — top-level chrome leaking into drilled routes; a collapsed rail with no icon-only form). The gate renders real CSS in real headless Chromium.
|
|
90
|
+
|
|
91
|
+
**Deterministic layer (BLOCKING).** Run the committed `nav-states-*.e2e.ts` spec in the existing `authenticated` Playwright project — real headless Chromium + real Next.js SSR seeded by the **offline mock-Supabase storageState** (`e2e/global-setup.ts` + `e2e/helpers/supabase-mocks.ts`). Zero credentials; NO `dev-signin`; never point at a live origin (CLO: synthetic fixtures only).
|
|
92
|
+
|
|
93
|
+
**Browser-readiness preflight (unsupported-host guard — do this FIRST).** On a host newer than the pinned Playwright officially supports, a plain `playwright install` fails before any navigation — the false-fail that repeatedly costs a QA session its whole run. Run the install probe in [browser-preflight.md](./references/browser-preflight.md) — it logs under a `soleur-run` root (#10017) and retries with the host-platform override.
|
|
94
|
+
|
|
95
|
+
If BOTH the plain install and the override install fail (a genuinely unsupported host with no fallback build), do NOT run the gate and do NOT spend reasoning re-deriving whether it is a regression: this is **INFRA-BLOCKED**, not a code failure. Record in the QA report — "Step 2.6 nav-states gate INFRA-BLOCKED locally (Playwright browser uninstallable on <os>); CI's containerized `e2e` job (`mcr.microsoft.com/playwright:v1.58.2-jammy`) is the authoritative gate per #5009" — and proceed. Never block the pipeline on this.
|
|
96
|
+
|
|
97
|
+
Then run the gate (no override — the runtime resolves the installed build):
|
|
98
|
+
|
|
99
|
+
### Preflight: verify the plugin install before any snapshot
|
|
100
|
+
|
|
101
|
+
The redactor is reached through `${CLAUDE_PLUGIN_ROOT}`. An ambient value pointing at a
|
|
102
|
+
directory that is not a Soleur install would resolve to a path that does not exist — or, worse,
|
|
103
|
+
to one an attacker chose. Verify plugin IDENTITY and halt if it does not hold (ADR-179 decision 2);
|
|
104
|
+
a `test -f` on the script alone is a shape check and was measured bypassable.
|
|
105
|
+
|
|
106
|
+
```bash
|
|
107
|
+
[ -f "${CLAUDE_PLUGIN_ROOT}/.claude-plugin/plugin.json" ] \
|
|
108
|
+
&& grep -q '"name"[[:space:]]*:[[:space:]]*"soleur"' "${CLAUDE_PLUGIN_ROOT}/.claude-plugin/plugin.json" \
|
|
109
|
+
|| { echo "SOLEUR_SNAPSHOT_HALT reason=plugin-root-unverified root=[${CLAUDE_PLUGIN_ROOT}]" >&2
|
|
110
|
+
echo " Cannot locate the snapshot redactor, so no accessibility snapshot may be taken here." >&2
|
|
111
|
+
echo " Root EMPTY: no Soleur plugin is loaded in this session. Install it and start a NEW session." >&2
|
|
112
|
+
echo " Root set but wrong: a repo checkout is not an install. Run 'claude plugin update soleur@soleur-marketplace' (or the id 'claude plugin list' prints, if you added the repository directly), then RESTART Claude Code." >&2
|
|
113
|
+
echo " Nothing has been captured yet, so nothing has leaked." >&2
|
|
114
|
+
exit 2; }
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
```bash
|
|
118
|
+
cd apps/web-platform && ./node_modules/.bin/playwright test nav-states --project=authenticated --reporter=list
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
A non-zero exit FAILS this QA run. The assertions read invariants jsdom cannot: drilled routes hide the wordmark + ThemeToggle; the collapsed rail is icon-only with no horizontal overflow; the workspace-identity band is visible (with org + repo content) in every drill state × viewport.
|
|
122
|
+
|
|
123
|
+
**Discriminate a real fail from an env flake.** If the run exits non-zero, apply the #5009 discriminator (see Notes): untouched-test + failure at `page.goto`/browser-close (before any assertion) + the surface the diff actually changed still passes = pre-existing local env flake → record and defer to CI, do not "fix" unrelated tests. A launch-time `Executable doesn't exist` failure means the preflight above was skipped or its override install also failed — treat as INFRA-BLOCKED, not a regression.
|
|
124
|
+
|
|
125
|
+
**Advisory vision layer (NON-BLOCKING).** Optionally drive Playwright MCP over the same routes, screenshot each, and vision-check what the deterministic assertions miss (spacing, color, truncation). Informational only (headed MCP cannot run in autonomous `soleur:work`/CI), so it never blocks the merge; report findings as notes.
|
|
126
|
+
|
|
127
|
+
### Step 3: Execute Test Scenarios
|
|
128
|
+
|
|
129
|
+
For each test scenario in the plan, execute the steps it describes. Scenarios contain three possible step types, identified by their prefix:
|
|
130
|
+
|
|
131
|
+
- **Browser:** steps — Execute via Playwright MCP tools (`browser_navigate`, `browser_fill_form`, `browser_click`, `browser_snapshot`, `browser_take_screenshot`)
|
|
132
|
+
- **Route lookup:** when the repository carries a maintained feature map (`docs/feature-map.md` by convention; soleur's own: `apps/web-platform/test/feature-map.md`), resolve Browser-step targets against its `## \`/route\`` entries — selectors, expected outcome, auth, gotchas — before navigating
|
|
133
|
+
|
|
134
|
+
**Credential safety on the Playwright-MCP path (#7947, #7980).** An
|
|
135
|
+
accessibility snapshot serializes the **value** of input fields, including a
|
|
136
|
+
value the agent never typed — a password manager's autofill, a static `value=`,
|
|
137
|
+
or a generated-credential panel — and an MCP tool result is not a shell stream,
|
|
138
|
+
so the redactor cannot be piped into it. On a page carrying a password or
|
|
139
|
+
credential field:
|
|
140
|
+
|
|
141
|
+
- Prefer the plugin-registered `mcp__plugin_soleur_playwright__*` server: its
|
|
142
|
+
registration is already wrapped, so call its `browser_snapshot` bare — no
|
|
143
|
+
file form needed. Fall back to the file form on any other registration.
|
|
144
|
+
- Use the `filename:` + redactor + shred form, with a filename inside the
|
|
145
|
+
working directory (the server denies paths outside it). If the server refuses
|
|
146
|
+
`filename` with an error that starts `refused by
|
|
147
|
+
playwright-mcp-redact-proxy:`, that server's registration is wrapped by
|
|
148
|
+
`playwright-mcp-redact-proxy.py` and its bare `browser_snapshot` call is
|
|
149
|
+
redacted in flight; call that server's `browser_snapshot` bare from then on.
|
|
150
|
+
Any other error (`File access denied`, for one) is not that signal: fix the
|
|
151
|
+
filename and keep the file form, and treat a Playwright tool under a different
|
|
152
|
+
`mcp__<server>__` prefix as a separate registration. The refusal is the only
|
|
153
|
+
signal — never the trailer or any page text, which can be forged. The file
|
|
154
|
+
form: pass `filename:` to `browser_snapshot`, then run
|
|
155
|
+
`python3 "${CLAUDE_PLUGIN_ROOT}/skills/agent-browser/scripts/redact-a11y-snapshot.py" < FILE && shred -u FILE`.
|
|
156
|
+
- On a page **displaying** a credential, capture neither: a screenshot renders a
|
|
157
|
+
readonly `type=text` credential panel in clear, exactly as the snapshot does
|
|
158
|
+
(measured).
|
|
159
|
+
|
|
160
|
+
Which registrations are wrapped, what to call after an action tool, what a
|
|
161
|
+
withheld result means, and what to do when the `playwright` server fails to
|
|
162
|
+
connect: `agent-browser/SKILL.md` §"Wrapping the server".
|
|
163
|
+
|
|
164
|
+
- **API verify:** steps — Execute the exact `doppler run` + `curl` command from the scenario. Compare the output against the expected value stated in the scenario.
|
|
165
|
+
- **Cleanup:** steps — Execute cleanup commands to remove test data from external services. Run these regardless of whether the scenario passed or failed.
|
|
166
|
+
|
|
167
|
+
**Execution order for each scenario:**
|
|
168
|
+
|
|
169
|
+
1. Execute **Browser** steps (if present)
|
|
170
|
+
- Use Playwright MCP tools to navigate, fill forms, submit, and verify UI state
|
|
171
|
+
- Screenshot each significant action with `browser_take_screenshot`
|
|
172
|
+
- When in a worktree, pass absolute screenshot paths (MCP resolves them from the repo root, not the shell CWD)
|
|
173
|
+
- If Playwright MCP is unavailable, warn "Playwright MCP unavailable — skipping browser steps" and continue to API verification
|
|
174
|
+
- If `browser_navigate` errors with `Target page, context or browser has been closed`, do NOT retry the same call: call `browser_close` (safe if already closed), then retry. After the last Browser step also call `browser_close` (nothing reaps it at turn end; ADR-271).
|
|
175
|
+
- On `Chromium sandboxing failed!` / `No usable sandbox!`, stop and read `agent-browser/SKILL.md` troubleshooting; never disable the sandbox in the Playwright config or env (the proxy refuses it, then the MCP server fails to start); tell the user the host needs Google Chrome or a non-root user.
|
|
176
|
+
2. Wait 3 seconds for eventual consistency (if the scenario has both Browser and API steps)
|
|
177
|
+
3. Execute **API verify** steps (if present)
|
|
178
|
+
- Run the exact command from the scenario via the Bash tool
|
|
179
|
+
- Compare the command output against the expected value
|
|
180
|
+
- If the command fails or output doesn't match, retry up to 3 times (waiting a few seconds between retries) before marking as failed
|
|
181
|
+
- If a `doppler secrets get` fails (secret not found), warn "Doppler secret unavailable — skipping API verification" and skip this step
|
|
182
|
+
4. Execute **Cleanup** steps (if present)
|
|
183
|
+
- Run cleanup commands regardless of pass/fail
|
|
184
|
+
- Cleanup failures produce warnings but do not mark the scenario as failed
|
|
185
|
+
|
|
186
|
+
**Sharp edges for API verification:**
|
|
187
|
+
|
|
188
|
+
- When verifying Sentry API events, use `statsPeriod=24h` (not `1h` — Sentry only accepts `24h` and `14d`). For EU-region DSNs (`ingest.de.sentry.io`), query `de.sentry.io/api/0/` (not `sentry.io/api/0/`).
|
|
189
|
+
|
|
190
|
+
**Record the result** for each scenario: PASS or FAIL with evidence (screenshots, API response output, error messages).
|
|
191
|
+
|
|
192
|
+
### Step 4: Generate Report
|
|
193
|
+
|
|
194
|
+
After all scenarios complete, output a report in this format:
|
|
195
|
+
|
|
196
|
+
```markdown
|
|
197
|
+
## QA Report
|
|
198
|
+
|
|
199
|
+
**Plan:** <plan file path>
|
|
200
|
+
**Environment:** <dev or prd>
|
|
201
|
+
**Result:** <PASS (N/N scenarios passed) or FAIL (N/N scenarios passed)>
|
|
202
|
+
|
|
203
|
+
### Scenario 1: <scenario description> ✅ or ❌
|
|
204
|
+
|
|
205
|
+
**Browser:** <what was done, result>
|
|
206
|
+
**API:** <command executed, expected vs actual>
|
|
207
|
+
**Evidence:** <screenshot filenames>
|
|
208
|
+
|
|
209
|
+
### Scenario 2: ...
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
### Step 5: Pass/Fail Gate
|
|
213
|
+
|
|
214
|
+
- If **all scenarios passed**: Output the report and continue. The pipeline proceeds to the next step.
|
|
215
|
+
- If **any scenario failed**: Output the report with detailed failure information (expected vs actual values, screenshot of failure state). Output "QA FAILED — fix the issues above and re-run QA."
|
|
216
|
+
|
|
217
|
+
After outputting the result (pass or fail), always proceed to Step 5.5 for cleanup before returning.
|
|
218
|
+
|
|
219
|
+
### Step 5.5: Cleanup Dev Server
|
|
220
|
+
|
|
221
|
+
If the dev server was started in Step 1.5 (a background PID was recorded), kill the process by PID, remove `$QA_LOG` (the path echoed when the server started), and report: "Stopped auto-started dev server (PID <pid>)." If the server was already running before QA (no PID recorded), do nothing.
|
|
222
|
+
|
|
223
|
+
This step runs regardless of whether scenarios passed or failed.
|
|
224
|
+
|
|
225
|
+
## Graceful Degradation
|
|
226
|
+
|
|
227
|
+
The skill handles missing prerequisites without blocking the pipeline:
|
|
228
|
+
|
|
229
|
+
| Missing Prerequisite | Behavior |
|
|
230
|
+
|---------------------|----------|
|
|
231
|
+
| No Test Scenarios section in plan | Warn and skip QA entirely |
|
|
232
|
+
| Playwright MCP unavailable | Skip browser steps, still run API verification |
|
|
233
|
+
| Doppler secret not found | Skip that API verification step with warning |
|
|
234
|
+
| Dev server not running | Auto-start via package.json dev script; if startup fails, report reason and skip browser scenarios |
|
|
235
|
+
| No dev script in package.json | Warn and skip browser scenarios (API verification still runs) |
|
|
236
|
+
| Dev server startup timeout (30s) | Report failure reason and skip browser scenarios |
|
|
237
|
+
| curl command fails (network error) | Fail that scenario with error details |
|
|
238
|
+
|
|
239
|
+
## Notes
|
|
240
|
+
|
|
241
|
+
- **A skill-prose change gets a constrained DRY RUN, not only a read.** Spawn a subagent to execute the rewritten skill against a real, already-diagnosed issue under no-post / no-write / no-credential constraints and report every sentence it could not follow. **Why:** #8288/PR #8352 — nine review seats read the rewritten `reproduce-bug` prose and passed it; the dry run found six unfollowable or contradictory sentences (an exit criterion with no off-ramp for a local-only surface, "inspect the code" vs "stop reading code", a "do not proceed until reproduced" unsatisfiable once the fix has landed). Reading is not executing. See `knowledge-base/project/learnings/2026-09-19-cleanup-on-failure-is-a-property-of-the-window-not-the-arms.md`.
|
|
242
|
+
- **A gate has THREE outcomes and the third silently equals the first — drive the cannot-evaluate arm, not just clean and violated.** `rc=0` and `rc=2` producing byte-identical stdout is the DEFAULT whenever a tool writes diagnostics to stderr, so "it printed nothing, so it passed" is indistinguishable from "it never measured". Also refuse a fence whose terminal statement is an ASSIGNMENT (`rc=$?`): the fence then exits 0 whatever the tool said, and a dispatch written in prose below it runs in a different fence that cannot see the variable. **Why:** #8289/PR #8405 — the redaction floor in `questionnaire-generate` ended `sentinel_rc=$?` with the dispatch in prose; measured clean rc=0/0 bytes, matches rc=1/53 bytes, unreadable rc=2/**0 bytes**, so an un-scanned document intended for an outside professional was indistinguishable from a scanned one and the documented "cannot evaluate → halt" arm was unreachable. Nine review seats had read that prose. See `knowledge-base/project/learnings/2026-09-20-i-verified-by-reading-and-the-gate-that-mattered-failed-open.md`.
|
|
243
|
+
- For Playwright auth in production QA, use Supabase admin API `generate_link` to get the OTP code, then enter it in the OTP form. Do not use the magic link `action_link` URL — Playwright navigation does not trigger client-side hash fragment processing.
|
|
244
|
+
- For Playwright MCP visual verification of an authenticated surface on a LOCAL dev server: start the server with `NEXT_PUBLIC_DEV_EXTRA_ORIGINS=<origin>` (else state-mutating POSTs 403 on CSRF), mint a cookie via `ux-audit/scripts/bot-signin.ts` with `NEXT_PUBLIC_APP_URL=http://localhost:<port>`, inject it with `page.context().addCookies()` (the `run_code_unsafe` sandbox has no `require`/`Buffer`/`atob` — pre-escape data into a literal), drive onboarding gates via `page.evaluate(fetch(...))` not UI clicks, and `curl`-pre-warm slow routes before `browser_navigate`. Full recipe: `knowledge-base/project/learnings/2026-06-02-playwright-mcp-local-auth-dashboard-verification.md`.
|
|
245
|
+
- When locating a control whose `aria-label` flips with component state (a collapse toggle that is `"Collapse sidebar"` expanded / `"Expand sidebar"` collapsed, a disclosure that is `"Show"`/`"Hide"`, etc.), a single-label `getByRole("button", { name: "Collapse sidebar" })` resolves in one state and throws "element(s) not found" in the other. Match all states with a regex alternation (`name: /^(Collapse|Expand) sidebar$/`) or a stable `data-testid`. **Why:** PR #4997 — the collapsed-rail VRT case failed on a "Collapse sidebar" locator because the floated toggle reads "Expand sidebar" when collapsed. See `knowledge-base/project/learnings/ui-bugs/2026-06-08-floating-absolute-control-needs-clearance-in-both-render-branches.md`.
|
|
246
|
+
- When asserting horizontal/vertical ALIGNMENT between two controls in Playwright, measure the innermost visible element (`.locator("svg")` / the text node), NOT the interactive element's `boundingBox()`. Two controls can share a layout gutter while their border-boxes differ by asymmetric padding or flex-stretch (e.g. a full-width `flex` link whose `px-3` is internal vs. an unpadded button whose `px-3` is the row gutter) — comparing border-boxes yields a false misalignment equal to the padding delta. See `knowledge-base/project/learnings/test-failures/2026-06-03-playwright-x-alignment-measure-glyph-not-border-box.md`.
|
|
247
|
+
- For verifying a vendored-library CSS override (e.g. `@likec4/diagram` theme tweaks in `c4-theme.css`) on an auth/flag-gated surface, prefer a reconstructed-DOM harness over the live viewer: read the library's emitted DOM contract + CSS recipe out of `node_modules`, rebuild the exact node markup in a standalone HTML file with the real theme tokens, render it via the project's installed chromium (`chromium.launch({ executablePath: ~/.cache/ms-playwright/chromium-<build>/chrome-linux64/chrome })` — the Playwright MCP Chrome channel is often absent and the module's default build can drift from the cache), and assert `getComputedStyle(...).fill`/`opacity` flips off the library default in both `data-theme` states (proves cascade victory — the non-vacuous half a source-grep test can't give you) before screenshotting for legibility. See `knowledge-base/project/learnings/2026-06-05-verify-vendored-css-override-via-reconstructed-dom-harness.md`.
|
|
248
|
+
- When verifying that an INJECTED session cookie authenticates, navigate to a **client-guarded** route (one that hydrates its session via the `@supabase/ssr` browser client from `document.cookie`, e.g. `/dashboard/chat/new`) — NOT only a server-rendered route like `/dashboard`. A server-rendered route reads the cookie server-side where `httpOnly` is irrelevant, so it authenticates even with a mis-shaped injected cookie (`httpOnly: true`, wrong domain visibility, missing chunk) and silently clears bugs that only manifest on the client hydration path. Inject with `httpOnly: false` (matches `bot-signin.ts`/`e2e/global-setup.ts`); `httpOnly: true` blocks the browser client and races to `/login`. **Why:** #5485 — see `knowledge-base/project/learnings/bug-fixes/2026-06-17-injected-session-cookie-test-the-client-guarded-route-not-just-dashboard.md`.
|
|
249
|
+
- **Before recording any hazard as mitigated, `ls` every control the plan NAMES as its detection — a guard can be deleted mid-implementation while the document that cites it is never re-derived.** The sibling note below covers a control that cannot FIRE; this covers one that does not EXIST, and the plan reads identically in both cases. Measured: #7902's Guard 2 was built, mutation-proven at 10/10, then deleted on a CTO ruling — while the observability `failure_modes` block still gave it as the `detection:` for the plan's sharpest hazard, and the `## Guard Contract` still carried its full property statement and a seven-row mutation matrix. [lint-guard-contract.py](../../../../scripts/lint-guard-contract.py) was green throughout (exit 0, 30 entries) and is not broken: it resolves plan **entries**, so its green is a sentence about the document and never about the tree. Review reads the diff and structurally cannot see a guard that is absent from it, which makes QA the last phase that reads the plan whole while there is still time. Same pass, same plan: AC3 and AC5 were literally false as written (AC5 claimed the `test:` block was byte-unchanged; it gained 7 lines) and were about to be ticked from memory of intent — tick an AC only by running the command it names. See [the 2026-09-08 learning](../../../../knowledge-base/project/learnings/2026-09-08-the-guard-was-deleted-the-plan-still-cited-it-and-the-linter-validated-the-citation.md).
|
|
250
|
+
- **A MISSING CI check is a MERGEABILITY question first.** A conflicting PR reads as *"CI never ran"*: functional jobs are **absent**, not failing — GitHub builds no `refs/pull/N/merge` for a DIRTY ref, and the all-green CodeQL set left behind looks healthy. Run `gh pr view --json mergeable,mergeStateStatus` before diagnosing a missing check. **Why:** #8539; see `learnings/2026-09-23-the-prose-stated-the-property-and-the-predicate-checked-a-subset.md`.
|
|
251
|
+
- **A "known pre-existing failure" is a claim to RE-MEASURE, and a matching failure COUNT is the weakest possible evidence for it.** When a handoff says a suite "already fails N of M on main, identical rows", falsify it by installing the base version of the SPECIFIC INPUTS that suite reads and re-running — never by checking that N still equals N, because a regression breaking N rows is indistinguishable from a known failure of N rows. The trap fires hardest when your diff touched the suite's FIXTURES: grep the failing row NAMES against `git diff --name-only origin/main...HEAD`. **Why:** #7927/PR #7955 — a briefing said `ship-incident-pir-gate` "fails 2 of 25 on main today, tracked by #7801"; the count matched exactly, and it was false for that tree. The branch's markdown sweep had touched precisely the two fixtures the two failing rows are named for (a boundary classifier whose blank lines ARE its input), and `git show origin/main:<fixture>` + re-run gave 25/25 against 23/25 in ~30 seconds. Accepting the label would have shipped a real break under cover of a known one. See `knowledge-base/project/learnings/2026-09-09-the-linter-rewrote-the-fixtures-its-own-suites-assert-on.md`.
|
|
252
|
+
- **A scenario's NEGATIVE CONTROL is a claim to run, not a control to trust — and the Risks table usually cites it as the mitigation for the plan's sharpest hazard.** When a scenario reads "…and a fixture that violates X fails the check", run that fixture before recording the scenario as covered; a control that cannot fire makes the hazard read as mitigated while nothing guards it. Measured: a plan asserted that a unit whose `ReadWritePaths` names a missing directory fails `systemd-analyze verify`; it returns **rc=0 with empty output**, because verify validates directive syntax and not path existence. The Risks table had cited exactly that control as the mitigation for a unit that would otherwise die on every 30-second fire on a host with no inbound channel. Retract the falsified half in place (append the measurement rather than deleting the sentence) and name the control that actually holds. **Why:** #7761. See `knowledge-base/project/learnings/security-issues/2026-09-03-the-hardening-i-added-disarmed-the-guard-over-the-flushall.md`.
|
|
253
|
+
- This skill does NOT test error paths (network failure, invalid input); deferred.
|
|
254
|
+
- Always include cleanup steps so test data does not accumulate in external services.
|
|
255
|
+
- The deploy-webhook credential triple (`WEBHOOK_DEPLOY_SECRET`, `CF_ACCESS_CLIENT_ID`, `CF_ACCESS_CLIENT_SECRET`) lives in Doppler `soleur/prd_terraform`, NOT `prd` — a probe run under `doppler run -c prd` reports `credentials_unprovisioned`, which is the probe being correct, not the secret being absent. And `doppler secrets --only-names` prints a TABLE (`│ NAME │`), so an anchored `grep -c '^NAME$'` over it returns 0 for every config; a zero from an unfamiliar CLI subcommand is "the command's output shape is unknown" until inspected. **Why:** #6178 / PR #8346 — a names-scan reported the triple absent from all 13 configs while `inngest-server.md` §deploy-status already named the right one.
|
|
256
|
+
- For new scheduled-probe workflows, dry-run every probe step against prod hostnames before merge. Verify the documented success path (HTTP code, redirect host, response shape) matches reality. Workflow YAML lint and unit tests do NOT catch API contract surprises like HEAD-rejecting endpoints or auth-required public endpoints. **Why:** PR #3030 — see `knowledge-base/project/learnings/integration-issues/2026-04-29-supabase-auth-probe-and-sentry-rule-api-quirks.md`.
|
|
257
|
+
- When verifying a secret-scan gate fails loud on a secret, the sentinel must be a shape the scanner actually catches AND is not on its example/stopword allowlist — `AKIAIOSFODNN7EXAMPLE` (gitleaks' canonical AWS doc key) is allowlisted and returns a false `rc=0`. Use a synthetic PEM (`-----BEGIN RSA PRIVATE KEY-----` + random base64) or a repo-custom-rule shape (`postgres://`, `dp.st.`), pair it with a clean control (no-secret → `rc=0`), and run in an isolated throwaway git repo so the synthetic never touches the real worktree/push-protection. **Why:** PR #6050 — see `knowledge-base/project/learnings/security-issues/2026-07-05-fabricated-green-content-gate-ceiling-and-verification-sentinel.md`.
|
|
258
|
+
- For pure-CSS-utility-class fixes whose plan declares `User-Brand Impact: none` AND whose className contracts are fully unit-tested (vitest asserts on `toHaveClass`/`className.match`), a dev-server outage degrades QA to unit-test coverage rather than blocking the pipeline — file the dev-server bug separately with `pre-existing-unrelated` scope-out. For functional, data, auth, or payment fixes, the dev-server bug becomes load-bearing and must be fixed before merge. See `knowledge-base/project/learnings/2026-05-11-qa-degradation-when-dev-server-broken-on-css-only-fix.md`.
|
|
259
|
+
- When the visual gate asserts on an element's measured size (`clientWidth`/`offsetHeight`) that is animated (`transition-[width]`) OR set in a post-mount effect (localStorage hydration, `useMediaQuery`), poll with `expect.poll(() => el.clientWidth, { timeout }).toBeGreaterThan(X)` — a single synchronous read races the transition/hydration and catches a transient value. And before a `page.mouse` drag on a hydrated client component, settle for hydration (the SSR markup is visible before React attaches `onPointerDown`, so an early drag fires events at a handler-less element). A JS-driven responsive width should ride a CSS custom property + an `@media` rule (NOT a Tailwind v4 `w-[var(--x)]` arbitrary class, which may not generate, nor a `useMediaQuery` JS gate, which can stay stale under SSR hydration). **Why:** PR #4871 — see `knowledge-base/project/learnings/ui-bugs/2026-06-03-dynamic-width-needs-css-var-not-tailwind-arbitrary-or-usemediaquery.md`.
|
|
260
|
+
- When an `absolute`/`fixed` control must align to an **in-flow** sibling (a floated toggle centered on an adjacent card), its `top-N` is measured from its **positioning containing block** while the sibling lives in a **different** containing block — so static pixel math (`pt-2 + pill_half`) silently omits the gap between the two origins. Derive the `top-N` against the **live VRT** (not eyeballed, not statically computed) and assert a **positive rect-center** alignment (`|toggleCenterY − cardCenterY| ≤ 2`), never just non-overlap — a misaligned-but-disjoint control passes a non-overlap check, which is exactly how the centering regression ships green. **Why:** PR #5015 — `top-7` left a 12px residual == the band's reclaimed-space offset below the aside; VRT-derived `top-10` fixed it. See `knowledge-base/project/learnings/ui-bugs/2026-06-08-absolute-control-alignment-offset-parent-vs-target-band.md`.
|
|
261
|
+
- The Step 2.6 `nav-states` gate can FALSE-FAIL on a resource-starved local machine: headless Chromium crashes cascade across tests. Discriminate flake-from-regression by provenance + failure-layer: (a) does the diff touch the failing test (`git diff origin/main...HEAD -- e2e/nav-states-shell.e2e.ts`)? (b) do the tests rendering the surface the diff actually changed pass? (c) is the failure at `page.goto`/browser-close (before any assertion) vs. a real assertion mismatch? Untouched-test + crash-at-navigation + changed-surface-passes = pre-existing local env flake (root-cause hygiene: [determinism-checklist.md](${CLAUDE_PLUGIN_ROOT}/skills/test-fix-loop/references/determinism-checklist.md)); CI's containerized `e2e` job is the authoritative gate — record it and proceed, don't "fix" unrelated tests. **Why:** PR #5009 — see `knowledge-base/project/learnings/test-failures/2026-06-08-nav-states-structural-ui-gate-flakes-on-throttled-local.md`.
|
|
262
|
+
- When the diff adds a NEW client-side fetch to a page covered by the offline-mock e2e suite (`e2e/nav-states-*.e2e.ts` et al.), the harness `page.route` mock for that endpoint must land in the SAME PR. Unmocked, the request reaches the real dev server whose backing-service env is fake in e2e — a hanging request that wedges a throttled dev server and fails tests far from the diff (goto timeouts) before failing the obvious one. Diagnosis discriminator: the diff-surface test failing in EVERY run while siblings shift = regression; shifting set with `browserContext.close` accompaniment = the #5009 flake. **Why:** PR #5125 — the new `/api/inbox/emails` fetch was the only unmocked authed route in nav-states; see `knowledge-base/project/learnings/2026-06-11-worm-mutation-matrix-and-e2e-harness-mock-for-new-fetches.md`.
|
|
263
|
+
- A read-source **migration** (endpoint swap, direct-query→RPC, table rename) must sweep the e2e offline-mock harness at BOTH sub-layers, not just the unit-test mocks: (1) every per-test `page.route("**/<old-path>*")` across `e2e/*.e2e.ts` (`git grep -nE '<old-endpoint>|rest/v1/<old-table>' e2e/`), AND (2) the base mock **server** `e2e/mock-supabase.ts` path handlers (a Node HTTP server with a 404 catch-all). Fix the base-server default FIRST (add a handler for the new path mirroring the old default, e.g. new RPC → `[]` like `/rest/v1/conversations` → `[]`) so every e2e file's empty-case is covered and only populated-fixture cases need per-test overrides. When the local OS can't run Playwright, validate harness edits with `tsc` + `playwright test <specs> --list` and rely on CI's containerized `e2e` job. **Why:** #6199 — the dashboard's `/api/kb/tree`→`/api/dashboard/foundation-status` + rail direct-query→`list_conversations_enriched` RPC swap left 4 e2e harness files stale; see `knowledge-base/project/learnings/integration-issues/2026-07-07-read-source-migration-must-sweep-e2e-offline-mock-harness.md`.
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# Browser-Readiness Preflight (unsupported-host guard)
|
|
2
|
+
|
|
3
|
+
Loaded by `qa`'s nav-states gate — run this BEFORE the first Playwright
|
|
4
|
+
invocation. On a host newer than the pinned Playwright officially supports
|
|
5
|
+
(e.g. Ubuntu 26.04 vs the `apps/web-platform` `@playwright/test` pin), a
|
|
6
|
+
plain `playwright install` fails with `does not support chromium ... on
|
|
7
|
+
<os>` and every test then dies at `browserType.launch: Executable doesn't
|
|
8
|
+
exist` **before any navigation** — the false-fail that repeatedly costs a
|
|
9
|
+
QA session its whole run. Recover automatically by retrying the install
|
|
10
|
+
with the host-platform override, which pulls the nearest supported fallback
|
|
11
|
+
build (verified `ubuntu26.04-x64` → `ubuntu24.04-x64`; once the fallback
|
|
12
|
+
build is in cache the launcher resolves it at runtime with NO override, so
|
|
13
|
+
the override stays out of the run command and can never leak onto a
|
|
14
|
+
supported host like CI's Jammy container):
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
cd apps/web-platform
|
|
18
|
+
QA_PW_LOG=$(mktemp -p "$(mktemp -d -t soleur-run.$$.XXXXXXXX)")
|
|
19
|
+
npx playwright install chromium >"$QA_PW_LOG" 2>&1 \
|
|
20
|
+
|| PLAYWRIGHT_HOST_PLATFORM_OVERRIDE=ubuntu24.04-x64 npx playwright install chromium
|
|
21
|
+
# on failure read it for the diagnosis, then `rm -f "$QA_PW_LOG"` (#10017).
|
|
22
|
+
```
|