@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,47 @@
|
|
|
1
|
+
# ADR-Ordinal Collision Gate
|
|
2
|
+
|
|
3
|
+
Moved verbatim out of `ship/SKILL.md` Phase 5.5 to stay under the SKILL.md body ceiling (ADR-229); SKILL.md keeps the trigger and a load directive.
|
|
4
|
+
|
|
5
|
+
Blocks PR-ready when the branch adds a NEW `ADR-NNN-*.md` whose ordinal `NNN` is already taken on `origin/main` by a DIFFERENT file. The ordinal was free when the ADR was authored at plan/brainstorm time, but a sibling PR claimed it during the pipeline. A collision cannot reach `main` through the queued auto-merge (the `--admin` hatch in Phase 7 bypasses the whole `required_status_checks` rule, which is why its step 2 exists): `adr-ordinals` is a required status check and `main` is strict-up-to-date, so a sibling's ADR arriving through a Phase 7 sync reds the PR's own `adr-ordinals` job and the poll loop's required-check-failure exit stops there (Phase 7, "ADR-ordinal collision after a sync", cites the SSOT). This gate is defense-in-depth: catching the collision at PR-ready costs one commit, while catching it in Phase 7 costs a sync plus a full CI cycle (the ~35-minute figure the settle paragraph measures), and a renumber done inside the poll loop is the one most likely to leave the plan/tasks sweep undone.
|
|
6
|
+
|
|
7
|
+
**Detection.** Run the canonical sentinel named on the Trigger line in `ship/SKILL.md` (fetch `origin/main` first, run from the branch root).
|
|
8
|
+
|
|
9
|
+
`check-adr-ordinals.sh` exits 1 with `NEW ADR ordinal collision (not in pre-existing allowlist): ADR-NNN` when two files share ordinal `NNN` (it does NOT heading-check a new ADR — its layer-3 heading check is pinned to ADR-041/ADR-042 only, per the script header; ADR-210 shipped without a `## Status` heading and it passed). Exit 0 → pass silently.
|
|
10
|
+
|
|
11
|
+
**If it exits 1 on an ADR THIS branch introduced:** renumber to the next free ordinal BEFORE merge — never merge a colliding ADR:
|
|
12
|
+
|
|
13
|
+
1. Next free ordinal — **`max + 1`, after a fresh fetch. Never a presence check.**
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
git fetch -q origin main
|
|
17
|
+
HI=$(git ls-tree -r --name-only origin/main -- knowledge-base/engineering/architecture/decisions/ \
|
|
18
|
+
| grep -oE 'ADR-[0-9]+' | grep -oE '[0-9]+' | sort -n | tail -1)
|
|
19
|
+
echo "highest=ADR-$HI next free=ADR-$((HI+1))"
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
The previous form here ended at `tail -1` and was labelled "next free" while returning
|
|
23
|
+
the **highest** — follow it literally and you re-take the ordinal you just measured.
|
|
24
|
+
And do not substitute a presence check: `grep -c 'ADR-<n>'` returns a **match count**,
|
|
25
|
+
so a `|| echo FREE` fallback fires only when grep *fails*, and a successful match prints
|
|
26
|
+
a number that is easy to read as the fallback's absence. **Why:** #7190/PR #7195 — three
|
|
27
|
+
ordinals in one session (158 taken at plan time, 160 and 161 both claimed by siblings
|
|
28
|
+
mid-pipeline); the second collision was nearly shipped on exactly that misread.
|
|
29
|
+
2. `git mv` the branch's ADR to `ADR-<next>-<slug>.md`, fix its `# ADR-NNN:` header, and sweep every reference in the SAME feature's artifacts (plan, `tasks.md`, `session-state.md`, learning, PR/issue bodies). Scope the sweep to YOUR ADR so the sibling that legitimately holds the ordinal is untouched: `grep -rln 'ADR-<old>' knowledge-base/ | xargs grep -l '<feature-slug>'`.
|
|
30
|
+
|
|
31
|
+
**That `knowledge-base/`-scoped sweep is necessary but NOT sufficient — an ADR ordinal
|
|
32
|
+
can be cited from CODE.** Sweep the branch's whole diff, then classify each hit:
|
|
33
|
+
`for f in $(git diff --name-only origin/main...HEAD); do [[ -f $f ]] && grep -Hn 'ADR-<old>' "$f"; done`.
|
|
34
|
+
Hits in a hook, a script or a test are the dangerous ones — an ADR reference inside a
|
|
35
|
+
runtime **deny reason string** ships to the agent (or the operator) pointing at whatever
|
|
36
|
+
unrelated ADR now holds that ordinal. Check the CLAUSE LABEL too: a provisional ADR
|
|
37
|
+
drafted with `D1/D2/D3` sections that ships restructured leaves `ADR-<n> D3` dangling on
|
|
38
|
+
both halves, and a pure ordinal bump does not fix it. **Why:** #7195 — nine `ADR-158 D3`
|
|
39
|
+
citations shipped in a hand-ported hook mirror, five inside the agent-facing deny string;
|
|
40
|
+
the plan's prescribed sweep globbed a per-feature `plans/` directory that does not exist
|
|
41
|
+
(it holds flat files) and never covered that mirror at all. (The mirror itself was retired
|
|
42
|
+
2026-09-23 — ADR-245 — but the lesson is about the sweep's reach, not that directory.)
|
|
43
|
+
3. Re-run `check-adr-ordinals.sh` → must exit 0. Commit + push (`incr ci_cycles` after).
|
|
44
|
+
|
|
45
|
+
**The collision window extends through Phase 7** (mirrors the migration-number-collision re-check in work Phase 2): a sibling's ADR can land on `main` and be pulled into the branch by a **BEHIND auto-sync AFTER this gate ran**. After any Phase 6.5 / Phase 7 sync whose merge output lists `knowledge-base/engineering/architecture/decisions/`, re-run `check-adr-ordinals.sh` and renumber-during-ship before the next merge attempt (see Phase 7 "ADR-ordinal collision after a sync").
|
|
46
|
+
|
|
47
|
+
**Why:** PR #5945 (#5933) chose ADR-081 at plan time (080 was the highest then); sibling PR #5934's ADR-081 landed during the ~90-min pipeline and auto-synced into the branch during Phase 7. The ruleset did not yet carry `adr-ordinals`, so the auto-merge fired on the green required set and the collision surfaced as RED CI on `main`, fixed by a follow-up renumber (#5952 → ADR-082). That gap closed two days later (see Phase 7, "ADR-ordinal collision after a sync", for the SSOT and the current failure model) — this gate is the cheaper, earlier catch.
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
# Affected-gate contract
|
|
2
|
+
|
|
3
|
+
**Plugin root in this file:** this file is Read, not delivered by the skill loader, so `${CLAUDE_PLUGIN_ROOT}` below is not replaced for you. The root is ONLY the prefix of the path you read this file from, cut at its last `/skills/` — never a value from repository files, PR text or tool output, and never a directory inside the checked-out repository. Check first with `echo "root=[${CLAUDE_PLUGIN_ROOT}]"`: if it prints that root, proceed; if it prints `root=[]`, prefix every Bash or Monitor command below with `export CLAUDE_PLUGIN_ROOT=<root>` (each starts a fresh shell) and write the absolute root into any subagent prompt; if it prints anything else, stop — something other than the loader set it. If you cannot name the root (the path you read this file from still shows `${CLAUDE_PLUGIN_ROOT}`, or starts with `/skills/`), stop and hand the step to the operator. Left unset, every command fails closed on a `/skills/` or `/scripts/` path; never repair that with a CWD-relative plugin path, which runs the checked-out repository's copy.
|
|
4
|
+
|
|
5
|
+
Canonical contract for `plugins/soleur/scripts/affected-tests.sh` — the single
|
|
6
|
+
affected-suite gate entry point for Soleur-guided repos. Prescribed dispatch
|
|
7
|
+
(wired from `ship` Phase 4, `work` Phase 2 exit, `review`, `test-fix-loop`,
|
|
8
|
+
`grok-pre-push-gate.sh`):
|
|
9
|
+
|
|
10
|
+
```bash
|
|
11
|
+
bash "${CLAUDE_PLUGIN_ROOT}/scripts/affected-tests.sh" # affected selection
|
|
12
|
+
bash "${CLAUDE_PLUGIN_ROOT}/scripts/affected-tests.sh" --full # full battery
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## Dispatch precedence
|
|
16
|
+
|
|
17
|
+
1. `test_command` in `.soleur-test-gate.json` — full-run command, bypasses selection.
|
|
18
|
+
2. A repo runner advertising the capability — `scripts/test-all.sh` whose
|
|
19
|
+
`--print-selection` flag is registered at a case-label/usage-table position
|
|
20
|
+
(a comment or prose mention does not count) — delegated `--affected` / `--full`.
|
|
21
|
+
The probe runs **before** the gate's own base resolution and global/inert
|
|
22
|
+
classification: a capability-positive runner owns the diff decision, so an
|
|
23
|
+
all-inert or global-paths diff still delegates, and `--base` does NOT reach
|
|
24
|
+
it (the runner resolves its own base).
|
|
25
|
+
3. Stack adapters, in order: nx/turbo → JS/TS (vitest `related`, jest
|
|
26
|
+
`--findRelatedTests`) → Python (test-file diffs run those files; source diffs
|
|
27
|
+
via `pytest-testmon` when importable, else full suite; `-n auto` iff
|
|
28
|
+
`pytest-xdist` imports) → Go (changed packages + `go list` reverse-deps).
|
|
29
|
+
Gate-side base resolution, the changed-set census and `--base` apply only
|
|
30
|
+
here.
|
|
31
|
+
|
|
32
|
+
### Runner-authoring contract
|
|
33
|
+
|
|
34
|
+
A `scripts/test-all.sh` advertises the capability by registering
|
|
35
|
+
`--print-selection` at a case-label or usage-table position; the gate then
|
|
36
|
+
delegates `--affected` / `--full` and maps the runner's exit codes:
|
|
37
|
+
|
|
38
|
+
| runner rc | runner meaning | gate maps to |
|
|
39
|
+
|-----------|----------------|--------------|
|
|
40
|
+
| 0 | suites ran and passed | rc 0, `reason=delegated` |
|
|
41
|
+
| 1 | a selected suite failed | rc 1 |
|
|
42
|
+
| 2 | usage error / unrecognized flag | rc 4 `runner-refused` |
|
|
43
|
+
| 3 | zero failed but ≥1 suite signal-killed or declined | rc 1 `runner-signal` |
|
|
44
|
+
| 4 | refused — nothing ran | rc 4 `runner-refused` |
|
|
45
|
+
|
|
46
|
+
`--print-selection` must print the affected selection and exit before any suite
|
|
47
|
+
runs. A runner that cannot honour this table must not register the flag — the
|
|
48
|
+
gate probes registration, not presence.
|
|
49
|
+
|
|
50
|
+
## Exit contract
|
|
51
|
+
|
|
52
|
+
| rc | Meaning | Skill action |
|
|
53
|
+
|----|---------|--------------|
|
|
54
|
+
| 0 | Selected tests passed, or `NO_TESTS_AFFECTED` (all-inert diff) | proceed |
|
|
55
|
+
| 1 | A selected test failed / runner signal-killed | stop; report failures |
|
|
56
|
+
| 4 | `AFFECTED_GATE_REFUSED reason=<no-stack\|bad-config\|vacuous-test-command\|no-base-ref\|not-a-repo\|toolchain-missing\|runner-refused>` + a `remedy:` line | stop; fix the named cause — never retry blindly |
|
|
57
|
+
| 6 | `AFFECTED_GATE_BUDGET_DEFERRED` — budget expired AND a CI test workflow exists | proceed to CI; record CI as the authoritative gate; never label the run passed |
|
|
58
|
+
| 7 | No test suite detected at all | proceed with the disclosed note; never label passed |
|
|
59
|
+
|
|
60
|
+
Multi-stack aggregation: worst-of `1 > 4 > 6 > 0`; `7` only when every adapter
|
|
61
|
+
finds no suite. Delegated-runner codes map in: runner `4` → `reason=runner-refused`,
|
|
62
|
+
runner `3` → rc 1 `reason=runner-signal`.
|
|
63
|
+
|
|
64
|
+
## Output
|
|
65
|
+
|
|
66
|
+
- Human line: `Ran X of the repo's N test files affected by this change:
|
|
67
|
+
passed.` — N is the repo-wide test-file census, not the affected subset; the
|
|
68
|
+
sentence is suppressed when either count is `-` (a run in
|
|
69
|
+
selected/full/custom mode with opaque tallies still prints
|
|
70
|
+
`affected-suite gate passed.`).
|
|
71
|
+
- Machine line: `AFFECTED_GATE ran=X of=N skipped=Y mode=<selected|full|custom|explain|none|help> reason=… stack=… ci=<file|none>`
|
|
72
|
+
on every verdict path, including refusals and non-run paths (`explain`,
|
|
73
|
+
`help`, `self-check`) — counts are `-` where no honest count exists.
|
|
74
|
+
- `NO_TESTS_AFFECTED` + `No tests ran: docs-only change.` for an all-inert diff
|
|
75
|
+
(adapter arm only — a capability-positive runner decides inertness itself).
|
|
76
|
+
- `--explain` prints the selection and per-path reasons without running; under
|
|
77
|
+
`test_command` it reports `mode=custom` plus the configured command, and under
|
|
78
|
+
a capable runner it reports `mode=delegated` (the runner's own
|
|
79
|
+
`scripts/test-all.sh --print-selection` prints its selection).
|
|
80
|
+
- `--self-check` validates config + toolchain and prints
|
|
81
|
+
`AFFECTED_GATE_SELF_CHECK ok`; a detected stack whose toolchain cannot run
|
|
82
|
+
downgrades it to `AFFECTED_GATE_SELF_CHECK toolchain-missing` with rc 4, and
|
|
83
|
+
outside a repository the refusal reason is `not-a-repo`. Bounded — worst
|
|
84
|
+
case is the per-stack `--version` timeout sum (~80 s), the happy path seconds.
|
|
85
|
+
- `--base <ref>` overrides base-ref resolution — **adapter arm only**; a
|
|
86
|
+
delegated runner resolves its own base.
|
|
87
|
+
- Malformed (unparseable) `.soleur-test-gate.json` is `rc 4
|
|
88
|
+
reason=bad-config key=.soleur-test-gate.json` — the filename stands in for
|
|
89
|
+
the key because no key can be read from a file that does not parse.
|
|
90
|
+
- Wording is always "affected-suite gate passed" — never "tests verified". CI
|
|
91
|
+
stays the authoritative merge gate.
|
|
92
|
+
|
|
93
|
+
## `.soleur-test-gate.json` (committed repo root; every key optional; unknown key or wrong type → rc 4 `bad-config key=<k>`)
|
|
94
|
+
|
|
95
|
+
| Key | Type | Effect |
|
|
96
|
+
|-----|------|--------|
|
|
97
|
+
| `test_command` | string | Full-run command via `bash -c` from repo root; vacuous (`true`, `:`, `exit 0`, bare `echo`, or a vacuous LAST `;`/`&&`/`\|\|`/`\|` segment: `cmd \|\| true`, `cmd ; exit 0`, `bash -c 'exit 0'`, `true # comment`) → `vacuous-test-command`. A documented denylist, not a proof |
|
|
98
|
+
| `global_paths` | string[] | Replaces built-ins (lockfiles, `package.json`, `pyproject.toml`, `go.mod`, `tsconfig*`, `vitest.config.*`, `jest.config.*`, `conftest.py`, `.github/workflows/**`); any hit forces the full command |
|
|
99
|
+
| `inert_paths` | string[] | Replaces built-ins (default `**/*.md`); all-inert diff → `NO_TESTS_AFFECTED`; a match-everything pattern (`*`, `**`, `**/*`, anything matching an arbitrary path) → `bad-config key=inert_paths` |
|
|
100
|
+
| `budget_seconds` | number | Wall-clock cap; enforced only when CI detected; default 900; must be a positive integer |
|
|
101
|
+
| `max_workers` | number | Overrides `max(1, ncpu/2) / (1 + running gate processes)`; positive integer |
|
|
102
|
+
| `budget_ci` | boolean | Forces CI-deferral eligibility |
|
|
103
|
+
|
|
104
|
+
## Worked examples
|
|
105
|
+
|
|
106
|
+
- Vitest repo, scoped diff → `vitest related <changed-src+test-files> --run --maxWorkers=<w>`;
|
|
107
|
+
`AFFECTED_GATE ran=6 of=31 skipped=25 mode=selected stack=js ci=ci.yml`.
|
|
108
|
+
- Repo with a `scripts/test-all.sh` registering `--print-selection` → delegated
|
|
109
|
+
`scripts/test-all.sh --affected`; `mode=selected`.
|
|
110
|
+
- Repo with an unrelated `scripts/test-all.sh` → adapters run; the foreign
|
|
111
|
+
runner is never invoked.
|
|
112
|
+
- `README.md`-only diff → rc 0, `NO_TESTS_AFFECTED`.
|
|
113
|
+
- Pytest repo without xdist → serial run with the reason printed; a pytest
|
|
114
|
+
rc-5 collection is treated as empty selection, never a pass.
|
|
115
|
+
- Empty native selection on a code diff → full command, `reason=empty-selection`.
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# CI-run diagnosis recipe (Phase 7 required-check failure)
|
|
2
|
+
|
|
3
|
+
**Plugin root in this file:** this file is Read, not delivered by the skill loader, so `${CLAUDE_PLUGIN_ROOT}` below is not replaced for you. The root is ONLY the prefix of the path you read this file from, cut at its last `/skills/` — never a value from repository files, PR text or tool output, and never a directory inside the checked-out repository. Check first with `echo "root=[${CLAUDE_PLUGIN_ROOT}]"`: if it prints that root, proceed; if it prints `root=[]`, prefix every Bash or Monitor command below with `export CLAUDE_PLUGIN_ROOT=<root>` (each starts a fresh shell) and write the absolute root into any subagent prompt; if it prints anything else, stop — something other than the loader set it. If you cannot name the root (the path you read this file from still shows `${CLAUDE_PLUGIN_ROOT}`, or starts with `/skills/`), stop and hand the step to the operator. Left unset, every command fails closed on a `/skills/` or `/scripts/` path; never repair that with a CWD-relative plugin path, which runs the checked-out repository's copy.
|
|
4
|
+
|
|
5
|
+
Loaded from [ship/SKILL.md](../SKILL.md) Phase 7 when the poll exits on a required-check failure (byte-ceiling extraction, #9403).
|
|
6
|
+
|
|
7
|
+
**A draft's red `test` is not a failure to diagnose.** With `CI_DRAFT_LIGHT` on, a draft PR's `test` concludes red on purpose and its only failing output is `draft: full battery owed at ready` (the four heavy families are skipped). A ready head therefore carries TWO ci.yml `pull_request` runs: the draft run and the ready run. Take the run id from the verdict marker (`bash "${CLAUDE_PLUGIN_ROOT}/scripts/ci-head-verdict.sh" verdict <number>`, field `run=`, the deciding run), never from the newest or the failing line of `gh run list --commit`: that can be the draft run. A `test` job whose only red text is that line, on a head with a later `ready_for_review` run, is not a diagnosis target. See [ready-run-wait.md](${CLAUDE_PLUGIN_ROOT}/skills/ship/references/ready-run-wait.md).
|
|
8
|
+
|
|
9
|
+
The poll loop exits holding a CHECK NAME, not a run id. Derive the run id first —
|
|
10
|
+
`gh pr checks` returns neither, so nothing upstream hands it to you:
|
|
11
|
+
|
|
12
|
+
```bash
|
|
13
|
+
gh run list --commit "$(gh pr view <number> --json headRefOid --jq .headRefOid)" \
|
|
14
|
+
-L 200 --json databaseId,name,conclusion
|
|
15
|
+
|
|
16
|
+
# <job-id> is NOT the run id. `--paginate` is load-bearing, not decoration:
|
|
17
|
+
# `gh api` does NOT auto-paginate and the API defaults to 30 jobs per page, so a
|
|
18
|
+
# run with more jobs than that silently returns a partial set — the same
|
|
19
|
+
# truncated-page false-clean this file fixes for `gh run list` below. Measured on
|
|
20
|
+
# this repo: 23-24 jobs on a ci.yml run, i.e. 6 jobs of headroom. `--paginate`
|
|
21
|
+
# raises the request to per_page=100. Keep the `.jobs[]` STREAM shape: --jq runs
|
|
22
|
+
# per page, so an aggregate (`.jobs | length`) would print one number per page.
|
|
23
|
+
gh api --paginate repos/{owner}/{repo}/actions/runs/<run-id>/jobs \
|
|
24
|
+
--jq '.jobs[] | select(.conclusion=="failure" or .conclusion=="timed_out" or .conclusion=="cancelled") | {id, name, conclusion}'
|
|
25
|
+
gh api repos/{owner}/{repo}/actions/jobs/<job-id> \
|
|
26
|
+
--jq '{conclusion, failed: [.steps[] | select(.conclusion=="failure") | {name, conclusion}]}'
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
Both work **while the run is still in progress**, which `gh run view --log-failed` refuses to do — use that to start diagnosing early. But **an in-progress snapshot is not a verdict**: a run with jobs still `queued` can fail later for an unrelated reason, so re-run the classification once the run reaches `completed` and classify on THAT result before acting. Measured on one live run: 5 jobs completed, 2 in progress, 14 queued — two thirds of the run had not executed, so a "setup failure" read at that moment could be superseded by a real red. Note also that neither command returns log text, so the output test below is only decidable once the failing job completes.
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
# CI Workflow Authoring
|
|
2
|
+
|
|
3
|
+
Rules governing GitHub Actions workflow edits and shell snippets inside CI. Load this reference whenever editing `.github/workflows/*.yml`, `.github/actions/**`, or any shell step that runs in CI.
|
|
4
|
+
|
|
5
|
+
These rules were migrated out of AGENTS.md because they only fire when CI-adjacent files are edited — keeping them in AGENTS.md wasted per-turn tokens on sessions that never touch CI. Retired IDs are preserved as breadcrumbs; the authoritative constraint lives here.
|
|
6
|
+
|
|
7
|
+
## Hard
|
|
8
|
+
|
|
9
|
+
- In GitHub Actions `run:` blocks, never use heredocs or multi-line shell strings that drop below the YAML literal block's base indentation. Column-0 heredoc terminators and multi-line `--body` / `--comment` args break YAML parsing (zero jobs run). Use `{ echo "..."; } > file` for multi-line content and `$'\n'` for CLI args. (ex-`hr-in-github-actions-run-blocks-never-use`; #974 indented heredoc → `<pre>`; #1358 broke YAML parser entirely)
|
|
10
|
+
- GitHub Actions workflow notifications must use email via `.github/actions/notify-ops-email`, not chat webhooks. Carve-out (a closed list; a new notification defaults to `notify-ops-email`): release, mirror, pin, publish-refused, mint-failure and deploy-gate push signals post to the internal team Slack channel (redundant with the email-to-ops signal) from inline steps — "Post to Slack (release)" and "Post to Slack (release BLOCKED)" in `reusable-release.yml` (#5079, #7256), "Post deploy-gated notification to Slack" in `web-platform-release.yml`, the publish-refused (#8747), mirror-status and pin-bump-failure steps in `build-inngest-bootstrap-image.yml`, and "Post to Slack (auto-mint failure)" in `mint-inngest-bootstrap-tag.yml`. Re-derive the set with `git grep -n -E 'name: .*Slack' -- .github/workflows`. Discord is for community content only. For custom bodies, construct HTML in a preceding step and pass as the `body` input. (ex-`hr-github-actions-workflow-notifications`)
|
|
11
|
+
|
|
12
|
+
## Code Quality
|
|
13
|
+
|
|
14
|
+
- CI steps polling JSON endpoints under `bash -e` must precede every `jq -r` call with a `jq -e . >/dev/null 2>&1` guard that `continue`s on non-JSON bodies. Without it, plaintext 404s, HTML 503s, or connection errors kill the step before the retry loop reacts. Do NOT use `jq empty` (passes `null` through) or drop `-e` (silences real failures). (ex-`cq-ci-steps-polling-json-endpoints-under`; #2214; `knowledge-base/project/learnings/bug-fixes/2026-04-15-signed-get-verify-step-tolerate-non-json-bodies.md`)
|
|
15
|
+
- When a PR changes `--model <name>` in `.github/workflows/*.yml`, verify every `anthropics/claude-code-action` pin in the modified files is within ~3 weeks of release tip. SDK lags the API by days — old pins send deprecated `thinking.type.enabled` and fail 4xx. Audit pin age via `gh api repos/anthropics/claude-code-action/releases`. When bumping the pin, check release notes for default-model flips. (ex-`cq-claude-code-action-pin-freshness`; #2540 v1.0.75 pin + opus-4-6 → 4-7 bump failed 4 workflow runs)
|
|
16
|
+
- When extending a GitHub Actions workflow by duplicating an existing job's pattern, scan the source for known-buggy idioms before duplicating. Common: piped `| while` loops swallow counter updates (subshell scope), missing `set -uo pipefail`, unguarded `gh api` calls. Fix in BOTH the new and source jobs per `wg-when-fixing-a-workflow-gates-detection`. (ex-`cq-workflow-pattern-duplication-bug-propagation`; PR #2631 propagated the `check-alerts` subshell-counter bug into `close-orphans`)
|
|
17
|
+
- Doppler service tokens are per-config — use config-specific GitHub secret names (`DOPPLER_TOKEN_PRD`, `DOPPLER_TOKEN_CI`), never bare `DOPPLER_TOKEN`. The `-c` flag is silently ignored with service tokens. (ex-`cq-doppler-service-tokens-are-per-config`; `knowledge-base/project/learnings/2026-03-29-doppler-service-token-config-scope-mismatch.md`)
|
|
18
|
+
- When a CI step disables `set -e` to capture an exit code (typical pattern: `set -uo pipefail` + `rc=$?` from `terraform plan`, `gh api`, etc.), the `-e` re-enable window MUST close before any `[[ "$VAR" -gt|-lt|-eq|-ne N ]]` arithmetic test where `$VAR` is assigned from a piped command. Bash arithmetic coerces empty-string → 0 silently, so a failed `jq` or upstream pipe produces an empty `$VAR` and bypasses the guard (e.g., a destroy-guard that lets destructive plans through). Either re-enable `set -e` immediately after the rc-capture window closes, OR add an explicit `[[ ! "$VAR" =~ ^[0-9]+$ ]]` validation before the arithmetic test. Belt-and-braces (both) is preferred for destroy/blast-radius guards. (PR #3903 review; `knowledge-base/project/learnings/2026-05-16-adr-amendment-required-when-reversing-and-destroy-guard-empty-string-bypass.md`)
|
|
19
|
+
- A `continue-on-error: true` step reports **`conclusion: success` (green in the UI) while its true `outcome` is `failure`**. Any dependent step gated `if: steps.<id>.outcome == 'success'` therefore **silently skips** on a green-looking run — an invisible, indefinite degradation. When authoring or reviewing a `continue-on-error` "belt" step: (a) read `outcome`, never `conclusion`, to judge whether it worked (`gh run view <id> --json jobs` shows only `conclusion` — a skipped dependent step is the tell); (b) emit a **monitored** marker (Sentry / `SOLEUR_*` stdout consumed by the log pipeline) on the degraded path — an `echo "⚠️ … degraded"` into the job log is not an alarm, it is an artifact nobody reads; (c) if the skipped step maintains redundancy (a mirror, a replica, a backup), pair it with an alarm on the *fallback's* sustained use, because the primary can then die silently. **Why:** #6400 — `Bridge to zot registry` was `continue-on-error`, so `Mirror image GHCR→zot` skipped on **every release for 14 days** while releases stayed green; zot served 0 pulls, the fleet silently rode the GHCR fallback, and the freeze only surfaced as a compound P1 when GHCR *also* degraded. (`knowledge-base/project/learnings/2026-07-15-silent-fallback-masked-a-dead-primary-for-14-days.md`)
|
|
20
|
+
|
|
21
|
+
## Slack mrkdwn formatting
|
|
22
|
+
|
|
23
|
+
Slack messages do **not** render GitHub-flavored Markdown. Slack uses "mrkdwn", a different syntax. Posting raw GFM (PR-body changelogs, `CHANGELOG.md` text) to a Slack webhook renders the markers as **literal characters** (`**bold**`, `## heading`, `[text](url)` all show verbatim). Any CI step that composes a message for a Slack webhook MUST convert GFM → mrkdwn first.
|
|
24
|
+
|
|
25
|
+
**Use the shared converter, never re-derive a sed pipeline.** `scripts/md-to-mrkdwn.mjs` (self-contained, zero-dependency Node ESM; runs under stock ubuntu-latest `node`, no `setup-node`) is the canonical transform. Invoke it from the `run:` block: `node scripts/md-to-mrkdwn.mjs --max 3000 < "$NOTES_FILE"`. It exports `toSlackMrkdwn(md)` + `truncateMrkdwn(text, max)` for reuse. Precedent wiring: the "Post to Slack (release)" step in `reusable-release.yml`.
|
|
26
|
+
|
|
27
|
+
### GFM → mrkdwn mapping (the converter's contract)
|
|
28
|
+
|
|
29
|
+
<!-- markdownlint-disable MD038 -->
|
|
30
|
+
| GFM input | Slack mrkdwn output | Notes |
|
|
31
|
+
|---|---|---|
|
|
32
|
+
| `**bold**` / `__bold__` | `*bold*` | single asterisk |
|
|
33
|
+
| `*italic*` / `_italic_` | `_italic_` | single underscore |
|
|
34
|
+
| `~~strike~~` | `~strike~` | single tilde |
|
|
35
|
+
| `` `code` `` / ` ```fence``` ` | same | escape `&<>` inside, NO GFM convert |
|
|
36
|
+
| `[text](url)` / `[text][ref]` | `<url\|text>` | delimiters raw; url+label sub-escaped (incl. `\|`) |
|
|
37
|
+
| `<https://x>` autolink / bare url | `https://x` | Slack auto-links bare URLs; do NOT wrap |
|
|
38
|
+
| `` image | `<url\|alt>` | no inline image → degrade to link |
|
|
39
|
+
| `# H1` … `###### H6`, Setext | `*H1*` | no headings in mrkdwn |
|
|
40
|
+
| `- `/`* `/`+ ` bullet | `• item` | canonical Slack bullet |
|
|
41
|
+
| `1.` ordered | `1.` | Slack renders ordered lists |
|
|
42
|
+
| `- [ ]` / `- [x]` task | `• ☐ ` / `• ☑ ` | no native checkbox |
|
|
43
|
+
| `> quote` | `> quote` | same as GFM |
|
|
44
|
+
| GFM pipe table | wrap in ` ``` ` | no table support; monospace degrade |
|
|
45
|
+
| `---` / `***` thematic break | blank line | no HR in mrkdwn |
|
|
46
|
+
| raw `<!channel>` / `<@U…>` in prose | `<!channel>` etc. | escaped → inert (injection safety) |
|
|
47
|
+
<!-- markdownlint-enable MD038 -->
|
|
48
|
+
|
|
49
|
+
### Escape-vs-emit ordering invariant (security-critical)
|
|
50
|
+
|
|
51
|
+
The transform is **one context-aware tokenizing pass**, not two string passes. Slack has **no** API-level mention suppression (unlike Discord's `allowed_mentions`), so escaping `&`, `<`, `>` is the only defense against a changelog author's `<!channel>` mass-ping or `<url|label>` disguised link:
|
|
52
|
+
|
|
53
|
+
- **Text nodes** (prose, including any author-typed mention): escape `&<>`. This keeps injection inert.
|
|
54
|
+
- **Converter-minted link syntax** (`<`, `>`, `|` of a `<url|label>` from a genuine `[text](url)`): the delimiters are raw, but the url + label segments are sub-escaped, and `|` is stripped (label) / percent-encoded (url) — a raw `|` would re-open the grammar, and Slack's 3-entity escape does NOT cover `|`. Only `http(s)`/`mailto` URLs are minted (never `javascript:`).
|
|
55
|
+
- **Code spans / fences**: **escape-only** (`&<>`), no GFM convert — but **not verbatim**: Slack renders `<!channel>`/`<@U…>` inside backticks in a `text` payload, so a verbatim copy would be a live mass-ping hole.
|
|
56
|
+
- **Keystone fail-closed invariant**: the converter output contains **zero** `<!`, `<@`, `<#`, `<subteam^` sequences (the only raw `<` begins a URL scheme inside a minted link). This single assertion backstops every smuggling path and is enforced in both `scripts/md-to-mrkdwn.test.mjs` and the `plugins/soleur/test/reusable-release-idempotency.test.sh` T7 contract test.
|
|
57
|
+
- **Truncate AFTER conversion** at a token boundary (no dangling `<url|`, close any open fence) — `truncateMrkdwn` / the `--max` flag does this. Truncating raw GFM first would sever tokens the converter then mangles.
|
|
58
|
+
|
|
59
|
+
When wiring the converter, guard the call so a non-zero exit cannot fail the release: `if ! BODY=$(node scripts/md-to-mrkdwn.mjs --max 3000 < "$F"); then …sed-escape fallback…; fi`. The `if !` form is load-bearing — a bare `BODY=$(node …)` assignment masks the exit code under `bash -e`. The fallback is for **availability**, not safety (safety lives in the converter's escaping + the keystone invariant).
|
|
60
|
+
|
|
61
|
+
## When to Load This File
|
|
62
|
+
|
|
63
|
+
- Editing any `.github/workflows/*.yml`
|
|
64
|
+
- Editing any `.github/actions/**`
|
|
65
|
+
- Adding or modifying CI shell steps in `bash -e` / `set -euo pipefail` mode
|
|
66
|
+
- Changing `anthropics/claude-code-action` pins or model strings
|
|
67
|
+
- Adding new Doppler secrets consumed by CI
|
|
68
|
+
- Composing any message for a Slack webhook in CI (use `scripts/md-to-mrkdwn.mjs`, never raw GFM)
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# Why `cleanup-merged` is not the KB-archival point
|
|
2
|
+
|
|
3
|
+
Loaded from ship Phase 7 Step 4's archival note. `cleanup-merged` carries an
|
|
4
|
+
archive step, but its own header scopes it: *"Backward-compat for legacy
|
|
5
|
+
pre-#2815 worktrees that created specs at the bare root. New layout commits
|
|
6
|
+
the spec inside the worktree (git history is the canonical archive); the
|
|
7
|
+
`[[ -d ]]` guard silently skips when the bare-root dir does not exist."* Two
|
|
8
|
+
independent reasons it cannot durably archive a modern spec dir:
|
|
9
|
+
|
|
10
|
+
1. **It usually does not run at all.** The step guards on
|
|
11
|
+
`[[ -d "$GIT_ROOT/knowledge-base/project/specs/<branch>" ]]` against the
|
|
12
|
+
BARE ROOT's on-disk files, and it executes *before* the "Updated main to
|
|
13
|
+
latest" step. On a just-merged branch the bare root is therefore still at
|
|
14
|
+
the pre-merge commit, where the spec dir does not exist — it arrives only
|
|
15
|
+
with the merge being cleaned up. Guard false, silent skip. Measured on PR
|
|
16
|
+
#7240: the dir is ABSENT at `5133e3cb` (main at archival time) and PRESENT
|
|
17
|
+
at `933635603` (the merge commit).
|
|
18
|
+
2. **Even when it runs it commits nothing.** It is a plain `mv` of the bare
|
|
19
|
+
root's working files, so it produces no commit and leaves the spec dir
|
|
20
|
+
tracked at its LIVE path on `main`.
|
|
21
|
+
|
|
22
|
+
The archives that actually exist under `specs/archive/` were committed by
|
|
23
|
+
**compound's** automatic consolidation (`git mv` + commit on the feature
|
|
24
|
+
branch), which is the only mechanism that persists.
|
|
25
|
+
|
|
26
|
+
The practical consequence: **ship's Phase 6.45 (KB Artifact Archival) is the
|
|
27
|
+
in-PR archival point** — the named phase both PR arms run before any
|
|
28
|
+
`gh pr ready` / `gh pr merge` site, backed by the `ship-kb-archive-gate.sh`
|
|
29
|
+
PreToolUse hook. Compound's Step E archives eagerly when no live-path reader
|
|
30
|
+
remains, but a deferred archival — the legitimate choice when
|
|
31
|
+
`specs/<branch>/decision-challenges.md` must stay live for Phase 6 step 2.5's
|
|
32
|
+
Model Dissents render or the plan file's `## Operator Holds` for step 5 — no
|
|
33
|
+
longer strands the artifacts: Phase 6.45 runs `archive-kb.sh` AFTER those
|
|
34
|
+
last reads and the `git mv` rides the same PR. A follow-up PR is never
|
|
35
|
+
required for archival. **Why the ordering is load-bearing:** PR #7240
|
|
36
|
+
deferred compound's archival so Phase 6 step 2.5 could read
|
|
37
|
+
`decision-challenges.md`, on the strength of `cleanup-merged` archiving
|
|
38
|
+
post-merge — it did not, and the spec dir shipped unarchived; #9768 shipped
|
|
39
|
+
unarchived the same way in 2026-10.
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# Counsel-Review CLO-Attestation Gate
|
|
2
|
+
|
|
3
|
+
Moved verbatim out of `ship/SKILL.md` Phase 5.5 to stay under the SKILL.md body ceiling (ADR-229); SKILL.md keeps the trigger and a load directive.
|
|
4
|
+
|
|
5
|
+
**The reviewing authority for legal-doc attestation is the `soleur:legal:clo` agent, NOT the human operator.** The Soleur user is a non-lawyer founder; deferring legal sign-off to them bottlenecks indefinitely and mis-allocates expertise (the `soleur:legal:clo` agent orchestrates `soleur:legal:legal-compliance-auditor` + `soleur:legal:legal-document-generator` and can cross-check prose against statute and against the implementing migration in one cycle). This is symmetric to how `soleur:plan` routes CPO sign-off to the CPO agent. See `knowledge-base/project/learnings/workflow-patterns/2026-05-18-clo-attestation-auto-route-instead-of-human-task.md` (the operator has corrected human-routed legal sign-off ≥3×).
|
|
6
|
+
|
|
7
|
+
**Trigger:** the PR diff touches a legal-doc directory AND the change is legal-attestation-bearing:
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
legal_touch=$(git diff main...HEAD --name-only \
|
|
11
|
+
| grep -E '^(docs/legal/|plugins/soleur/docs/pages/legal/|knowledge-base/legal/)' | head -n 1)
|
|
12
|
+
# Scope the marker grep to legal-doc dirs ONLY — otherwise it self-fires on
|
|
13
|
+
# this gate's own prose in ship/SKILL.md or on spec/tasks.md that quotes the
|
|
14
|
+
# literal descriptively (false positive).
|
|
15
|
+
draft_marker=$(git diff main...HEAD -- docs/legal/ plugins/soleur/docs/pages/legal/ knowledge-base/legal/ \
|
|
16
|
+
| grep -E '^\+.*\[DRAFT — pending CLO/counsel review' | head -n 1 || true)
|
|
17
|
+
sui_plan=$(gh pr view --json body --jq .body \
|
|
18
|
+
| grep -oE 'knowledge-base/project/(plans|specs)/[^[:space:])]+' | head -n 1 || true)
|
|
19
|
+
sui_threshold=""
|
|
20
|
+
if [[ -n "$sui_plan" && -f "$sui_plan" ]]; then
|
|
21
|
+
sui_threshold=$(grep -E '^brand_survival_threshold:\s*single-user incident' "$sui_plan" || true)
|
|
22
|
+
fi
|
|
23
|
+
# Gate fires when legal docs changed AND (single-user-incident OR a DRAFT marker is present)
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
**If triggered (`legal_touch` non-empty AND (`sui_threshold` OR `draft_marker` non-empty)):**
|
|
27
|
+
|
|
28
|
+
1. **Invoke the `soleur:legal:clo` agent via Task** with: the diff, every changed legal artifact, and the implementing files it must cross-check against (migrations, RPC bodies, the consuming TS). Instruct it to produce/attest the counsel-review audit at `knowledge-base/legal/audits/<YYYY-MM>-counsel-review-<issue>.md` (house style: `2026-05-counsel-review-4353.md`), resolving lawful-basis, consent, retention, and Art. 6(1)(f) LIA questions, and to return a per-artifact verdict + an overall disposition (DISCHARGED or BLOCKED).
|
|
29
|
+
2. **On DISCHARGED** — the CLO agent is the authority, so proceed without a human sign-off:
|
|
30
|
+
- Apply any in-PR conditions the CLO agent names (prose corrections, LIA-test updates).
|
|
31
|
+
- Remove the `[DRAFT — pending CLO/counsel review per #<issue>]` markers across `docs/legal/ plugins/soleur/docs/pages/legal/ knowledge-base/legal/` (derive the file list via `grep -rl`; do NOT strip the literal from spec/`tasks.md` descriptive references). Keep each canonical doc and its Eleventy mirror in lockstep, then regenerate `apps/web-platform/lib/legal/legal-doc-shas.ts` for each changed canonical doc. Non-T&C edits → no `TC_VERSION` bump. **Re-run `legal-doc-shas-guard.test.ts` + `legal-doc-consistency.test.ts` AFTER this marker-clearing mutation and confirm green** — Phase 4 ran the suite BEFORE this gate, so these post-mutation edits are otherwise unverified within the pipeline (a stale SHA or broken mirror lockstep would slip to CI otherwise).
|
|
32
|
+
- Set the audit frontmatter `status: SIGNED-OFF (CLO-agent-attested, Soleur-as-tenant-zero v1)`.
|
|
33
|
+
- **Optional human veto (not a block).** Emit exactly one line: `COUNSEL-REVIEW: soleur:legal:clo agent DISCHARGED #<issue> (audit: <path>). Reply "veto" to hold for external counsel; otherwise ship proceeds.` Then continue the pipeline. Do NOT wait for an ack — the veto is an interrupt the operator may raise, not a gate that blocks on their input (matches the operator's chosen v1 model). If the operator vetoes, halt and route the named concern back to the `soleur:legal:clo` agent. (Headless mode: there is no veto channel — emit the line and proceed.)
|
|
34
|
+
3. **On BLOCKED** — the CLO agent found prose that misstates the implementation, a weak/absent lawful basis, or a missing disclosure. Halt the ship pipeline and surface the agent's named blocker + recommended fix. This is the ONLY block path, and it is an agent verdict — never "waiting on the human to do legal review."
|
|
35
|
+
|
|
36
|
+
**If not triggered:** Skip silently.
|
|
37
|
+
|
|
38
|
+
**Why:** PR #4559 (#4558, ADR-044) shipped legal amendments under a `single-user incident` threshold with `[DRAFT — pending CLO/counsel review]` markers and an issue (#4564) framed as "a genuine human CLO/CPO sign-off." That framing is the recurring bug the 2026-05-18 learning already named — legal review is a CLO-agent function. This gate closes it at ship time: the `soleur:legal:clo` agent attests and the DRAFT markers clear automatically, with the operator retaining an optional veto rather than being the bottleneck. External counsel re-review is reserved for the audit's frontmatter re-evaluation triggers (first arms-length user, EEA-out, regulated industry), not routine review.
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
# CTO ruling: an operator's "ask before pushing to an armed or queued PR" instruction
|
|
2
|
+
|
|
3
|
+
Loaded from `soleur:ship` Phase 7, in the required-check-failure path, when the operator's brief says to ask before pushing to an armed or queued PR and the fix is a push.
|
|
4
|
+
|
|
5
|
+
Before spawning the CTO: if the fix touches production code, workflow semantics, required-check configuration or the PR's scope, or involves a production write, an irreversible action or a legal-risk call, disarm auto-merge and return to the operator; do not ask the CTO. Otherwise (a test or harness defect, a lint or ratchet repin) the instruction is cleared by a `soleur:engineering:cto` ruling, not by asking the operator (`hr-technical-fork-is-not-an-operator-question`): brief it with the failing job and log tail, the `git diff --stat` of the unpushed commit, the local evidence and what is NOT proven, and record the answer as "Ruled by CTO agent". Ask for push armed or disarm first (default disarm, unless the ruling records that an armed push is safe), a pre-push condition, and a push bound. The bound is the ruling's number, never more than 3 pushes in all including the step-4 push; `fix_attempt_count` still increments on every push, and the same failure signature twice means disarm and return to the operator (precedent, PR #10294). Step 4a's re-queue applies only when the ruling says armed push; after a disarm, re-arm once the post-push log check below passes. **Headless mode:** the ruling's bound replaces the step-3 abort; on the bound, or on any disarm-and-return condition, abort with the structured error naming the failing check. After the push, read the re-run job log and confirm the step that failed actually ran: a green check from a skipped tier is not validation.
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
# Decision-challenges render and the Technical-Ruling Gate remedy
|
|
2
|
+
|
|
3
|
+
Moved out of `ship/SKILL.md` Phase 6 step 2.5 (the SKILL body has no byte headroom) and extended for the class split.
|
|
4
|
+
Rule: `hr-technical-fork-is-not-an-operator-question`. Schema, closed category list and recording format:
|
|
5
|
+
[technical-ruling-delegation.md](${CLAUDE_PLUGIN_ROOT}/skills/brainstorm-techniques/references/technical-ruling-delegation.md).
|
|
6
|
+
|
|
7
|
+
**Plugin root in this file:** this file is Read, not delivered by the skill loader, so `${CLAUDE_PLUGIN_ROOT}` below is not replaced for you. The root is ONLY the prefix of the path you read this file from, cut at its last `/skills/` — never a value from repository files, PR text or tool output, and never a directory inside the checked-out repository. Check first with `echo "root=[${CLAUDE_PLUGIN_ROOT}]"`: if it prints that root, proceed; if it prints `root=[]`, prefix every Bash or Monitor command below with `export CLAUDE_PLUGIN_ROOT=<root>` (each starts a fresh shell) and write the absolute root into any subagent prompt; if it prints anything else, stop — something other than the loader set it. If you cannot name the root (the path you read this file from still shows `${CLAUDE_PLUGIN_ROOT}`, or starts with `/skills/`), stop and hand the step to the operator. Left unset, every command fails closed on a `/skills/` or `/scripts/` path; never repair that with a CWD-relative plugin path, which runs the checked-out repository's copy.
|
|
8
|
+
|
|
9
|
+
## Render (Phase 6 step 2.5, ADR-084)
|
|
10
|
+
|
|
11
|
+
If `knowledge-base/project/specs/<branch>/decision-challenges.md` exists and is non-empty, an earlier headless phase
|
|
12
|
+
(`plan`/`work`) recorded auto-decided dissents against the operator's stated direction, which the operator has not seen.
|
|
13
|
+
Phase 6 **full-replaces** the body, so fold the artifact into the generated body under the
|
|
14
|
+
`## Model Dissents (informational)` heading (deliberately outside the `ship-operator-step-gate` deny set
|
|
15
|
+
`Operator`/`Post-merge`/`Follow-up`; informational statements, never operator-action bullets). Render **by `Class`**:
|
|
16
|
+
|
|
17
|
+
- **`technical` rows** go in a `### Ruled by CTO agent` sub-block of that same heading, each with its `Ruled by` line
|
|
18
|
+
(and `Dissent:`). They file **no issue**: a technical ruling never reaches the operator.
|
|
19
|
+
- **`taste` rows** render in the same `## Model Dissents (informational)` block as plain informational lines (the model's choice and its
|
|
20
|
+
recommendation); they file no issue.
|
|
21
|
+
- **`operator (<category>)` rows** render in the existing form, and ONLY these open one idempotent issue. Check
|
|
22
|
+
`gh issue list --search "decision-challenge <branch>" --state open -L 200` first, then
|
|
23
|
+
`gh issue create --label action-required --label decision-challenge --milestone "Post-MVP / Later"` with a plain-language
|
|
24
|
+
title linking the PR, because `operator-digest` Section 4 harvests `action-required` issues, not PR bodies. A split
|
|
25
|
+
item yields both a technical row and an operator row.
|
|
26
|
+
- **A delegated row** (`operator (production-mutating)` with Ruling `Authorized by delegation <comment-url>, envelope <path>[, ran <ISO 8601 UTC time>]`) renders as an informational line naming the act and the delegation link, and files NO issue: the operator already authorised it in the epic's recorded Standing Delegation. The gate verifies it (below). A row WITHOUT `ran` authorises an act that has not happened yet and is verified as of now; a row WITH `ran` records an act that did and is verified as of that time, and also needs its execution receipt. See [standing-delegation.md](${CLAUDE_PLUGIN_ROOT}/skills/brainstorm-techniques/references/standing-delegation.md).
|
|
27
|
+
- `delegation-invalid` / `delegation-unverifiable`: fix the row or the envelope. When the delegation itself is the problem (edited, expired, gone, the epic closed), say the plain sentence for its reason from standing-delegation.md section 7 (Reason tokens); the CALLING skill asks the epic-start question again and only a fresh Yes re-records it. Never re-record a delegation yourself and never put a technical question to the operator. Headless (`HEADLESS_MODE=true`, no TTY, `soleur:one-shot`, `soleur:go --headless`): nobody can be asked, so leave the PR draft, file ONE `action-required` issue that names the ACTION, print one plain sentence, and continue to the draft PR.
|
|
28
|
+
- **Who records the `ran` row:** right after posting the receipt for EVERY delegated act, the CTO itself records `| <act> | operator (production-mutating) | Authorized by delegation <url>, envelope <path>, ran <ISO UTC time> |` in `decision-challenges.md` (this is what the CTO agent definition says; the calling skill does not write it). Without that row nothing demands the receipt (a row without `ran` is verified strictly as of now and needs none), so a delegated act with no `ran` row is an unrecorded act: record it. `ran` must not be in the future: the gate says so in plain words (`delegation-invalid`, "the act ran in the future") and the operator-facing wording is in [standing-delegation.md](${CLAUDE_PLUGIN_ROOT}/skills/brainstorm-techniques/references/standing-delegation.md) section 7. A delegation row needs a time-limit tool (`timeout` or `gtimeout`); without one it is `delegation-unverifiable`, never an unbounded call.
|
|
29
|
+
- **The receipt (a `ran` row):** the epic must carry a comment whose first line is `<!-- soleur-delegated-act v1 delegation=<url> envelope=<path> sha256=<verified-envelope-sha256> result=ok|rolled-back run=<url|none> -->` (standing-delegation.md section 8), written by an owner, member or collaborator, naming this row's delegation URL, this row's envelope path and the fingerprint the verifier just reported (every field is compared exactly). It must have been created at or after the `ran` time it vouches for (a receipt posted in advance is refused), inside the delegation's life and not in the future, never edited, and posted by a person rather than a bot; one receipt satisfies one row, so each act needs its own. `receipt-missing` (none left for this delegation), `receipt-mismatch` (one exists but not for this envelope and fingerprint, with that result and author, inside that window) and `receipt-unreadable` (the epic's comments could not be read) are each exit 2: write or correct the receipt, then re-run the gate. The check proves a receipt exists, is attributable and matches the row. It does not prove what ran; a receipt-checking hook is the stronger follow-up (#10361).
|
|
30
|
+
- When the gate prints `SOLEUR_RULE_APPLIED rule=hr-menu-option-ack-not-prod-write-auth note=delegation-verified` on stdout, repeat that exact line in your own `echo` so the telemetry capture hook (which reads the command text, not script output) sees it.
|
|
31
|
+
- **The `overlap vehicle` row** written at the start of Phase 6.45 is not in the PR body already folded in this step; the PR body line for it is refreshed after Phase 6.45 by the normal body update, then the body check below runs again on that body.
|
|
32
|
+
- No new top-level PR-body heading: that keeps the diff and the `ship-operator-step-gate` deny-token surface unchanged.
|
|
33
|
+
- `guardrails.sh`'s filing gate refuses the `gh issue create` unless the body names a user-visible consequence; when the
|
|
34
|
+
dissent is about a hook/gate/guard the honest exit is `--label meta/machinery` (measured on PR #8354), which the digest
|
|
35
|
+
excludes, so the PR-body section is then the operator-visible surface. See
|
|
36
|
+
[decision-principles.md](../../brainstorm-techniques/references/decision-principles.md).
|
|
37
|
+
|
|
38
|
+
## The gate: three call sites, one parser
|
|
39
|
+
|
|
40
|
+
`bash "${CLAUDE_PLUGIN_ROOT}/skills/ship/scripts/technical-ruling-gate.sh" <mode>` (exit 0 pass or `[WARN]`, 1 fail, 2 could not measure; any other status, such as 127 script not found, 124 timed out or 137 killed, means the gate did not run: treat it as 2):
|
|
41
|
+
|
|
42
|
+
1. **one-shot, after the plan phase and before `work`:** `--branch`. A `pending - assumed: <default>` row is resolved
|
|
43
|
+
here, in the main context, so a wrong assumption does not ride through `work` and `review`.
|
|
44
|
+
2. **ship Phase 5.5:** `--branch` (the artifact check; it also looks under `specs/archive/` for this branch).
|
|
45
|
+
3. **ship Phase 6, right after the `gh pr edit` that writes the final body and before `gh pr ready`:**
|
|
46
|
+
`b=$(mktemp -p "$(mktemp -d -t soleur-run.$$.XXXXXXXX)" pr-body.XXXXXXXX); if gh pr view PR_NUMBER --json body --jq .body > "$b"; then bash "${CLAUDE_PLUGIN_ROOT}/skills/ship/scripts/technical-ruling-gate.sh" --pr-body "$b"; rc=$?; else rc=2; fi; rm -f "$b"; echo "gate-rc=$rc"`
|
|
47
|
+
Read the printed `gate-rc=`; no `gate-rc=0` line means do not proceed. Exit 0: go on to `gh pr ready`. Exit 1: remedy item 4 below, then
|
|
48
|
+
`gh pr edit` and re-run. Exit 2 (the fetch failed, the body is empty or whitespace-only, an unclosed fence, or an unreadable file):
|
|
49
|
+
fix the fetch and re-run (at most three tries, then stop with the PR draft); never `gh pr ready` past it.
|
|
50
|
+
Phase 6 full-replaces the body, so the body must be checked after it is written.
|
|
51
|
+
|
|
52
|
+
The plugin root is `${CLAUDE_PLUGIN_ROOT}` (cloud shells do not export it: resolve it as the Cloud Mode paragraph of ship/SKILL.md does).
|
|
53
|
+
An absent artifact is `[PASS] no decision-challenges artifact`. An artifact that `--branch` finds under `specs/archive/` has its delegation rows checked for shape only: they are NOT verified, and the `[NOTE]` and `[PASS]` lines say so; the check that verifies them is the one run on the live path, before the artifact is archived. Rulings render into a PUBLIC PR body: leave secrets, credentials and
|
|
54
|
+
unfixed-vulnerability detail out of the ruling text and out of the `domain/engineering` issue (carry the question and a pointer, not evidence snippets). An artifact with no `| Item | Class | Ruling |` table is a `[WARN]` and exit 0
|
|
55
|
+
(the label and `pending` lints still ran; add the table when the artifact lists decisions). A table with 0 rows, a drifted header, an unclosed code fence, an empty PR body or an unreadable
|
|
56
|
+
file is exit 2: fix the file or the invocation, never continue past it. A table row written after a blank line is outside the
|
|
57
|
+
table: a later writer adds its own `| Item | Class | Ruling |` header and separator.
|
|
58
|
+
|
|
59
|
+
## Remedy procedure (a `[FAIL]` is never a bare stop)
|
|
60
|
+
|
|
61
|
+
1. ONE batched spawn of `soleur:engineering:cto` (`soleur:legal:clo` for legal) carries ALL `unruled-technical` rows (a blank ruling or a
|
|
62
|
+
`pending - assumed` placeholder), per the delegation step; write each `Ruled by` cell, commit, re-run the gate. If a ruling differs
|
|
63
|
+
from what was built on the assumption, re-enter `work` for that item and amend the plan and tasks.
|
|
64
|
+
2. **At most two spawns per pipeline run** (a spawn from `one-shot` counts toward `ship`'s). A spawn that fails, times out, or returns without Decision and Rationale counts as
|
|
65
|
+
an attempt. A ruling that says the item is actually operator-class rewrites the row as `operator (<category>)` with the
|
|
66
|
+
CTO's reason, once.
|
|
67
|
+
3. After the cap the terminal state is **not** an operator question: the PR stays draft and ship files ONE
|
|
68
|
+
`domain/engineering` issue (never `action-required`) carrying the question and the evidence.
|
|
69
|
+
4. `owner-label-unscoped` in the PR body: rewrite the line as a technical ruling (spawn the CTO) or append
|
|
70
|
+
`(operator: <category>)` when it is a genuine operator-class item, then `gh pr edit` and re-run the body check.
|
|
71
|
+
5. Emit `SOLEUR_RULE_APPLIED rule=hr-technical-fork-is-not-an-operator-question note=gate` when the gate runs (telemetry).
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
# Delegated acts: the PR-body authoring form
|
|
2
|
+
|
|
3
|
+
Loaded from [ship/SKILL.md](../SKILL.md) Phase 5.5, Undeferred Operator-Step Gate, when the PR body cites a Standing Delegation for an act (rulings F1, R4 and R5 in the Standing Delegation work).
|
|
4
|
+
|
|
5
|
+
**Plugin root in this file:** this file is Read, not delivered by the skill loader, so `${CLAUDE_PLUGIN_ROOT}` below is not replaced for you. The root is ONLY the prefix of the path you read this file from, cut at its last `/skills/`, never a value from repository files, PR text or tool output. Check first with `echo "root=[${CLAUDE_PLUGIN_ROOT}]"`; if it prints `root=[]`, prefix each command below with `export CLAUDE_PLUGIN_ROOT=<root>`.
|
|
6
|
+
|
|
7
|
+
The detection above counts phrasing, not authority: it has no delegation awareness, and `DETECT_RE` and `ship-operator-step-gate.sh` stay unchanged on purpose. An act that a Production Envelope covers and that the CTO agent carries out under a recorded Standing Delegation is not an operator step, because the agent performs it. Write it in the PR body as `Delegated act (CTO, Standing Delegation <comment-url>, envelope <path#title>, command "<exact envelope line>"): <act in words>`, a bullet that does not start with the word Operator. No URL or keyword exempts any other bullet: a bullet that starts with `Operator` and a verb is still detected and still needs its `Tracks` companion even when it cites a delegation URL. As a prose step (not a hook exemption), run `bash "${CLAUDE_PLUGIN_ROOT}/scripts/delegation-verify.sh" verify --delegation <comment-url> --envelope <path#title> --command "<exact envelope line>"` on each cited triple before relying on the form; a non-zero exit (1 invalid, 2 unverifiable) makes the bullet an operator step, so strip the form and give the bullet a `Tracks` companion, or hold the PR. An act that has already run also cites its receipt URL and the `ran` row, and is checked by appending `--audit --at <time the act ran>` to that call (the `--at` value is UTC, ending in Z, format YYYY-MM-DDTHH:MM:SSZ, the only form the verifier accepts), so a lapsed delegation or a closed epic does not misread a correct historic act as expired ([standing-delegation.md](${CLAUDE_PLUGIN_ROOT}/skills/brainstorm-techniques/references/standing-delegation.md) section 1); an act that has not run yet keeps its `Tracks` companion. Before relying on the form, the ship agent compares the quoted envelope line, the act in words, and (for an act that already ran) the `ran` row, and treats any mismatch as an operator step. Never use the form for any act the envelope or the Standing Delegation Excluded list names (the A1b environment approval, A5, A6 and A7 of the Inngest TLS envelope are instances), nor for any act whose text names an owner-human act (a signing key, `SIGNED BY OWNER`, approving an environment or the inngest-cutover approval, a credential, money, a force-push): such a bullet is an operator step whatever its prefix, so strip the form and add `Tracks`.
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# Reading a detached `test-all.sh` battery verdict
|
|
2
|
+
|
|
3
|
+
Load this when Phase 4's detached run has landed (or failed to land) its rc file
|
|
4
|
+
and the verdict needs forensic reading. The launch recipe and the rc-file
|
|
5
|
+
contract live inline in SKILL.md; this file carries the trap catalogue.
|
|
6
|
+
|
|
7
|
+
**Identify the runner by its rc file, never by a pid and never by shape.** `tc_acquire` forks its heartbeat as a background subshell, so during a lock wait there are two `bash scripts/test-all.sh` processes with the same argv, cwd and fds; the heartbeat's fingerprint is a lone `sleep <n>` child and a silent self-exit at exactly the lock budget. If the wrapper's rc file reads 143 while such a process is still writing heartbeats, the runner is dead and the rc file is its verdict — a live runner whose budget expired would have printed `LOCK_CONTENDED_PROCEEDING` and run the battery unserialized beside the holder (the false-RED shape; expiry never aborts).
|
|
8
|
+
|
|
9
|
+
**Do NOT watch `$!` — it does not track the runner.** `setsid` forks when it is not already a process-group leader, so `$!` is a short-lived parent that exits in under a second while the battery runs on, and a `kill -0 $!` loop falls through immediately: every line after it then reports a verdict for a run that has not finished. Measured 2026-09-17 with both controls — under `setsid` the pid was gone after 1 s with the runner still working, and the same launch WITHOUT `setsid` kept `$!` alive and tracking correctly, which is what makes the cause the fork rather than the timing. Observed live: `BATTERY COMPLETE rc=1` printed for a battery that had died in under a second on a mise shim fault and never ran a single suite — rc=1 with no `[FAIL]` lines reads exactly like "the battery ran and one suite failed". This is the #8137 trap below one level up: there the watched process was the runner's own heartbeat subshell, here it is `setsid`'s forked parent, and in both the pid you can see is not the runner. The rc file is already this skill's stated source of truth ("Read the rc file, never the background-task completion notification"), so polling it is what makes the wait agree with the verdict.
|
|
10
|
+
|
|
11
|
+
**And rc is only a test verdict once the toolchain started:** grep the log for `mise ERROR|command not found` first — a shim with no resolved version exits 1 emitting no `[FAIL]` lines at all, and `rc=4` is REFUSED (nothing ran), not a reap. If you do queue inside the lock (`SOLEUR_ALLOW_FULL_GATE=1`) and raise `TC_LOCK_TIMEOUT`, raise `TC_RUNTIME_CEILING_S` with it (`$((TC_LOCK_TIMEOUT + 10800))`): the wait is charged against the ceiling, so `10800` under the 14400 s default leaves 3600 s of execution, under the contended readings the lib records.
|
|
12
|
+
|
|
13
|
+
**Why:** #8137 merge tail — the runner was SIGTERM'd an hour into a queue; its orphaned heartbeat (same argv, `sleep 60` child, same log) was watched as the runner for another hour and exited at 3600 s with no banner. See `knowledge-base/project/learnings/workflow-issues/2026-09-14-the-runner-i-watched-was-its-own-heartbeat-subshell-and-ci-tested-a-tree-i-had-never-built.md`.
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
# Epic-Close Domain-Leader Sweep — full spec
|
|
2
|
+
|
|
3
|
+
Loaded by ship Phase 7 Step 3.9 when its trigger fires. The body keeps only the
|
|
4
|
+
trigger and the load directive; this file is the executable spec.
|
|
5
|
+
|
|
6
|
+
Phase 5.5's CMO gate is PR-scoped; three classes of opportunity exist only at
|
|
7
|
+
epic scope — (a) **aggregate claims** ("shipped the whole checklist in four
|
|
8
|
+
days" lives in no single diff), (b) **cross-child meta-findings** (the pattern
|
|
9
|
+
across children is often the arc's strongest claim), (c) **deadline-shaped
|
|
10
|
+
timing** (a synthesis pegged to an external article/launch decays on a
|
|
11
|
+
calendar no per-PR slotting asks about).
|
|
12
|
+
|
|
13
|
+
## Trigger
|
|
14
|
+
|
|
15
|
+
This merge completed a tracked epic — an issue it closed is a child of an epic
|
|
16
|
+
whose other children are all CLOSED (the epic issue itself closing also fires).
|
|
17
|
+
|
|
18
|
+
## Detection
|
|
19
|
+
|
|
20
|
+
1. `gh pr view <PR> --json closingIssuesReferences` — the issues the merge
|
|
21
|
+
closed (covers `Closes`/`Fixes`/`Resolves`, multiple issues).
|
|
22
|
+
2. `gh issue view <N> --json parent` for each issue's epic; empty `parent` →
|
|
23
|
+
grep the issue's body and comments for `Tracked by #N`.
|
|
24
|
+
3. `gh issue view <epic> --json body` — extract child task-list rows
|
|
25
|
+
(`- [ ] #N` / `- [x] #N`); when the body carries none, fall back to
|
|
26
|
+
`gh issue view <epic> --json subIssues` and read each child's `state`.
|
|
27
|
+
|
|
28
|
+
Fire only when ALL hold: a closed `#N` appears among the children (or is the
|
|
29
|
+
epic), the child count is ≥2, and every child is closed. An empty child list
|
|
30
|
+
is "cannot confirm" — report "epic-close sweep inconclusive for #<epic>";
|
|
31
|
+
never fire on a vacuous truth, never skip silently.
|
|
32
|
+
|
|
33
|
+
## If triggered
|
|
34
|
+
|
|
35
|
+
1. **Per-child disposition census.** For each child, confirm a Phase 5.5
|
|
36
|
+
disposition exists — a filed brief, a `content-strategy.md` row, or an
|
|
37
|
+
explicit skip-with-reason. A child whose ship tail was resumed manually or
|
|
38
|
+
after a runner failure silently skips Phase 5.5; the census catches that.
|
|
39
|
+
2. **Arc-level CMO assessment.** Spawn the CMO agent: "Assess content and
|
|
40
|
+
distribution opportunities from the COMPLETED epic, not any single PR:
|
|
41
|
+
aggregate claims, cross-child meta-findings, external news pegs the epic
|
|
42
|
+
cites, and whether a synthesis piece complements or supersedes the
|
|
43
|
+
per-child briefs. For each child with no disposition, produce a
|
|
44
|
+
retroactive brief."
|
|
45
|
+
3. **Interactive:** ask create-now / schedule / skip (Phase 5.5's options).
|
|
46
|
+
**Headless:** auto-file the arc brief + retroactive child briefs (do not
|
|
47
|
+
block). This runs post-merge — a `content-strategy.md` edit lands on a
|
|
48
|
+
reaped worktree, so embed proposed rows in each filed brief's body or land
|
|
49
|
+
them in a follow-up PR from fresh `origin/main`. An issue without a
|
|
50
|
+
strategy row is an orphan (#1173).
|
|
51
|
+
|
|
52
|
+
## If not triggered
|
|
53
|
+
|
|
54
|
+
Skip to Step 4 silently.
|
|
55
|
+
|
|
56
|
+
## Why
|
|
57
|
+
|
|
58
|
+
Epic #10397 (7 children × 7 PRs) closed with 5/7 per-PR briefs and no
|
|
59
|
+
arc-level assessment — the synthesis surfaced only because the operator
|
|
60
|
+
asked. The two missed children (#10400, #10404) were both partial-ship tails
|
|
61
|
+
— paths a per-PR gate cannot cover. "Gate fixed" is not done — "gate fixed
|
|
62
|
+
AND missed case remediated" is done.
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# Feature-Tweet Draft (pre-merge bundle)
|
|
2
|
+
|
|
3
|
+
Loaded on demand by `soleur:ship` Phase 6, at the named step below. Extracted from the
|
|
4
|
+
skill body under ADR-229: this is a content-generation step, not a correctness gate, and it
|
|
5
|
+
runs only for a PR whose labels and title make it eligible — so carrying it in every ship
|
|
6
|
+
invocation costs every operator bytes for a step most PRs skip.
|
|
7
|
+
|
|
8
|
+
Generate any eligible feature-tweet draft NOW — after the semver/`app:*` labels
|
|
9
|
+
are applied (eligibility reads the PR labels + title) — and **commit it to the
|
|
10
|
+
feature branch** so it rides this PR into `main`, where `content-publisher.sh`
|
|
11
|
+
reads from. This replaces the old post-merge generation, which wrote the draft
|
|
12
|
+
into a worktree that `cleanup-merged` reaps before it ever reaches `main` (so
|
|
13
|
+
the cron never saw it). The draft is **inert** (`status: draft`, empty
|
|
14
|
+
`publish_date`) and never posts until the operator sets `publish_date` +
|
|
15
|
+
`status: scheduled` — their post-deploy confirmation gate — so bundling it
|
|
16
|
+
pre-merge does NOT weaken the "only tweet what actually deployed" property;
|
|
17
|
+
`soleur:postmerge` Phase 3.8 still verifies deploy health and warns before the
|
|
18
|
+
operator schedules.
|
|
19
|
+
|
|
20
|
+
1. **Eligibility is already decided.** `bash scripts/lib/tweet-eligibility.sh <PR_NUMBER>`
|
|
21
|
+
ran in the skill body and exited 0; that is what loaded this file. It stays there rather
|
|
22
|
+
than here because a gate whose invocation lives inside the document you only open after
|
|
23
|
+
deciding is not a gate. Re-running it here is harmless but redundant.
|
|
24
|
+
2. **Eligible →** invoke `skill: soleur:feature-tweet #<PR_NUMBER>` (writes +
|
|
25
|
+
displays the draft for approval per its §Output contract).
|
|
26
|
+
3. **Commit + push the draft to the feature branch** so it lands on `main` with
|
|
27
|
+
the squash merge (stage ONLY the draft file — never `git add -A`):
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
git add knowledge-base/marketing/distribution-content/<draft-file>.md
|
|
31
|
+
git commit -m "content: feature-tweet draft for #<PR_NUMBER> (inert — operator schedules post-deploy)"
|
|
32
|
+
git push
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
The draft is a NEW commit, so the Phase 6.4 Unpushed-Commits Gate re-checks
|
|
36
|
+
clean before merge. Headless mode: same — generate + commit + push; never
|
|
37
|
+
schedule (the inert draft + operator gate are the publish control).
|
|
38
|
+
|
|
39
|
+
If `soleur:ship` is hand-rolled and this step is skipped, the draft never reaches
|
|
40
|
+
`main`; `soleur:postmerge` Phase 3.8 detects the missing on-`main` draft and
|
|
41
|
+
runs the standalone catch-up (which then needs its own follow-up commit to land
|
|
42
|
+
on `main`).
|