@soleur/opencode 0.0.0-stage → 3.354.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/agents.manifest.json +476 -0
- package/.claude-plugin/plugin.json +42 -0
- package/README.md +44 -2
- package/agents/community/.gitkeep +0 -0
- package/agents/engineering/cto.md +87 -0
- package/agents/engineering/design/ddd-architect.md +95 -0
- package/agents/engineering/discovery/agent-finder.md +214 -0
- package/agents/engineering/discovery/functional-discovery.md +182 -0
- package/agents/engineering/infra/infra-security.md +151 -0
- package/agents/engineering/infra/platform-strategist.md +109 -0
- package/agents/engineering/infra/terraform-architect.md +171 -0
- package/agents/engineering/prompt-engineer.md +37 -0
- package/agents/engineering/research/best-practices-researcher.md +115 -0
- package/agents/engineering/research/framework-docs-researcher.md +93 -0
- package/agents/engineering/research/git-history-analyzer.md +53 -0
- package/agents/engineering/research/learnings-researcher.md +285 -0
- package/agents/engineering/research/repo-research-analyst.md +118 -0
- package/agents/engineering/review/agent-native-reviewer.md +279 -0
- package/agents/engineering/review/architecture-strategist.md +61 -0
- package/agents/engineering/review/code-quality-analyst.md +92 -0
- package/agents/engineering/review/code-simplicity-reviewer.md +109 -0
- package/agents/engineering/review/data-integrity-guardian.md +82 -0
- package/agents/engineering/review/data-migration-expert.md +98 -0
- package/agents/engineering/review/deployment-verification-agent.md +183 -0
- package/agents/engineering/review/dhh-rails-reviewer.md +46 -0
- package/agents/engineering/review/kieran-rails-reviewer.md +87 -0
- package/agents/engineering/review/legacy-code-expert.md +55 -0
- package/agents/engineering/review/observability-coverage-reviewer.md +147 -0
- package/agents/engineering/review/pattern-recognition-specialist.md +59 -0
- package/agents/engineering/review/performance-oracle.md +130 -0
- package/agents/engineering/review/security-sentinel.md +167 -0
- package/agents/engineering/review/semgrep-sast.md +36 -0
- package/agents/engineering/review/test-design-reviewer.md +150 -0
- package/agents/engineering/review/user-impact-reviewer.md +70 -0
- package/agents/engineering/workflow/pr-comment-resolver.md +69 -0
- package/agents/finance/budget-analyst.md +29 -0
- package/agents/finance/cfo.md +44 -0
- package/agents/finance/financial-reporter.md +30 -0
- package/agents/finance/revenue-analyst.md +30 -0
- package/agents/legal/clo.md +115 -0
- package/agents/legal/legal-compliance-auditor.md +110 -0
- package/agents/legal/legal-document-generator.md +134 -0
- package/agents/marketing/analytics-analyst.md +25 -0
- package/agents/marketing/brand-architect.md +181 -0
- package/agents/marketing/cmo.md +76 -0
- package/agents/marketing/conversion-optimizer.md +19 -0
- package/agents/marketing/copywriter.md +20 -0
- package/agents/marketing/fact-checker.md +70 -0
- package/agents/marketing/growth-strategist.md +145 -0
- package/agents/marketing/paid-media-strategist.md +28 -0
- package/agents/marketing/pricing-strategist.md +17 -0
- package/agents/marketing/programmatic-seo-specialist.md +25 -0
- package/agents/marketing/retention-strategist.md +23 -0
- package/agents/marketing/seo-aeo-analyst.md +164 -0
- package/agents/operations/coo.md +50 -0
- package/agents/operations/ops-advisor.md +78 -0
- package/agents/operations/ops-provisioner.md +101 -0
- package/agents/operations/ops-research.md +52 -0
- package/agents/operations/service-automator.md +278 -0
- package/agents/product/business-validator.md +206 -0
- package/agents/product/competitive-intelligence.md +89 -0
- package/agents/product/cpo.md +63 -0
- package/agents/product/design/ux-design-lead.md +209 -0
- package/agents/product/spec-flow-analyzer.md +122 -0
- package/agents/sales/cro.md +44 -0
- package/agents/sales/deal-architect.md +29 -0
- package/agents/sales/outbound-strategist.md +29 -0
- package/agents/sales/pipeline-analyst.md +29 -0
- package/agents/support/cco.md +48 -0
- package/agents/support/community-manager.md +570 -0
- package/agents/support/ticket-triage.md +70 -0
- package/bin/soleur-opencode.js +29 -0
- package/commands/go.md +660 -0
- package/commands/help.md +273 -0
- package/commands/sync.md +977 -0
- package/commands/version.md +103 -0
- package/hooks/antigravity-hooks.json +84 -0
- package/hooks/antigravity-session-start.sh +15 -0
- package/hooks/bare-root-cwd-guard.sh +131 -0
- package/hooks/browser-snapshot-credential-guard.sh +200 -0
- package/hooks/codex-session-start.sh +9 -0
- package/hooks/compaction-state.sh +525 -0
- package/hooks/destructive-command-guard.sh +1387 -0
- package/hooks/devin-session-start.sh +90 -0
- package/hooks/ext-filter-detect.sh +171 -0
- package/hooks/hooks.json +133 -0
- package/hooks/lib/hook-tool-kind.sh +24 -0
- package/hooks/lib/log-rotation.sh +176 -0
- package/hooks/lib/shell-argv.pl +576 -0
- package/hooks/memory-backstop.sh +1114 -0
- package/hooks/operator-stage-approval.sh +391 -0
- package/hooks/stop-hook.sh +367 -0
- package/hooks/unkept-promise-hook.sh +383 -0
- package/hooks/version-banner.sh +127 -0
- package/hooks/welcome-hook.sh +50 -0
- package/install.js +29 -0
- package/lib/agent-registry.ts +154 -0
- package/lib/c4-canonical-cli.mjs +34 -0
- package/lib/c4-canonical.mjs +46 -0
- package/lib/c4-from-components.ts +554 -0
- package/lib/go-routing.ts +81 -0
- package/lib/grok-inspect-contract.ts +311 -0
- package/lib/harness-model-map.ts +101 -0
- package/lib/harness-parity.ts +726 -0
- package/lib/harness-tool-map.ts +180 -0
- package/lib/harness.ts +716 -0
- package/lib/heartbeat-live-reconcile.ts +1153 -0
- package/lib/heartbeat-manifest.ts +361 -0
- package/lib/kb-coverage.ts +252 -0
- package/lib/pr-merge-poll.ts +103 -0
- package/lib/workflow-fidelity.ts +388 -0
- package/opencode/INSTRUCTIONS.md +171 -0
- package/opencode/agents/engineering/cto.md +10 -0
- package/opencode/agents/engineering/design/ddd-architect.md +10 -0
- package/opencode/agents/engineering/discovery/agent-finder.md +10 -0
- package/opencode/agents/engineering/discovery/functional-discovery.md +10 -0
- package/opencode/agents/engineering/infra/infra-security.md +10 -0
- package/opencode/agents/engineering/infra/platform-strategist.md +10 -0
- package/opencode/agents/engineering/infra/terraform-architect.md +10 -0
- package/opencode/agents/engineering/prompt-engineer.md +10 -0
- package/opencode/agents/engineering/research/best-practices-researcher.md +10 -0
- package/opencode/agents/engineering/research/framework-docs-researcher.md +10 -0
- package/opencode/agents/engineering/research/git-history-analyzer.md +10 -0
- package/opencode/agents/engineering/research/learnings-researcher.md +10 -0
- package/opencode/agents/engineering/research/repo-research-analyst.md +10 -0
- package/opencode/agents/engineering/review/agent-native-reviewer.md +10 -0
- package/opencode/agents/engineering/review/architecture-strategist.md +10 -0
- package/opencode/agents/engineering/review/code-quality-analyst.md +10 -0
- package/opencode/agents/engineering/review/code-simplicity-reviewer.md +10 -0
- package/opencode/agents/engineering/review/data-integrity-guardian.md +10 -0
- package/opencode/agents/engineering/review/data-migration-expert.md +10 -0
- package/opencode/agents/engineering/review/deployment-verification-agent.md +10 -0
- package/opencode/agents/engineering/review/dhh-rails-reviewer.md +10 -0
- package/opencode/agents/engineering/review/kieran-rails-reviewer.md +10 -0
- package/opencode/agents/engineering/review/legacy-code-expert.md +10 -0
- package/opencode/agents/engineering/review/observability-coverage-reviewer.md +10 -0
- package/opencode/agents/engineering/review/pattern-recognition-specialist.md +10 -0
- package/opencode/agents/engineering/review/performance-oracle.md +10 -0
- package/opencode/agents/engineering/review/security-sentinel.md +10 -0
- package/opencode/agents/engineering/review/semgrep-sast.md +10 -0
- package/opencode/agents/engineering/review/test-design-reviewer.md +10 -0
- package/opencode/agents/engineering/review/user-impact-reviewer.md +10 -0
- package/opencode/agents/engineering/workflow/pr-comment-resolver.md +10 -0
- package/opencode/agents/finance/budget-analyst.md +10 -0
- package/opencode/agents/finance/cfo.md +10 -0
- package/opencode/agents/finance/financial-reporter.md +10 -0
- package/opencode/agents/finance/revenue-analyst.md +10 -0
- package/opencode/agents/legal/clo.md +10 -0
- package/opencode/agents/legal/legal-compliance-auditor.md +10 -0
- package/opencode/agents/legal/legal-document-generator.md +10 -0
- package/opencode/agents/marketing/analytics-analyst.md +10 -0
- package/opencode/agents/marketing/brand-architect.md +10 -0
- package/opencode/agents/marketing/cmo.md +10 -0
- package/opencode/agents/marketing/conversion-optimizer.md +10 -0
- package/opencode/agents/marketing/copywriter.md +10 -0
- package/opencode/agents/marketing/fact-checker.md +10 -0
- package/opencode/agents/marketing/growth-strategist.md +10 -0
- package/opencode/agents/marketing/paid-media-strategist.md +10 -0
- package/opencode/agents/marketing/pricing-strategist.md +10 -0
- package/opencode/agents/marketing/programmatic-seo-specialist.md +10 -0
- package/opencode/agents/marketing/retention-strategist.md +10 -0
- package/opencode/agents/marketing/seo-aeo-analyst.md +10 -0
- package/opencode/agents/operations/coo.md +10 -0
- package/opencode/agents/operations/ops-advisor.md +10 -0
- package/opencode/agents/operations/ops-provisioner.md +10 -0
- package/opencode/agents/operations/ops-research.md +10 -0
- package/opencode/agents/operations/service-automator.md +10 -0
- package/opencode/agents/product/business-validator.md +10 -0
- package/opencode/agents/product/competitive-intelligence.md +10 -0
- package/opencode/agents/product/cpo.md +10 -0
- package/opencode/agents/product/design/ux-design-lead.md +10 -0
- package/opencode/agents/product/spec-flow-analyzer.md +10 -0
- package/opencode/agents/sales/cro.md +10 -0
- package/opencode/agents/sales/deal-architect.md +10 -0
- package/opencode/agents/sales/outbound-strategist.md +10 -0
- package/opencode/agents/sales/pipeline-analyst.md +10 -0
- package/opencode/agents/support/cco.md +10 -0
- package/opencode/agents/support/community-manager.md +10 -0
- package/opencode/agents/support/ticket-triage.md +10 -0
- package/opencode/commands/go.md +10 -0
- package/opencode/commands/help.md +10 -0
- package/opencode/commands/sync.md +10 -0
- package/opencode/commands/version.md +11 -0
- package/opencode/opencode.json +8 -0
- package/opencode/plugin.ts +818 -0
- package/package.json +36 -4
- package/scripts/admin-merge-ready.sh +545 -0
- package/scripts/admin-merge-ready.test.sh +753 -0
- package/scripts/affected-tests.sh +908 -0
- package/scripts/affected-tests.test.sh +1797 -0
- package/scripts/alpha-metrics.sh +78 -0
- package/scripts/alpha-metrics.test.sh +115 -0
- package/scripts/ancestor-signal-helpers.baseline.txt +16 -0
- package/scripts/audit-flag-flip.sh +107 -0
- package/scripts/check-red-on-main.sh +316 -0
- package/scripts/ci-head-verdict.sh +411 -0
- package/scripts/cloud-detect.sh +193 -0
- package/scripts/delegation-verify.sh +657 -0
- package/scripts/delegation-verify.test.sh +1424 -0
- package/scripts/deploy-arm.sh +475 -0
- package/scripts/domain-model-drift.sh +419 -0
- package/scripts/emit-decision.sh +144 -0
- package/scripts/emit-decision.test.sh +144 -0
- package/scripts/ext-filter-divergence-corpus.txt +15 -0
- package/scripts/ext-filter-divergence.sh +189 -0
- package/scripts/generate-c4-from-components.ts +442 -0
- package/scripts/grok-fidelity-gate.sh +68 -0
- package/scripts/grok-pre-push-gate.sh +232 -0
- package/scripts/harness-discovery-smoke.ts +906 -0
- package/scripts/harness-parity-census.ts +92 -0
- package/scripts/inngest-luks-alert-armed-probe.ts +29 -0
- package/scripts/install-opencode-adapter.ts +509 -0
- package/scripts/lib/affected-tests/common.sh +365 -0
- package/scripts/lib/affected-tests/go.sh +157 -0
- package/scripts/lib/affected-tests/js.sh +188 -0
- package/scripts/lib/affected-tests/nx-turbo.sh +98 -0
- package/scripts/lib/affected-tests/python.sh +185 -0
- package/scripts/lib/context-sanitize.sh +49 -0
- package/scripts/lib/domain-model-lib.sh +180 -0
- package/scripts/lib/ext-filter-grammar.tsv +34 -0
- package/scripts/lib/operator-script.sh +1236 -0
- package/scripts/lib/proc.sh +580 -0
- package/scripts/lib/session-state.sh +748 -0
- package/scripts/lib/tmp-classify.sh +843 -0
- package/scripts/lib/wrapper-boundary.sh +47 -0
- package/scripts/lint-ratchet.py +1547 -0
- package/scripts/monitor-pr-checks.sh +441 -0
- package/scripts/pipeline-tally.sh +756 -0
- package/scripts/pipeline-tally.test.sh +740 -0
- package/scripts/plugin-version.sh +528 -0
- package/scripts/precommit-guard.sh +115 -0
- package/scripts/precommit-guard.test.sh +254 -0
- package/scripts/reconcile-live-heartbeats.ts +705 -0
- package/scripts/render-c4-model.sh +217 -0
- package/scripts/resolve-git-root.sh +55 -0
- package/scripts/resolve-regenerable-conflicts.sh +363 -0
- package/scripts/resolve-regenerable-conflicts.test.sh +780 -0
- package/scripts/ruff-requirements.txt +22 -0
- package/scripts/run-in-pid-namespace.sh +98 -0
- package/scripts/run-in-pid-namespace.test.sh +290 -0
- package/scripts/scan-ancestor-signal-helpers.py +556 -0
- package/scripts/scan-ancestor-signal-helpers.test.sh +670 -0
- package/scripts/setup-ralph-loop.sh +238 -0
- package/scripts/sync-cursor-name-map.ts +316 -0
- package/scripts/sync-grok-agent-compat.ts +188 -0
- package/scripts/sync-npm-package.ts +165 -0
- package/scripts/sync-opencode-adapter.ts +498 -0
- package/scripts/sync-pr-behind.sh +647 -0
- package/scripts/sync-pr-behind.test.sh +252 -0
- package/scripts/taste-profile-update.sh +180 -0
- package/scripts/taste-profile-update.test.sh +167 -0
- package/scripts/write-budget-marker.sh +23 -0
- package/scripts/write-kb-coverage.ts +113 -0
- package/skills/admin-ip-refresh/SKILL.md +81 -0
- package/skills/admin-ip-refresh/references/admin-ip-refresh-procedure.md +201 -0
- package/skills/agent-browser/SKILL.md +698 -0
- package/skills/agent-browser/scripts/playwright-mcp-profile-slot.sh +304 -0
- package/skills/agent-browser/scripts/playwright-mcp-redact-proxy.py +964 -0
- package/skills/agent-browser/scripts/redact-a11y-snapshot.py +443 -0
- package/skills/agent-browser/test/fixtures/capture-playwright-mcp-fixtures.py +217 -0
- package/skills/agent-browser/test/fixtures/fake-passthrough-proxy.py +24 -0
- package/skills/agent-browser/test/fixtures/fake-playwright-mcp.py +131 -0
- package/skills/agent-browser/test/fixtures/make-proxy-mutant.py +48 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/dialog-link-injection.json +10 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/empty-content.json +5 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/error-and-result.json +4 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/error-code-bool.json +6 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/error-code-string.json +6 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/error-message-tree.json +6 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/error-no-data.json +6 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/error-string.json +4 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/error-with-data.json +9 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/evaluate-escaped-object.json +10 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/invalid-utf8.json +4 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/link-result.json +10 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/list-two-results.json +6 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/meta-in-result.json +13 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/no-content.json +5 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/quoted-key.json +10 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/resource-block.json +18 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/result-and-method.json +11 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/result-string.json +3 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/run-code-escaped-one-row.json +10 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/run-code-escaped.json +10 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/structured-content.json +13 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/tools-list-no-tools.json +5 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/tree-no-credential.json +10 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/two-text-blocks.json +14 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/unparsable-line.json +3 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/value-contains-brace.json +10 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/value-contains-link-substring.json +10 -0
- package/skills/agent-browser/test/fixtures/playwright-mcp-0.0.78/close.json +12 -0
- package/skills/agent-browser/test/fixtures/playwright-mcp-0.0.78/evaluate.json +12 -0
- package/skills/agent-browser/test/fixtures/playwright-mcp-0.0.78/find.json +12 -0
- package/skills/agent-browser/test/fixtures/playwright-mcp-0.0.78/framing.json +6 -0
- package/skills/agent-browser/test/fixtures/playwright-mcp-0.0.78/initialize.json +14 -0
- package/skills/agent-browser/test/fixtures/playwright-mcp-0.0.78/navigate-link.json +12 -0
- package/skills/agent-browser/test/fixtures/playwright-mcp-0.0.78/navigate.json +12 -0
- package/skills/agent-browser/test/fixtures/playwright-mcp-0.0.78/roots-list-request.json +5 -0
- package/skills/agent-browser/test/fixtures/playwright-mcp-0.0.78/screenshot.json +17 -0
- package/skills/agent-browser/test/fixtures/playwright-mcp-0.0.78/snapshot-filename.json +12 -0
- package/skills/agent-browser/test/fixtures/playwright-mcp-0.0.78/snapshot-meta-json.json +12 -0
- package/skills/agent-browser/test/fixtures/playwright-mcp-0.0.78/snapshot-meta-raw.json +12 -0
- package/skills/agent-browser/test/fixtures/playwright-mcp-0.0.78/snapshot.json +12 -0
- package/skills/agent-browser/test/fixtures/playwright-mcp-0.0.78/tools-list.json +827 -0
- package/skills/agent-browser/test/fixtures/proxy-session-driver.py +138 -0
- package/skills/agent-browser/test/fixtures/session-facts.py +102 -0
- package/skills/agent-browser/test/playwright-mcp-lifetime.test.sh +1620 -0
- package/skills/agent-browser/test/playwright-mcp-redact-proxy.test.sh +1599 -0
- package/skills/agent-browser/test/redact-a11y-snapshot.test.sh +527 -0
- package/skills/agent-native-architecture/SKILL.md +479 -0
- package/skills/agent-native-architecture/references/action-parity-discipline.md +430 -0
- package/skills/agent-native-architecture/references/agent-execution-patterns.md +483 -0
- package/skills/agent-native-architecture/references/agent-native-testing.md +605 -0
- package/skills/agent-native-architecture/references/architecture-patterns.md +493 -0
- package/skills/agent-native-architecture/references/dynamic-context-injection.md +358 -0
- package/skills/agent-native-architecture/references/files-universal-interface.md +314 -0
- package/skills/agent-native-architecture/references/from-primitives-to-domain-tools.md +381 -0
- package/skills/agent-native-architecture/references/mcp-tool-design.md +524 -0
- package/skills/agent-native-architecture/references/mobile-patterns.md +897 -0
- package/skills/agent-native-architecture/references/product-implications.md +478 -0
- package/skills/agent-native-architecture/references/refactoring-to-prompt-native.md +342 -0
- package/skills/agent-native-architecture/references/self-modification.md +294 -0
- package/skills/agent-native-architecture/references/shared-workspace-architecture.md +700 -0
- package/skills/agent-native-architecture/references/system-prompt-design.md +263 -0
- package/skills/agent-native-audit/SKILL.md +300 -0
- package/skills/agent-native-audit/workflows/agent-native-audit.workflow.js +423 -0
- package/skills/andrew-kane-gem-writer/SKILL.md +189 -0
- package/skills/andrew-kane-gem-writer/references/database-adapters.md +231 -0
- package/skills/andrew-kane-gem-writer/references/module-organization.md +121 -0
- package/skills/andrew-kane-gem-writer/references/rails-integration.md +183 -0
- package/skills/andrew-kane-gem-writer/references/resources.md +126 -0
- package/skills/andrew-kane-gem-writer/references/testing-patterns.md +261 -0
- package/skills/architecture/SKILL.md +436 -0
- package/skills/architecture/references/adr-template.md +154 -0
- package/skills/architecture/references/likec4-reference.md +136 -0
- package/skills/architecture/references/nfr-reference.md +126 -0
- package/skills/archive-kb/SKILL.md +86 -0
- package/skills/archive-kb/scripts/archive-kb.sh +300 -0
- package/skills/archive-kb/test/archive-kb-partial-run.test.sh +276 -0
- package/skills/atdd-developer/SKILL.md +65 -0
- package/skills/brainstorm/SKILL.md +701 -0
- package/skills/brainstorm/references/brainstorm-brand-workshop.md +153 -0
- package/skills/brainstorm/references/brainstorm-domain-config.md +63 -0
- package/skills/brainstorm/references/brainstorm-validation-workshop.md +65 -0
- package/skills/brainstorm/references/ui-surface-terms.md +42 -0
- package/skills/brainstorm-techniques/SKILL.md +231 -0
- package/skills/brainstorm-techniques/references/decision-principles.md +150 -0
- package/skills/brainstorm-techniques/references/phase-boundaries.md +103 -0
- package/skills/brainstorm-techniques/references/standing-delegation.md +407 -0
- package/skills/brainstorm-techniques/references/technical-ruling-delegation.md +174 -0
- package/skills/campaign-calendar/SKILL.md +145 -0
- package/skills/cf-token-scope/SKILL.md +164 -0
- package/skills/cf-token-scope/references/widen-playbook.md +114 -0
- package/skills/cf-token-scope/scripts/cf-token-scope.sh +253 -0
- package/skills/changelog/SKILL.md +142 -0
- package/skills/code-to-prd/SKILL.md +66 -0
- package/skills/code-to-prd/references/banner-template.md +12 -0
- package/skills/code-to-prd/references/prd-template.md +41 -0
- package/skills/code-to-prd/scripts/code-to-prd.sh +634 -0
- package/skills/code-to-prd/test/code-to-prd.test.sh +447 -0
- package/skills/code-to-prd/test/fixture/.env.example +7 -0
- package/skills/code-to-prd/test/fixture/app/about/page.tsx +11 -0
- package/skills/code-to-prd/test/fixture/app/api/health/route.ts +10 -0
- package/skills/code-to-prd/test/fixture/app/page.tsx +14 -0
- package/skills/code-to-prd/test/fixture/next.config.mjs +3 -0
- package/skills/code-to-prd/test/fixture/package.json +6 -0
- package/skills/cohort-status/SKILL.md +62 -0
- package/skills/community/SKILL.md +210 -0
- package/skills/community/scripts/bsky-community.sh +644 -0
- package/skills/community/scripts/bsky-setup.sh +631 -0
- package/skills/community/scripts/community-router.sh +93 -0
- package/skills/community/scripts/discord-community.sh +487 -0
- package/skills/community/scripts/discord-setup.sh +784 -0
- package/skills/community/scripts/github-community.sh +706 -0
- package/skills/community/scripts/hn-community.sh +233 -0
- package/skills/community/scripts/lib/hmac-sha1-b64.sh +126 -0
- package/skills/community/scripts/linkedin-community.sh +750 -0
- package/skills/community/scripts/linkedin-setup.sh +758 -0
- package/skills/community/scripts/x-community.sh +890 -0
- package/skills/community/scripts/x-setup.sh +713 -0
- package/skills/community/test/community-argv.test.sh +2922 -0
- package/skills/community/test/github-community.test.sh +981 -0
- package/skills/competitive-analysis/SKILL.md +69 -0
- package/skills/competitive-analysis/references/peer-plugin-audit.md +218 -0
- package/skills/compound/SKILL.md +673 -0
- package/skills/compound/scripts/token-efficiency-report.sh +334 -0
- package/skills/compound/test/phase-16.test.sh +379 -0
- package/skills/compound-capture/SKILL.md +791 -0
- package/skills/compound-capture/assets/critical-pattern-template.md +37 -0
- package/skills/compound-capture/assets/resolution-template.md +116 -0
- package/skills/compound-capture/references/yaml-schema.md +67 -0
- package/skills/compound-capture/schema.yaml +181 -0
- package/skills/constraint-scaffold/SKILL.md +175 -0
- package/skills/constraint-scaffold/references/boundary-readme.template +35 -0
- package/skills/constraint-scaffold/references/constraint-gates-workflow.template +69 -0
- package/skills/constraint-scaffold/references/depcruise-config.template +230 -0
- package/skills/constraint-scaffold/references/fix-constraints-stage-a.template +240 -0
- package/skills/constraint-scaffold/references/fix-constraints-stage-b.template +313 -0
- package/skills/constraint-scaffold/references/shared-runner.template +135 -0
- package/skills/constraint-scaffold/scripts/constraint-scaffold.sh +589 -0
- package/skills/constraint-scaffold/test/bite-proof.test.sh +1338 -0
- package/skills/constraint-scaffold/test/boundary.test.sh +734 -0
- package/skills/constraint-scaffold/test/emit-fix-constraints.test.sh +193 -0
- package/skills/constraint-scaffold/test/generator.test.sh +93 -0
- package/skills/constraint-scaffold/test/parity.test.sh +285 -0
- package/skills/content-writer/SKILL.md +242 -0
- package/skills/content-writer/scripts/blog-jargon-scan.sh +42 -0
- package/skills/cron-delete/SKILL.md +56 -0
- package/skills/cron-list/SKILL.md +54 -0
- package/skills/deepen-plan/SKILL.md +937 -0
- package/skills/deepen-plan/workflows/deepen-plan.workflow.js +488 -0
- package/skills/deploy/SKILL.md +115 -0
- package/skills/deploy/references/hetzner-setup.md +67 -0
- package/skills/deploy/scripts/deploy.sh +37 -0
- package/skills/deploy-docs/SKILL.md +95 -0
- package/skills/dhh-rails-style/SKILL.md +203 -0
- package/skills/dhh-rails-style/references/architecture.md +717 -0
- package/skills/dhh-rails-style/references/controllers.md +323 -0
- package/skills/dhh-rails-style/references/frontend.md +556 -0
- package/skills/dhh-rails-style/references/gems.md +316 -0
- package/skills/dhh-rails-style/references/models.md +388 -0
- package/skills/dhh-rails-style/references/testing.md +354 -0
- package/skills/discord-content/SKILL.md +126 -0
- package/skills/docs-site/SKILL.md +214 -0
- package/skills/drain-labeled-backlog/SKILL.md +203 -0
- package/skills/drain-labeled-backlog/scripts/group-by-area.sh +208 -0
- package/skills/drain-labeled-backlog/workflows/drain-labeled-backlog.workflow.js +433 -0
- package/skills/drain-prs/SKILL.md +143 -0
- package/skills/drain-prs/scripts/triage-prs.sh +192 -0
- package/skills/drain-prs/test/argv-ceiling.test.sh +183 -0
- package/skills/dspy-ruby/SKILL.md +634 -0
- package/skills/dspy-ruby/assets/config-template.rb +359 -0
- package/skills/dspy-ruby/assets/module-template.rb +326 -0
- package/skills/dspy-ruby/assets/signature-template.rb +143 -0
- package/skills/dspy-ruby/references/core-concepts.md +268 -0
- package/skills/dspy-ruby/references/optimization.md +623 -0
- package/skills/dspy-ruby/references/providers.md +335 -0
- package/skills/eval-harness/README.md +194 -0
- package/skills/eval-harness/SKILL.md +157 -0
- package/skills/eval-harness/enums/go-routes.json +13 -0
- package/skills/eval-harness/enums/incident-threshold.json +5 -0
- package/skills/eval-harness/enums/lane.json +5 -0
- package/skills/eval-harness/enums/tool-selection.json +20 -0
- package/skills/eval-harness/enums/triage-levels.json +5 -0
- package/skills/eval-harness/gated-skills.json +34 -0
- package/skills/eval-harness/models.generated.json +5 -0
- package/skills/eval-harness/promptfooconfig-go-routing.yaml +35 -0
- package/skills/eval-harness/promptfooconfig-incident-threshold.yaml +32 -0
- package/skills/eval-harness/promptfooconfig-lane-inference.yaml +33 -0
- package/skills/eval-harness/promptfooconfig-ticket-triage.yaml +34 -0
- package/skills/eval-harness/promptfooconfig-tool-selection.yaml +33 -0
- package/skills/eval-harness/prompts/go-baseline.txt +6 -0
- package/skills/eval-harness/prompts/go-skill.txt +21 -0
- package/skills/eval-harness/prompts/incident-threshold-baseline.txt +6 -0
- package/skills/eval-harness/prompts/incident-threshold-skill.txt +12 -0
- package/skills/eval-harness/prompts/lane-inference-baseline.txt +6 -0
- package/skills/eval-harness/prompts/lane-inference-skill.txt +15 -0
- package/skills/eval-harness/prompts/tool-selection-baseline.txt +19 -0
- package/skills/eval-harness/prompts/tool-selection-skill.txt +22 -0
- package/skills/eval-harness/prompts/triage-baseline.txt +7 -0
- package/skills/eval-harness/prompts/triage-skill.txt +10 -0
- package/skills/eval-harness/scripts/eval-gate.cjs +318 -0
- package/skills/eval-harness/scripts/extract-block.cjs +87 -0
- package/skills/eval-harness/scripts/gate-classification.cjs +28 -0
- package/skills/eval-harness/scripts/gen-models.sh +41 -0
- package/skills/eval-harness/scripts/gen-skill-prompt.cjs +177 -0
- package/skills/eval-harness/scripts/measure-classification.cjs +30 -0
- package/skills/eval-harness/scripts/parse-label.cjs +93 -0
- package/skills/eval-harness/scripts/verdict.cjs +132 -0
- package/skills/eval-harness/tasks/go-routing.jsonl +8 -0
- package/skills/eval-harness/tasks/incident-threshold.jsonl +7 -0
- package/skills/eval-harness/tasks/lane-inference.jsonl +7 -0
- package/skills/eval-harness/tasks/ticket-triage.jsonl +6 -0
- package/skills/eval-harness/tasks/tool-selection.jsonl +15 -0
- package/skills/eval-harness/test/eval-gate.test.sh +132 -0
- package/skills/eval-harness/test/extract-block.test.sh +87 -0
- package/skills/eval-harness/test/gate-classification.test.sh +77 -0
- package/skills/eval-harness/test/gen-models.test.sh +75 -0
- package/skills/eval-harness/test/measure-classification.test.sh +74 -0
- package/skills/eval-harness/test/parse-label.test.sh +129 -0
- package/skills/eval-harness/test/registry-completeness.test.sh +109 -0
- package/skills/eval-harness/test/verdict.test.sh +123 -0
- package/skills/every-style-editor/SKILL.md +142 -0
- package/skills/every-style-editor/references/EVERY_WRITE_STYLE.md +529 -0
- package/skills/feature-tweet/SKILL.md +199 -0
- package/skills/feature-video/SKILL.md +412 -0
- package/skills/feature-video/scripts/check_deps.sh +281 -0
- package/skills/file-todos/SKILL.md +267 -0
- package/skills/file-todos/assets/todo-template.md +166 -0
- package/skills/fix-issue/SKILL.md +278 -0
- package/skills/fix-issue/references/agent-authored-exclusion.md +120 -0
- package/skills/fix-issue/references/exclude-label-jq-snippet.md +97 -0
- package/skills/flag-bootstrap/SETUP.md +142 -0
- package/skills/flag-create/SKILL.md +145 -0
- package/skills/flag-create/scripts/create.sh +273 -0
- package/skills/flag-delete/SKILL.md +167 -0
- package/skills/flag-delete/scripts/delete.sh +288 -0
- package/skills/flag-list/SKILL.md +99 -0
- package/skills/flag-list/scripts/list.sh +275 -0
- package/skills/flag-set-role/SKILL.md +229 -0
- package/skills/flag-set-role/scripts/flip.sh +774 -0
- package/skills/frontend-anti-slop/SKILL.md +106 -0
- package/skills/frontend-anti-slop/references/anti-patterns.md +199 -0
- package/skills/frontend-anti-slop/references/slop-rules.md +65 -0
- package/skills/frontend-anti-slop/scripts/tier1-scan.ts +525 -0
- package/skills/frontend-design/SKILL.md +77 -0
- package/skills/gdpr-gate/NOTICE +136 -0
- package/skills/gdpr-gate/SKILL.md +341 -0
- package/skills/gdpr-gate/references/fields.md +160 -0
- package/skills/gdpr-gate/references/layers/api-layer.md +355 -0
- package/skills/gdpr-gate/references/layers/auth-sessions.md +290 -0
- package/skills/gdpr-gate/references/layers/data-in-transit.md +331 -0
- package/skills/gdpr-gate/references/layers/data-lifecycle.md +341 -0
- package/skills/gdpr-gate/references/layers/frontend.md +249 -0
- package/skills/gdpr-gate/references/layers/testing-seeding.md +256 -0
- package/skills/gdpr-gate/references/leakage-vectors.md +248 -0
- package/skills/gdpr-gate/references/legacy/legal-consent-v1-prose.md +48 -0
- package/skills/gdpr-gate/references/legal-consent.md +140 -0
- package/skills/gdpr-gate/references/non-negotiables.md +60 -0
- package/skills/gdpr-gate/scripts/gdpr-gate.sh +271 -0
- package/skills/gdpr-gate/scripts/notice-frontmatter.sh +337 -0
- package/skills/gdpr-gate/scripts/path-denylist.txt +39 -0
- package/skills/gdpr-gate/scripts/repo-scan.sh +158 -0
- package/skills/gdpr-gate/scripts/vendor-drift-classify.sh +120 -0
- package/skills/gdpr-gate/scripts/vendor-pin-integrity.sh +237 -0
- package/skills/gemini-imagegen/SKILL.md +283 -0
- package/skills/gemini-imagegen/requirements.txt +5 -0
- package/skills/gemini-imagegen/scripts/_error_handling.py +146 -0
- package/skills/gemini-imagegen/scripts/compose_images.py +150 -0
- package/skills/gemini-imagegen/scripts/edit_image.py +137 -0
- package/skills/gemini-imagegen/scripts/gemini_images.py +256 -0
- package/skills/gemini-imagegen/scripts/generate_image.py +147 -0
- package/skills/gemini-imagegen/scripts/multi_turn_chat.py +223 -0
- package/skills/gemini-imagegen/scripts/test_error_handling.py +179 -0
- package/skills/git-worktree/SKILL.md +534 -0
- package/skills/git-worktree/scripts/git-repo-readiness-diag.sh +98 -0
- package/skills/git-worktree/scripts/worktree-manager.sh +4773 -0
- package/skills/git-worktree/test/create-from-origin-main.test.sh +116 -0
- package/skills/git-worktree/test/lease-protects-active.test.sh +1056 -0
- package/skills/git-worktree/test/no-repo-fail-loud.test.sh +88 -0
- package/skills/git-worktree/test/orphan-reaper-honest-count.test.sh +379 -0
- package/skills/git-worktree/test/reap-archive-persistence.test.sh +725 -0
- package/skills/git-worktree/test/stale-lock-sweep.test.sh +176 -0
- package/skills/go/SKILL.md +54 -0
- package/skills/growth/SKILL.md +164 -0
- package/skills/harvest-debt/SKILL.md +78 -0
- package/skills/harvest-debt/scripts/harvest-debt.sh +114 -0
- package/skills/heal-skill/SKILL.md +173 -0
- package/skills/help/SKILL.md +46 -0
- package/skills/incident/NOTICE +39 -0
- package/skills/incident/SKILL.md +395 -0
- package/skills/incident/scripts/dry-run.sh +448 -0
- package/skills/incident/scripts/redact-engine.py +412 -0
- package/skills/incident/scripts/redact-sentinel.sh +44 -0
- package/skills/incident/templates/pir.md +139 -0
- package/skills/incident/test/fixtures/dry-run-incident.json +26 -0
- package/skills/incident/test/fixtures/dry-run-secret-leak.json +26 -0
- package/skills/incident/test/fixtures/legacy-bash-scanner.sh +82 -0
- package/skills/incident/test/fixtures/positive-corpus.md +87 -0
- package/skills/incident/test/redact-sentinel.test.sh +1420 -0
- package/skills/invoice/SKILL.md +206 -0
- package/skills/kb-glossary/SKILL.md +71 -0
- package/skills/kb-glossary/references/glossary-format.md +111 -0
- package/skills/kb-glossary/references/rejected-request-register.md +115 -0
- package/skills/kb-search/SKILL.md +276 -0
- package/skills/kb-search/scripts/kb-search-cache.sh +123 -0
- package/skills/legal-audit/SKILL.md +161 -0
- package/skills/legal-generate/NOTICE +242 -0
- package/skills/legal-generate/SKILL.md +244 -0
- package/skills/legal-generate/references/templates/advisor-agreement/template.md +12 -0
- package/skills/legal-generate/references/templates/business-associate-agreement/template.md +112 -0
- package/skills/legal-generate/references/templates/cookie-notice/template.md +82 -0
- package/skills/legal-generate/references/templates/dpa-global/template.md +439 -0
- package/skills/legal-generate/references/templates/dpa-us/template.md +222 -0
- package/skills/legal-generate/references/templates/employee-offer-letter/template.md +75 -0
- package/skills/legal-generate/references/templates/master-services-agreement/template.md +252 -0
- package/skills/legal-generate/references/templates/mutual-nda/template.md +66 -0
- package/skills/legal-generate/references/templates/one-way-nda/template.md +38 -0
- package/skills/legal-generate/references/templates/privacy-policy-gdpr/template.md +427 -0
- package/skills/legal-generate/references/templates/privacy-policy-us/template.md +313 -0
- package/skills/legal-generate/references/templates/terms-of-use/template.md +75 -0
- package/skills/legal-generate/scripts/strip-vendor-credit.sh +96 -0
- package/skills/linear-fetch/SKILL.md +247 -0
- package/skills/linear-fetch/scripts/assert-no-linear-telemetry.sh +66 -0
- package/skills/linear-fetch/scripts/redact-linear-urls.sh +51 -0
- package/skills/linear-fetch/scripts/render-caller-template.sh +36 -0
- package/skills/linear-fetch/test/assert-no-linear-telemetry.test.sh +113 -0
- package/skills/linear-fetch/test/parity.test.sh +112 -0
- package/skills/linear-fetch/test/persist-safe-integration.test.sh +191 -0
- package/skills/linear-fetch/test/redact-linear-urls.test.sh +226 -0
- package/skills/merge-pr/SKILL.md +670 -0
- package/skills/model-launch-review/SKILL.md +255 -0
- package/skills/model-launch-review/scripts/audit-models.sh +501 -0
- package/skills/one-shot/SKILL.md +316 -0
- package/skills/one-shot/references/token-discipline.md +74 -0
- package/skills/operator-bootstrap/SKILL.md +412 -0
- package/skills/operator-bootstrap/template.sh +439 -0
- package/skills/operator-digest/SKILL.md +287 -0
- package/skills/operator-digest/assets/operator-digest.workflow.yml +175 -0
- package/skills/operator-digest/scripts/digest-scrub.sh +119 -0
- package/skills/operator-digest/scripts/provision-operator-digest-repo.sh +147 -0
- package/skills/operator-rephrase/SKILL.md +98 -0
- package/skills/pencil-setup/SKILL.md +201 -0
- package/skills/pencil-setup/scripts/check_deps.sh +556 -0
- package/skills/pencil-setup/scripts/copy_adapter.sh +80 -0
- package/skills/pencil-setup/scripts/package-lock.json +1172 -0
- package/skills/pencil-setup/scripts/package.json +14 -0
- package/skills/pencil-setup/scripts/pencil-error-enrichment.mjs +21 -0
- package/skills/pencil-setup/scripts/pencil-mcp-adapter.mjs +733 -0
- package/skills/pencil-setup/scripts/pencil-response-classify.mjs +38 -0
- package/skills/pencil-setup/scripts/pencil-save-gate.mjs +26 -0
- package/skills/pencil-setup/scripts/sanitize-filename.mjs +25 -0
- package/skills/plan/SKILL.md +1140 -0
- package/skills/plan/references/differential-migration-testing.md +185 -0
- package/skills/plan/references/plan-community-discovery.md +42 -0
- package/skills/plan/references/plan-founder-check.md +137 -0
- package/skills/plan/references/plan-functional-overlap.md +25 -0
- package/skills/plan/references/plan-host-fanout.md +51 -0
- package/skills/plan/references/plan-issue-templates.md +779 -0
- package/skills/plan/references/plan-network-outage-checklist.md +131 -0
- package/skills/plan/references/plan-scope-check.md +126 -0
- package/skills/plan/references/plan-sharp-edges.md +331 -0
- package/skills/plan/references/plan-signoff-lifecycle.md +12 -0
- package/skills/plan/references/webapp-cwv-observability.md +143 -0
- package/skills/plan-review/SKILL.md +91 -0
- package/skills/plan-review/lib/named-panel.mjs +58 -0
- package/skills/plan-review/workflows/plan-review.workflow.js +477 -0
- package/skills/postmerge/SKILL.md +642 -0
- package/skills/postmerge/references/deploy-status-debugging.md +141 -0
- package/skills/postmerge/references/graceful-degradation.md +20 -0
- package/skills/postmerge/references/sentry-error-count-delta.md +137 -0
- package/skills/preflight/SKILL.md +1553 -0
- package/skills/preflight/references/check-13-founder-check.md +286 -0
- package/skills/preflight/scripts/founder-check.py +1640 -0
- package/skills/preflight/scripts/parse-form-a.awk +107 -0
- package/skills/preflight/scripts/probe-verb-gate.sh +108 -0
- package/skills/product-roadmap/SKILL.md +357 -0
- package/skills/product-roadmap/scripts/roadmap-reconcile.sh +327 -0
- package/skills/provision-cloudflare/SKILL.md +67 -0
- package/skills/provision-cloudflare/scripts/provision-cloudflare.sh +271 -0
- package/skills/provision-doppler/SKILL.md +58 -0
- package/skills/provision-doppler/scripts/provision-doppler.sh +358 -0
- package/skills/provision-github/SKILL.md +59 -0
- package/skills/provision-github/scripts/provision-github.sh +300 -0
- package/skills/provision-hetzner/SKILL.md +76 -0
- package/skills/provision-hetzner/scripts/provision-hetzner.sh +262 -0
- package/skills/provision-hetzner/test/fixture/knowledge-base/legal/tenant-dpa-register.md +26 -0
- package/skills/provision-hetzner/test/fixture/provision-hetzner-dry-run.golden +34 -0
- package/skills/provision-hetzner/test/provision-hetzner-characterization.test.sh +227 -0
- package/skills/qa/SKILL.md +263 -0
- package/skills/qa/references/browser-preflight.md +22 -0
- package/skills/questionnaire-generate/SKILL.md +328 -0
- package/skills/questionnaire-generate/references/questionnaire.template +60 -0
- package/skills/rclone/SKILL.md +162 -0
- package/skills/rclone/scripts/check_setup.sh +63 -0
- package/skills/release-announce/SKILL.md +65 -0
- package/skills/release-docs/SKILL.md +92 -0
- package/skills/reproduce-bug/SKILL.md +358 -0
- package/skills/resolve-debt/SKILL.md +85 -0
- package/skills/resolve-debt/scripts/resolve-debt.py +584 -0
- package/skills/resolve-parallel/SKILL.md +45 -0
- package/skills/resolve-parallel/workflows/resolve-parallel.workflow.js +415 -0
- package/skills/resolve-pr-parallel/SKILL.md +68 -0
- package/skills/resolve-pr-parallel/workflows/resolve-pr-parallel.workflow.js +419 -0
- package/skills/resolve-todo-parallel/SKILL.md +57 -0
- package/skills/resolve-todo-parallel/workflows/resolve-todo-parallel.workflow.js +398 -0
- package/skills/review/SKILL.md +1620 -0
- package/skills/review/references/anti-slop-scanner-hook.md +40 -0
- package/skills/review/references/defect-classes-migrations.md +9 -0
- package/skills/review/references/generated-input-oracle-surfaces.md +15 -0
- package/skills/review/references/review-e2e-testing.md +116 -0
- package/skills/review/references/review-evidence-comment.md +36 -0
- package/skills/review/references/review-todo-structure.md +165 -0
- package/skills/review/references/risk-tier-and-fix-rounds.md +97 -0
- package/skills/review/references/semgrep-custom-rules.yaml +174 -0
- package/skills/review/references/ultrathink-phases.md +98 -0
- package/skills/review/references/wfs.md +6 -0
- package/skills/review/scripts/emit-review-trailer.sh +499 -0
- package/skills/review/scripts/ensure-semgrep.sh +99 -0
- package/skills/review/scripts/fix-round-seats.sh +197 -0
- package/skills/review/test/emit-review-trailer.test.sh +387 -0
- package/skills/review/test/ensure-semgrep.test.sh +111 -0
- package/skills/review/test/fix-round-seats.test.sh +237 -0
- package/skills/review/workflows/README.md +147 -0
- package/skills/review/workflows/review.workflow.js +667 -0
- package/skills/schedule/SKILL.md +796 -0
- package/skills/seo-aeo/SKILL.md +139 -0
- package/skills/seo-aeo/scripts/validate-csp.sh +233 -0
- package/skills/seo-aeo/scripts/validate-seo.sh +262 -0
- package/skills/ship/SKILL.md +3023 -0
- package/skills/ship/references/adr-ordinal-collision.md +47 -0
- package/skills/ship/references/affected-gate-contract.md +115 -0
- package/skills/ship/references/ci-run-diagnosis.md +29 -0
- package/skills/ship/references/ci-workflow-authoring.md +68 -0
- package/skills/ship/references/cleanup-merged-archival.md +39 -0
- package/skills/ship/references/counsel-review-clo-attestation.md +38 -0
- package/skills/ship/references/cto-ruling-armed-push.md +5 -0
- package/skills/ship/references/decision-challenges-render.md +71 -0
- package/skills/ship/references/delegated-act-authoring-form.md +7 -0
- package/skills/ship/references/detached-battery-verdict.md +13 -0
- package/skills/ship/references/epic-close-sweep.md +62 -0
- package/skills/ship/references/feature-tweet-draft.md +42 -0
- package/skills/ship/references/followthrough-issue-body-template.md +47 -0
- package/skills/ship/references/followthrough-stub-template.sh +92 -0
- package/skills/ship/references/merge-queue-dequeue.md +39 -0
- package/skills/ship/references/operator-holds.md +179 -0
- package/skills/ship/references/pipeline-tally-render.md +43 -0
- package/skills/ship/references/pr-overlap.md +153 -0
- package/skills/ship/references/queue-mode.md +7 -0
- package/skills/ship/references/ready-run-wait.md +36 -0
- package/skills/ship/references/red-on-main-quarantine.md +110 -0
- package/skills/ship/references/register-update-pr-pattern.md +88 -0
- package/skills/ship/references/settle-then-admin-merge.md +130 -0
- package/skills/ship/references/supabase-column-probe.md +13 -0
- package/skills/ship/scripts/auto-close-scan.sh +76 -0
- package/skills/ship/scripts/battery-owed.sh +403 -0
- package/skills/ship/scripts/hold-gate-eval.sh +410 -0
- package/skills/ship/scripts/net-issue-flow.sh +665 -0
- package/skills/ship/scripts/pr-overlap-preflight.sh +483 -0
- package/skills/ship/scripts/ship-pir-action-items-gate.sh +246 -0
- package/skills/ship/scripts/technical-ruling-gate.sh +444 -0
- package/skills/skill-creator/SKILL.md +299 -0
- package/skills/skill-creator/references/api-security.md +248 -0
- package/skills/skill-creator/references/authoring-levers.md +110 -0
- package/skills/skill-creator/references/be-clear-and-direct.md +587 -0
- package/skills/skill-creator/references/best-practices.md +431 -0
- package/skills/skill-creator/references/common-patterns.md +639 -0
- package/skills/skill-creator/references/core-principles.md +193 -0
- package/skills/skill-creator/references/executable-code.md +188 -0
- package/skills/skill-creator/references/iteration-and-testing.md +509 -0
- package/skills/skill-creator/references/official-spec.md +193 -0
- package/skills/skill-creator/references/recommended-structure.md +180 -0
- package/skills/skill-creator/references/skill-structure.md +396 -0
- package/skills/skill-creator/references/using-scripts.md +122 -0
- package/skills/skill-creator/references/using-templates.md +120 -0
- package/skills/skill-creator/references/workflows-and-validation.md +541 -0
- package/skills/skill-creator/scripts/init_skill.py +322 -0
- package/skills/skill-creator/scripts/package_skill.py +110 -0
- package/skills/skill-creator/scripts/quick_validate.py +64 -0
- package/skills/skill-creator/templates/router-skill.md +73 -0
- package/skills/skill-creator/templates/simple-skill.md +34 -0
- package/skills/skill-creator/workflows/add-reference.md +96 -0
- package/skills/skill-creator/workflows/add-script.md +104 -0
- package/skills/skill-creator/workflows/add-template.md +83 -0
- package/skills/skill-creator/workflows/add-workflow.md +128 -0
- package/skills/skill-creator/workflows/audit-skill.md +159 -0
- package/skills/skill-creator/workflows/create-domain-expertise-skill.md +623 -0
- package/skills/skill-creator/workflows/create-new-skill.md +207 -0
- package/skills/skill-creator/workflows/get-guidance.md +134 -0
- package/skills/skill-creator/workflows/upgrade-to-router.md +170 -0
- package/skills/skill-creator/workflows/verify-skill.md +226 -0
- package/skills/skill-security-scan/SKILL.md +145 -0
- package/skills/skill-security-scan/references/disclaimer.md +21 -0
- package/skills/skill-security-scan/references/first-party-allowlist.yaml +38 -0
- package/skills/skill-security-scan/references/override-artifact-schema.json +68 -0
- package/skills/skill-security-scan/references/override-mechanism.md +171 -0
- package/skills/skill-security-scan/references/redirect-domains.yaml +27 -0
- package/skills/skill-security-scan/references/regex-patterns.md +136 -0
- package/skills/skill-security-scan/references/rules/code-exec.yaml +70 -0
- package/skills/skill-security-scan/references/rules/filesystem-boundary.yaml +29 -0
- package/skills/skill-security-scan/references/rules/manifest.yaml +44 -0
- package/skills/skill-security-scan/references/rules/supply-chain.yaml +36 -0
- package/skills/skill-security-scan/references/scan-meta-schema.json +63 -0
- package/skills/skill-security-scan/references/test-fixtures/clean-soleur-style.skill.md +23 -0
- package/skills/skill-security-scan/references/test-fixtures/clean-third-party.skill.md +26 -0
- package/skills/skill-security-scan/references/test-fixtures/malicious-codeexec.skill.md +23 -0
- package/skills/skill-security-scan/references/test-fixtures/malicious-curl-pipe-bash.skill.md +69 -0
- package/skills/skill-security-scan/references/test-fixtures/malicious-prompt-injection.skill.md +17 -0
- package/skills/skill-security-scan/references/test-fixtures/malicious-telemetry-beacon.skill.md +23 -0
- package/skills/skill-security-scan/references/typosquat-targets.yaml +65 -0
- package/skills/skill-security-scan/scripts/check-codeexec.sh +41 -0
- package/skills/skill-security-scan/scripts/check-filesystem-boundary.sh +19 -0
- package/skills/skill-security-scan/scripts/check-prompt-injection.sh +95 -0
- package/skills/skill-security-scan/scripts/check-supply-chain.sh +219 -0
- package/skills/skill-security-scan/scripts/check-telemetry-surface.sh +126 -0
- package/skills/skill-security-scan/scripts/lib.sh +197 -0
- package/skills/skill-security-scan/scripts/parse-override.sh +231 -0
- package/skills/skill-security-scan/scripts/run-scan.sh +342 -0
- package/skills/skill-security-scan/scripts/run-self-test.sh +95 -0
- package/skills/skill-security-scan/test/argv-ceiling.test.sh +180 -0
- package/skills/skill-security-scan/test/meta-dir-reap.test.sh +411 -0
- package/skills/skill-security-scan/test/parse-override.test.sh +607 -0
- package/skills/skill-security-scan/test/redact-pii-ghs-shape.test.sh +251 -0
- package/skills/social-distribute/SKILL.md +485 -0
- package/skills/spec-templates/SKILL.md +274 -0
- package/skills/sync/SKILL.md +49 -0
- package/skills/test-browser/SKILL.md +464 -0
- package/skills/test-browser/references/feature-map.md +161 -0
- package/skills/test-fix-loop/SKILL.md +159 -0
- package/skills/test-fix-loop/references/determinism-checklist.md +154 -0
- package/skills/triage/SKILL.md +402 -0
- package/skills/trigger-cron/SKILL.md +136 -0
- package/skills/trigger-cron/scripts/trigger.sh +198 -0
- package/skills/user-set-role/SKILL.md +147 -0
- package/skills/user-set-role/scripts/set-role.sh +218 -0
- package/skills/user-story-writer/SKILL.md +77 -0
- package/skills/ux-audit/SKILL.md +251 -0
- package/skills/ux-audit/references/finding.schema.json +62 -0
- package/skills/ux-audit/references/route-list.yaml +95 -0
- package/skills/ux-audit/scripts/bot-fixture.ts +270 -0
- package/skills/ux-audit/scripts/bot-signin.ts +135 -0
- package/skills/ux-audit/scripts/dedup-hash.ts +46 -0
- package/skills/verification-scaffold/SKILL.md +73 -0
- package/skills/verification-scaffold/references/gitleaks.toml.template +13 -0
- package/skills/verification-scaffold/references/guardrail-audit.md +156 -0
- package/skills/verification-scaffold/references/guards/block-stash-hook.sh.template +72 -0
- package/skills/verification-scaffold/references/guards/commit-on-main-hook.sh.template +82 -0
- package/skills/verification-scaffold/references/guards/orphan-test-check.sh.template +102 -0
- package/skills/verification-scaffold/references/guards/precommit-guard.sh.template +115 -0
- package/skills/verification-scaffold/references/guards/secret-scan-hook.sh.template +176 -0
- package/skills/verification-scaffold/references/guards/verification-gates.yml.template +49 -0
- package/skills/verification-scaffold/references/guards/wrapper-boundary.sh.template +47 -0
- package/skills/verification-scaffold/references/guards.tsv +21 -0
- package/skills/verification-scaffold/references/verification-readme.template +55 -0
- package/skills/verification-scaffold/scripts/verification-scaffold.sh +785 -0
- package/skills/verification-scaffold/test/bite-proof.test.sh +159 -0
- package/skills/verification-scaffold/test/generator.test.sh +319 -0
- package/skills/verification-scaffold/test/manifest.test.sh +144 -0
- package/skills/work/SKILL.md +1480 -0
- package/skills/work/references/end-of-work-resume.md +7 -0
- package/skills/work/references/hook-test-main-cwd.md +24 -0
- package/skills/work/references/key-principles.md +83 -0
- package/skills/work/references/property-testing.md +122 -0
- package/skills/work/references/sql-security-definer-rpc-scaffold.sql +78 -0
- package/skills/work/references/work-agent-teams.md +97 -0
- package/skills/work/references/work-lifecycle-parallel.md +147 -0
- package/skills/work/references/work-lockfile-bumps.md +97 -0
- package/skills/work/references/work-scratch-sandboxes.md +212 -0
- package/skills/work/references/work-subagent-fanout.md +61 -0
- package/skills/work/references/work-test-harness-sharp-edges.md +73 -0
- package/skills/xcode-test/SKILL.md +360 -0
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
#
|
|
3
|
+
# alpha-metrics.sh -- print the aggregate a tester pastes back at checkpoint.
|
|
4
|
+
#
|
|
5
|
+
# Usage: run inside the project repo: bash plugins/soleur/scripts/alpha-metrics.sh
|
|
6
|
+
#
|
|
7
|
+
# Reads .soleur/decisions.jsonl (and the rotated .1) at the git root and prints
|
|
8
|
+
# aggregate counts ONLY: total lines, per-skill / per-agent_domain / per-harness
|
|
9
|
+
# breakdowns, first/last timestamps. Metadata is already allowlisted at write
|
|
10
|
+
# time, but this script still prints counts and fields only — never raw lines.
|
|
11
|
+
#
|
|
12
|
+
# Missing or empty output is a SIGNAL, not a zero:
|
|
13
|
+
# SOLEUR_EMIT_ABSENT -- no log exists (stale install / emit never ran)
|
|
14
|
+
# SOLEUR_EMIT_EMPTY -- log exists with zero records (kill-switch set,
|
|
15
|
+
# unwritable dir, or a brand-new install)
|
|
16
|
+
# Neither means "the tester did nothing". Never report absence as zero usage.
|
|
17
|
+
#
|
|
18
|
+
# Portability: awk/grep/sed/wc/sort/head only — stock macOS bash 3.2-safe.
|
|
19
|
+
|
|
20
|
+
set -uo pipefail
|
|
21
|
+
|
|
22
|
+
DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
23
|
+
# shellcheck source=plugins/soleur/scripts/resolve-git-root.sh
|
|
24
|
+
. "$DIR/resolve-git-root.sh" 2>/dev/null || {
|
|
25
|
+
echo "SOLEUR_EMIT_ABSENT — not inside a git repository"
|
|
26
|
+
exit 0
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
LOG_DIR="$GIT_ROOT/.soleur"
|
|
30
|
+
LOG="$LOG_DIR/decisions.jsonl"
|
|
31
|
+
ROT="$LOG.1"
|
|
32
|
+
|
|
33
|
+
if [ ! -f "$LOG" ] && [ ! -f "$ROT" ]; then
|
|
34
|
+
echo "SOLEUR_EMIT_ABSENT — no decision log at .soleur/decisions.jsonl"
|
|
35
|
+
echo "(a stale plugin install or emit has never fired; this is NOT proof of zero usage)"
|
|
36
|
+
exit 0
|
|
37
|
+
fi
|
|
38
|
+
|
|
39
|
+
if [ ! -s "$LOG" ] && [ ! -s "$ROT" ]; then
|
|
40
|
+
echo "SOLEUR_EMIT_EMPTY — the log exists but holds no records"
|
|
41
|
+
echo "(kill-switch SOLEUR_DISABLE_DECISION_LOG, an unwritable .soleur, or a brand-new install)"
|
|
42
|
+
exit 0
|
|
43
|
+
fi
|
|
44
|
+
|
|
45
|
+
# Merge current + rotated; each line is one allowlisted JSON object.
|
|
46
|
+
INPUT="$(cat "$LOG" "$ROT" 2>/dev/null)"
|
|
47
|
+
|
|
48
|
+
total="$(printf '%s\n' "$INPUT" | grep -c '^{"v":' )"
|
|
49
|
+
lines="$(printf '%s\n' "$INPUT" | grep -c .)"
|
|
50
|
+
malformed=$((lines - total))
|
|
51
|
+
first="$(printf '%s\n' "$INPUT" | sed -n 's/.*"ts":"\([^"]*\)".*/\1/p' | sort | head -1)"
|
|
52
|
+
last="$(printf '%s\n' "$INPUT" | sed -n 's/.*"ts":"\([^"]*\)".*/\1/p' | sort | tail -1)"
|
|
53
|
+
|
|
54
|
+
echo "=== .soleur/decisions.jsonl aggregate ==="
|
|
55
|
+
echo "records: $total"
|
|
56
|
+
[ "$malformed" -gt 0 ] && echo "malformed: $malformed line(s) skipped (corrupt log — not counted)"
|
|
57
|
+
echo "first: ${first:-unknown}"
|
|
58
|
+
echo "last: ${last:-unknown}"
|
|
59
|
+
echo
|
|
60
|
+
|
|
61
|
+
count_field() { # $1 = json field name
|
|
62
|
+
printf '%s\n' "$INPUT" \
|
|
63
|
+
| sed -n "s/.*\"$1\":\"\([^\"]*\)\".*/\1/p" \
|
|
64
|
+
| grep -v '^$' \
|
|
65
|
+
| sort | uniq -c | sort -rn \
|
|
66
|
+
| awk '{printf " %-6s %s\n", $1, $2}'
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
echo "by event:"; count_field event
|
|
70
|
+
echo "by label:"; count_field label
|
|
71
|
+
echo "by skill:"; count_field skill
|
|
72
|
+
echo "by agent_domain:"; count_field agent_domain
|
|
73
|
+
echo "by harness:"; count_field harness
|
|
74
|
+
|
|
75
|
+
echo
|
|
76
|
+
echo "Knowledge-base growth (run in this repo):"
|
|
77
|
+
echo " git log --since=<onboard-date> --name-only -- knowledge-base/ | grep -c '^knowledge-base/'"
|
|
78
|
+
exit 0
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
#
|
|
3
|
+
# Tests for alpha-metrics.sh — the checkpoint aggregate printer.
|
|
4
|
+
#
|
|
5
|
+
# Load-bearing contract: ABSENT/EMPTY markers must render as signals, never as
|
|
6
|
+
# a zero count. A tester who did nothing and a tester whose emit never ran are
|
|
7
|
+
# different worlds; the print must not conflate them.
|
|
8
|
+
|
|
9
|
+
set -uo pipefail
|
|
10
|
+
export TMPDIR="${TMPDIR:-/var/tmp}"
|
|
11
|
+
|
|
12
|
+
DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
13
|
+
SUT="$DIR/alpha-metrics.sh"
|
|
14
|
+
EMIT="$DIR/emit-decision.sh"
|
|
15
|
+
|
|
16
|
+
# trap BEFORE sourcing test-helpers.sh so the helpers' composed EXIT trap
|
|
17
|
+
# (<prior>; _soleur_sb_cleanup) stacks on ours instead of being clobbered by it.
|
|
18
|
+
TMP="$(mktemp -d -t alpham.XXXXXXXX)" || { echo "mktemp failed" >&2; exit 2; }
|
|
19
|
+
trap 'rm -rf "$TMP"' EXIT
|
|
20
|
+
|
|
21
|
+
# shellcheck source=plugins/soleur/test/test-helpers.sh
|
|
22
|
+
source "$DIR/../test/test-helpers.sh" || { echo "FATAL: could not source test-helpers.sh" >&2; exit 2; }
|
|
23
|
+
set +e -uo pipefail
|
|
24
|
+
|
|
25
|
+
passes=0
|
|
26
|
+
fails=0
|
|
27
|
+
CASES=0
|
|
28
|
+
|
|
29
|
+
pass() { passes=$((passes + 1)); printf ' ok %s\n' "$1"; }
|
|
30
|
+
fail() { fails=$((fails + 1)); printf ' FAIL %s\n' "$1"; [[ -n "${2:-}" ]] && printf ' %s\n' "$2"; return 0; }
|
|
31
|
+
assert() {
|
|
32
|
+
CASES=$((CASES + 1))
|
|
33
|
+
if eval "$2"; then pass "$1"; else fail "$1" "${3:-$2}"; fi
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
printf '\n=== alpha-metrics.sh ===\n\n'
|
|
37
|
+
[[ -f "$SUT" ]] || { printf '\n[FATAL] SUT missing at %s\n' "$SUT" >&2; exit 1; }
|
|
38
|
+
|
|
39
|
+
new_repo() { # $1 = name
|
|
40
|
+
local d="$TMP/$1"; mkdir -p "$d"
|
|
41
|
+
git -C "$d" init -q -b main
|
|
42
|
+
git -C "$d" config user.email soleur-test@example.invalid
|
|
43
|
+
git -C "$d" config user.name "Soleur Test"
|
|
44
|
+
git -C "$d" config commit.gpgsign false
|
|
45
|
+
git -C "$d" commit -q --allow-empty -m "base"
|
|
46
|
+
printf '%s' "$d"
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
# --- ABSENT: no log at all --------------------------------------------------
|
|
50
|
+
|
|
51
|
+
RA="$TMP/no-log"; new_repo no-log >/dev/null
|
|
52
|
+
out="$(cd "$RA" && bash "$SUT")"
|
|
53
|
+
assert "missing log -> SOLEUR_EMIT_ABSENT" "[[ '$out' == *SOLEUR_EMIT_ABSENT* ]]"
|
|
54
|
+
assert "absent never prints a zero count" "! printf '%s' '$out' | grep -c >/dev/null 'records: *0'"
|
|
55
|
+
|
|
56
|
+
# --- EMPTY: log exists, zero records -----------------------------------------
|
|
57
|
+
|
|
58
|
+
RB="$TMP/empty-log"; new_repo empty-log >/dev/null
|
|
59
|
+
mkdir -p "$RB/.soleur"; touch "$RB/.soleur/decisions.jsonl"
|
|
60
|
+
out="$(cd "$RB" && bash "$SUT")"
|
|
61
|
+
assert "empty log -> SOLEUR_EMIT_EMPTY" "[[ '$out' == *SOLEUR_EMIT_EMPTY* ]]"
|
|
62
|
+
assert "empty never prints a zero count" "! printf '%s' '$out' | grep -c >/dev/null 'records: *0'"
|
|
63
|
+
|
|
64
|
+
# --- POPULATED: real emits aggregate -----------------------------------------
|
|
65
|
+
|
|
66
|
+
RC="$TMP/pop"; new_repo pop >/dev/null
|
|
67
|
+
( cd "$RC"
|
|
68
|
+
bash "$EMIT" --event route_decision --label work
|
|
69
|
+
bash "$EMIT" --event route_decision --label brainstorm
|
|
70
|
+
bash "$EMIT" --event route_decision --label work
|
|
71
|
+
bash "$EMIT" --event tool_invocation --label flag-list --skill flag-list --agent_domain ops )
|
|
72
|
+
out="$(cd "$RC" && bash "$SUT")"
|
|
73
|
+
assert "counts 4 records" "printf '%s' '$out' | grep -c >/dev/null 'records: *4'"
|
|
74
|
+
assert "per-event count present" "printf '%s' '$out' | grep -A3 'by event:' | grep -c >/dev/null 'route_decision'"
|
|
75
|
+
assert "per-label count shows work=2" "printf '%s' '$out' | grep -A5 'by label:' | grep -cE >/dev/null '^ *2 +work'"
|
|
76
|
+
assert "per-domain count shows ops=1" "printf '%s' '$out' | grep -A4 'by agent_domain:' | grep -c >/dev/null 'ops'"
|
|
77
|
+
assert "per-harness count is non-empty" "printf '%s' '$out' | grep -A3 'by harness:' | grep -cE >/dev/null '^ *[0-9]+ +[a-zA-Z]'"
|
|
78
|
+
assert "first/last timestamps printed" "printf '%s' '$out' | grep -c >/dev/null 'first:' && printf '%s' '$out' | grep -c >/dev/null 'last:'"
|
|
79
|
+
assert "KB-growth instruction printed" "printf '%s' '$out' | grep -c >/dev/null 'git log --since'"
|
|
80
|
+
|
|
81
|
+
# --- ROTATED: merged read ----------------------------------------------------
|
|
82
|
+
|
|
83
|
+
RD="$TMP/rot"; new_repo rot >/dev/null
|
|
84
|
+
( cd "$RD" && bash "$EMIT" --event route_decision --label one )
|
|
85
|
+
printf '{"v":1,"ts":"2026-01-01T00:00:00Z","event":"route_decision","label":"old","skill":"","agent_domain":"","harness":"claude","session_id":"s","plugin_sha":"x","repo_hash":"h"}\n' > "$RD/.soleur/decisions.jsonl.1"
|
|
86
|
+
out="$(cd "$RD" && bash "$SUT")"
|
|
87
|
+
assert "rotated lines merge into the count" "printf '%s' '$out' | grep -c >/dev/null 'records: *2'"
|
|
88
|
+
|
|
89
|
+
# --- ORDERING: first/last carry VALUES, not just labels ----------------------
|
|
90
|
+
|
|
91
|
+
RE="$TMP/order"; new_repo order >/dev/null
|
|
92
|
+
mkdir -p "$RE/.soleur"
|
|
93
|
+
printf '%s\n' '{"v":1,"ts":"2026-03-05T00:00:00Z","event":"route_decision","label":"b","skill":"","agent_domain":"","harness":"x","session_id":"s","plugin_sha":"p","repo_hash":"h"}' \
|
|
94
|
+
'{"v":1,"ts":"2026-03-01T00:00:00Z","event":"route_decision","label":"a","skill":"","agent_domain":"","harness":"x","session_id":"s","plugin_sha":"p","repo_hash":"h"}' \
|
|
95
|
+
> "$RE/.soleur/decisions.jsonl"
|
|
96
|
+
out="$(cd "$RE" && bash "$SUT")"
|
|
97
|
+
assert "first: carries the EARLIEST ts (not just the label)" \
|
|
98
|
+
"printf '%s' '$out' | grep -c >/dev/null 'first: 2026-03-01'"
|
|
99
|
+
assert "last: carries the LATEST ts" \
|
|
100
|
+
"printf '%s' '$out' | grep -c >/dev/null 'last: 2026-03-05'"
|
|
101
|
+
|
|
102
|
+
# --- CORRUPTION: a malformed line is surfaced, not silently counted ----------
|
|
103
|
+
|
|
104
|
+
RF="$TMP/bad"; new_repo bad >/dev/null
|
|
105
|
+
mkdir -p "$RF/.soleur"
|
|
106
|
+
printf '%s\n' '{"v":1,"ts":"2026-03-01T00:00:00Z","event":"route_decision","label":"ok","skill":"","agent_domain":"","harness":"x","session_id":"s","plugin_sha":"p","repo_hash":"h"}' \
|
|
107
|
+
'garbage-not-json' \
|
|
108
|
+
> "$RF/.soleur/decisions.jsonl"
|
|
109
|
+
out="$(cd "$RF" && bash "$SUT")"
|
|
110
|
+
assert "malformed lines are reported, not silently dropped" \
|
|
111
|
+
"printf '%s' '$out' | grep -c >/dev/null 'malformed: 1'"
|
|
112
|
+
|
|
113
|
+
printf '\n=== alpha-metrics: %d passed, %d failed (of %d) ===\n' "$passes" "$fails" "$CASES"
|
|
114
|
+
# Anti-vacuity floor (#7408 class): a suite that ran nothing must not exit green.
|
|
115
|
+
[[ "$fails" -eq 0 && "$CASES" -ge 15 ]]
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# ancestor-signal baseline: one row per gated finding, <path> TAB <class> TAB <normalised line>.
|
|
2
|
+
# Classes: W ancestor walk that signals (must read bounded=yes), P signal to the parent, G all-process signal.
|
|
3
|
+
# Maintenance: an in-place replacement of an existing row (same path and class, e.g. after an unrelated edit of
|
|
4
|
+
# that line) is allowed; a net addition needs a reviewer's read; otherwise the file may only shrink. A stale row
|
|
5
|
+
# (no live line) and an unbounded W are red. bounded=yes is LEXICAL (a non-comment SOLEUR_TEST_SUITE_PID
|
|
6
|
+
# comparison with exit, break or return near the walk), not proof of containment.
|
|
7
|
+
# Regenerate: python3 plugins/soleur/scripts/scan-ancestor-signal-helpers.py --write-baseline <this file>
|
|
8
|
+
# (overwrites the whole file: review the diff row by row).
|
|
9
|
+
apps/web-platform/infra/arm-heartbeats.test.sh P if [[ "$seen" -ge "$FAKE_CUT_AFTER" ]]; then kill -9 "$PPID" 2>/dev/null; exit 0; fi
|
|
10
|
+
apps/web-platform/infra/git-data-luks-reopen.test.sh P [ -f "$FX/luksopen_kill" ] && kill -TERM "$PPID"
|
|
11
|
+
apps/web-platform/infra/run-registered-suites.test.sh P kill -9 "$_shim" 2>/dev/null
|
|
12
|
+
apps/web-platform/infra/workspaces-boot-unlock.test.sh P [ -f "$FX/luksopen_kill" ] && kill -TERM "$PPID"
|
|
13
|
+
apps/web-platform/infra/workspaces-luks-provision.test.sh P [ -f "$st/crash_after_luksFormat" ] && kill -9 "$PPID"
|
|
14
|
+
apps/web-platform/infra/workspaces-luks-provision.test.sh P [ -f "$st/crash_after_mkfs" ] && kill -9 "$PPID"
|
|
15
|
+
plugins/soleur/scripts/resolve-regenerable-conflicts.test.sh W p=$(awk '{print $4}' "/proc/$p/stat" 2>/dev/null)
|
|
16
|
+
plugins/soleur/test/roadmap-reconcile.test.sh W top=$p; p=$(awk '{print $4}' "/proc/$p/stat")
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Shared WORM audit-append helper for the flag-tooling skills (#4581 PR-1).
|
|
3
|
+
#
|
|
4
|
+
# Appends a row to public.flag_flip_audit via the SECURITY DEFINER PostgREST RPC
|
|
5
|
+
# `audit_flag_flip` (migration 071), replacing the prior `psql` binary dependency
|
|
6
|
+
# so the sanctioned path runs on any machine (no psql/sudo).
|
|
7
|
+
#
|
|
8
|
+
# Sourced by:
|
|
9
|
+
# plugins/soleur/skills/flag-create/scripts/create.sh
|
|
10
|
+
# plugins/soleur/skills/flag-delete/scripts/delete.sh
|
|
11
|
+
# plugins/soleur/skills/flag-set-role/scripts/flip.sh
|
|
12
|
+
# plugins/soleur/skills/user-set-role/scripts/set-role.sh
|
|
13
|
+
#
|
|
14
|
+
# Contract:
|
|
15
|
+
# audit_flag_flip_rpc <url> <srk> <flag> <env> <target> <action> <before> <after> <actor>
|
|
16
|
+
#
|
|
17
|
+
# <url> SUPABASE_URL of the audit DB (callers resolve from Doppler -c dev,
|
|
18
|
+
# matching the historical DATABASE_URL_POOLER -c dev audit target).
|
|
19
|
+
# <srk> SUPABASE_SERVICE_ROLE_KEY for <url> (the RPC is GRANTed to service_role only).
|
|
20
|
+
# <before>/<after> LITERAL JSON tokens: `true` | `false` | `null`. Passed via
|
|
21
|
+
# `jq --argjson` so they reach the bool columns as JSON bool/null,
|
|
22
|
+
# not strings (a `--arg` string fails PostgREST bool coercion).
|
|
23
|
+
#
|
|
24
|
+
# Approval method (#8486, ADR-249): the body carries p_approval_method:"tty-ack"
|
|
25
|
+
# (migration 140) ONLY when the operator-script library's class-2 ack has set the
|
|
26
|
+
# plain shell variable SOLEUR_OP_ACKED=tty-ack in this process. Without it the
|
|
27
|
+
# helper refuses with rc 4 before any request, so an audit append placed before
|
|
28
|
+
# the ack fails closed and the WORM value means "the ack returned here". The
|
|
29
|
+
# value is self-reported by the script, not proof that a person typed.
|
|
30
|
+
#
|
|
31
|
+
# Behavior: append-before-flip — the caller MUST call this BEFORE any Flagsmith /
|
|
32
|
+
# Supabase mutation, and abort the flip on a non-zero return. Returns:
|
|
33
|
+
# 0 audit row written (echoes the row uuid on stdout)
|
|
34
|
+
# 4 audit append failed (non-2xx, empty body, or missing/null id) — caller exits 4
|
|
35
|
+
#
|
|
36
|
+
# Requires: curl, jq.
|
|
37
|
+
audit_flag_flip_rpc() {
|
|
38
|
+
local url="$1" srk="$2" flag="$3" env="$4" target="$5" action="$6" before="$7" after="$8" actor="$9"
|
|
39
|
+
local body resp code id
|
|
40
|
+
|
|
41
|
+
# Observability (review #8650): the WORM audit trail failing is the one failure
|
|
42
|
+
# this script's own contract exists to make impossible to miss. stderr alone is
|
|
43
|
+
# sufficient for an ack-refusal (the operator is at the keyboard that just typed
|
|
44
|
+
# `yes`), but a durable, names-not-values ledger row survives past a scrolled
|
|
45
|
+
# terminal. `soleur_op_ledger_note` is defined by operator-script.sh, which every
|
|
46
|
+
# caller sources before this function is ever invoked (append-before-flip runs
|
|
47
|
+
# after the ack) — guard with `declare -F` so this stays safe if that assumption
|
|
48
|
+
# ever stops holding.
|
|
49
|
+
# Always returns 0 — this is bookkeeping around a failure already being
|
|
50
|
+
# reported, and running under the caller's `set -e` a nonzero return here
|
|
51
|
+
# would abort the function before its own `return 4` executes.
|
|
52
|
+
_audit_failed_marker() {
|
|
53
|
+
printf 'SOLEUR_BOOTSTRAP_AUDIT_APPEND_FAILED reason=%s\n' "$1" >&2
|
|
54
|
+
if declare -F soleur_op_ledger_note >/dev/null 2>&1; then
|
|
55
|
+
soleur_op_ledger_note audit_append_failed "$flag" "$1" || true
|
|
56
|
+
fi
|
|
57
|
+
return 0
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
if [[ "${SOLEUR_OP_ACKED:-}" != "tty-ack" ]]; then
|
|
61
|
+
echo "FATAL: audit append before the ack — the class-2 yes prompt has not returned in this process (#8486)" >&2
|
|
62
|
+
_audit_failed_marker no-ack
|
|
63
|
+
return 4
|
|
64
|
+
fi
|
|
65
|
+
command -v jq >/dev/null || { echo "FATAL: jq not found (audit append)" >&2; _audit_failed_marker no-jq; return 4; }
|
|
66
|
+
command -v curl >/dev/null || { echo "FATAL: curl not found (audit append)" >&2; _audit_failed_marker no-curl; return 4; }
|
|
67
|
+
|
|
68
|
+
# --argjson for the bool/null args; --arg for the text args.
|
|
69
|
+
body=$(jq -nc \
|
|
70
|
+
--arg f "$flag" --arg e "$env" --arg t "$target" \
|
|
71
|
+
--arg a "$action" --arg ac "$actor" --arg am "$SOLEUR_OP_ACKED" \
|
|
72
|
+
--argjson b "$before" --argjson af "$after" \
|
|
73
|
+
'{p_flag_name:$f, p_env:$e, p_target:$t, p_action:$a, p_before_bool:$b, p_after_bool:$af, p_actor:$ac, p_approval_method:$am}') \
|
|
74
|
+
|| { echo "FATAL: failed to build audit RPC body (bad before/after token: '$before'/'$after')" >&2; _audit_failed_marker bad-body; return 4; }
|
|
75
|
+
|
|
76
|
+
# Token-shape guard (never echoes the value): the key is written into curl's stdin
|
|
77
|
+
# config below, so a quote or newline in it would inject a config directive. An
|
|
78
|
+
# unusable key makes zero curl calls and the same failure outcome (rc 4) as any other
|
|
79
|
+
# failed append, never success.
|
|
80
|
+
_audit_bearer_ok() { local LC_ALL=C; case "${1:-}" in ''|*[!A-Za-z0-9._~+/=-]*) return 1 ;; esac; }
|
|
81
|
+
_audit_bearer_ok "$srk" \
|
|
82
|
+
|| { echo "FATAL: audit append key has an unexpected shape (not sent)" >&2; _audit_failed_marker bad-key-shape; return 4; }
|
|
83
|
+
|
|
84
|
+
# The service-role key rides curl's stdin config channel (both the apikey and the
|
|
85
|
+
# Authorization header), never its argument list.
|
|
86
|
+
resp=$(curl --disable --noproxy '*' -sS -w '\n%{http_code}' -X POST \
|
|
87
|
+
-H "Content-Type: application/json" -H "Accept: application/json" \
|
|
88
|
+
--config - \
|
|
89
|
+
"${url}/rest/v1/rpc/audit_flag_flip" -d "$body" \
|
|
90
|
+
< <(printf 'header = "apikey: %s"\nheader = "Authorization: Bearer %s"\n' "$srk" "$srk")) \
|
|
91
|
+
|| { echo "FATAL: audit RPC request failed (transport error)" >&2; _audit_failed_marker curl-error; return 4; }
|
|
92
|
+
|
|
93
|
+
code=$(printf '%s' "$resp" | tail -n1)
|
|
94
|
+
body=$(printf '%s' "$resp" | sed '$d')
|
|
95
|
+
[[ "$code" =~ ^2[0-9][0-9]$ ]] \
|
|
96
|
+
|| { echo "FATAL: audit RPC non-2xx (HTTP $code): $body" >&2; _audit_failed_marker "http-$code"; return 4; }
|
|
97
|
+
|
|
98
|
+
# RETURNS uuid -> PostgREST emits a bare JSON scalar; array branch is dead-but-safe.
|
|
99
|
+
# `|| id=""` makes the no-id path deterministic under the caller's `set -e` (a jq
|
|
100
|
+
# parse failure on garbage/empty body would otherwise abort the subshell before the
|
|
101
|
+
# guard); the uuid-shape match then rejects empty/null/non-uuid (incl. a 2xx `{}`).
|
|
102
|
+
id=$(printf '%s' "$body" | jq -r 'if type=="array" then .[0] else . end' 2>/dev/null) || id=""
|
|
103
|
+
[[ "$id" =~ ^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$ ]] \
|
|
104
|
+
|| { echo "FATAL: audit RPC returned no valid uuid: $body" >&2; _audit_failed_marker no-valid-uuid; return 4; }
|
|
105
|
+
|
|
106
|
+
printf '%s' "$id"
|
|
107
|
+
}
|
|
@@ -0,0 +1,316 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# check-red-on-main.sh "<check-name>" --run-id <failing-run-id> [--report] [--repo owner/repo]
|
|
3
|
+
# check-red-on-main.sh --self-test
|
|
4
|
+
# check-red-on-main.sh --help
|
|
5
|
+
#
|
|
6
|
+
# WHY THIS EXISTS (#9402). A PR whose check is red because MAIN is red pays rerun cycles and
|
|
7
|
+
# autonomous-fix attempts for a failure it did not cause -- PR #9339 paid three reruns of
|
|
8
|
+
# `deploy-script-tests (1/4)` while that leg was red on main. "Confirmed pre-existing" was an
|
|
9
|
+
# agent judgment call with no mechanical probe; this script is the probe. It answers one
|
|
10
|
+
# question: did the newest completed main-branch run of the SAME workflow that exercised a job
|
|
11
|
+
# of the EXACT same name conclude it non-green?
|
|
12
|
+
#
|
|
13
|
+
# HOW IT DECIDES.
|
|
14
|
+
# * The failing check's workflow is resolved through the run it failed in:
|
|
15
|
+
# `gh api repos/{o}/{r}/actions/runs/<run-id>` -> .workflow_id. `gh pr checks`' `link` field
|
|
16
|
+
# already carries `actions/runs/<run-id>`.
|
|
17
|
+
# * Up to 5 completed main-branch runs of that workflow are listed, newest first
|
|
18
|
+
# (`actions/workflows/<id>/runs?branch=main&status=completed&per_page=5`).
|
|
19
|
+
# * In each run the job named EXACTLY <check-name> is looked up. Matrix suffixes like `(1/4)`
|
|
20
|
+
# are part of the name -- the parent `deploy-script-tests` never answers for the leg, and a
|
|
21
|
+
# prefix match would read a green parent as a green leg.
|
|
22
|
+
# * skipped/absent jobs are NOT evidence: a path-filtered main push that never ran the job
|
|
23
|
+
# says nothing, so the scan continues to older runs in the window.
|
|
24
|
+
# * The FIRST run where the job reached a real conclusion decides:
|
|
25
|
+
# red-on-main -- conclusion in {failure, timed_out, cancelled, startup_failure}
|
|
26
|
+
# green-on-main -- conclusion in {success, neutral}
|
|
27
|
+
# no-evidence -- no run in the window exercised the job -> NOT quarantined
|
|
28
|
+
# `cancelled` is red by the same `!= 'success'` convention notify-main-failure uses;
|
|
29
|
+
# `startup_failure` is red because the runner never got to measure the job. `skipped`,
|
|
30
|
+
# `stale`, and `action_required` are not evidence -- the job never produced a verdict
|
|
31
|
+
# on code, so the scan continues to older runs in the window.
|
|
32
|
+
#
|
|
33
|
+
# EXIT CODES (the contract every caller branches on).
|
|
34
|
+
# 0 green-on-main the check is healthy on main -- this PR's red is its own
|
|
35
|
+
# 1 red-on-main same-named job is red on the newest exercising main run -> quarantine
|
|
36
|
+
# 2 no-evidence no main run in the window exercised the job -> NOT quarantined
|
|
37
|
+
# 3 error usage error, gh/jq missing, API failure, unparseable body.
|
|
38
|
+
# ERRORS NEVER QUARANTINE -- an unproven claim is worse than a rerun.
|
|
39
|
+
#
|
|
40
|
+
# Every invocation prints exactly one stdout marker as its LAST stdout line:
|
|
41
|
+
# SOLEUR_RED_ON_MAIN verdict=<v> check="<name>" main_run=<id|none> main_conclusion=<c|none>
|
|
42
|
+
# with ` reason=<api|parse|missing-tool|usage|mktemp|interrupted>` appended on the error
|
|
43
|
+
# path. All diagnostics go
|
|
44
|
+
# to stderr so the marker is the only stdout line.
|
|
45
|
+
#
|
|
46
|
+
# --report (the only write path; dedupe is sentinel-keyed, mirroring main-health-monitor):
|
|
47
|
+
# * red-on-main: list open `ci/main-broken` issues, find those carrying
|
|
48
|
+
# `<!-- soleur:red-on-main check="<name>" -->` (oldest first), comment on the oldest; if
|
|
49
|
+
# none, `gh label create ci/main-broken --force 2>/dev/null || true` then file with
|
|
50
|
+
# --milestone "Post-MVP / Later" --label ci/main-broken --label meta/machinery --label
|
|
51
|
+
# type/chore. A LIST FAILURE warns and files NOTHING -- never a duplicate on a transient
|
|
52
|
+
# error (#1357 lesson: the rate-limit response is this query's own failure condition).
|
|
53
|
+
# * green-on-main: comment-and-close EVERY open issue carrying OUR sentinel for that exact
|
|
54
|
+
# check name -- never a human-filed tracker, never another check's sentinel (#7374's
|
|
55
|
+
# out-of-scope-green lesson is what the sentinel encodes).
|
|
56
|
+
# * no-evidence/error: no issue operations at all.
|
|
57
|
+
#
|
|
58
|
+
# `gh api` GET calls embed the query in the URL -- never `-f`/`--raw-field`, which flips the
|
|
59
|
+
# request to POST and 404s the actions runs endpoints (measured 2026-09-29, PR #9233). And
|
|
60
|
+
# `gh api` has no `--arg` (cli/cli#10263): two-stage `gh api URL | jq --arg` is the only
|
|
61
|
+
# sanctioned shape. `gh api` also has no `-R/--repo` flag, so --repo is embedded in the path.
|
|
62
|
+
set -uo pipefail
|
|
63
|
+
|
|
64
|
+
readonly MARKER="SOLEUR_RED_ON_MAIN"
|
|
65
|
+
|
|
66
|
+
usage() {
|
|
67
|
+
cat <<'EOF'
|
|
68
|
+
usage: check-red-on-main.sh "<check-name>" --run-id <failing-run-id> [--report] [--repo owner/repo]
|
|
69
|
+
check-red-on-main.sh --self-test
|
|
70
|
+
check-red-on-main.sh --help
|
|
71
|
+
|
|
72
|
+
Answers whether the check that failed in run <failing-run-id> is ALSO failing on main: scans up
|
|
73
|
+
to 5 completed main-branch runs of the same workflow, newest first, for a job named EXACTLY
|
|
74
|
+
<check-name> (matrix suffixes included). Skipped/absent jobs are not evidence.
|
|
75
|
+
|
|
76
|
+
exit 0 green-on-main | 1 red-on-main (quarantine) | 2 no-evidence (not quarantined) | 3 error
|
|
77
|
+
|
|
78
|
+
Last stdout line, on every path except --help and --self-test:
|
|
79
|
+
SOLEUR_RED_ON_MAIN verdict=<v> check="<name>" main_run=<id|none> main_conclusion=<c|none> [reason=<r>]
|
|
80
|
+
|
|
81
|
+
--report files/dedupes a `ci/main-broken` tracker keyed on the sentinel
|
|
82
|
+
`<!-- soleur:red-on-main check="<name>" -->` on red, and comments+closes sentinel-owned issues
|
|
83
|
+
on green. Errors and no-evidence never file and never close.
|
|
84
|
+
EOF
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
CHECK_OUT="-"; MAIN_RUN="none"; MAIN_CONCL="none"; REASON="none"
|
|
88
|
+
|
|
89
|
+
marker() { # <verdict> ; always the LAST stdout line
|
|
90
|
+
if [[ "$1" == error ]]; then
|
|
91
|
+
printf '%s verdict=error check="%s" main_run=%s main_conclusion=%s reason=%s\n' \
|
|
92
|
+
"$MARKER" "$CHECK_OUT" "$MAIN_RUN" "$MAIN_CONCL" "$REASON"
|
|
93
|
+
else
|
|
94
|
+
printf '%s verdict=%s check="%s" main_run=%s main_conclusion=%s\n' \
|
|
95
|
+
"$MARKER" "$1" "$CHECK_OUT" "$MAIN_RUN" "$MAIN_CONCL"
|
|
96
|
+
fi
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
die3() { # <message> <reason-token>
|
|
100
|
+
printf 'check-red-on-main: ERROR: %s\n' "$1" >&2
|
|
101
|
+
REASON="$2"; marker error; exit 3
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
usage_error() {
|
|
105
|
+
printf 'check-red-on-main: %s\n' "$1" >&2
|
|
106
|
+
usage >&2
|
|
107
|
+
REASON=usage; marker error; exit 3
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
# ── the pure classifier ─────────────────────────────────────────────────────────────────────
|
|
111
|
+
# job_verdict <check-name> -- reads ONE OR MORE concatenated jobs-page objects on stdin (the
|
|
112
|
+
# `gh api --paginate` output shape) and prints "<red|green|none> <conclusion-or->". `none`
|
|
113
|
+
# covers absent, skipped, stale, action_required, and still-running jobs alike: only a real
|
|
114
|
+
# conclusion is evidence.
|
|
115
|
+
job_verdict() {
|
|
116
|
+
local name="$1" pair
|
|
117
|
+
pair=$(jq -sr --arg n "$name" '
|
|
118
|
+
[ .[] | .jobs[]? | select(.name == $n) ] as $m
|
|
119
|
+
| if ($m | length) == 0 then "ABSENT -"
|
|
120
|
+
else (((($m | map(select(.status == "completed")) | .[0]) // $m[0]).status // "-")
|
|
121
|
+
+ " " + (((($m | map(select(.status == "completed")) | .[0]) // $m[0]).conclusion // "-"))) end') \
|
|
122
|
+
|| return 3
|
|
123
|
+
case "$pair" in
|
|
124
|
+
"completed failure"|"completed timed_out"|"completed cancelled"|"completed startup_failure") echo "red ${pair#* }" ;;
|
|
125
|
+
"completed success"|"completed neutral") echo "green ${pair#* }" ;;
|
|
126
|
+
*) echo "none ${pair#* }" ;;
|
|
127
|
+
esac
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
self_test() {
|
|
131
|
+
command -v jq >/dev/null 2>&1 || { echo "check-red-on-main: jq required for --self-test" >&2; exit 3; }
|
|
132
|
+
local name='deploy-script-tests (1/4)' fails=0
|
|
133
|
+
st() { # <want-verdict> <json-docs...>
|
|
134
|
+
local want="$1"; shift
|
|
135
|
+
local doc got=""
|
|
136
|
+
for doc in "$@"; do got+="$doc"$'\n'; done
|
|
137
|
+
got=$(printf '%s' "$got" | job_verdict "$name") || { echo " self-test: job_verdict errored" >&2; fails=$((fails + 1)); return; }
|
|
138
|
+
[[ "${got%% *}" == "$want" ]] || { echo " self-test: want $want, got '$got'" >&2; fails=$((fails + 1)); }
|
|
139
|
+
}
|
|
140
|
+
st red '{"jobs":[{"name":"deploy-script-tests (1/4)","status":"completed","conclusion":"failure"}]}'
|
|
141
|
+
st red '{"jobs":[{"name":"deploy-script-tests (1/4)","status":"completed","conclusion":"cancelled"}]}'
|
|
142
|
+
st red '{"jobs":[{"name":"deploy-script-tests (1/4)","status":"completed","conclusion":"timed_out"}]}'
|
|
143
|
+
st red '{"jobs":[{"name":"deploy-script-tests (1/4)","status":"completed","conclusion":"startup_failure"}]}'
|
|
144
|
+
st green '{"jobs":[{"name":"deploy-script-tests (1/4)","status":"completed","conclusion":"success"}]}'
|
|
145
|
+
st green '{"jobs":[{"name":"deploy-script-tests (1/4)","status":"completed","conclusion":"neutral"}]}'
|
|
146
|
+
st none '{"jobs":[{"name":"deploy-script-tests (1/4)","status":"completed","conclusion":"skipped"}]}'
|
|
147
|
+
st none '{"jobs":[{"name":"deploy-script-tests (1/4)","status":"completed","conclusion":"stale"}]}'
|
|
148
|
+
st none '{"jobs":[{"name":"deploy-script-tests (1/4)","status":"completed","conclusion":"action_required"}]}'
|
|
149
|
+
st none '{"jobs":[{"name":"deploy-script-tests (1/4)","status":"in_progress","conclusion":null}]}'
|
|
150
|
+
st none '{"jobs":[{"name":"deploy-script-tests","status":"completed","conclusion":"failure"}]}'
|
|
151
|
+
st none '{"jobs":[{"name":"lint","status":"completed","conclusion":"failure"}]}'
|
|
152
|
+
# two concatenated page objects (the --paginate output shape) must still find the job
|
|
153
|
+
st red '{"total_count":41,"jobs":[{"name":"lint","status":"completed","conclusion":"success"}]}' \
|
|
154
|
+
'{"total_count":41,"jobs":[{"name":"deploy-script-tests (1/4)","status":"completed","conclusion":"failure"}]}'
|
|
155
|
+
if (( fails > 0 )); then
|
|
156
|
+
printf 'SOLEUR_RED_ON_MAIN_SELFTEST failed (%s case(s))\n' "$fails" >&2; exit 3
|
|
157
|
+
fi
|
|
158
|
+
echo "SOLEUR_RED_ON_MAIN_SELFTEST ok"
|
|
159
|
+
exit 0
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
# ── args ──────────────────────────────────────────────────────────────────────────────────────
|
|
163
|
+
CHECK=""; RUN_ID=""; REPORT=0; REPO=""; SELFTEST=0
|
|
164
|
+
while [[ $# -gt 0 ]]; do
|
|
165
|
+
case "$1" in
|
|
166
|
+
--self-test) SELFTEST=1; shift ;;
|
|
167
|
+
--help|-h) usage; exit 0 ;;
|
|
168
|
+
--run-id)
|
|
169
|
+
[[ "${2-}" =~ ^[0-9]+$ ]] || usage_error "--run-id needs a numeric workflow-run id"
|
|
170
|
+
RUN_ID="$2"; shift 2 ;;
|
|
171
|
+
--report) REPORT=1; shift ;;
|
|
172
|
+
--repo)
|
|
173
|
+
[[ "${2-}" =~ ^[A-Za-z0-9_.-]+/[A-Za-z0-9_.-]+$ ]] || usage_error "--repo needs owner/repo"
|
|
174
|
+
REPO="$2"; shift 2 ;;
|
|
175
|
+
-*) usage_error "unknown flag $1" ;;
|
|
176
|
+
*) [[ -z "$CHECK" ]] || usage_error "unexpected extra argument $1"; CHECK="$1"; shift ;;
|
|
177
|
+
esac
|
|
178
|
+
done
|
|
179
|
+
(( SELFTEST == 1 )) && self_test
|
|
180
|
+
[[ -n "$CHECK" ]] || usage_error "<check-name> is required"
|
|
181
|
+
# Check names are PR-author-controlled text reaching the operator's terminal, the stdout
|
|
182
|
+
# marker, and (under --report) issue titles/bodies: control characters would let a crafted
|
|
183
|
+
# name forge terminal escapes, split the monitor's TSV rows, or break the sentinel.
|
|
184
|
+
[[ "$CHECK" != *'"'* && "$CHECK" != *'-->'* && "$CHECK" != *[[:cntrl:]]* && "$CHECK" != *$'\x7f'* ]] \
|
|
185
|
+
|| usage_error "check name cannot carry a double-quote, a control character, or '-->' (sentinel/marker safety)"
|
|
186
|
+
CHECK_OUT="$CHECK"
|
|
187
|
+
[[ -n "$RUN_ID" ]] || usage_error "--run-id <failing-run-id> is required"
|
|
188
|
+
|
|
189
|
+
for bin in gh jq; do
|
|
190
|
+
command -v "$bin" >/dev/null 2>&1 || { echo "check-red-on-main: ERROR: $bin not found on PATH" >&2; REASON="missing-tool"; marker error; exit 3; }
|
|
191
|
+
done
|
|
192
|
+
|
|
193
|
+
WORK="$(mktemp -d)" || { echo "check-red-on-main: ERROR: mktemp failed" >&2; REASON=mktemp; marker error; exit 3; }
|
|
194
|
+
trap 'rm -rf "$WORK"' EXIT
|
|
195
|
+
trap 'REASON=interrupted; marker error; exit 130' INT TERM HUP
|
|
196
|
+
|
|
197
|
+
# gh api has no -R/--repo flag: --repo is embedded in the endpoint path instead.
|
|
198
|
+
if [[ -n "$REPO" ]]; then RP="repos/$REPO"; REPO_ARG=(--repo "$REPO"); else RP="repos/{owner}/{repo}"; REPO_ARG=(); fi
|
|
199
|
+
|
|
200
|
+
# ── resolve the workflow through the failing run ─────────────────────────────────────────────
|
|
201
|
+
gh api "$RP/actions/runs/$RUN_ID" > "$WORK/run.json" 2>"$WORK/gh-err" \
|
|
202
|
+
|| die3 "gh api actions/runs/$RUN_ID failed: $(head -c 200 "$WORK/gh-err" | tr '\n' ' ')" api
|
|
203
|
+
jq -e 'type == "object" and (.workflow_id | type) == "number"' "$WORK/run.json" >/dev/null 2>&1 \
|
|
204
|
+
|| die3 "unparseable actions/runs/$RUN_ID response (no numeric workflow_id)" parse
|
|
205
|
+
WFID=$(jq -r '.workflow_id' "$WORK/run.json")
|
|
206
|
+
|
|
207
|
+
# ── windowed scan of completed main runs, newest first ───────────────────────────────────────
|
|
208
|
+
gh api "$RP/actions/workflows/$WFID/runs?branch=main&status=completed&per_page=5" > "$WORK/wfruns.json" 2>"$WORK/gh-err" \
|
|
209
|
+
|| die3 "gh api workflows/$WFID/runs failed: $(head -c 200 "$WORK/gh-err" | tr '\n' ' ')" api
|
|
210
|
+
jq -e 'type == "object" and (.workflow_runs | type) == "array"' "$WORK/wfruns.json" >/dev/null 2>&1 \
|
|
211
|
+
|| die3 "unparseable workflow-runs response" parse
|
|
212
|
+
IDS_RAW=$(jq -r '[.workflow_runs[:5][] | .id | select(type == "number")] | .[]' "$WORK/wfruns.json") \
|
|
213
|
+
|| die3 "unparseable workflow-runs response" parse
|
|
214
|
+
|
|
215
|
+
OUTCOME=""
|
|
216
|
+
while IFS= read -r rid; do
|
|
217
|
+
[[ -n "$rid" ]] || continue
|
|
218
|
+
# </dev/null: the run-id herestring feeds the loop's stdin; a gh flag that ever read stdin
|
|
219
|
+
# would drain it. Same guard on the report() close loop below.
|
|
220
|
+
gh api --paginate "$RP/actions/runs/$rid/jobs?per_page=100" > "$WORK/jobs.json" 2>"$WORK/gh-err" </dev/null \
|
|
221
|
+
|| die3 "gh api actions/runs/$rid/jobs failed: $(head -c 200 "$WORK/gh-err" | tr '\n' ' ')" api
|
|
222
|
+
jv=$(job_verdict "$CHECK" < "$WORK/jobs.json") \
|
|
223
|
+
|| die3 "unparseable jobs response for main run $rid" parse
|
|
224
|
+
case "${jv%% *}" in
|
|
225
|
+
red|green) OUTCOME="${jv%% *}"; MAIN_RUN="$rid"; MAIN_CONCL="${jv#* }"; break ;;
|
|
226
|
+
none) ;;
|
|
227
|
+
esac
|
|
228
|
+
done <<<"$IDS_RAW"
|
|
229
|
+
|
|
230
|
+
case "$OUTCOME" in
|
|
231
|
+
red) VERDICT=red-on-main; RC=1 ;;
|
|
232
|
+
green) VERDICT=green-on-main; RC=0 ;;
|
|
233
|
+
*) VERDICT=no-evidence; RC=2 ;;
|
|
234
|
+
esac
|
|
235
|
+
|
|
236
|
+
# ── --report: sentinel-keyed issue file/dedupe/close ─────────────────────────────────────────
|
|
237
|
+
report() {
|
|
238
|
+
local SENTINEL="<!-- soleur:red-on-main check=\"$CHECK\" -->"
|
|
239
|
+
local rc=0 open_json
|
|
240
|
+
# rc captured separately: `|| true` would collapse "no tracker" and "API error" into the same
|
|
241
|
+
# empty string, and the filer would file a duplicate on a transient failure (#1357 lesson).
|
|
242
|
+
# No --search: the issue LIST api is strongly consistent, while search indexes a new issue
|
|
243
|
+
# seconds-to-minutes late — two probes close together could then each file a duplicate
|
|
244
|
+
# tracker. Mirrors main-health-monitor's idiom: list the labeled issues, filter the
|
|
245
|
+
# sentinel locally.
|
|
246
|
+
open_json=$(gh issue list "${REPO_ARG[@]}" --label "ci/main-broken" --state open \
|
|
247
|
+
--json number,body --limit 100) || rc=$?
|
|
248
|
+
if [[ "$rc" -ne 0 ]] || ! jq -e 'type == "array"' <<<"$open_json" >/dev/null 2>&1; then
|
|
249
|
+
echo "check-red-on-main: could not list ci/main-broken issues (rc=$rc) -- not filing or closing anything, to avoid acting on a transient error" >&2
|
|
250
|
+
return 0
|
|
251
|
+
fi
|
|
252
|
+
|
|
253
|
+
if [[ "$VERDICT" == red-on-main ]]; then
|
|
254
|
+
# OLDEST first: gh issue list returns created-DESC, so .[0] unsorted is the NEWEST -- an
|
|
255
|
+
# older tracker would be orphaned and keep the file-new arm unreachable forever.
|
|
256
|
+
local existing
|
|
257
|
+
existing=$(jq -r --arg s "$SENTINEL" \
|
|
258
|
+
'[.[] | select(.body | type == "string" and contains($s)) | .number] | sort | .[0] // empty' \
|
|
259
|
+
<<<"$open_json" 2>/dev/null) || existing=""
|
|
260
|
+
if [[ -n "$existing" ]]; then
|
|
261
|
+
# >/dev/null: gh prints the comment URL on stdout — the marker is the only stdout line.
|
|
262
|
+
gh issue comment "$existing" "${REPO_ARG[@]}" --body \
|
|
263
|
+
"Still red on main: check \`$CHECK\` concluded $MAIN_CONCL on main run $MAIN_RUN. (probe run: $RUN_ID)" \
|
|
264
|
+
>/dev/null || echo "check-red-on-main: could not comment on #$existing" >&2
|
|
265
|
+
echo "check-red-on-main: commented on existing sentinel tracker #$existing" >&2
|
|
266
|
+
return 0
|
|
267
|
+
fi
|
|
268
|
+
gh label create "ci/main-broken" --force "${REPO_ARG[@]}" >/dev/null 2>&1 || true
|
|
269
|
+
local url
|
|
270
|
+
url=$(gh issue create "${REPO_ARG[@]}" \
|
|
271
|
+
--title "Red on main: $CHECK" \
|
|
272
|
+
--body "$(printf '%s\n' \
|
|
273
|
+
"$SENTINEL" \
|
|
274
|
+
"" \
|
|
275
|
+
"Check \`$CHECK\` is failing on main." \
|
|
276
|
+
"" \
|
|
277
|
+
"- Newest exercising main run: $MAIN_RUN (conclusion: $MAIN_CONCL)" \
|
|
278
|
+
"- Observed failing on PR-side run: $RUN_ID" \
|
|
279
|
+
"" \
|
|
280
|
+
"Filed by check-red-on-main.sh --report: this check is quarantined for PR rerun/fix" \
|
|
281
|
+
"decisions while it is red on main. This tracker is auto-closed when the check goes" \
|
|
282
|
+
"green on main again — to verify/close, re-run" \
|
|
283
|
+
"\`check-red-on-main.sh \"$CHECK\" --run-id <any run id of this workflow> --report\`;" \
|
|
284
|
+
"a green verdict closes this issue.")" \
|
|
285
|
+
--label "ci/main-broken" --label "meta/machinery" --label "type/chore" \
|
|
286
|
+
--milestone "Post-MVP / Later" 2>/dev/null) || url=""
|
|
287
|
+
if [[ -n "$url" ]]; then
|
|
288
|
+
echo "check-red-on-main: filed tracker $url" >&2
|
|
289
|
+
else
|
|
290
|
+
echo "check-red-on-main: issue create failed -- the red-on-main verdict stands but no tracker was filed" >&2
|
|
291
|
+
fi
|
|
292
|
+
return 0
|
|
293
|
+
fi
|
|
294
|
+
|
|
295
|
+
# green-on-main: comment-and-close ONLY issues carrying OUR sentinel for this check name --
|
|
296
|
+
# every one of them, never a human-filed or other-sentinel tracker.
|
|
297
|
+
local mine n
|
|
298
|
+
mine=$(jq -r --arg s "$SENTINEL" \
|
|
299
|
+
'[.[] | select(.body | type == "string" and contains($s)) | .number] | sort | .[]' \
|
|
300
|
+
<<<"$open_json" 2>/dev/null) || mine=""
|
|
301
|
+
while IFS= read -r n; do
|
|
302
|
+
[[ -n "$n" ]] || continue
|
|
303
|
+
gh issue close "$n" "${REPO_ARG[@]}" --comment \
|
|
304
|
+
"Check \`$CHECK\` is green on main again (run $MAIN_RUN, conclusion $MAIN_CONCL). Auto-closing." \
|
|
305
|
+
>/dev/null </dev/null || echo "check-red-on-main: could not close #$n" >&2
|
|
306
|
+
echo "check-red-on-main: closed sentinel tracker #$n -- main is green again" >&2
|
|
307
|
+
done <<<"$mine"
|
|
308
|
+
return 0
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
if (( REPORT == 1 )) && [[ "$VERDICT" == red-on-main || "$VERDICT" == green-on-main ]]; then
|
|
312
|
+
report
|
|
313
|
+
fi
|
|
314
|
+
|
|
315
|
+
marker "$VERDICT"
|
|
316
|
+
exit "$RC"
|