@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,198 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# trigger-cron — fire an allowlisted cron manual-trigger via the internal HTTP
|
|
3
|
+
# route (no SSH). See plugins/soleur/skills/trigger-cron/SKILL.md.
|
|
4
|
+
#
|
|
5
|
+
# The no-SSH replacement for the on-host `inngest send` loopback path (#4734,
|
|
6
|
+
# #4742). Reads INNGEST_MANUAL_TRIGGER_SECRET read-only from Doppler and POSTs
|
|
7
|
+
# to https://app.soleur.ai/api/internal/trigger-cron.
|
|
8
|
+
#
|
|
9
|
+
# Allowlisted events are derived from EXPECTED_CRON_FUNCTIONS in
|
|
10
|
+
# apps/web-platform/server/inngest/cron-manifest.ts — there is NO second
|
|
11
|
+
# hand-maintained list here (mirrors lib/inngest/manual-trigger-allowlist.ts).
|
|
12
|
+
|
|
13
|
+
set -euo pipefail
|
|
14
|
+
|
|
15
|
+
# (#7797) Refuse to run under shell tracing. UNCONDITIONAL — deliberately NOT
|
|
16
|
+
# gated on a non-emptiness test of the credential variable, because
|
|
17
|
+
# INNGEST_MANUAL_TRIGGER_SECRET is acquired by `doppler secrets get` BELOW this
|
|
18
|
+
# point, so a conditional arm would test an empty variable at guard time, open,
|
|
19
|
+
# and then trace the acquisition itself.
|
|
20
|
+
#
|
|
21
|
+
# STREAM CONTRACT: this script's stdout is a DATA channel — it prints `HTTP <code>`
|
|
22
|
+
# then the response body, and SKILL.md's preflight block grep-parses
|
|
23
|
+
# `SOLEUR_TRIGGER_CRON_HALT reason=…` markers on stdout. So the refusal is emitted
|
|
24
|
+
# in that documented marker shape rather than as a bare `[FATAL] …` line, which the
|
|
25
|
+
# preflight consumer would read as a data row. Stdout, not stderr, because agent
|
|
26
|
+
# runtimes surface stdout and swallow stderr (constitution.md > Code Style).
|
|
27
|
+
case "$-" in
|
|
28
|
+
*x*)
|
|
29
|
+
printf 'SOLEUR_TRIGGER_CRON_HALT reason=xtrace-credential-bound issue=7797\n'
|
|
30
|
+
printf 'trigger-cron: refusing to run under xtrace — this script handles a live credential and -x would print it. No event has been fired and no secret has been read.\n'
|
|
31
|
+
exit 78
|
|
32
|
+
;;
|
|
33
|
+
esac
|
|
34
|
+
|
|
35
|
+
# (#7873) `--disable` closes ~/.curlrc and `--noproxy '*'` closes the proxy vars,
|
|
36
|
+
# but neither touches the env that subverts TLS ITSELF. SSLKEYLOGFILE writes the
|
|
37
|
+
# session keys and the CA vars substitute the trust store, so a CURL_CA_BUNDLE
|
|
38
|
+
# MITM of the manual-trigger secret works with every other guard fully intact.
|
|
39
|
+
unset SSLKEYLOGFILE CURL_CA_BUNDLE SSL_CERT_FILE SSL_CERT_DIR CURL_HOME \
|
|
40
|
+
HOSTALIASES LOCALDOMAIN RES_OPTIONS
|
|
41
|
+
|
|
42
|
+
ROUTE_URL="https://app.soleur.ai/api/internal/trigger-cron"
|
|
43
|
+
SECRET_NAME="INNGEST_MANUAL_TRIGGER_SECRET"
|
|
44
|
+
DOPPLER_PROJECT="soleur"
|
|
45
|
+
|
|
46
|
+
usage() {
|
|
47
|
+
cat <<'EOF'
|
|
48
|
+
Usage:
|
|
49
|
+
trigger.sh --list
|
|
50
|
+
trigger.sh --event cron/<name>.manual-trigger [--data '<json-object>'] \
|
|
51
|
+
[--config prd|dev] [--dry-run]
|
|
52
|
+
|
|
53
|
+
Flags:
|
|
54
|
+
--list Print allowlisted events (from cron-manifest.ts) and exit.
|
|
55
|
+
--event <name> The cron/<name>.manual-trigger event to fire.
|
|
56
|
+
--data '<json>' Optional per-cron event.data (JSON object). The route stamps
|
|
57
|
+
trigger/at over it; caller cannot override them.
|
|
58
|
+
--config <env> Doppler config to read the secret from (default: prd).
|
|
59
|
+
--dry-run Print the curl invocation without firing.
|
|
60
|
+
EOF
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
# Locate the cron manifest from the repo root (works from any CWD inside the repo).
|
|
64
|
+
repo_root() {
|
|
65
|
+
git rev-parse --show-toplevel 2>/dev/null || {
|
|
66
|
+
echo "trigger.sh: not inside a git repo (cannot locate cron-manifest.ts)" >&2
|
|
67
|
+
exit 2
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
# Extract the allowlisted manual-trigger events from cron-manifest.ts.
|
|
72
|
+
# Parses the EXPECTED_CRON_FUNCTIONS array literal (cron-<name>) and applies the
|
|
73
|
+
# same transform as manualTriggerEventFor: cron-<name> -> cron/<name>.manual-trigger.
|
|
74
|
+
list_events() {
|
|
75
|
+
local manifest="$1"
|
|
76
|
+
[[ -f "$manifest" ]] || { echo "trigger.sh: manifest not found: $manifest" >&2; exit 2; }
|
|
77
|
+
awk '
|
|
78
|
+
/EXPECTED_CRON_FUNCTIONS/ { inarr=1 }
|
|
79
|
+
inarr && /\];/ { inarr=0 }
|
|
80
|
+
inarr {
|
|
81
|
+
while (match($0, /"cron-[a-z0-9-]+"/)) {
|
|
82
|
+
tok = substr($0, RSTART+1, RLENGTH-2) # strip surrounding quotes
|
|
83
|
+
sub(/^cron-/, "", tok)
|
|
84
|
+
print "cron/" tok ".manual-trigger"
|
|
85
|
+
$0 = substr($0, RSTART+RLENGTH)
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
' "$manifest" | sort -u
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
LIST=0
|
|
92
|
+
EVENT=""
|
|
93
|
+
DATA=""
|
|
94
|
+
CONFIG="prd"
|
|
95
|
+
DRY_RUN=0
|
|
96
|
+
|
|
97
|
+
while [[ $# -gt 0 ]]; do
|
|
98
|
+
case "$1" in
|
|
99
|
+
--list) LIST=1; shift ;;
|
|
100
|
+
--event) EVENT="${2:-}"; shift 2 ;;
|
|
101
|
+
--data) DATA="${2:-}"; shift 2 ;;
|
|
102
|
+
--config) CONFIG="${2:-}"; shift 2 ;;
|
|
103
|
+
--dry-run) DRY_RUN=1; shift ;;
|
|
104
|
+
-h|--help) usage; exit 0 ;;
|
|
105
|
+
*) echo "trigger.sh: unknown flag: $1" >&2; usage >&2; exit 2 ;;
|
|
106
|
+
esac
|
|
107
|
+
done
|
|
108
|
+
|
|
109
|
+
ROOT="$(repo_root)"
|
|
110
|
+
MANIFEST="$ROOT/apps/web-platform/server/inngest/cron-manifest.ts"
|
|
111
|
+
|
|
112
|
+
if [[ "$LIST" -eq 1 ]]; then
|
|
113
|
+
list_events "$MANIFEST"
|
|
114
|
+
exit 0
|
|
115
|
+
fi
|
|
116
|
+
|
|
117
|
+
if [[ -z "$EVENT" ]]; then
|
|
118
|
+
echo "trigger.sh: --event is required (or use --list)" >&2
|
|
119
|
+
usage >&2
|
|
120
|
+
exit 2
|
|
121
|
+
fi
|
|
122
|
+
|
|
123
|
+
case "$CONFIG" in
|
|
124
|
+
prd|dev) ;;
|
|
125
|
+
*) echo "trigger.sh: --config must be 'prd' or 'dev' (got: $CONFIG)" >&2; exit 2 ;;
|
|
126
|
+
esac
|
|
127
|
+
|
|
128
|
+
# Validate the event against the manifest-derived allowlist (fail fast before
|
|
129
|
+
# minting a Doppler read or hitting the route). The `--` stops grep from
|
|
130
|
+
# interpreting an event string that begins with `-` as an option.
|
|
131
|
+
if ! grep -qxF -- "$EVENT" < <(list_events "$MANIFEST"); then
|
|
132
|
+
echo "trigger.sh: '$EVENT' is not an allowlisted manual-trigger event." >&2
|
|
133
|
+
echo "Run 'trigger.sh --list' to see valid events." >&2
|
|
134
|
+
exit 2
|
|
135
|
+
fi
|
|
136
|
+
|
|
137
|
+
# Build the JSON body. --data must be a JSON object if provided.
|
|
138
|
+
if [[ -n "$DATA" ]]; then
|
|
139
|
+
if ! echo "$DATA" | jq -e 'type == "object"' >/dev/null 2>&1; then
|
|
140
|
+
echo "trigger.sh: --data must be a JSON object (got: $DATA)" >&2
|
|
141
|
+
exit 2
|
|
142
|
+
fi
|
|
143
|
+
BODY=$(jq -nc --arg ev "$EVENT" --argjson d "$DATA" '{event: $ev, data: $d}')
|
|
144
|
+
else
|
|
145
|
+
BODY=$(jq -nc --arg ev "$EVENT" '{event: $ev}')
|
|
146
|
+
fi
|
|
147
|
+
|
|
148
|
+
if [[ "$DRY_RUN" -eq 1 ]]; then
|
|
149
|
+
printf '%s\n' "# dry-run (config=$CONFIG): would POST to $ROUTE_URL"
|
|
150
|
+
printf '%s\n' "TOKEN=\$(doppler secrets get $SECRET_NAME -p $DOPPLER_PROJECT -c $CONFIG --plain)"
|
|
151
|
+
# The printed recipe carries a live bearer, so it must TEACH the confined form:
|
|
152
|
+
# `--disable` literally first (it aborts ~/.curlrc parsing, and later is too
|
|
153
|
+
# late) and `--noproxy '*'` (#7873), with the bearer on curl's stdin config
|
|
154
|
+
# channel so a copy-paste never puts the token on argv (#7843).
|
|
155
|
+
printf '%s\n' "curl --disable --noproxy '*' -sS -X POST $ROUTE_URL \\"
|
|
156
|
+
printf '%s\n' " -H 'content-type: application/json' \\"
|
|
157
|
+
printf '%s\n' " -d '$BODY' -w '\\n%{http_code}\\n' \\"
|
|
158
|
+
printf '%s\n' " --config - < <(printf 'header = \"Authorization: Bearer %s\"\\n' \"\$TOKEN\")"
|
|
159
|
+
exit 0
|
|
160
|
+
fi
|
|
161
|
+
|
|
162
|
+
# Read the secret read-only and fire. The token reaches curl on its stdin config
|
|
163
|
+
# channel (never its argument list), is unset right after the call, and is never
|
|
164
|
+
# echoed.
|
|
165
|
+
TOKEN="$(doppler secrets get "$SECRET_NAME" -p "$DOPPLER_PROJECT" -c "$CONFIG" --plain)"
|
|
166
|
+
if [[ -z "$TOKEN" ]]; then
|
|
167
|
+
echo "trigger.sh: $SECRET_NAME is empty in Doppler $DOPPLER_PROJECT/$CONFIG" >&2
|
|
168
|
+
exit 2
|
|
169
|
+
fi
|
|
170
|
+
|
|
171
|
+
# Token-shape guard (never echoes the value): the token is written into curl's stdin
|
|
172
|
+
# config below, so a quote or newline in it would inject a config directive. An unusable
|
|
173
|
+
# token makes zero curl calls and exits 2, the same code as an empty secret, never 0.
|
|
174
|
+
_bearer_ok() { local LC_ALL=C; case "${1:-}" in ''|*[!A-Za-z0-9._~+/=-]*) return 1 ;; esac; }
|
|
175
|
+
if ! _bearer_ok "$TOKEN"; then
|
|
176
|
+
echo "trigger.sh: $SECRET_NAME in Doppler $DOPPLER_PROJECT/$CONFIG has an unexpected shape; nothing was sent" >&2
|
|
177
|
+
exit 2
|
|
178
|
+
fi
|
|
179
|
+
|
|
180
|
+
# mktemp, not $$: a PID is predictable and reused across concurrent runs in shared shells
|
|
181
|
+
# (same reason token-efficiency-report.sh's SHORTSTAT_TMP mktemp+EXIT-trap block rejects it).
|
|
182
|
+
# See ADR-009 Amendment.
|
|
183
|
+
RESP=$(mktemp -t trigger-cron-resp.XXXXXXXX)
|
|
184
|
+
trap 'rm -f "$RESP"' EXIT INT TERM
|
|
185
|
+
HTTP_CODE=$(curl --disable --noproxy '*' -sS -o "$RESP" -w '%{http_code}' \
|
|
186
|
+
-X POST "$ROUTE_URL" \
|
|
187
|
+
-H 'content-type: application/json' \
|
|
188
|
+
-d "$BODY" \
|
|
189
|
+
--config - \
|
|
190
|
+
< <(printf 'header = "Authorization: Bearer %s"\n' "$TOKEN"))
|
|
191
|
+
unset TOKEN
|
|
192
|
+
|
|
193
|
+
echo "HTTP $HTTP_CODE"
|
|
194
|
+
cat "$RESP" 2>/dev/null && echo
|
|
195
|
+
rm -f "$RESP"
|
|
196
|
+
|
|
197
|
+
# 202 = dispatched. Anything else is a failure the caller must act on.
|
|
198
|
+
[[ "$HTTP_CODE" == "202" ]] || exit 1
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: user-set-role
|
|
3
|
+
description: "This skill should be used to promote or demote a user's flag-targeting role across Supabase users.role and the Flagsmith identity trait."
|
|
4
|
+
disable-model-invocation: true
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
<!-- soleur-cloud-mode:start -->
|
|
8
|
+
**Cloud Mode (Devin):** before pipeline work run `bash "${CLAUDE_PLUGIN_ROOT}/scripts/cloud-detect.sh"`. If `CLAUDE_PLUGIN_ROOT` is unset (cloud exec shells do not export it), resolve the root by IDENTITY, never by script basename: for `d` in `"$HOME/.local/share/devin/cli/plugins/cache"` and `/opt/.devin/plugins`, skip unless `[ -d "$d" ]`, then `MANIFEST="$(find "$d" -path '*/.claude-plugin/plugin.json' -exec grep -l '"name"[[:space:]]*:[[:space:]]*"soleur"' {} + 2>/dev/null | head -1)"`, `ROOT="${MANIFEST%/.claude-plugin/plugin.json}"` — one resolution, two consumers: `$ROOT/scripts/cloud-detect.sh` and `$ROOT/scripts/precommit-guard.sh`. (Shape check, not authentication: a planted `{"name":"soleur"}` dir passes — ADR-179 A11.) `local` or `not-local:no-devin-env` proceeds normally; any other `not-local:<reason>` applies `<plugin-root>/devin/INSTRUCTIONS.md` §Cloud Mode: emit the `--banner`, fan out sequentially with `Reviewed-Coverage: sequential-fallback` disclosure (never claim an independent review ran), `message_user` ack before any secrets read or production mutation, and run `precommit-guard.sh` before any `git commit` — hooks do not fire in cloud.
|
|
9
|
+
<!-- soleur-cloud-mode:end -->
|
|
10
|
+
|
|
11
|
+
<!-- grok-harness-invoke:start -->
|
|
12
|
+
**Grok Build (`plugins/soleur/lib/harness.ts` `invokeSkill()`):** Read this SKILL.md in this process and run it to completion. A one-segment `soleur:<name>` in this document names a SKILL — on Grok Build, Read `plugins/soleur/skills/<name>/SKILL.md` in this process; it is not a nested tool_use. A multi-segment id such as `soleur:<domain>:<name>` names an AGENT: spawn it, never Read it, and on Grok Build spawn_subagent takes the id with its colons replaced by hyphens (`agentIdToGrokSubagentType`). **Claude Code:** Skill tool for a skill (`soleur:<name>`), Task tool with `subagent_type` for an agent. Forbidden is executing a subset, not the Read.
|
|
13
|
+
<!-- grok-harness-invoke:end -->
|
|
14
|
+
|
|
15
|
+
# user-set-role
|
|
16
|
+
|
|
17
|
+
The only approved path for mutating `public.users.role`. Migration 054's
|
|
18
|
+
trigger blocks non-service-role connections from updating that column, so
|
|
19
|
+
direct PostgREST writes from authenticated users always fail — this skill
|
|
20
|
+
runs the service-role write + the Flagsmith identity trait write together
|
|
21
|
+
to keep the two sides aligned.
|
|
22
|
+
|
|
23
|
+
## When to use
|
|
24
|
+
|
|
25
|
+
- Promoting yourself or a teammate to the `dev` cohort so you receive
|
|
26
|
+
per-role flag previews before flags promote to `prd`.
|
|
27
|
+
- Demoting a user back to `prd` when they no longer need preview access.
|
|
28
|
+
|
|
29
|
+
## When NOT to use
|
|
30
|
+
|
|
31
|
+
- Bulk role changes (>5 users at once) — script doesn't batch; run
|
|
32
|
+
individually for now.
|
|
33
|
+
- Trying to promote a Supabase user that doesn't exist — skill fails
|
|
34
|
+
early with a clear error.
|
|
35
|
+
|
|
36
|
+
## Arguments
|
|
37
|
+
|
|
38
|
+
<arguments> #$ARGUMENTS </arguments>
|
|
39
|
+
|
|
40
|
+
Required positional args: `<email-or-userId> <prd|dev>`.
|
|
41
|
+
|
|
42
|
+
- `<email-or-userId>`: email address (resolved to UUID via Supabase) OR
|
|
43
|
+
a Supabase auth UUID directly.
|
|
44
|
+
- `<prd|dev>`: target role.
|
|
45
|
+
|
|
46
|
+
Flag `--dry-run` runs lookup + diff (no writes).
|
|
47
|
+
|
|
48
|
+
## Prerequisites
|
|
49
|
+
|
|
50
|
+
- `doppler` CLI authenticated; access to `soleur/prd` config (for
|
|
51
|
+
`SUPABASE_SERVICE_ROLE_KEY` + `NEXT_PUBLIC_SUPABASE_URL`).
|
|
52
|
+
- `doppler` access to `soleur/cli_ops` (for
|
|
53
|
+
`FLAGSMITH_MANAGEMENT_API_KEY`).
|
|
54
|
+
- `curl` + `python3` on PATH.
|
|
55
|
+
|
|
56
|
+
## Procedure
|
|
57
|
+
|
|
58
|
+
The agent runs only the preview (`--dry-run` is honoured in the third position
|
|
59
|
+
only; anything else there, or a fourth argument, exits `2`):
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
bash "${CLAUDE_PLUGIN_ROOT}/skills/user-set-role/scripts/set-role.sh" <email|uuid> <prd|dev> --dry-run
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
## The write is the one typed-`yes` handoff (ADR-249)
|
|
66
|
+
|
|
67
|
+
The write path asks for a typed `yes` through the operator-script library's TTY
|
|
68
|
+
acknowledgement, because the audit row this script writes records only that kind of
|
|
69
|
+
acknowledgement (ADR-249); moving it to the staged agent-run approval gate that
|
|
70
|
+
generated operator scripts use is tracked in #9387. It has no skip variable and no
|
|
71
|
+
flag. An agent's shell has no TTY, so a write run there stops with exit `64` and `SOLEUR_BOOTSTRAP_INPUT_REQUIRED` on
|
|
72
|
+
stdout, before any credential is fetched. Exit `64` is a refusal, never a success.
|
|
73
|
+
The agent therefore does every other step itself (reads, the dry-run preview,
|
|
74
|
+
preflight, verification) and hands over only the typed-`yes` write:
|
|
75
|
+
|
|
76
|
+
1. Runs the script with `--dry-run` and shows the preview. That mode needs no TTY
|
|
77
|
+
and makes no writes.
|
|
78
|
+
2. Prints the exact write command below, in a fenced block, for the operator to type
|
|
79
|
+
at a terminal prompt (Warp), the one step an agent cannot take. It replaces `<WORKTREE>` with the absolute path of
|
|
80
|
+
the worktree that holds this change (`git rev-parse --show-toplevel`) and
|
|
81
|
+
`<ARGS>` with `<email|uuid> <prd|dev>`, without `--dry-run`. It never prints a
|
|
82
|
+
`${CLAUDE_PLUGIN_ROOT}` or repo-relative form. A plugin-root or repo-relative path resolves against whatever directory the operator's terminal happens to be in; the absolute worktree path does not.
|
|
83
|
+
3. Does not run the command, and does not run it through Claude Code's `!` prefix
|
|
84
|
+
either (whether that gives the command a TTY is unmeasured, ADR-249). The
|
|
85
|
+
printed command is an undone operator step under
|
|
86
|
+
`wg-block-pr-ready-on-undeferred-operator-steps`: record it where the pipeline
|
|
87
|
+
tracks operator steps, and do not mark a PR ready until the operator says it ran.
|
|
88
|
+
|
|
89
|
+
<!-- operator-write-command -->
|
|
90
|
+
```bash
|
|
91
|
+
cd <WORKTREE> && bash <WORKTREE>/plugins/soleur/skills/user-set-role/scripts/set-role.sh <ARGS>
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
The operator types `yes` at the prompt. Any other answer stops the script with exit
|
|
95
|
+
`1` and `SOLEUR_BOOTSTRAP_ABORTED stage=ack`, before anything is written.
|
|
96
|
+
|
|
97
|
+
The script (full procedure in [scripts/set-role.sh](./scripts/set-role.sh)):
|
|
98
|
+
|
|
99
|
+
1. **Validate args** — role in `{prd, dev}`; identifier looks like
|
|
100
|
+
email-or-UUID.
|
|
101
|
+
2. **Resolve userId** — if input is an email, look up via service-role
|
|
102
|
+
Supabase REST: `GET /rest/v1/users?email=eq.<email>&select=id,role`.
|
|
103
|
+
If input is UUID, use directly + read current role for the diff.
|
|
104
|
+
3. **Diff** — if `current_role == target_role`, exit 0 ("no change").
|
|
105
|
+
4. **Print pre/post** — user UUID + email + current role + target role.
|
|
106
|
+
5. **Operator ack** — a typed `yes` at the TTY prompt per
|
|
107
|
+
`hr-menu-option-ack-not-prod-write-auth` (no flag skips it; no TTY means exit
|
|
108
|
+
`64` before any credential fetch). Both role values change a PRD user.
|
|
109
|
+
6. **Update Supabase** — `PATCH /rest/v1/users?id=eq.<uuid>` with
|
|
110
|
+
`{ "role": "<target>" }`. Service-role JWT bypasses the trigger.
|
|
111
|
+
7. **Update Flagsmith identity trait** — POST to
|
|
112
|
+
`/api/v1/environments/{env_id}/identities/{userId}/traits/` with
|
|
113
|
+
`trait_key=role`, `trait_value=<target>`. Done for BOTH dev (env 90722)
|
|
114
|
+
and prd (env 90721) so the user's flag resolution matches in either
|
|
115
|
+
environment.
|
|
116
|
+
8. **Re-verify** — re-read `users.role` AND the Flagsmith identity trait
|
|
117
|
+
in each env. Assert matches `<target>`.
|
|
118
|
+
|
|
119
|
+
## Exit codes
|
|
120
|
+
|
|
121
|
+
- `0` — success / no-op / dry-run clean.
|
|
122
|
+
- `1` — validation failure (bad role, malformed identifier), or the operator did
|
|
123
|
+
not type `yes` (`SOLEUR_BOOTSTRAP_ABORTED stage=ack`; nothing written).
|
|
124
|
+
- `2` — prerequisite missing (Doppler, env vars), or a bad third/fourth argument.
|
|
125
|
+
- `3` — user not found in Supabase.
|
|
126
|
+
- `4` — Supabase write failed.
|
|
127
|
+
- `5` — Flagsmith trait write failed (Supabase already updated;
|
|
128
|
+
re-run is idempotent on Supabase side and will re-apply the trait).
|
|
129
|
+
- `64` — a write run with no TTY (`SOLEUR_BOOTSTRAP_INPUT_REQUIRED`): hand the
|
|
130
|
+
command to the operator (above).
|
|
131
|
+
|
|
132
|
+
## Sharp edges
|
|
133
|
+
|
|
134
|
+
- **30s flag-cache TTL.** The user's resolved flag values won't pick up
|
|
135
|
+
the new role until the per-replica per-role cache TTL elapses (max 30s).
|
|
136
|
+
Skill prints this hint after success.
|
|
137
|
+
- **Trait write is fire-and-forget on the identity side.** Flagsmith
|
|
138
|
+
upserts traits; calling with the same value twice is a no-op.
|
|
139
|
+
- **Email collision.** If two users somehow share an email (shouldn't
|
|
140
|
+
happen — `public.users(email)` is unique), the skill aborts with
|
|
141
|
+
exit 3 + the conflicting UUIDs.
|
|
142
|
+
|
|
143
|
+
## Cross-references
|
|
144
|
+
|
|
145
|
+
- Migration: `apps/web-platform/supabase/migrations/054_users_role_column.sql`
|
|
146
|
+
- ADR: `knowledge-base/engineering/architecture/decisions/ADR-038-feature-flags-flagsmith.md`
|
|
147
|
+
- Sibling skills: `soleur:flag-set-role`, `soleur:flag-create`
|
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Promote/demote a Soleur user's flag-targeting role.
|
|
3
|
+
#
|
|
4
|
+
# Contract: SKILL.md in the parent directory.
|
|
5
|
+
# Usage: bash set-role.sh <email|uuid> <prd|dev> [--dry-run]
|
|
6
|
+
#
|
|
7
|
+
# Every write run changes a PRD user (both role values). Run it in your OWN
|
|
8
|
+
# terminal: the ack below needs a person to type yes. An agent runs only
|
|
9
|
+
# `--dry-run` and prints this command for the operator.
|
|
10
|
+
#
|
|
11
|
+
# Exit codes:
|
|
12
|
+
# 0 — success / dry-run
|
|
13
|
+
# 1 — usage error, or the operator did not type yes at the ack
|
|
14
|
+
# (stdout: SOLEUR_BOOTSTRAP_ABORTED stage=ack; nothing mutated)
|
|
15
|
+
# 2 — prerequisite missing, or more than three arguments / a third argument
|
|
16
|
+
# other than --dry-run
|
|
17
|
+
# 3 — user lookup failed
|
|
18
|
+
# 4 — audit append or Supabase update failed
|
|
19
|
+
# 5 — Flagsmith trait write failed
|
|
20
|
+
# 64 — no TTY on stdin for a write run (stdout: SOLEUR_BOOTSTRAP_INPUT_REQUIRED);
|
|
21
|
+
# refused before any credential fetch or network call (#8486)
|
|
22
|
+
|
|
23
|
+
set -euo pipefail
|
|
24
|
+
|
|
25
|
+
# (#7797) Refuse to run under shell tracing. UNCONDITIONAL — deliberately NOT
|
|
26
|
+
# gated on a non-emptiness test of the credential variable, because
|
|
27
|
+
# every credential this script handles (SUPABASE_SERVICE_ROLE_KEY for soleur/prd,
|
|
28
|
+
# which bypasses RLS across every customer's rows, plus the Flagsmith management
|
|
29
|
+
# key) is acquired by `doppler secrets get` BELOW this point, so a conditional arm
|
|
30
|
+
# would test an empty variable at guard time, open, and then trace the acquisition
|
|
31
|
+
# itself. The refusal prints on STDOUT because agent runtimes surface stdout and
|
|
32
|
+
# swallow stderr (knowledge-base/project/constitution.md > Code Style); a swallowed
|
|
33
|
+
# refusal leaves the operator with a bare exit 78 and no explanation.
|
|
34
|
+
case "$-" in
|
|
35
|
+
*x*)
|
|
36
|
+
printf '[FATAL] refusing to run under xtrace: this script handles a live credential and -x would print it (see #7797)\n'
|
|
37
|
+
exit 78
|
|
38
|
+
;;
|
|
39
|
+
esac
|
|
40
|
+
|
|
41
|
+
# (#7873) `--disable` closes ~/.curlrc and `--noproxy '*'` closes the proxy vars,
|
|
42
|
+
# but neither touches the env that subverts TLS ITSELF. SSLKEYLOGFILE writes the
|
|
43
|
+
# session keys and the CA vars substitute the trust store, so a CURL_CA_BUNDLE
|
|
44
|
+
# MITM of the service-role key works with every other guard fully intact.
|
|
45
|
+
unset SSLKEYLOGFILE CURL_CA_BUNDLE SSL_CERT_FILE SSL_CERT_DIR CURL_HOME \
|
|
46
|
+
HOSTALIASES LOCALDOMAIN RES_OPTIONS
|
|
47
|
+
|
|
48
|
+
# Shared WORM audit-append helper (PostgREST RPC; no DB-CLI binary). See #4581 PR-1.
|
|
49
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
50
|
+
source "$SCRIPT_DIR/../../../scripts/audit-flag-flip.sh"
|
|
51
|
+
|
|
52
|
+
# Human-presence gate (#8486, ADR-249). Every production write below waits on the
|
|
53
|
+
# operator-script library's class-2 ack, which has NO skip variable and no flag:
|
|
54
|
+
# it needs a person typing `yes` at a terminal, so an agent's tool subprocess
|
|
55
|
+
# (no TTY) is refused with exit 64 before any credential fetch. Clear anything an
|
|
56
|
+
# inherited environment could use to pre-empt the library's double-source guard
|
|
57
|
+
# or to stand in for its ack before sourcing it. (BASH_ENV runs before this
|
|
58
|
+
# script and cannot be cleared from inside it — recorded in ADR-249 as a
|
|
59
|
+
# hijack-class residual.)
|
|
60
|
+
unset _SOLEUR_OPERATOR_SCRIPT_LOADED SOLEUR_OP_ACKED
|
|
61
|
+
unset -f soleur_op_ack_or_die soleur_op_input_required soleur_op_aborted
|
|
62
|
+
# shellcheck source=../../../scripts/lib/operator-script.sh
|
|
63
|
+
source "$SCRIPT_DIR/../../../scripts/lib/operator-script.sh"
|
|
64
|
+
[[ ${SOLEUR_OP_LIB_API:-0} -eq 1 ]] || {
|
|
65
|
+
printf 'SOLEUR_BOOTSTRAP_LIB_INCOMPATIBLE need=1 got=%s\n' "${SOLEUR_OP_LIB_API:-0}"
|
|
66
|
+
exit 64
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
readonly FLAGSMITH_API="https://api.flagsmith.com/api/v1"
|
|
70
|
+
readonly FLAGSMITH_ENV_DEV_ID=90722
|
|
71
|
+
readonly FLAGSMITH_ENV_PRD_ID=90721
|
|
72
|
+
|
|
73
|
+
# The parser honours --dry-run ONLY in position 3, so anything else there (or a
|
|
74
|
+
# fourth argument) is refused rather than silently read as a write (#8486).
|
|
75
|
+
[[ $# -le 3 ]] || { echo "set-role.sh takes at most three arguments (got $#)" >&2; exit 2; }
|
|
76
|
+
[[ -z "${3:-}" || "${3:-}" == "--dry-run" ]] || { echo "third argument must be --dry-run (got: ${3})" >&2; exit 2; }
|
|
77
|
+
DRY_RUN=0
|
|
78
|
+
if [[ "${3:-}" == "--dry-run" ]]; then DRY_RUN=1; fi
|
|
79
|
+
|
|
80
|
+
IDENT="${1:-}"
|
|
81
|
+
TARGET="${2:-}"
|
|
82
|
+
|
|
83
|
+
usage() {
|
|
84
|
+
echo "Usage: set-role.sh <email|uuid> <prd|dev> [--dry-run]" >&2
|
|
85
|
+
exit 1
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
[[ -z "$IDENT" || -z "$TARGET" ]] && usage
|
|
89
|
+
[[ "$TARGET" != "prd" && "$TARGET" != "dev" ]] && { echo "role must be prd|dev (got: $TARGET)" >&2; usage; }
|
|
90
|
+
|
|
91
|
+
# UUID v4 regex (loose — Supabase auth uses standard v4).
|
|
92
|
+
UUID_RE='^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$'
|
|
93
|
+
|
|
94
|
+
# --- no TTY, no write: refuse before any credential fetch or network call ---
|
|
95
|
+
if [[ $DRY_RUN -eq 0 ]]; then [[ -t 0 ]] || soleur_op_input_required "destructive-write-ack(no-skip-variable-by-design)" ack; fi
|
|
96
|
+
|
|
97
|
+
command -v curl >/dev/null || { echo "missing: curl" >&2; exit 2; }
|
|
98
|
+
command -v doppler >/dev/null || { echo "missing: doppler" >&2; exit 2; }
|
|
99
|
+
command -v python3 >/dev/null || { echo "missing: python3" >&2; exit 2; }
|
|
100
|
+
|
|
101
|
+
SUPA_URL=$(doppler secrets get NEXT_PUBLIC_SUPABASE_URL -p soleur -c prd --plain 2>/dev/null || true)
|
|
102
|
+
SUPA_KEY=$(doppler secrets get SUPABASE_SERVICE_ROLE_KEY -p soleur -c prd --plain 2>/dev/null || true)
|
|
103
|
+
FLAGSMITH_TOKEN=$(doppler secrets get FLAGSMITH_MANAGEMENT_API_KEY -p soleur -c cli_ops --plain 2>/dev/null || true)
|
|
104
|
+
[[ -z "$SUPA_URL" || -z "$SUPA_KEY" ]] && { echo "missing Supabase secrets in soleur/prd" >&2; exit 2; }
|
|
105
|
+
[[ -z "$FLAGSMITH_TOKEN" ]] && { echo "missing FLAGSMITH_MANAGEMENT_API_KEY in soleur/cli_ops" >&2; exit 2; }
|
|
106
|
+
|
|
107
|
+
# Token-shape guard: a newline in the key would inject a curl config directive on the stdin
|
|
108
|
+
# channel below. Never echoes the value.
|
|
109
|
+
_bearer_ok() { local LC_ALL=C; case "${1:-}" in ''|*[!A-Za-z0-9._~+/=-]*) return 1 ;; esac; }
|
|
110
|
+
_bearer_ok "$SUPA_KEY" || { echo "SUPABASE_SERVICE_ROLE_KEY has an unexpected shape" >&2; exit 2; }
|
|
111
|
+
|
|
112
|
+
# The service-role key travels on curl's stdin config channel (both headers), never on argv.
|
|
113
|
+
supa() {
|
|
114
|
+
curl --disable --noproxy '*' -sS -H "Content-Type: application/json" "$@" --config - \
|
|
115
|
+
< <(printf 'header = "apikey: %s"\nheader = "Authorization: Bearer %s"\n' "$SUPA_KEY" "$SUPA_KEY")
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
# The Flagsmith management key travels the same way: a stdin config header, never argv.
|
|
119
|
+
_bearer_ok "$FLAGSMITH_TOKEN" || { echo "FLAGSMITH_MANAGEMENT_API_KEY has an unexpected shape" >&2; exit 2; }
|
|
120
|
+
fs_api() {
|
|
121
|
+
curl --disable --noproxy '*' -sS -H "Content-Type: application/json" "$@" --config - \
|
|
122
|
+
< <(printf 'header = "Authorization: Api-Key %s"\n' "$FLAGSMITH_TOKEN")
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
# --- resolve user ----------------------------------------------------------
|
|
126
|
+
if [[ "$IDENT" =~ $UUID_RE ]]; then
|
|
127
|
+
USER_ID="$IDENT"
|
|
128
|
+
echo "→ Using UUID directly: $USER_ID"
|
|
129
|
+
else
|
|
130
|
+
echo "→ Resolving email '$IDENT' to UUID via Supabase…"
|
|
131
|
+
# URL-encode the email (`+` → `%2B` etc.) so PostgREST receives it intact.
|
|
132
|
+
EMAIL_ENC=$(python3 -c "import urllib.parse, sys; print(urllib.parse.quote(sys.argv[1], safe=''))" "$IDENT")
|
|
133
|
+
ROWS=$(supa "${SUPA_URL}/rest/v1/users?email=eq.${EMAIL_ENC}&select=id,email,role")
|
|
134
|
+
COUNT=$(echo "$ROWS" | python3 -c 'import json,sys; d=json.load(sys.stdin); print(len(d))')
|
|
135
|
+
[[ "$COUNT" == "0" ]] && { echo "no user with email '$IDENT'" >&2; exit 3; }
|
|
136
|
+
[[ "$COUNT" -gt "1" ]] && { echo "MULTIPLE users with email '$IDENT' — abort." >&2; echo "$ROWS" >&2; exit 3; }
|
|
137
|
+
USER_ID=$(echo "$ROWS" | python3 -c 'import json,sys; print(json.load(sys.stdin)[0]["id"])')
|
|
138
|
+
fi
|
|
139
|
+
|
|
140
|
+
# USER_ID is interpolated into the request URL: only a literal-anchored UUID may reach it.
|
|
141
|
+
[[ "$USER_ID" =~ ^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$ ]] || { echo "refusing: resolved user id is not a UUID" >&2; exit 3; }
|
|
142
|
+
|
|
143
|
+
# Read current role.
|
|
144
|
+
CUR_ROWS=$(supa "${SUPA_URL}/rest/v1/users?id=eq.${USER_ID}&select=id,email,role")
|
|
145
|
+
[[ "$(echo "$CUR_ROWS" | python3 -c 'import json,sys; print(len(json.load(sys.stdin)))')" == "0" ]] && { echo "no users.row for UUID $USER_ID" >&2; exit 3; }
|
|
146
|
+
CUR_ROLE=$(echo "$CUR_ROWS" | python3 -c 'import json,sys; print(json.load(sys.stdin)[0]["role"])')
|
|
147
|
+
EMAIL=$(echo "$CUR_ROWS" | python3 -c 'import json,sys; print(json.load(sys.stdin)[0]["email"])')
|
|
148
|
+
|
|
149
|
+
echo " user: $EMAIL ($USER_ID) current role: $CUR_ROLE target: $TARGET"
|
|
150
|
+
|
|
151
|
+
if [[ "$CUR_ROLE" == "$TARGET" ]]; then
|
|
152
|
+
echo "✓ No change — role is already '$TARGET'. Re-applying Flagsmith trait anyway for idempotency."
|
|
153
|
+
if [[ $DRY_RUN -eq 1 ]]; then exit 0; fi
|
|
154
|
+
fi
|
|
155
|
+
|
|
156
|
+
# --- ack ------------------------------------------------------------------
|
|
157
|
+
if [[ $DRY_RUN -eq 1 ]]; then
|
|
158
|
+
echo "(dry-run — exiting 0)"
|
|
159
|
+
exit 0
|
|
160
|
+
fi
|
|
161
|
+
|
|
162
|
+
soleur_op_ack_or_die "Set the role of ${EMAIL} (${USER_ID}) to '${TARGET}' in Supabase prd and Flagsmith (dev + prd) now? Type yes: "
|
|
163
|
+
|
|
164
|
+
# --- audit append (WORM) — BEFORE the users.role mutation (append-before-flip) -------
|
|
165
|
+
# A failed audit must abort the script before any prod mutation; otherwise a role
|
|
166
|
+
# change could land in prd with no WORM accountability row (#4581 review FINDING 1).
|
|
167
|
+
ACTOR=$(doppler secrets get OPERATOR_EMAIL -p soleur -c cli_ops --plain 2>/dev/null | tr '[:upper:]' '[:lower:]')
|
|
168
|
+
[[ -z "$ACTOR" ]] && { echo "FATAL: OPERATOR_EMAIL not in Doppler soleur/cli_ops" >&2; exit 4; }
|
|
169
|
+
|
|
170
|
+
# Audit DB target = soleur/dev (preserves the historical dev-DB audit destination);
|
|
171
|
+
# distinct from the prd SUPA_URL/SUPA_KEY used for the users.role PATCH below.
|
|
172
|
+
# `|| true` normalizes a Doppler auth/network failure to the exit-4 contract (the
|
|
173
|
+
# [[ -z ]] guard) instead of letting `set -e` abort at the assignment with exit 1.
|
|
174
|
+
AUDIT_URL=$(doppler secrets get SUPABASE_URL -p soleur -c dev --plain 2>/dev/null) || true
|
|
175
|
+
AUDIT_SRK=$(doppler secrets get SUPABASE_SERVICE_ROLE_KEY -p soleur -c dev --plain 2>/dev/null) || true
|
|
176
|
+
[[ -z "$AUDIT_URL" || -z "$AUDIT_SRK" ]] && { echo "FATAL: SUPABASE_URL / SUPABASE_SERVICE_ROLE_KEY not in Doppler soleur/dev" >&2; exit 4; }
|
|
177
|
+
|
|
178
|
+
# NOTE(#4581): AUDIT_ACTION tautology (both branches "on") is a pre-existing bug,
|
|
179
|
+
# out of scope for the transport swap; see #4593. Role assignment records "on".
|
|
180
|
+
AUDIT_ACTION=$([[ "$CUR_ROLE" == "$TARGET" ]] && echo "on" || echo "on")
|
|
181
|
+
AUDIT_ID=$(audit_flag_flip_rpc "$AUDIT_URL" "$AUDIT_SRK" "user-role" "prd" "user:$USER_ID" "$AUDIT_ACTION" null null "$ACTOR") || exit 4
|
|
182
|
+
echo " audit_id=$AUDIT_ID"
|
|
183
|
+
|
|
184
|
+
# --- update Supabase (AFTER the audit row is committed) -------------------------------
|
|
185
|
+
if [[ "$CUR_ROLE" != "$TARGET" ]]; then
|
|
186
|
+
echo "→ Updating Supabase users.role…"
|
|
187
|
+
RESP=$(supa -X PATCH "${SUPA_URL}/rest/v1/users?id=eq.${USER_ID}" \
|
|
188
|
+
-H 'Prefer: return=representation' \
|
|
189
|
+
-d "{\"role\": \"$TARGET\"}")
|
|
190
|
+
echo "$RESP" | python3 -c '
|
|
191
|
+
import json, sys
|
|
192
|
+
d = json.load(sys.stdin)
|
|
193
|
+
if not isinstance(d, list) or not d:
|
|
194
|
+
print(json.dumps(d), file=sys.stderr); sys.exit(4)
|
|
195
|
+
print(" updated:", d[0]["email"], "role →", d[0]["role"])
|
|
196
|
+
' || exit 4
|
|
197
|
+
fi
|
|
198
|
+
|
|
199
|
+
# --- update Flagsmith identity trait (both envs) --------------------------
|
|
200
|
+
for ENV_PAIR in "dev:$FLAGSMITH_ENV_DEV_ID" "prd:$FLAGSMITH_ENV_PRD_ID"; do
|
|
201
|
+
ENV_NAME=${ENV_PAIR%:*}
|
|
202
|
+
ENV_ID=${ENV_PAIR#*:}
|
|
203
|
+
echo "→ Writing Flagsmith trait role=$TARGET for identity $USER_ID in env=$ENV_NAME ($ENV_ID)…"
|
|
204
|
+
fs_api -X POST "${FLAGSMITH_API}/environments/${ENV_ID}/identities/${USER_ID}/traits/" \
|
|
205
|
+
-d "{\"trait_key\":\"role\",\"trait_value\":\"$TARGET\"}" \
|
|
206
|
+
| python3 -c '
|
|
207
|
+
import json, sys
|
|
208
|
+
d = json.load(sys.stdin)
|
|
209
|
+
if isinstance(d, dict) and d.get("trait_key") == "role":
|
|
210
|
+
print(" ✓ wrote:", d)
|
|
211
|
+
else:
|
|
212
|
+
print(" ! response:", json.dumps(d), file=sys.stderr); sys.exit(5)
|
|
213
|
+
' || exit 5
|
|
214
|
+
done
|
|
215
|
+
|
|
216
|
+
echo
|
|
217
|
+
echo "✓ Done. The per-role flag cache TTL is 30s; user's resolved flags update within that window."
|
|
218
|
+
exit 0
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: user-story-writer
|
|
3
|
+
description: "This skill should be used when decomposing feature requirements into granular, implementable user stories. It applies Elephant Carpaccio slicing, INVEST criteria, and story prioritization."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
<!-- grok-harness-invoke:start -->
|
|
7
|
+
**Grok Build (`plugins/soleur/lib/harness.ts` `invokeSkill()`):** Read this SKILL.md in this process and run it to completion. A one-segment `soleur:<name>` in this document names a SKILL — on Grok Build, Read `plugins/soleur/skills/<name>/SKILL.md` in this process; it is not a nested tool_use. A multi-segment id such as `soleur:<domain>:<name>` names an AGENT: spawn it, never Read it, and on Grok Build spawn_subagent takes the id with its colons replaced by hyphens (`agentIdToGrokSubagentType`). **Claude Code:** Skill tool for a skill (`soleur:<name>`), Task tool with `subagent_type` for an agent. Forbidden is executing a subset, not the Read.
|
|
8
|
+
<!-- grok-harness-invoke:end -->
|
|
9
|
+
|
|
10
|
+
# User Story Writer
|
|
11
|
+
|
|
12
|
+
Decompose a problem statement or feature requirement into thin, vertical user stories that deliver end-to-end value.
|
|
13
|
+
|
|
14
|
+
## When to Use
|
|
15
|
+
|
|
16
|
+
- Breaking down a feature into sprint-sized work items
|
|
17
|
+
- Decomposing a vague requirement into concrete stories
|
|
18
|
+
- Prioritizing a backlog by risk and value
|
|
19
|
+
|
|
20
|
+
## Constraints
|
|
21
|
+
|
|
22
|
+
This is a story-writing role. Do not suggest implementation details, code examples, technical architectures, or testing frameworks. Focus exclusively on user needs, business value, and acceptance criteria in user terms.
|
|
23
|
+
|
|
24
|
+
## Process
|
|
25
|
+
|
|
26
|
+
### 1. Analyze the Problem
|
|
27
|
+
|
|
28
|
+
- Identify the core user need and key stakeholders
|
|
29
|
+
- Map the problem domain and user personas
|
|
30
|
+
- Clarify scope boundaries
|
|
31
|
+
|
|
32
|
+
### 2. Slice with Elephant Carpaccio
|
|
33
|
+
|
|
34
|
+
Break the problem into the thinnest possible vertical slices. Each slice must deliver a complete, working capability a user can interact with -- not a technical layer.
|
|
35
|
+
|
|
36
|
+
### 3. Write INVEST-Compliant Stories
|
|
37
|
+
|
|
38
|
+
Every story must satisfy all six INVEST criteria (Independent, Negotiable, Valuable, Estimable, Small, Testable).
|
|
39
|
+
|
|
40
|
+
### 4. Structure Each Story
|
|
41
|
+
|
|
42
|
+
```
|
|
43
|
+
**Story Title**: [Descriptive name]
|
|
44
|
+
**As a** [user type]
|
|
45
|
+
**I want** [functionality]
|
|
46
|
+
**So that** [business value]
|
|
47
|
+
|
|
48
|
+
**Acceptance Criteria**:
|
|
49
|
+
- [Specific, testable criterion 1]
|
|
50
|
+
- [Specific, testable criterion 2]
|
|
51
|
+
|
|
52
|
+
**Definition of Done**:
|
|
53
|
+
- [User-facing quality requirement]
|
|
54
|
+
- [Business completion criterion]
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
### 5. Prioritize and Sequence
|
|
58
|
+
|
|
59
|
+
Order stories by:
|
|
60
|
+
|
|
61
|
+
1. Risk reduction -- tackle unknowns early
|
|
62
|
+
2. User value delivery
|
|
63
|
+
3. Dependencies between stories
|
|
64
|
+
4. Learning opportunities
|
|
65
|
+
|
|
66
|
+
### 6. Validate Completeness
|
|
67
|
+
|
|
68
|
+
Confirm the full set of stories covers the original problem without gaps or overlaps.
|
|
69
|
+
|
|
70
|
+
## Output Format
|
|
71
|
+
|
|
72
|
+
Produce a structured document containing:
|
|
73
|
+
|
|
74
|
+
- Problem summary and user personas
|
|
75
|
+
- Prioritized list of user stories (using the template above)
|
|
76
|
+
- Rationale for decomposition approach and sequencing
|
|
77
|
+
- Summary of how stories collectively solve the original problem
|