@soleur/opencode 0.0.0-stage → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/agents.manifest.json +476 -0
- package/.claude-plugin/plugin.json +42 -0
- package/README.md +44 -2
- package/agents/community/.gitkeep +0 -0
- package/agents/engineering/cto.md +87 -0
- package/agents/engineering/design/ddd-architect.md +95 -0
- package/agents/engineering/discovery/agent-finder.md +214 -0
- package/agents/engineering/discovery/functional-discovery.md +182 -0
- package/agents/engineering/infra/infra-security.md +151 -0
- package/agents/engineering/infra/platform-strategist.md +109 -0
- package/agents/engineering/infra/terraform-architect.md +171 -0
- package/agents/engineering/prompt-engineer.md +37 -0
- package/agents/engineering/research/best-practices-researcher.md +115 -0
- package/agents/engineering/research/framework-docs-researcher.md +93 -0
- package/agents/engineering/research/git-history-analyzer.md +53 -0
- package/agents/engineering/research/learnings-researcher.md +285 -0
- package/agents/engineering/research/repo-research-analyst.md +118 -0
- package/agents/engineering/review/agent-native-reviewer.md +279 -0
- package/agents/engineering/review/architecture-strategist.md +61 -0
- package/agents/engineering/review/code-quality-analyst.md +92 -0
- package/agents/engineering/review/code-simplicity-reviewer.md +109 -0
- package/agents/engineering/review/data-integrity-guardian.md +82 -0
- package/agents/engineering/review/data-migration-expert.md +98 -0
- package/agents/engineering/review/deployment-verification-agent.md +183 -0
- package/agents/engineering/review/dhh-rails-reviewer.md +46 -0
- package/agents/engineering/review/kieran-rails-reviewer.md +87 -0
- package/agents/engineering/review/legacy-code-expert.md +55 -0
- package/agents/engineering/review/observability-coverage-reviewer.md +147 -0
- package/agents/engineering/review/pattern-recognition-specialist.md +59 -0
- package/agents/engineering/review/performance-oracle.md +130 -0
- package/agents/engineering/review/security-sentinel.md +167 -0
- package/agents/engineering/review/semgrep-sast.md +36 -0
- package/agents/engineering/review/test-design-reviewer.md +150 -0
- package/agents/engineering/review/user-impact-reviewer.md +70 -0
- package/agents/engineering/workflow/pr-comment-resolver.md +69 -0
- package/agents/finance/budget-analyst.md +29 -0
- package/agents/finance/cfo.md +44 -0
- package/agents/finance/financial-reporter.md +30 -0
- package/agents/finance/revenue-analyst.md +30 -0
- package/agents/legal/clo.md +115 -0
- package/agents/legal/legal-compliance-auditor.md +110 -0
- package/agents/legal/legal-document-generator.md +134 -0
- package/agents/marketing/analytics-analyst.md +25 -0
- package/agents/marketing/brand-architect.md +181 -0
- package/agents/marketing/cmo.md +76 -0
- package/agents/marketing/conversion-optimizer.md +19 -0
- package/agents/marketing/copywriter.md +20 -0
- package/agents/marketing/fact-checker.md +70 -0
- package/agents/marketing/growth-strategist.md +145 -0
- package/agents/marketing/paid-media-strategist.md +28 -0
- package/agents/marketing/pricing-strategist.md +17 -0
- package/agents/marketing/programmatic-seo-specialist.md +25 -0
- package/agents/marketing/retention-strategist.md +23 -0
- package/agents/marketing/seo-aeo-analyst.md +164 -0
- package/agents/operations/coo.md +50 -0
- package/agents/operations/ops-advisor.md +78 -0
- package/agents/operations/ops-provisioner.md +101 -0
- package/agents/operations/ops-research.md +52 -0
- package/agents/operations/service-automator.md +278 -0
- package/agents/product/business-validator.md +206 -0
- package/agents/product/competitive-intelligence.md +89 -0
- package/agents/product/cpo.md +63 -0
- package/agents/product/design/ux-design-lead.md +209 -0
- package/agents/product/spec-flow-analyzer.md +122 -0
- package/agents/sales/cro.md +44 -0
- package/agents/sales/deal-architect.md +29 -0
- package/agents/sales/outbound-strategist.md +29 -0
- package/agents/sales/pipeline-analyst.md +29 -0
- package/agents/support/cco.md +48 -0
- package/agents/support/community-manager.md +570 -0
- package/agents/support/ticket-triage.md +70 -0
- package/bin/soleur-opencode.js +29 -0
- package/commands/go.md +659 -0
- package/commands/help.md +273 -0
- package/commands/sync.md +977 -0
- package/commands/version.md +103 -0
- package/hooks/antigravity-hooks.json +84 -0
- package/hooks/antigravity-session-start.sh +15 -0
- package/hooks/bare-root-cwd-guard.sh +131 -0
- package/hooks/browser-snapshot-credential-guard.sh +200 -0
- package/hooks/codex-session-start.sh +9 -0
- package/hooks/compaction-state.sh +525 -0
- package/hooks/destructive-command-guard.sh +1387 -0
- package/hooks/devin-session-start.sh +90 -0
- package/hooks/ext-filter-detect.sh +171 -0
- package/hooks/hooks.json +133 -0
- package/hooks/lib/hook-tool-kind.sh +24 -0
- package/hooks/lib/log-rotation.sh +176 -0
- package/hooks/lib/shell-argv.pl +576 -0
- package/hooks/memory-backstop.sh +1114 -0
- package/hooks/operator-stage-approval.sh +391 -0
- package/hooks/stop-hook.sh +367 -0
- package/hooks/unkept-promise-hook.sh +383 -0
- package/hooks/version-banner.sh +127 -0
- package/hooks/welcome-hook.sh +50 -0
- package/install.js +108 -0
- package/lib/agent-registry.ts +154 -0
- package/lib/c4-canonical-cli.mjs +34 -0
- package/lib/c4-canonical.mjs +46 -0
- package/lib/c4-from-components.ts +554 -0
- package/lib/go-routing.ts +81 -0
- package/lib/grok-inspect-contract.ts +311 -0
- package/lib/harness-model-map.ts +101 -0
- package/lib/harness-parity.ts +726 -0
- package/lib/harness-tool-map.ts +180 -0
- package/lib/harness.ts +716 -0
- package/lib/heartbeat-live-reconcile.ts +1153 -0
- package/lib/heartbeat-manifest.ts +342 -0
- package/lib/kb-coverage.ts +252 -0
- package/lib/pr-merge-poll.ts +103 -0
- package/lib/workflow-fidelity.ts +388 -0
- package/opencode/INSTRUCTIONS.md +152 -0
- package/opencode/agents/engineering/cto.md +10 -0
- package/opencode/agents/engineering/design/ddd-architect.md +10 -0
- package/opencode/agents/engineering/discovery/agent-finder.md +10 -0
- package/opencode/agents/engineering/discovery/functional-discovery.md +10 -0
- package/opencode/agents/engineering/infra/infra-security.md +10 -0
- package/opencode/agents/engineering/infra/platform-strategist.md +10 -0
- package/opencode/agents/engineering/infra/terraform-architect.md +10 -0
- package/opencode/agents/engineering/prompt-engineer.md +10 -0
- package/opencode/agents/engineering/research/best-practices-researcher.md +10 -0
- package/opencode/agents/engineering/research/framework-docs-researcher.md +10 -0
- package/opencode/agents/engineering/research/git-history-analyzer.md +10 -0
- package/opencode/agents/engineering/research/learnings-researcher.md +10 -0
- package/opencode/agents/engineering/research/repo-research-analyst.md +10 -0
- package/opencode/agents/engineering/review/agent-native-reviewer.md +10 -0
- package/opencode/agents/engineering/review/architecture-strategist.md +10 -0
- package/opencode/agents/engineering/review/code-quality-analyst.md +10 -0
- package/opencode/agents/engineering/review/code-simplicity-reviewer.md +10 -0
- package/opencode/agents/engineering/review/data-integrity-guardian.md +10 -0
- package/opencode/agents/engineering/review/data-migration-expert.md +10 -0
- package/opencode/agents/engineering/review/deployment-verification-agent.md +10 -0
- package/opencode/agents/engineering/review/dhh-rails-reviewer.md +10 -0
- package/opencode/agents/engineering/review/kieran-rails-reviewer.md +10 -0
- package/opencode/agents/engineering/review/legacy-code-expert.md +10 -0
- package/opencode/agents/engineering/review/observability-coverage-reviewer.md +10 -0
- package/opencode/agents/engineering/review/pattern-recognition-specialist.md +10 -0
- package/opencode/agents/engineering/review/performance-oracle.md +10 -0
- package/opencode/agents/engineering/review/security-sentinel.md +10 -0
- package/opencode/agents/engineering/review/semgrep-sast.md +10 -0
- package/opencode/agents/engineering/review/test-design-reviewer.md +10 -0
- package/opencode/agents/engineering/review/user-impact-reviewer.md +10 -0
- package/opencode/agents/engineering/workflow/pr-comment-resolver.md +10 -0
- package/opencode/agents/finance/budget-analyst.md +10 -0
- package/opencode/agents/finance/cfo.md +10 -0
- package/opencode/agents/finance/financial-reporter.md +10 -0
- package/opencode/agents/finance/revenue-analyst.md +10 -0
- package/opencode/agents/legal/clo.md +10 -0
- package/opencode/agents/legal/legal-compliance-auditor.md +10 -0
- package/opencode/agents/legal/legal-document-generator.md +10 -0
- package/opencode/agents/marketing/analytics-analyst.md +10 -0
- package/opencode/agents/marketing/brand-architect.md +10 -0
- package/opencode/agents/marketing/cmo.md +10 -0
- package/opencode/agents/marketing/conversion-optimizer.md +10 -0
- package/opencode/agents/marketing/copywriter.md +10 -0
- package/opencode/agents/marketing/fact-checker.md +10 -0
- package/opencode/agents/marketing/growth-strategist.md +10 -0
- package/opencode/agents/marketing/paid-media-strategist.md +10 -0
- package/opencode/agents/marketing/pricing-strategist.md +10 -0
- package/opencode/agents/marketing/programmatic-seo-specialist.md +10 -0
- package/opencode/agents/marketing/retention-strategist.md +10 -0
- package/opencode/agents/marketing/seo-aeo-analyst.md +10 -0
- package/opencode/agents/operations/coo.md +10 -0
- package/opencode/agents/operations/ops-advisor.md +10 -0
- package/opencode/agents/operations/ops-provisioner.md +10 -0
- package/opencode/agents/operations/ops-research.md +10 -0
- package/opencode/agents/operations/service-automator.md +10 -0
- package/opencode/agents/product/business-validator.md +10 -0
- package/opencode/agents/product/competitive-intelligence.md +10 -0
- package/opencode/agents/product/cpo.md +10 -0
- package/opencode/agents/product/design/ux-design-lead.md +10 -0
- package/opencode/agents/product/spec-flow-analyzer.md +10 -0
- package/opencode/agents/sales/cro.md +10 -0
- package/opencode/agents/sales/deal-architect.md +10 -0
- package/opencode/agents/sales/outbound-strategist.md +10 -0
- package/opencode/agents/sales/pipeline-analyst.md +10 -0
- package/opencode/agents/support/cco.md +10 -0
- package/opencode/agents/support/community-manager.md +10 -0
- package/opencode/agents/support/ticket-triage.md +10 -0
- package/opencode/commands/go.md +10 -0
- package/opencode/commands/help.md +10 -0
- package/opencode/commands/sync.md +10 -0
- package/opencode/commands/version.md +11 -0
- package/opencode/opencode.json +8 -0
- package/opencode/plugin.ts +493 -0
- package/package.json +36 -4
- package/scripts/admin-merge-ready.sh +545 -0
- package/scripts/admin-merge-ready.test.sh +753 -0
- package/scripts/affected-tests.sh +908 -0
- package/scripts/affected-tests.test.sh +1797 -0
- package/scripts/alpha-metrics.sh +78 -0
- package/scripts/alpha-metrics.test.sh +115 -0
- package/scripts/ancestor-signal-helpers.baseline.txt +16 -0
- package/scripts/audit-flag-flip.sh +107 -0
- package/scripts/check-red-on-main.sh +316 -0
- package/scripts/ci-head-verdict.sh +363 -0
- package/scripts/cloud-detect.sh +193 -0
- package/scripts/delegation-verify.sh +657 -0
- package/scripts/delegation-verify.test.sh +1424 -0
- package/scripts/deploy-arm.sh +475 -0
- package/scripts/domain-model-drift.sh +419 -0
- package/scripts/emit-decision.sh +144 -0
- package/scripts/emit-decision.test.sh +144 -0
- package/scripts/ext-filter-divergence-corpus.txt +15 -0
- package/scripts/ext-filter-divergence.sh +189 -0
- package/scripts/generate-c4-from-components.ts +442 -0
- package/scripts/grok-fidelity-gate.sh +68 -0
- package/scripts/grok-pre-push-gate.sh +232 -0
- package/scripts/harness-discovery-smoke.ts +906 -0
- package/scripts/harness-parity-census.ts +92 -0
- package/scripts/inngest-luks-alert-armed-probe.ts +29 -0
- package/scripts/install-opencode-adapter.ts +520 -0
- package/scripts/lib/affected-tests/common.sh +365 -0
- package/scripts/lib/affected-tests/go.sh +157 -0
- package/scripts/lib/affected-tests/js.sh +188 -0
- package/scripts/lib/affected-tests/nx-turbo.sh +98 -0
- package/scripts/lib/affected-tests/python.sh +185 -0
- package/scripts/lib/context-sanitize.sh +49 -0
- package/scripts/lib/domain-model-lib.sh +180 -0
- package/scripts/lib/ext-filter-grammar.tsv +34 -0
- package/scripts/lib/operator-script.sh +1236 -0
- package/scripts/lib/proc.sh +580 -0
- package/scripts/lib/session-state.sh +748 -0
- package/scripts/lib/tmp-classify.sh +843 -0
- package/scripts/lib/wrapper-boundary.sh +47 -0
- package/scripts/lint-ratchet.py +1547 -0
- package/scripts/monitor-pr-checks.sh +441 -0
- package/scripts/pipeline-tally.sh +756 -0
- package/scripts/pipeline-tally.test.sh +740 -0
- package/scripts/plugin-version.sh +528 -0
- package/scripts/precommit-guard.sh +113 -0
- package/scripts/precommit-guard.test.sh +254 -0
- package/scripts/reconcile-live-heartbeats.ts +705 -0
- package/scripts/render-c4-model.sh +217 -0
- package/scripts/resolve-git-root.sh +55 -0
- package/scripts/resolve-regenerable-conflicts.sh +363 -0
- package/scripts/resolve-regenerable-conflicts.test.sh +780 -0
- package/scripts/ruff-requirements.txt +22 -0
- package/scripts/run-in-pid-namespace.sh +98 -0
- package/scripts/run-in-pid-namespace.test.sh +290 -0
- package/scripts/scan-ancestor-signal-helpers.py +556 -0
- package/scripts/scan-ancestor-signal-helpers.test.sh +670 -0
- package/scripts/setup-ralph-loop.sh +238 -0
- package/scripts/sync-cursor-name-map.ts +316 -0
- package/scripts/sync-grok-agent-compat.ts +188 -0
- package/scripts/sync-npm-package.ts +178 -0
- package/scripts/sync-opencode-adapter.ts +479 -0
- package/scripts/sync-pr-behind.sh +534 -0
- package/scripts/sync-pr-behind.test.sh +252 -0
- package/scripts/taste-profile-update.sh +180 -0
- package/scripts/taste-profile-update.test.sh +167 -0
- package/scripts/write-budget-marker.sh +23 -0
- package/scripts/write-kb-coverage.ts +113 -0
- package/skills/admin-ip-refresh/SKILL.md +81 -0
- package/skills/admin-ip-refresh/references/admin-ip-refresh-procedure.md +201 -0
- package/skills/agent-browser/SKILL.md +698 -0
- package/skills/agent-browser/scripts/playwright-mcp-profile-slot.sh +304 -0
- package/skills/agent-browser/scripts/playwright-mcp-redact-proxy.py +964 -0
- package/skills/agent-browser/scripts/redact-a11y-snapshot.py +443 -0
- package/skills/agent-browser/test/fixtures/capture-playwright-mcp-fixtures.py +217 -0
- package/skills/agent-browser/test/fixtures/fake-passthrough-proxy.py +24 -0
- package/skills/agent-browser/test/fixtures/fake-playwright-mcp.py +131 -0
- package/skills/agent-browser/test/fixtures/make-proxy-mutant.py +48 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/dialog-link-injection.json +10 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/empty-content.json +5 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/error-and-result.json +4 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/error-code-bool.json +6 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/error-code-string.json +6 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/error-message-tree.json +6 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/error-no-data.json +6 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/error-string.json +4 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/error-with-data.json +9 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/evaluate-escaped-object.json +10 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/invalid-utf8.json +4 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/link-result.json +10 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/list-two-results.json +6 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/meta-in-result.json +13 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/no-content.json +5 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/quoted-key.json +10 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/resource-block.json +18 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/result-and-method.json +11 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/result-string.json +3 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/run-code-escaped-one-row.json +10 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/run-code-escaped.json +10 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/structured-content.json +13 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/tools-list-no-tools.json +5 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/tree-no-credential.json +10 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/two-text-blocks.json +14 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/unparsable-line.json +3 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/value-contains-brace.json +10 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/value-contains-link-substring.json +10 -0
- package/skills/agent-browser/test/fixtures/playwright-mcp-0.0.78/close.json +12 -0
- package/skills/agent-browser/test/fixtures/playwright-mcp-0.0.78/evaluate.json +12 -0
- package/skills/agent-browser/test/fixtures/playwright-mcp-0.0.78/find.json +12 -0
- package/skills/agent-browser/test/fixtures/playwright-mcp-0.0.78/framing.json +6 -0
- package/skills/agent-browser/test/fixtures/playwright-mcp-0.0.78/initialize.json +14 -0
- package/skills/agent-browser/test/fixtures/playwright-mcp-0.0.78/navigate-link.json +12 -0
- package/skills/agent-browser/test/fixtures/playwright-mcp-0.0.78/navigate.json +12 -0
- package/skills/agent-browser/test/fixtures/playwright-mcp-0.0.78/roots-list-request.json +5 -0
- package/skills/agent-browser/test/fixtures/playwright-mcp-0.0.78/screenshot.json +17 -0
- package/skills/agent-browser/test/fixtures/playwright-mcp-0.0.78/snapshot-filename.json +12 -0
- package/skills/agent-browser/test/fixtures/playwright-mcp-0.0.78/snapshot-meta-json.json +12 -0
- package/skills/agent-browser/test/fixtures/playwright-mcp-0.0.78/snapshot-meta-raw.json +12 -0
- package/skills/agent-browser/test/fixtures/playwright-mcp-0.0.78/snapshot.json +12 -0
- package/skills/agent-browser/test/fixtures/playwright-mcp-0.0.78/tools-list.json +827 -0
- package/skills/agent-browser/test/fixtures/proxy-session-driver.py +138 -0
- package/skills/agent-browser/test/fixtures/session-facts.py +102 -0
- package/skills/agent-browser/test/playwright-mcp-lifetime.test.sh +1620 -0
- package/skills/agent-browser/test/playwright-mcp-redact-proxy.test.sh +1599 -0
- package/skills/agent-browser/test/redact-a11y-snapshot.test.sh +527 -0
- package/skills/agent-native-architecture/SKILL.md +479 -0
- package/skills/agent-native-architecture/references/action-parity-discipline.md +430 -0
- package/skills/agent-native-architecture/references/agent-execution-patterns.md +483 -0
- package/skills/agent-native-architecture/references/agent-native-testing.md +605 -0
- package/skills/agent-native-architecture/references/architecture-patterns.md +493 -0
- package/skills/agent-native-architecture/references/dynamic-context-injection.md +358 -0
- package/skills/agent-native-architecture/references/files-universal-interface.md +314 -0
- package/skills/agent-native-architecture/references/from-primitives-to-domain-tools.md +381 -0
- package/skills/agent-native-architecture/references/mcp-tool-design.md +524 -0
- package/skills/agent-native-architecture/references/mobile-patterns.md +897 -0
- package/skills/agent-native-architecture/references/product-implications.md +478 -0
- package/skills/agent-native-architecture/references/refactoring-to-prompt-native.md +342 -0
- package/skills/agent-native-architecture/references/self-modification.md +294 -0
- package/skills/agent-native-architecture/references/shared-workspace-architecture.md +700 -0
- package/skills/agent-native-architecture/references/system-prompt-design.md +263 -0
- package/skills/agent-native-audit/SKILL.md +300 -0
- package/skills/agent-native-audit/workflows/agent-native-audit.workflow.js +423 -0
- package/skills/andrew-kane-gem-writer/SKILL.md +189 -0
- package/skills/andrew-kane-gem-writer/references/database-adapters.md +231 -0
- package/skills/andrew-kane-gem-writer/references/module-organization.md +121 -0
- package/skills/andrew-kane-gem-writer/references/rails-integration.md +183 -0
- package/skills/andrew-kane-gem-writer/references/resources.md +126 -0
- package/skills/andrew-kane-gem-writer/references/testing-patterns.md +261 -0
- package/skills/architecture/SKILL.md +436 -0
- package/skills/architecture/references/adr-template.md +154 -0
- package/skills/architecture/references/likec4-reference.md +136 -0
- package/skills/architecture/references/nfr-reference.md +126 -0
- package/skills/archive-kb/SKILL.md +86 -0
- package/skills/archive-kb/scripts/archive-kb.sh +300 -0
- package/skills/archive-kb/test/archive-kb-partial-run.test.sh +276 -0
- package/skills/atdd-developer/SKILL.md +65 -0
- package/skills/brainstorm/SKILL.md +701 -0
- package/skills/brainstorm/references/brainstorm-brand-workshop.md +153 -0
- package/skills/brainstorm/references/brainstorm-domain-config.md +63 -0
- package/skills/brainstorm/references/brainstorm-validation-workshop.md +65 -0
- package/skills/brainstorm/references/ui-surface-terms.md +42 -0
- package/skills/brainstorm-techniques/SKILL.md +231 -0
- package/skills/brainstorm-techniques/references/decision-principles.md +150 -0
- package/skills/brainstorm-techniques/references/phase-boundaries.md +103 -0
- package/skills/brainstorm-techniques/references/standing-delegation.md +407 -0
- package/skills/brainstorm-techniques/references/technical-ruling-delegation.md +174 -0
- package/skills/campaign-calendar/SKILL.md +145 -0
- package/skills/cf-token-scope/SKILL.md +164 -0
- package/skills/cf-token-scope/references/widen-playbook.md +114 -0
- package/skills/cf-token-scope/scripts/cf-token-scope.sh +253 -0
- package/skills/changelog/SKILL.md +142 -0
- package/skills/code-to-prd/SKILL.md +66 -0
- package/skills/code-to-prd/references/banner-template.md +12 -0
- package/skills/code-to-prd/references/prd-template.md +41 -0
- package/skills/code-to-prd/scripts/code-to-prd.sh +634 -0
- package/skills/code-to-prd/test/code-to-prd.test.sh +447 -0
- package/skills/code-to-prd/test/fixture/.env.example +7 -0
- package/skills/code-to-prd/test/fixture/app/about/page.tsx +11 -0
- package/skills/code-to-prd/test/fixture/app/api/health/route.ts +10 -0
- package/skills/code-to-prd/test/fixture/app/page.tsx +14 -0
- package/skills/code-to-prd/test/fixture/next.config.mjs +3 -0
- package/skills/code-to-prd/test/fixture/package.json +6 -0
- package/skills/cohort-status/SKILL.md +62 -0
- package/skills/community/SKILL.md +210 -0
- package/skills/community/scripts/bsky-community.sh +644 -0
- package/skills/community/scripts/bsky-setup.sh +631 -0
- package/skills/community/scripts/community-router.sh +93 -0
- package/skills/community/scripts/discord-community.sh +487 -0
- package/skills/community/scripts/discord-setup.sh +784 -0
- package/skills/community/scripts/github-community.sh +706 -0
- package/skills/community/scripts/hn-community.sh +233 -0
- package/skills/community/scripts/lib/hmac-sha1-b64.sh +126 -0
- package/skills/community/scripts/linkedin-community.sh +750 -0
- package/skills/community/scripts/linkedin-setup.sh +758 -0
- package/skills/community/scripts/x-community.sh +890 -0
- package/skills/community/scripts/x-setup.sh +713 -0
- package/skills/community/test/community-argv.test.sh +2922 -0
- package/skills/community/test/github-community.test.sh +981 -0
- package/skills/competitive-analysis/SKILL.md +69 -0
- package/skills/competitive-analysis/references/peer-plugin-audit.md +218 -0
- package/skills/compound/SKILL.md +673 -0
- package/skills/compound/scripts/token-efficiency-report.sh +334 -0
- package/skills/compound/test/phase-16.test.sh +379 -0
- package/skills/compound-capture/SKILL.md +791 -0
- package/skills/compound-capture/assets/critical-pattern-template.md +37 -0
- package/skills/compound-capture/assets/resolution-template.md +116 -0
- package/skills/compound-capture/references/yaml-schema.md +67 -0
- package/skills/compound-capture/schema.yaml +181 -0
- package/skills/constraint-scaffold/SKILL.md +175 -0
- package/skills/constraint-scaffold/references/boundary-readme.template +35 -0
- package/skills/constraint-scaffold/references/constraint-gates-workflow.template +69 -0
- package/skills/constraint-scaffold/references/depcruise-config.template +230 -0
- package/skills/constraint-scaffold/references/fix-constraints-stage-a.template +240 -0
- package/skills/constraint-scaffold/references/fix-constraints-stage-b.template +313 -0
- package/skills/constraint-scaffold/references/shared-runner.template +135 -0
- package/skills/constraint-scaffold/scripts/constraint-scaffold.sh +589 -0
- package/skills/constraint-scaffold/test/bite-proof.test.sh +1338 -0
- package/skills/constraint-scaffold/test/boundary.test.sh +734 -0
- package/skills/constraint-scaffold/test/emit-fix-constraints.test.sh +193 -0
- package/skills/constraint-scaffold/test/generator.test.sh +93 -0
- package/skills/constraint-scaffold/test/parity.test.sh +285 -0
- package/skills/content-writer/SKILL.md +242 -0
- package/skills/content-writer/scripts/blog-jargon-scan.sh +42 -0
- package/skills/cron-delete/SKILL.md +56 -0
- package/skills/cron-list/SKILL.md +54 -0
- package/skills/deepen-plan/SKILL.md +937 -0
- package/skills/deepen-plan/workflows/deepen-plan.workflow.js +488 -0
- package/skills/deploy/SKILL.md +115 -0
- package/skills/deploy/references/hetzner-setup.md +65 -0
- package/skills/deploy/scripts/deploy.sh +37 -0
- package/skills/deploy-docs/SKILL.md +95 -0
- package/skills/dhh-rails-style/SKILL.md +203 -0
- package/skills/dhh-rails-style/references/architecture.md +717 -0
- package/skills/dhh-rails-style/references/controllers.md +323 -0
- package/skills/dhh-rails-style/references/frontend.md +556 -0
- package/skills/dhh-rails-style/references/gems.md +316 -0
- package/skills/dhh-rails-style/references/models.md +388 -0
- package/skills/dhh-rails-style/references/testing.md +354 -0
- package/skills/discord-content/SKILL.md +126 -0
- package/skills/docs-site/SKILL.md +214 -0
- package/skills/drain-labeled-backlog/SKILL.md +203 -0
- package/skills/drain-labeled-backlog/scripts/group-by-area.sh +208 -0
- package/skills/drain-labeled-backlog/workflows/drain-labeled-backlog.workflow.js +433 -0
- package/skills/drain-prs/SKILL.md +142 -0
- package/skills/drain-prs/scripts/triage-prs.sh +192 -0
- package/skills/drain-prs/test/argv-ceiling.test.sh +183 -0
- package/skills/dspy-ruby/SKILL.md +634 -0
- package/skills/dspy-ruby/assets/config-template.rb +359 -0
- package/skills/dspy-ruby/assets/module-template.rb +326 -0
- package/skills/dspy-ruby/assets/signature-template.rb +143 -0
- package/skills/dspy-ruby/references/core-concepts.md +268 -0
- package/skills/dspy-ruby/references/optimization.md +623 -0
- package/skills/dspy-ruby/references/providers.md +335 -0
- package/skills/eval-harness/README.md +194 -0
- package/skills/eval-harness/SKILL.md +157 -0
- package/skills/eval-harness/enums/go-routes.json +13 -0
- package/skills/eval-harness/enums/incident-threshold.json +5 -0
- package/skills/eval-harness/enums/lane.json +5 -0
- package/skills/eval-harness/enums/tool-selection.json +20 -0
- package/skills/eval-harness/enums/triage-levels.json +5 -0
- package/skills/eval-harness/gated-skills.json +34 -0
- package/skills/eval-harness/models.generated.json +5 -0
- package/skills/eval-harness/promptfooconfig-go-routing.yaml +35 -0
- package/skills/eval-harness/promptfooconfig-incident-threshold.yaml +32 -0
- package/skills/eval-harness/promptfooconfig-lane-inference.yaml +33 -0
- package/skills/eval-harness/promptfooconfig-ticket-triage.yaml +34 -0
- package/skills/eval-harness/promptfooconfig-tool-selection.yaml +33 -0
- package/skills/eval-harness/prompts/go-baseline.txt +6 -0
- package/skills/eval-harness/prompts/go-skill.txt +21 -0
- package/skills/eval-harness/prompts/incident-threshold-baseline.txt +6 -0
- package/skills/eval-harness/prompts/incident-threshold-skill.txt +12 -0
- package/skills/eval-harness/prompts/lane-inference-baseline.txt +6 -0
- package/skills/eval-harness/prompts/lane-inference-skill.txt +15 -0
- package/skills/eval-harness/prompts/tool-selection-baseline.txt +19 -0
- package/skills/eval-harness/prompts/tool-selection-skill.txt +22 -0
- package/skills/eval-harness/prompts/triage-baseline.txt +7 -0
- package/skills/eval-harness/prompts/triage-skill.txt +10 -0
- package/skills/eval-harness/scripts/eval-gate.cjs +318 -0
- package/skills/eval-harness/scripts/extract-block.cjs +87 -0
- package/skills/eval-harness/scripts/gate-classification.cjs +28 -0
- package/skills/eval-harness/scripts/gen-models.sh +41 -0
- package/skills/eval-harness/scripts/gen-skill-prompt.cjs +177 -0
- package/skills/eval-harness/scripts/measure-classification.cjs +30 -0
- package/skills/eval-harness/scripts/parse-label.cjs +93 -0
- package/skills/eval-harness/scripts/verdict.cjs +132 -0
- package/skills/eval-harness/tasks/go-routing.jsonl +8 -0
- package/skills/eval-harness/tasks/incident-threshold.jsonl +7 -0
- package/skills/eval-harness/tasks/lane-inference.jsonl +7 -0
- package/skills/eval-harness/tasks/ticket-triage.jsonl +6 -0
- package/skills/eval-harness/tasks/tool-selection.jsonl +15 -0
- package/skills/eval-harness/test/eval-gate.test.sh +132 -0
- package/skills/eval-harness/test/extract-block.test.sh +87 -0
- package/skills/eval-harness/test/gate-classification.test.sh +77 -0
- package/skills/eval-harness/test/gen-models.test.sh +75 -0
- package/skills/eval-harness/test/measure-classification.test.sh +74 -0
- package/skills/eval-harness/test/parse-label.test.sh +129 -0
- package/skills/eval-harness/test/registry-completeness.test.sh +109 -0
- package/skills/eval-harness/test/verdict.test.sh +123 -0
- package/skills/every-style-editor/SKILL.md +142 -0
- package/skills/every-style-editor/references/EVERY_WRITE_STYLE.md +529 -0
- package/skills/feature-tweet/SKILL.md +199 -0
- package/skills/feature-video/SKILL.md +412 -0
- package/skills/feature-video/scripts/check_deps.sh +281 -0
- package/skills/file-todos/SKILL.md +267 -0
- package/skills/file-todos/assets/todo-template.md +166 -0
- package/skills/fix-issue/SKILL.md +278 -0
- package/skills/fix-issue/references/agent-authored-exclusion.md +118 -0
- package/skills/fix-issue/references/exclude-label-jq-snippet.md +96 -0
- package/skills/flag-bootstrap/SETUP.md +142 -0
- package/skills/flag-create/SKILL.md +145 -0
- package/skills/flag-create/scripts/create.sh +273 -0
- package/skills/flag-delete/SKILL.md +167 -0
- package/skills/flag-delete/scripts/delete.sh +288 -0
- package/skills/flag-list/SKILL.md +99 -0
- package/skills/flag-list/scripts/list.sh +275 -0
- package/skills/flag-set-role/SKILL.md +229 -0
- package/skills/flag-set-role/scripts/flip.sh +774 -0
- package/skills/frontend-anti-slop/SKILL.md +106 -0
- package/skills/frontend-anti-slop/references/anti-patterns.md +199 -0
- package/skills/frontend-anti-slop/references/slop-rules.md +65 -0
- package/skills/frontend-anti-slop/scripts/tier1-scan.ts +525 -0
- package/skills/frontend-design/SKILL.md +77 -0
- package/skills/gdpr-gate/NOTICE +136 -0
- package/skills/gdpr-gate/SKILL.md +341 -0
- package/skills/gdpr-gate/references/fields.md +160 -0
- package/skills/gdpr-gate/references/layers/api-layer.md +355 -0
- package/skills/gdpr-gate/references/layers/auth-sessions.md +290 -0
- package/skills/gdpr-gate/references/layers/data-in-transit.md +331 -0
- package/skills/gdpr-gate/references/layers/data-lifecycle.md +341 -0
- package/skills/gdpr-gate/references/layers/frontend.md +249 -0
- package/skills/gdpr-gate/references/layers/testing-seeding.md +256 -0
- package/skills/gdpr-gate/references/leakage-vectors.md +248 -0
- package/skills/gdpr-gate/references/legacy/legal-consent-v1-prose.md +48 -0
- package/skills/gdpr-gate/references/legal-consent.md +140 -0
- package/skills/gdpr-gate/references/non-negotiables.md +60 -0
- package/skills/gdpr-gate/scripts/gdpr-gate.sh +271 -0
- package/skills/gdpr-gate/scripts/notice-frontmatter.sh +337 -0
- package/skills/gdpr-gate/scripts/path-denylist.txt +39 -0
- package/skills/gdpr-gate/scripts/repo-scan.sh +158 -0
- package/skills/gdpr-gate/scripts/vendor-drift-classify.sh +120 -0
- package/skills/gdpr-gate/scripts/vendor-pin-integrity.sh +237 -0
- package/skills/gemini-imagegen/SKILL.md +283 -0
- package/skills/gemini-imagegen/requirements.txt +5 -0
- package/skills/gemini-imagegen/scripts/_error_handling.py +146 -0
- package/skills/gemini-imagegen/scripts/compose_images.py +150 -0
- package/skills/gemini-imagegen/scripts/edit_image.py +137 -0
- package/skills/gemini-imagegen/scripts/gemini_images.py +256 -0
- package/skills/gemini-imagegen/scripts/generate_image.py +147 -0
- package/skills/gemini-imagegen/scripts/multi_turn_chat.py +223 -0
- package/skills/gemini-imagegen/scripts/test_error_handling.py +179 -0
- package/skills/git-worktree/SKILL.md +534 -0
- package/skills/git-worktree/scripts/git-repo-readiness-diag.sh +98 -0
- package/skills/git-worktree/scripts/worktree-manager.sh +4773 -0
- package/skills/git-worktree/test/create-from-origin-main.test.sh +116 -0
- package/skills/git-worktree/test/lease-protects-active.test.sh +1056 -0
- package/skills/git-worktree/test/no-repo-fail-loud.test.sh +88 -0
- package/skills/git-worktree/test/orphan-reaper-honest-count.test.sh +379 -0
- package/skills/git-worktree/test/reap-archive-persistence.test.sh +725 -0
- package/skills/git-worktree/test/stale-lock-sweep.test.sh +176 -0
- package/skills/go/SKILL.md +54 -0
- package/skills/growth/SKILL.md +164 -0
- package/skills/harvest-debt/SKILL.md +78 -0
- package/skills/harvest-debt/scripts/harvest-debt.sh +114 -0
- package/skills/heal-skill/SKILL.md +173 -0
- package/skills/help/SKILL.md +46 -0
- package/skills/incident/NOTICE +39 -0
- package/skills/incident/SKILL.md +395 -0
- package/skills/incident/scripts/dry-run.sh +448 -0
- package/skills/incident/scripts/redact-engine.py +412 -0
- package/skills/incident/scripts/redact-sentinel.sh +44 -0
- package/skills/incident/templates/pir.md +139 -0
- package/skills/incident/test/fixtures/dry-run-incident.json +26 -0
- package/skills/incident/test/fixtures/dry-run-secret-leak.json +26 -0
- package/skills/incident/test/fixtures/legacy-bash-scanner.sh +82 -0
- package/skills/incident/test/fixtures/positive-corpus.md +87 -0
- package/skills/incident/test/redact-sentinel.test.sh +1420 -0
- package/skills/invoice/SKILL.md +206 -0
- package/skills/kb-glossary/SKILL.md +71 -0
- package/skills/kb-glossary/references/glossary-format.md +111 -0
- package/skills/kb-glossary/references/rejected-request-register.md +115 -0
- package/skills/kb-search/SKILL.md +276 -0
- package/skills/kb-search/scripts/kb-search-cache.sh +123 -0
- package/skills/legal-audit/SKILL.md +161 -0
- package/skills/legal-generate/NOTICE +242 -0
- package/skills/legal-generate/SKILL.md +244 -0
- package/skills/legal-generate/references/templates/advisor-agreement/template.md +12 -0
- package/skills/legal-generate/references/templates/business-associate-agreement/template.md +112 -0
- package/skills/legal-generate/references/templates/cookie-notice/template.md +82 -0
- package/skills/legal-generate/references/templates/dpa-global/template.md +439 -0
- package/skills/legal-generate/references/templates/dpa-us/template.md +222 -0
- package/skills/legal-generate/references/templates/employee-offer-letter/template.md +75 -0
- package/skills/legal-generate/references/templates/master-services-agreement/template.md +252 -0
- package/skills/legal-generate/references/templates/mutual-nda/template.md +66 -0
- package/skills/legal-generate/references/templates/one-way-nda/template.md +38 -0
- package/skills/legal-generate/references/templates/privacy-policy-gdpr/template.md +427 -0
- package/skills/legal-generate/references/templates/privacy-policy-us/template.md +313 -0
- package/skills/legal-generate/references/templates/terms-of-use/template.md +75 -0
- package/skills/legal-generate/scripts/strip-vendor-credit.sh +96 -0
- package/skills/linear-fetch/SKILL.md +247 -0
- package/skills/linear-fetch/scripts/assert-no-linear-telemetry.sh +66 -0
- package/skills/linear-fetch/scripts/redact-linear-urls.sh +51 -0
- package/skills/linear-fetch/scripts/render-caller-template.sh +36 -0
- package/skills/linear-fetch/test/assert-no-linear-telemetry.test.sh +113 -0
- package/skills/linear-fetch/test/parity.test.sh +112 -0
- package/skills/linear-fetch/test/persist-safe-integration.test.sh +191 -0
- package/skills/linear-fetch/test/redact-linear-urls.test.sh +226 -0
- package/skills/merge-pr/SKILL.md +668 -0
- package/skills/model-launch-review/SKILL.md +255 -0
- package/skills/model-launch-review/scripts/audit-models.sh +501 -0
- package/skills/one-shot/SKILL.md +316 -0
- package/skills/one-shot/references/token-discipline.md +74 -0
- package/skills/operator-bootstrap/SKILL.md +412 -0
- package/skills/operator-bootstrap/template.sh +439 -0
- package/skills/operator-digest/SKILL.md +287 -0
- package/skills/operator-digest/assets/operator-digest.workflow.yml +175 -0
- package/skills/operator-digest/scripts/digest-scrub.sh +119 -0
- package/skills/operator-digest/scripts/provision-operator-digest-repo.sh +147 -0
- package/skills/operator-rephrase/SKILL.md +98 -0
- package/skills/pencil-setup/SKILL.md +201 -0
- package/skills/pencil-setup/scripts/check_deps.sh +556 -0
- package/skills/pencil-setup/scripts/copy_adapter.sh +80 -0
- package/skills/pencil-setup/scripts/package-lock.json +1172 -0
- package/skills/pencil-setup/scripts/package.json +14 -0
- package/skills/pencil-setup/scripts/pencil-error-enrichment.mjs +21 -0
- package/skills/pencil-setup/scripts/pencil-mcp-adapter.mjs +733 -0
- package/skills/pencil-setup/scripts/pencil-response-classify.mjs +38 -0
- package/skills/pencil-setup/scripts/pencil-save-gate.mjs +26 -0
- package/skills/pencil-setup/scripts/sanitize-filename.mjs +25 -0
- package/skills/plan/SKILL.md +1140 -0
- package/skills/plan/references/differential-migration-testing.md +185 -0
- package/skills/plan/references/plan-community-discovery.md +42 -0
- package/skills/plan/references/plan-founder-check.md +137 -0
- package/skills/plan/references/plan-functional-overlap.md +25 -0
- package/skills/plan/references/plan-host-fanout.md +51 -0
- package/skills/plan/references/plan-issue-templates.md +779 -0
- package/skills/plan/references/plan-network-outage-checklist.md +131 -0
- package/skills/plan/references/plan-scope-check.md +126 -0
- package/skills/plan/references/plan-sharp-edges.md +325 -0
- package/skills/plan/references/plan-signoff-lifecycle.md +12 -0
- package/skills/plan/references/webapp-cwv-observability.md +143 -0
- package/skills/plan-review/SKILL.md +91 -0
- package/skills/plan-review/lib/named-panel.mjs +58 -0
- package/skills/plan-review/workflows/plan-review.workflow.js +477 -0
- package/skills/postmerge/SKILL.md +642 -0
- package/skills/postmerge/references/deploy-status-debugging.md +138 -0
- package/skills/postmerge/references/graceful-degradation.md +20 -0
- package/skills/postmerge/references/sentry-error-count-delta.md +137 -0
- package/skills/preflight/SKILL.md +1553 -0
- package/skills/preflight/references/check-13-founder-check.md +286 -0
- package/skills/preflight/scripts/founder-check.py +1640 -0
- package/skills/preflight/scripts/parse-form-a.awk +107 -0
- package/skills/preflight/scripts/probe-verb-gate.sh +108 -0
- package/skills/product-roadmap/SKILL.md +357 -0
- package/skills/product-roadmap/scripts/roadmap-reconcile.sh +327 -0
- package/skills/provision-cloudflare/SKILL.md +67 -0
- package/skills/provision-cloudflare/scripts/provision-cloudflare.sh +271 -0
- package/skills/provision-doppler/SKILL.md +58 -0
- package/skills/provision-doppler/scripts/provision-doppler.sh +358 -0
- package/skills/provision-github/SKILL.md +59 -0
- package/skills/provision-github/scripts/provision-github.sh +300 -0
- package/skills/provision-hetzner/SKILL.md +76 -0
- package/skills/provision-hetzner/scripts/provision-hetzner.sh +262 -0
- package/skills/provision-hetzner/test/fixture/knowledge-base/legal/tenant-dpa-register.md +26 -0
- package/skills/provision-hetzner/test/fixture/provision-hetzner-dry-run.golden +34 -0
- package/skills/provision-hetzner/test/provision-hetzner-characterization.test.sh +227 -0
- package/skills/qa/SKILL.md +263 -0
- package/skills/qa/references/browser-preflight.md +22 -0
- package/skills/questionnaire-generate/SKILL.md +328 -0
- package/skills/questionnaire-generate/references/questionnaire.template +60 -0
- package/skills/rclone/SKILL.md +162 -0
- package/skills/rclone/scripts/check_setup.sh +63 -0
- package/skills/release-announce/SKILL.md +65 -0
- package/skills/release-docs/SKILL.md +92 -0
- package/skills/reproduce-bug/SKILL.md +358 -0
- package/skills/resolve-debt/SKILL.md +85 -0
- package/skills/resolve-debt/scripts/resolve-debt.py +584 -0
- package/skills/resolve-parallel/SKILL.md +45 -0
- package/skills/resolve-parallel/workflows/resolve-parallel.workflow.js +415 -0
- package/skills/resolve-pr-parallel/SKILL.md +68 -0
- package/skills/resolve-pr-parallel/workflows/resolve-pr-parallel.workflow.js +419 -0
- package/skills/resolve-todo-parallel/SKILL.md +57 -0
- package/skills/resolve-todo-parallel/workflows/resolve-todo-parallel.workflow.js +398 -0
- package/skills/review/SKILL.md +1621 -0
- package/skills/review/references/anti-slop-scanner-hook.md +40 -0
- package/skills/review/references/defect-classes-migrations.md +9 -0
- package/skills/review/references/generated-input-oracle-surfaces.md +15 -0
- package/skills/review/references/review-e2e-testing.md +116 -0
- package/skills/review/references/review-todo-structure.md +165 -0
- package/skills/review/references/risk-tier-and-fix-rounds.md +95 -0
- package/skills/review/references/semgrep-custom-rules.yaml +174 -0
- package/skills/review/references/ultrathink-phases.md +98 -0
- package/skills/review/references/wfs.md +6 -0
- package/skills/review/scripts/emit-review-trailer.sh +499 -0
- package/skills/review/scripts/ensure-semgrep.sh +99 -0
- package/skills/review/scripts/fix-round-seats.sh +197 -0
- package/skills/review/test/emit-review-trailer.test.sh +387 -0
- package/skills/review/test/ensure-semgrep.test.sh +111 -0
- package/skills/review/test/fix-round-seats.test.sh +237 -0
- package/skills/review/workflows/README.md +147 -0
- package/skills/review/workflows/review.workflow.js +667 -0
- package/skills/schedule/SKILL.md +796 -0
- package/skills/seo-aeo/SKILL.md +139 -0
- package/skills/seo-aeo/scripts/validate-csp.sh +233 -0
- package/skills/seo-aeo/scripts/validate-seo.sh +262 -0
- package/skills/ship/SKILL.md +3022 -0
- package/skills/ship/references/adr-ordinal-collision.md +47 -0
- package/skills/ship/references/affected-gate-contract.md +115 -0
- package/skills/ship/references/ci-run-diagnosis.md +29 -0
- package/skills/ship/references/ci-workflow-authoring.md +68 -0
- package/skills/ship/references/counsel-review-clo-attestation.md +38 -0
- package/skills/ship/references/cto-ruling-armed-push.md +5 -0
- package/skills/ship/references/decision-challenges-render.md +71 -0
- package/skills/ship/references/detached-battery-verdict.md +13 -0
- package/skills/ship/references/feature-tweet-draft.md +42 -0
- package/skills/ship/references/followthrough-issue-body-template.md +47 -0
- package/skills/ship/references/followthrough-stub-template.sh +92 -0
- package/skills/ship/references/merge-queue-dequeue.md +39 -0
- package/skills/ship/references/operator-holds.md +149 -0
- package/skills/ship/references/pipeline-tally-render.md +43 -0
- package/skills/ship/references/pr-overlap.md +153 -0
- package/skills/ship/references/queue-mode.md +7 -0
- package/skills/ship/references/ready-run-wait.md +36 -0
- package/skills/ship/references/red-on-main-quarantine.md +110 -0
- package/skills/ship/references/register-update-pr-pattern.md +88 -0
- package/skills/ship/references/settle-then-admin-merge.md +130 -0
- package/skills/ship/references/supabase-column-probe.md +13 -0
- package/skills/ship/scripts/auto-close-scan.sh +76 -0
- package/skills/ship/scripts/battery-owed.sh +403 -0
- package/skills/ship/scripts/hold-gate-eval.sh +410 -0
- package/skills/ship/scripts/net-issue-flow.sh +665 -0
- package/skills/ship/scripts/pr-overlap-preflight.sh +483 -0
- package/skills/ship/scripts/ship-pir-action-items-gate.sh +246 -0
- package/skills/ship/scripts/technical-ruling-gate.sh +444 -0
- package/skills/skill-creator/SKILL.md +299 -0
- package/skills/skill-creator/references/api-security.md +248 -0
- package/skills/skill-creator/references/authoring-levers.md +110 -0
- package/skills/skill-creator/references/be-clear-and-direct.md +587 -0
- package/skills/skill-creator/references/best-practices.md +431 -0
- package/skills/skill-creator/references/common-patterns.md +639 -0
- package/skills/skill-creator/references/core-principles.md +193 -0
- package/skills/skill-creator/references/executable-code.md +188 -0
- package/skills/skill-creator/references/iteration-and-testing.md +509 -0
- package/skills/skill-creator/references/official-spec.md +193 -0
- package/skills/skill-creator/references/recommended-structure.md +180 -0
- package/skills/skill-creator/references/skill-structure.md +396 -0
- package/skills/skill-creator/references/using-scripts.md +122 -0
- package/skills/skill-creator/references/using-templates.md +120 -0
- package/skills/skill-creator/references/workflows-and-validation.md +541 -0
- package/skills/skill-creator/scripts/init_skill.py +322 -0
- package/skills/skill-creator/scripts/package_skill.py +110 -0
- package/skills/skill-creator/scripts/quick_validate.py +64 -0
- package/skills/skill-creator/templates/router-skill.md +73 -0
- package/skills/skill-creator/templates/simple-skill.md +34 -0
- package/skills/skill-creator/workflows/add-reference.md +96 -0
- package/skills/skill-creator/workflows/add-script.md +104 -0
- package/skills/skill-creator/workflows/add-template.md +83 -0
- package/skills/skill-creator/workflows/add-workflow.md +128 -0
- package/skills/skill-creator/workflows/audit-skill.md +159 -0
- package/skills/skill-creator/workflows/create-domain-expertise-skill.md +623 -0
- package/skills/skill-creator/workflows/create-new-skill.md +207 -0
- package/skills/skill-creator/workflows/get-guidance.md +134 -0
- package/skills/skill-creator/workflows/upgrade-to-router.md +170 -0
- package/skills/skill-creator/workflows/verify-skill.md +226 -0
- package/skills/skill-security-scan/SKILL.md +145 -0
- package/skills/skill-security-scan/references/disclaimer.md +21 -0
- package/skills/skill-security-scan/references/first-party-allowlist.yaml +38 -0
- package/skills/skill-security-scan/references/override-artifact-schema.json +68 -0
- package/skills/skill-security-scan/references/override-mechanism.md +171 -0
- package/skills/skill-security-scan/references/redirect-domains.yaml +27 -0
- package/skills/skill-security-scan/references/regex-patterns.md +136 -0
- package/skills/skill-security-scan/references/rules/code-exec.yaml +70 -0
- package/skills/skill-security-scan/references/rules/filesystem-boundary.yaml +29 -0
- package/skills/skill-security-scan/references/rules/manifest.yaml +44 -0
- package/skills/skill-security-scan/references/rules/supply-chain.yaml +36 -0
- package/skills/skill-security-scan/references/scan-meta-schema.json +63 -0
- package/skills/skill-security-scan/references/test-fixtures/clean-soleur-style.skill.md +23 -0
- package/skills/skill-security-scan/references/test-fixtures/clean-third-party.skill.md +26 -0
- package/skills/skill-security-scan/references/test-fixtures/malicious-codeexec.skill.md +23 -0
- package/skills/skill-security-scan/references/test-fixtures/malicious-curl-pipe-bash.skill.md +69 -0
- package/skills/skill-security-scan/references/test-fixtures/malicious-prompt-injection.skill.md +17 -0
- package/skills/skill-security-scan/references/test-fixtures/malicious-telemetry-beacon.skill.md +23 -0
- package/skills/skill-security-scan/references/typosquat-targets.yaml +65 -0
- package/skills/skill-security-scan/scripts/check-codeexec.sh +41 -0
- package/skills/skill-security-scan/scripts/check-filesystem-boundary.sh +19 -0
- package/skills/skill-security-scan/scripts/check-prompt-injection.sh +95 -0
- package/skills/skill-security-scan/scripts/check-supply-chain.sh +219 -0
- package/skills/skill-security-scan/scripts/check-telemetry-surface.sh +126 -0
- package/skills/skill-security-scan/scripts/lib.sh +197 -0
- package/skills/skill-security-scan/scripts/parse-override.sh +231 -0
- package/skills/skill-security-scan/scripts/run-scan.sh +342 -0
- package/skills/skill-security-scan/scripts/run-self-test.sh +95 -0
- package/skills/skill-security-scan/test/argv-ceiling.test.sh +180 -0
- package/skills/skill-security-scan/test/meta-dir-reap.test.sh +411 -0
- package/skills/skill-security-scan/test/parse-override.test.sh +607 -0
- package/skills/skill-security-scan/test/redact-pii-ghs-shape.test.sh +251 -0
- package/skills/social-distribute/SKILL.md +485 -0
- package/skills/spec-templates/SKILL.md +274 -0
- package/skills/sync/SKILL.md +49 -0
- package/skills/test-browser/SKILL.md +464 -0
- package/skills/test-browser/references/feature-map.md +161 -0
- package/skills/test-fix-loop/SKILL.md +159 -0
- package/skills/test-fix-loop/references/determinism-checklist.md +154 -0
- package/skills/triage/SKILL.md +402 -0
- package/skills/trigger-cron/SKILL.md +136 -0
- package/skills/trigger-cron/scripts/trigger.sh +198 -0
- package/skills/user-set-role/SKILL.md +147 -0
- package/skills/user-set-role/scripts/set-role.sh +218 -0
- package/skills/user-story-writer/SKILL.md +77 -0
- package/skills/ux-audit/SKILL.md +251 -0
- package/skills/ux-audit/references/finding.schema.json +62 -0
- package/skills/ux-audit/references/route-list.yaml +95 -0
- package/skills/ux-audit/scripts/bot-fixture.ts +270 -0
- package/skills/ux-audit/scripts/bot-signin.ts +135 -0
- package/skills/ux-audit/scripts/dedup-hash.ts +46 -0
- package/skills/work/SKILL.md +1479 -0
- package/skills/work/references/end-of-work-resume.md +7 -0
- package/skills/work/references/hook-test-main-cwd.md +24 -0
- package/skills/work/references/key-principles.md +83 -0
- package/skills/work/references/property-testing.md +122 -0
- package/skills/work/references/sql-security-definer-rpc-scaffold.sql +78 -0
- package/skills/work/references/work-agent-teams.md +97 -0
- package/skills/work/references/work-lifecycle-parallel.md +147 -0
- package/skills/work/references/work-lockfile-bumps.md +97 -0
- package/skills/work/references/work-scratch-sandboxes.md +212 -0
- package/skills/work/references/work-subagent-fanout.md +61 -0
- package/skills/work/references/work-test-harness-sharp-edges.md +73 -0
- package/skills/xcode-test/SKILL.md +360 -0
|
@@ -0,0 +1,644 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# bsky-community.sh -- Bluesky AT Protocol wrapper for community operations
|
|
3
|
+
#
|
|
4
|
+
# Usage: bsky-community.sh <command> [args]
|
|
5
|
+
# Commands:
|
|
6
|
+
# create-session - Test auth, output session JSON
|
|
7
|
+
# post <text> [--reply-to-uri URI --reply-to-cid CID - Create a post (optionally as reply)
|
|
8
|
+
# --root-uri URI --root-cid CID]
|
|
9
|
+
# get-metrics - Fetch profile stats (followers, etc.)
|
|
10
|
+
# get-notifications [--limit N] [--cursor CURSOR] - Fetch mention notifications
|
|
11
|
+
#
|
|
12
|
+
# Environment variables (required):
|
|
13
|
+
# BSKY_HANDLE - Bluesky handle (e.g., soleur.bsky.social)
|
|
14
|
+
# BSKY_APP_PASSWORD - App password
|
|
15
|
+
# BSKY_ALLOW_POST - Set to "true" to enable posting (defense-in-depth guard)
|
|
16
|
+
#
|
|
17
|
+
# Exit codes:
|
|
18
|
+
# 0 - Success
|
|
19
|
+
# 1 - General error
|
|
20
|
+
# 2 - Rate limit exhausted after retries
|
|
21
|
+
#
|
|
22
|
+
# Output: JSON to stdout
|
|
23
|
+
# Errors: Messages to stderr, exit 1
|
|
24
|
+
|
|
25
|
+
set -euo pipefail
|
|
26
|
+
|
|
27
|
+
# (#7797) Xtrace refusal -- the FIRST thing after `set …`, so nothing above it is
|
|
28
|
+
# traced. This script ships to installed Soleur CLIs: the terminal it runs in
|
|
29
|
+
# belongs to the founder, and `bash -x` would print their live Bluesky
|
|
30
|
+
# credentials. The `:+x` form tests non-emptiness WITHOUT expanding the value, so
|
|
31
|
+
# the guard cannot leak the thing it is refusing over. CONDITIONAL, and that is
|
|
32
|
+
# measured rather than inherited -- and the measurement is NOT "nothing is acquired
|
|
33
|
+
# at runtime", which would be FALSE here: `create_session` POSTs BSKY_APP_PASSWORD
|
|
34
|
+
# and mints an ACCESS_JWT from the response body, which later requests carry as a
|
|
35
|
+
# bearer. The property that actually holds is narrower and is what makes the arm
|
|
36
|
+
# sound: every runtime acquisition on this path is GATED on BSKY_APP_PASSWORD --
|
|
37
|
+
# the same variable this guard tests -- so no password means no JWT, and the guard
|
|
38
|
+
# cannot be empty while any credential is live. A founder tracing with none set
|
|
39
|
+
# keeps full tracing.
|
|
40
|
+
#
|
|
41
|
+
# Stated this way on purpose (#7898 review). The first cut claimed the file
|
|
42
|
+
# acquires nothing at runtime; that is true of discord/linkedin/x-community and
|
|
43
|
+
# false of this one, and a template carrying the wrong reason invites the next
|
|
44
|
+
# author to copy it into a file where the acquisition is NOT gated.
|
|
45
|
+
# Refusal goes to STDOUT, not stderr: agent runtimes surface stdout and swallow
|
|
46
|
+
# stderr (constitution.md > Code Style > Always), and a swallowed security refusal
|
|
47
|
+
# leaves the user with a bare `exit 78` and no text at all.
|
|
48
|
+
case "$-" in
|
|
49
|
+
*x*)
|
|
50
|
+
if [ -n "${BSKY_APP_PASSWORD:+x}" ]; then
|
|
51
|
+
printf 'Refusing to run under `bash -x`: BSKY_APP_PASSWORD is set, and tracing would print it to your terminal. To trace safely, unset it and re-run.\n'
|
|
52
|
+
exit 78
|
|
53
|
+
fi
|
|
54
|
+
;;
|
|
55
|
+
esac
|
|
56
|
+
|
|
57
|
+
# (#7873) `--disable` closes ~/.curlrc and `--noproxy '*'` closes the proxy
|
|
58
|
+
# variables, but NEITHER touches the trust store or the TLS session-key log. On an
|
|
59
|
+
# installed CLI the environment belongs to someone who is not us, so
|
|
60
|
+
# a substituted `CURL_CA_BUNDLE` is a clean MITM of the founder's platform
|
|
61
|
+
# token with every other guard fully intact, and `SSLKEYLOGFILE` is passive
|
|
62
|
+
# decryption with no MITM at all. Matches the line in scripts/betterstack-query.sh.
|
|
63
|
+
unset SSLKEYLOGFILE CURL_CA_BUNDLE SSL_CERT_FILE SSL_CERT_DIR CURL_HOME \
|
|
64
|
+
HOSTALIASES LOCALDOMAIN RES_OPTIONS
|
|
65
|
+
|
|
66
|
+
# --- Transport-confinement diagnostics (#7873) --------------------------------
|
|
67
|
+
# Every credentialed `curl` below carries `--disable --noproxy '*'` and discards
|
|
68
|
+
# curl's own stderr (which can carry the URL). A failed request then has four
|
|
69
|
+
# competing causes the founder cannot tell apart: the proxy this script
|
|
70
|
+
# deliberately bypassed, a ~/.curlrc that `--disable` dropped, a TLS trust
|
|
71
|
+
# variable it cleared, or an ordinary network failure. So each failure emits ONE
|
|
72
|
+
# structured marker carrying the discriminators, beside a human line that names
|
|
73
|
+
# the bypass instead of blaming the founder's connectivity.
|
|
74
|
+
SOLEUR_TRANSPORT_SCRIPT="bsky-community.sh"
|
|
75
|
+
SOLEUR_TRANSPORT_PLATFORM="Bluesky"
|
|
76
|
+
|
|
77
|
+
# The request helpers below run inside `$(...)`, where fd 1 is the capture pipe.
|
|
78
|
+
# Save the script's real stdout so the marker reaches the founder's terminal (and
|
|
79
|
+
# the always-on PostToolUse Bash extractor) instead of being swallowed into a
|
|
80
|
+
# variable. The marker is on stdout BY DESIGN -- the call sites' `2>/dev/null` is
|
|
81
|
+
# what keeps curl's URL-carrying stderr out of the transcript, and it must not be
|
|
82
|
+
# able to suppress the diagnostic too.
|
|
83
|
+
exec 3>&1
|
|
84
|
+
|
|
85
|
+
# Which proxy variables are non-empty, or `none`.
|
|
86
|
+
proxy_env_names() {
|
|
87
|
+
local names="" n
|
|
88
|
+
for n in HTTP_PROXY HTTPS_PROXY ALL_PROXY NO_PROXY http_proxy https_proxy all_proxy no_proxy; do
|
|
89
|
+
if [[ -n "${!n-}" ]]; then
|
|
90
|
+
names="${names},${n}"
|
|
91
|
+
fi
|
|
92
|
+
done
|
|
93
|
+
if [[ -z "$names" ]]; then
|
|
94
|
+
printf 'none'
|
|
95
|
+
else
|
|
96
|
+
printf '%s' "${names#,}"
|
|
97
|
+
fi
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
# True when a proxy this script deliberately bypasses is configured. NO_PROXY
|
|
101
|
+
# alone is not one -- it only ever narrows proxying, so it cannot be the cause.
|
|
102
|
+
proxy_bypassed() {
|
|
103
|
+
[[ -n "${HTTP_PROXY:-}${HTTPS_PROXY:-}${ALL_PROXY:-}${http_proxy:-}${https_proxy:-}${all_proxy:-}" ]]
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
# One line, eight fields, on the saved stdout.
|
|
107
|
+
#
|
|
108
|
+
# Two fields were literals in the first cut and are now MEASURED (#7898 review):
|
|
109
|
+
# `noproxy_applied` was the constant "true", which ASSERTS the property instead of
|
|
110
|
+
# observing it -- dropping --noproxy from a call site left the diagnostic still
|
|
111
|
+
# claiming it was applied. It now reports whether a proxy was actually configured
|
|
112
|
+
# for this request to bypass, which is the fact a reader needs. `refusal` was the
|
|
113
|
+
# constant "none" at every call site, so the cause it exists to discriminate could
|
|
114
|
+
# never appear; the field stays for a caller that can refuse for a named cause, and
|
|
115
|
+
# this script has none, so it passes "none".
|
|
116
|
+
#
|
|
117
|
+
# `tls_env_cleared` is new. The prologue unsets CURL_CA_BUNDLE/SSL_CERT_FILE et al,
|
|
118
|
+
# which is correct against an attacker and BREAKS a founder whose corporate CA
|
|
119
|
+
# arrives that way -- curl then exits 60 and, without this field, the event is
|
|
120
|
+
# indistinguishable from an ordinary network failure.
|
|
121
|
+
emit_transport_diag() {
|
|
122
|
+
local curl_exit="$1" refusal="$2" surface="installed-cli" curlrc="false" noproxy="false"
|
|
123
|
+
# The hosted sandbox always sets this (agent-env.ts > AGENT_ENV_OVERRIDES); an
|
|
124
|
+
# installed CLI does not. A label on the event, not a gate on behaviour.
|
|
125
|
+
if [[ -n "${CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC:-}" ]]; then
|
|
126
|
+
surface="in-sandbox"
|
|
127
|
+
fi
|
|
128
|
+
if [[ -f "${HOME:-}/.curlrc" ]]; then
|
|
129
|
+
curlrc="true"
|
|
130
|
+
fi
|
|
131
|
+
if proxy_bypassed; then
|
|
132
|
+
noproxy="true"
|
|
133
|
+
fi
|
|
134
|
+
printf 'SOLEUR_TRANSPORT_DIAG surface=%s script=%s curl_exit=%s refusal=%s proxy_env=%s curlrc_present=%s noproxy_applied=%s tls_env_cleared=%s\n' \
|
|
135
|
+
"$surface" "$SOLEUR_TRANSPORT_SCRIPT" "$curl_exit" "$refusal" \
|
|
136
|
+
"$(proxy_env_names)" "$curlrc" "$noproxy" "true" >&3
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
# Replaces the bare "Check your network connection and try again." on a
|
|
140
|
+
# credentialed-curl failure. With a proxy set, that line blames the founder for a
|
|
141
|
+
# bypass this script chose.
|
|
142
|
+
report_transport_failure() {
|
|
143
|
+
local curl_exit="${1:-unknown}"
|
|
144
|
+
local detail="${2:-Failed to connect to the ${SOLEUR_TRANSPORT_PLATFORM} API.}"
|
|
145
|
+
emit_transport_diag "$curl_exit" "none"
|
|
146
|
+
echo "Error: ${detail}" >&2
|
|
147
|
+
# Ordered by how specific the evidence is. Each arm names something THIS script
|
|
148
|
+
# did, so the founder is never told to go debug their own network for a choice
|
|
149
|
+
# made here. The bare "check your connection" line is the LAST resort, not the
|
|
150
|
+
# default -- it was the default in the first cut, which meant a founder whose
|
|
151
|
+
# corporate CA or curlrc we had just discarded was blamed for it (#7898 review).
|
|
152
|
+
if [[ "$curl_exit" == "60" || "$curl_exit" == "35" || "$curl_exit" == "77" ]]; then
|
|
153
|
+
# 60 peer-certificate, 35 TLS handshake, 77 CA-bundle unreadable.
|
|
154
|
+
echo "This looks like a TLS trust failure. This script deliberately clears CURL_CA_BUNDLE, SSL_CERT_FILE, SSL_CERT_DIR and SSLKEYLOGFILE before the request, because those variables can redirect or expose a request carrying your ${SOLEUR_TRANSPORT_PLATFORM} credential." >&2
|
|
155
|
+
echo "If your machine needs a corporate CA to reach ${SOLEUR_TRANSPORT_PLATFORM}, that is not currently supported -- please open an issue at https://github.com/jikig-ai/soleur/issues." >&2
|
|
156
|
+
elif proxy_bypassed; then
|
|
157
|
+
echo "This request deliberately bypasses your proxy ($(proxy_env_names)), because a proxy can redirect a request carrying your ${SOLEUR_TRANSPORT_PLATFORM} token." >&2
|
|
158
|
+
echo "If you need Soleur to reach ${SOLEUR_TRANSPORT_PLATFORM} through your proxy, that is not currently supported -- please open an issue at https://github.com/jikig-ai/soleur/issues." >&2
|
|
159
|
+
elif [[ -f "${HOME:-}/.curlrc" ]]; then
|
|
160
|
+
echo "You have a ~/.curlrc, and this request deliberately ignores it (--disable), because a curlrc can redirect a request carrying your ${SOLEUR_TRANSPORT_PLATFORM} token. If it configures a proxy or a CA bundle you need, that is why this failed." >&2
|
|
161
|
+
echo "That is not currently supported -- please open an issue at https://github.com/jikig-ai/soleur/issues." >&2
|
|
162
|
+
else
|
|
163
|
+
echo "Check your network connection and try again." >&2
|
|
164
|
+
fi
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
# readonly (#7898 review): `cmd_verify` and friends run `set -a; source "$env_file"; set +a`
|
|
168
|
+
# BELOW this line, so a plain assignment here is rebindable by the repo's .env --
|
|
169
|
+
# which retargets the credentialed request while every transport flag stays intact.
|
|
170
|
+
# That is the "--disable and --noproxy are intact and irrelevant" shape this change
|
|
171
|
+
# exists to close, one layer up. readonly makes the destination non-rebindable.
|
|
172
|
+
readonly BSKY_API="https://bsky.social/xrpc"
|
|
173
|
+
|
|
174
|
+
# --- Session state (per-invocation, not cached) ---
|
|
175
|
+
|
|
176
|
+
ACCESS_JWT=""
|
|
177
|
+
USER_DID=""
|
|
178
|
+
|
|
179
|
+
# --- Bearer transport (#7843) ---
|
|
180
|
+
# ACCESS_JWT is parsed out of an API reply, so it is RESPONSE-DERIVED: untrusted bytes. It
|
|
181
|
+
# rides curl's STDIN config channel (`--config -`), never its argument list, where every
|
|
182
|
+
# local user would read it from /proc/<pid>/cmdline. That channel is line-oriented, so a
|
|
183
|
+
# token holding a quote and a newline could append a `url = "..."` directive and make curl
|
|
184
|
+
# issue a second request. The guard refuses anything outside the JWT/base64url alphabet
|
|
185
|
+
# BEFORE the value is formatted into the stream, and never echoes it.
|
|
186
|
+
_bearer_ok() { local LC_ALL=C; case "${1:-}" in ''|*[!A-Za-z0-9._~+/=-]*) return 1 ;; esac; }
|
|
187
|
+
|
|
188
|
+
# Every authenticated request goes through here: ONE place owns the transport flags
|
|
189
|
+
# (`--disable` first, `--noproxy '*'`), the token-shape guard and the header. Returns 120
|
|
190
|
+
# with zero curl calls when the token is unusable; callers map that to a refusal.
|
|
191
|
+
bsky_authed_curl() {
|
|
192
|
+
_bearer_ok "$ACCESS_JWT" || return 120
|
|
193
|
+
curl --disable --noproxy '*' "$@" --config - \
|
|
194
|
+
< <(printf 'header = "Authorization: Bearer %s"\n' "$ACCESS_JWT")
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
# --- createSession body transport (#9597) ---
|
|
198
|
+
# The createSession body carries the app password and a user-supplied handle. Neither may
|
|
199
|
+
# ride curl's argument list (readable by every local user in /proc/<pid>/cmdline). The
|
|
200
|
+
# createSession call has no bearer config, so curl's stdin is free: `jq` builds the body and
|
|
201
|
+
# pipes it to `curl --data-binary @-` (NOT `-d @-`, which strips CR/LF). The values reach
|
|
202
|
+
# `jq` through its ENVIRONMENT as an inline assignment prefix (`$ENV.X`), never `jq --arg`
|
|
203
|
+
# (jq's own argv is world-readable too). This script never `export`s them: the BSKY_ID /
|
|
204
|
+
# BSKY_PW aliases live on the one jq child only. (BSKY_HANDLE / BSKY_APP_PASSWORD themselves
|
|
205
|
+
# are whatever the CALLER exported, so later children inherit those regardless.) No file, no
|
|
206
|
+
# trap: the secret exists only in the processes' memory and the pipe.
|
|
207
|
+
|
|
208
|
+
# A control character can never be part of a handle or an app password. Refusing one
|
|
209
|
+
# before anything is sent keeps garbage off the wire; jq escapes everything else (a handle
|
|
210
|
+
# holding a double quote is escaped, never injected into the JSON).
|
|
211
|
+
_bsky_cred_ok() { local LC_ALL=C; case "${1:-}" in ''|*[[:cntrl:]]*) return 1 ;; esac; }
|
|
212
|
+
|
|
213
|
+
# A fixed, value-free marker plus ONE human line on stderr, naming only which FIELD was
|
|
214
|
+
# refused (never the handle or the password), and a non-zero exit. $2 is the variable name.
|
|
215
|
+
# `post` also runs HOSTED, from scripts/content-publisher.sh, which captures stderr into its
|
|
216
|
+
# fallback-issue path: the exit is 1, never 0 or 3.
|
|
217
|
+
bsky_refuse() {
|
|
218
|
+
printf 'SOLEUR_CREDENTIAL_REFUSED script=%s reason=%s\n' "$SOLEUR_TRANSPORT_SCRIPT" "$1" >&2
|
|
219
|
+
echo "Error: ${2} is empty or contains a control character (for example a stray carriage return or newline from a copy-paste or a CRLF .env file), so nothing was sent. Remove it and retry. The value is not shown." >&2
|
|
220
|
+
exit 1
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
# --- Dependency checks ---
|
|
224
|
+
|
|
225
|
+
require_jq() {
|
|
226
|
+
if ! command -v jq &>/dev/null; then
|
|
227
|
+
echo "Error: jq is required but not installed." >&2
|
|
228
|
+
echo "Install it: https://jqlang.github.io/jq/download/" >&2
|
|
229
|
+
exit 1
|
|
230
|
+
fi
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
require_credentials() {
|
|
234
|
+
local missing=()
|
|
235
|
+
|
|
236
|
+
if [[ -z "${BSKY_HANDLE:-}" ]]; then
|
|
237
|
+
missing+=("BSKY_HANDLE")
|
|
238
|
+
fi
|
|
239
|
+
if [[ -z "${BSKY_APP_PASSWORD:-}" ]]; then
|
|
240
|
+
missing+=("BSKY_APP_PASSWORD")
|
|
241
|
+
fi
|
|
242
|
+
|
|
243
|
+
if [[ ${#missing[@]} -gt 0 ]]; then
|
|
244
|
+
echo "Error: Missing Bluesky credentials: ${missing[*]}" >&2
|
|
245
|
+
echo "" >&2
|
|
246
|
+
echo "To configure:" >&2
|
|
247
|
+
echo " 1. Create an account at https://bsky.app" >&2
|
|
248
|
+
echo " 2. Go to Settings > App Passwords > Add App Password" >&2
|
|
249
|
+
echo " 3. Export BSKY_HANDLE and BSKY_APP_PASSWORD as environment variables, without typing a value into the command (its text is kept in the transcript and the shell history): in a terminal, read -rs BSKY_APP_PASSWORD; export BSKY_APP_PASSWORD" >&2
|
|
250
|
+
exit 1
|
|
251
|
+
fi
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
# --- Session management ---
|
|
255
|
+
|
|
256
|
+
# Create a fresh session. Sets ACCESS_JWT and USER_DID globals.
|
|
257
|
+
create_session() {
|
|
258
|
+
local response http_code body
|
|
259
|
+
|
|
260
|
+
local __curl_rc=0
|
|
261
|
+
# Refuse BEFORE the body is built so a refused value never reaches a child process.
|
|
262
|
+
_bsky_cred_ok "${BSKY_HANDLE:-}" || bsky_refuse control_char BSKY_HANDLE
|
|
263
|
+
_bsky_cred_ok "${BSKY_APP_PASSWORD:-}" || bsky_refuse control_char BSKY_APP_PASSWORD
|
|
264
|
+
# The body is built into a variable FIRST, so a jq failure is classified as what it is (a
|
|
265
|
+
# body-build failure) and never reaches curl: it does not depend on `pipefail`, and it can
|
|
266
|
+
# never read as a transport failure or as a successful empty POST. The credentials reach jq
|
|
267
|
+
# only through its inline environment prefix; `printf` is a builtin, so the body (which holds
|
|
268
|
+
# the password) is on no argv; curl reads it from stdin.
|
|
269
|
+
local req_body
|
|
270
|
+
req_body=$(BSKY_ID="$BSKY_HANDLE" BSKY_PW="$BSKY_APP_PASSWORD" \
|
|
271
|
+
jq -n '{identifier: $ENV.BSKY_ID, password: $ENV.BSKY_PW}') || {
|
|
272
|
+
echo "Error: could not build the Bluesky createSession request body (jq failed); nothing was sent." >&2
|
|
273
|
+
exit 1
|
|
274
|
+
}
|
|
275
|
+
response=$(printf '%s' "$req_body" \
|
|
276
|
+
| curl --disable --noproxy '*' -s -w "\n%{http_code}" \
|
|
277
|
+
-X POST \
|
|
278
|
+
-H "Content-Type: application/json" \
|
|
279
|
+
--data-binary @- \
|
|
280
|
+
"${BSKY_API}/com.atproto.server.createSession" 2>/dev/null) || __curl_rc=$?
|
|
281
|
+
if (( __curl_rc != 0 )); then
|
|
282
|
+
report_transport_failure "$__curl_rc" "Failed to connect to Bluesky API."
|
|
283
|
+
exit 1
|
|
284
|
+
fi
|
|
285
|
+
|
|
286
|
+
http_code=$(echo "$response" | tail -1)
|
|
287
|
+
body=$(echo "$response" | sed '$d')
|
|
288
|
+
|
|
289
|
+
case "$http_code" in
|
|
290
|
+
2[0-9][0-9])
|
|
291
|
+
if ! echo "$body" | jq . >/dev/null 2>&1; then
|
|
292
|
+
echo "Error: Bluesky API returned malformed JSON for createSession." >&2
|
|
293
|
+
exit 1
|
|
294
|
+
fi
|
|
295
|
+
ACCESS_JWT=$(echo "$body" | jq -r '.accessJwt // empty')
|
|
296
|
+
USER_DID=$(echo "$body" | jq -r '.did // empty')
|
|
297
|
+
if [[ -z "$ACCESS_JWT" || -z "$USER_DID" ]]; then
|
|
298
|
+
echo "Error: Session response missing accessJwt or DID." >&2
|
|
299
|
+
exit 1
|
|
300
|
+
fi
|
|
301
|
+
if ! _bearer_ok "$ACCESS_JWT"; then
|
|
302
|
+
ACCESS_JWT=""
|
|
303
|
+
echo "Error: Session response carried an accessJwt with an unexpected shape; refusing to use it." >&2
|
|
304
|
+
exit 1
|
|
305
|
+
fi
|
|
306
|
+
;;
|
|
307
|
+
401)
|
|
308
|
+
echo "Error: Bluesky returned 401 Unauthorized." >&2
|
|
309
|
+
echo "Your handle or app password may be incorrect." >&2
|
|
310
|
+
exit 1
|
|
311
|
+
;;
|
|
312
|
+
*)
|
|
313
|
+
local message
|
|
314
|
+
message=$(echo "$body" | jq -r '.message // .error // "Unknown error"' 2>/dev/null || echo "Unknown error")
|
|
315
|
+
echo "Error: Bluesky API returned HTTP ${http_code}: ${message}" >&2
|
|
316
|
+
exit 1
|
|
317
|
+
;;
|
|
318
|
+
esac
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
# --- Response handling ---
|
|
322
|
+
|
|
323
|
+
# Handle HTTP response from Bluesky API
|
|
324
|
+
# Arguments: http_code body endpoint depth retry_cmd...
|
|
325
|
+
handle_response() {
|
|
326
|
+
local http_code="$1"
|
|
327
|
+
local body="$2"
|
|
328
|
+
local endpoint="$3"
|
|
329
|
+
local depth="$4"
|
|
330
|
+
shift 4
|
|
331
|
+
local -a retry_cmd=("$@")
|
|
332
|
+
|
|
333
|
+
case "$http_code" in
|
|
334
|
+
2[0-9][0-9])
|
|
335
|
+
if ! echo "$body" | jq . >/dev/null 2>&1; then
|
|
336
|
+
echo "Error: Bluesky API returned malformed JSON for ${endpoint}." >&2
|
|
337
|
+
exit 1
|
|
338
|
+
fi
|
|
339
|
+
echo "$body"
|
|
340
|
+
;;
|
|
341
|
+
401)
|
|
342
|
+
echo "Error: Bluesky API returned 401 Unauthorized for ${endpoint}." >&2
|
|
343
|
+
echo "Your credentials may be expired or invalid." >&2
|
|
344
|
+
exit 1
|
|
345
|
+
;;
|
|
346
|
+
429)
|
|
347
|
+
# Bluesky uses ratelimit-reset header (Unix timestamp).
|
|
348
|
+
# In curl response body, fall back to a sensible default.
|
|
349
|
+
local retry_after=5
|
|
350
|
+
echo "Rate limited. Retrying after ${retry_after}s (attempt $((depth + 1))/3)..." >&2
|
|
351
|
+
sleep "$retry_after"
|
|
352
|
+
"${retry_cmd[@]}"
|
|
353
|
+
;;
|
|
354
|
+
*)
|
|
355
|
+
local message
|
|
356
|
+
message=$(echo "$body" | jq -r '.message // .error // "Unknown error"' 2>/dev/null || echo "Unknown error")
|
|
357
|
+
echo "Error: Bluesky API returned HTTP ${http_code} for ${endpoint}: ${message}" >&2
|
|
358
|
+
exit 1
|
|
359
|
+
;;
|
|
360
|
+
esac
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
# --- Request helpers ---
|
|
364
|
+
|
|
365
|
+
# Make an authenticated GET request
|
|
366
|
+
# Arguments: endpoint [query_string] [depth]
|
|
367
|
+
get_request() {
|
|
368
|
+
local endpoint="$1"
|
|
369
|
+
local query_string="${2:-}"
|
|
370
|
+
local depth="${3:-0}"
|
|
371
|
+
|
|
372
|
+
if (( depth >= 3 )); then
|
|
373
|
+
echo "Error: Bluesky API rate limit exceeded after 3 retries for ${endpoint}." >&2
|
|
374
|
+
exit 2
|
|
375
|
+
fi
|
|
376
|
+
|
|
377
|
+
local url="${BSKY_API}/${endpoint}"
|
|
378
|
+
if [[ -n "$query_string" ]]; then
|
|
379
|
+
url="${url}?${query_string}"
|
|
380
|
+
fi
|
|
381
|
+
|
|
382
|
+
local response http_code body
|
|
383
|
+
local __curl_rc=0
|
|
384
|
+
response=$(bsky_authed_curl -s -w "\n%{http_code}" \
|
|
385
|
+
"$url" 2>/dev/null) || __curl_rc=$?
|
|
386
|
+
if (( __curl_rc == 120 )); then
|
|
387
|
+
echo "Error: Bluesky session token has an unexpected shape; refusing to send it." >&2
|
|
388
|
+
exit 1
|
|
389
|
+
fi
|
|
390
|
+
if (( __curl_rc != 0 )); then
|
|
391
|
+
report_transport_failure "$__curl_rc" "Failed to connect to Bluesky API."
|
|
392
|
+
exit 1
|
|
393
|
+
fi
|
|
394
|
+
|
|
395
|
+
http_code=$(echo "$response" | tail -1)
|
|
396
|
+
body=$(echo "$response" | sed '$d')
|
|
397
|
+
|
|
398
|
+
handle_response "$http_code" "$body" "$endpoint" "$depth" \
|
|
399
|
+
get_request "$endpoint" "$query_string" "$((depth + 1))"
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
# Make an authenticated POST request
|
|
403
|
+
# Arguments: endpoint [json_body] [depth]
|
|
404
|
+
post_request() {
|
|
405
|
+
local endpoint="$1"
|
|
406
|
+
local json_body="${2:-}"
|
|
407
|
+
local depth="${3:-0}"
|
|
408
|
+
|
|
409
|
+
if (( depth >= 3 )); then
|
|
410
|
+
echo "Error: Bluesky API rate limit exceeded after 3 retries for ${endpoint}." >&2
|
|
411
|
+
exit 2
|
|
412
|
+
fi
|
|
413
|
+
|
|
414
|
+
local url="${BSKY_API}/${endpoint}"
|
|
415
|
+
# `--disable` first and `--noproxy '*'` plus the bearer are added by bsky_authed_curl.
|
|
416
|
+
local -a curl_args=(
|
|
417
|
+
-s -w "\n%{http_code}"
|
|
418
|
+
-H "Content-Type: application/json"
|
|
419
|
+
)
|
|
420
|
+
|
|
421
|
+
if [[ -n "$json_body" ]]; then
|
|
422
|
+
curl_args+=(-X POST -d "$json_body")
|
|
423
|
+
fi
|
|
424
|
+
|
|
425
|
+
local response http_code body
|
|
426
|
+
local __curl_rc=0
|
|
427
|
+
response=$(bsky_authed_curl "${curl_args[@]}" "$url" 2>/dev/null) || __curl_rc=$?
|
|
428
|
+
if (( __curl_rc == 120 )); then
|
|
429
|
+
echo "Error: Bluesky session token has an unexpected shape; refusing to send it." >&2
|
|
430
|
+
exit 1
|
|
431
|
+
fi
|
|
432
|
+
if (( __curl_rc != 0 )); then
|
|
433
|
+
report_transport_failure "$__curl_rc" "Failed to connect to Bluesky API."
|
|
434
|
+
exit 1
|
|
435
|
+
fi
|
|
436
|
+
|
|
437
|
+
http_code=$(echo "$response" | tail -1)
|
|
438
|
+
body=$(echo "$response" | sed '$d')
|
|
439
|
+
|
|
440
|
+
handle_response "$http_code" "$body" "$endpoint" "$depth" \
|
|
441
|
+
post_request "$endpoint" "$json_body" "$((depth + 1))"
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
# --- Commands ---
|
|
445
|
+
|
|
446
|
+
cmd_create_session() {
|
|
447
|
+
create_session
|
|
448
|
+
echo "{\"did\": \"${USER_DID}\", \"handle\": \"${BSKY_HANDLE}\"}" | jq .
|
|
449
|
+
echo "Session created for @${BSKY_HANDLE} (${USER_DID})" >&2
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
cmd_post() {
|
|
453
|
+
# Guard: require explicit opt-in to post.
|
|
454
|
+
if [[ "${BSKY_ALLOW_POST:-}" != "true" ]]; then
|
|
455
|
+
echo "Error: BSKY_ALLOW_POST is not set to 'true'." >&2
|
|
456
|
+
echo "Set BSKY_ALLOW_POST=true to enable posting." >&2
|
|
457
|
+
return 1
|
|
458
|
+
fi
|
|
459
|
+
|
|
460
|
+
local text=""
|
|
461
|
+
local reply_to_uri="" reply_to_cid="" root_uri="" root_cid=""
|
|
462
|
+
|
|
463
|
+
# Parse arguments
|
|
464
|
+
while [[ $# -gt 0 ]]; do
|
|
465
|
+
case "$1" in
|
|
466
|
+
--reply-to-uri) reply_to_uri="$2"; shift 2 ;;
|
|
467
|
+
--reply-to-cid) reply_to_cid="$2"; shift 2 ;;
|
|
468
|
+
--root-uri) root_uri="$2"; shift 2 ;;
|
|
469
|
+
--root-cid) root_cid="$2"; shift 2 ;;
|
|
470
|
+
*)
|
|
471
|
+
if [[ -z "$text" ]]; then
|
|
472
|
+
text="$1"
|
|
473
|
+
else
|
|
474
|
+
echo "Error: Unexpected argument '$1'" >&2
|
|
475
|
+
exit 1
|
|
476
|
+
fi
|
|
477
|
+
shift
|
|
478
|
+
;;
|
|
479
|
+
esac
|
|
480
|
+
done
|
|
481
|
+
|
|
482
|
+
if [[ -z "$text" ]]; then
|
|
483
|
+
echo "Error: Post text is required." >&2
|
|
484
|
+
echo "Usage: bsky-community.sh post <text> [--reply-to-uri URI --reply-to-cid CID --root-uri URI --root-cid CID]" >&2
|
|
485
|
+
exit 1
|
|
486
|
+
fi
|
|
487
|
+
|
|
488
|
+
# Validate length (codepoint count as grapheme approximation)
|
|
489
|
+
local char_count
|
|
490
|
+
char_count=$(printf '%s' "$text" | wc -m)
|
|
491
|
+
if (( char_count > 300 )); then
|
|
492
|
+
echo "Error: Post exceeds 300 character limit (${char_count} characters)." >&2
|
|
493
|
+
exit 1
|
|
494
|
+
fi
|
|
495
|
+
|
|
496
|
+
create_session
|
|
497
|
+
|
|
498
|
+
# Build record JSON
|
|
499
|
+
local created_at
|
|
500
|
+
created_at=$(date -u +"%Y-%m-%dT%H:%M:%S.000Z")
|
|
501
|
+
|
|
502
|
+
local record
|
|
503
|
+
record=$(jq -n \
|
|
504
|
+
--arg type "app.bsky.feed.post" \
|
|
505
|
+
--arg text "$text" \
|
|
506
|
+
--arg created_at "$created_at" \
|
|
507
|
+
'{
|
|
508
|
+
"$type": $type,
|
|
509
|
+
"text": $text,
|
|
510
|
+
"createdAt": $created_at
|
|
511
|
+
}')
|
|
512
|
+
|
|
513
|
+
# Add reply references if provided
|
|
514
|
+
if [[ -n "$reply_to_uri" && -n "$reply_to_cid" ]]; then
|
|
515
|
+
# If root not specified, parent is the root (first reply in thread)
|
|
516
|
+
if [[ -z "$root_uri" ]]; then
|
|
517
|
+
root_uri="$reply_to_uri"
|
|
518
|
+
root_cid="$reply_to_cid"
|
|
519
|
+
fi
|
|
520
|
+
|
|
521
|
+
record=$(echo "$record" | jq \
|
|
522
|
+
--arg parent_uri "$reply_to_uri" \
|
|
523
|
+
--arg parent_cid "$reply_to_cid" \
|
|
524
|
+
--arg root_uri "$root_uri" \
|
|
525
|
+
--arg root_cid "$root_cid" \
|
|
526
|
+
'. + {
|
|
527
|
+
"reply": {
|
|
528
|
+
"root": {"uri": $root_uri, "cid": $root_cid},
|
|
529
|
+
"parent": {"uri": $parent_uri, "cid": $parent_cid}
|
|
530
|
+
}
|
|
531
|
+
}')
|
|
532
|
+
fi
|
|
533
|
+
|
|
534
|
+
local request_body
|
|
535
|
+
request_body=$(jq -n \
|
|
536
|
+
--arg repo "$USER_DID" \
|
|
537
|
+
--arg collection "app.bsky.feed.post" \
|
|
538
|
+
--argjson record "$record" \
|
|
539
|
+
'{
|
|
540
|
+
"repo": $repo,
|
|
541
|
+
"collection": $collection,
|
|
542
|
+
"record": $record
|
|
543
|
+
}')
|
|
544
|
+
|
|
545
|
+
local result
|
|
546
|
+
result=$(post_request "com.atproto.repo.createRecord" "$request_body")
|
|
547
|
+
|
|
548
|
+
# Return uri and cid for thread chaining
|
|
549
|
+
echo "$result" | jq '{uri, cid}'
|
|
550
|
+
}
|
|
551
|
+
|
|
552
|
+
cmd_get_metrics() {
|
|
553
|
+
create_session
|
|
554
|
+
|
|
555
|
+
local body
|
|
556
|
+
body=$(get_request "app.bsky.actor.getProfile" "actor=${USER_DID}")
|
|
557
|
+
|
|
558
|
+
echo "$body" | jq '{
|
|
559
|
+
handle: .handle,
|
|
560
|
+
displayName: .displayName,
|
|
561
|
+
followersCount: .followersCount,
|
|
562
|
+
followsCount: .followsCount,
|
|
563
|
+
postsCount: .postsCount,
|
|
564
|
+
description: .description
|
|
565
|
+
}'
|
|
566
|
+
}
|
|
567
|
+
|
|
568
|
+
cmd_get_notifications() {
|
|
569
|
+
local limit=50
|
|
570
|
+
local cursor=""
|
|
571
|
+
|
|
572
|
+
while [[ $# -gt 0 ]]; do
|
|
573
|
+
case "$1" in
|
|
574
|
+
--limit) limit="$2"; shift 2 ;;
|
|
575
|
+
--cursor) cursor="$2"; shift 2 ;;
|
|
576
|
+
*)
|
|
577
|
+
echo "Error: Unknown option '$1'" >&2
|
|
578
|
+
exit 1
|
|
579
|
+
;;
|
|
580
|
+
esac
|
|
581
|
+
done
|
|
582
|
+
|
|
583
|
+
create_session
|
|
584
|
+
|
|
585
|
+
local query="limit=${limit}"
|
|
586
|
+
if [[ -n "$cursor" ]]; then
|
|
587
|
+
query="${query}&cursor=${cursor}"
|
|
588
|
+
fi
|
|
589
|
+
|
|
590
|
+
local body
|
|
591
|
+
body=$(get_request "app.bsky.notification.listNotifications" "$query")
|
|
592
|
+
|
|
593
|
+
# Filter for mentions only and extract relevant fields
|
|
594
|
+
echo "$body" | jq '{
|
|
595
|
+
notifications: [.notifications[] | select(.reason == "mention") | {
|
|
596
|
+
uri: .uri,
|
|
597
|
+
cid: .cid,
|
|
598
|
+
author_handle: .author.handle,
|
|
599
|
+
author_name: (.author.displayName // .author.handle),
|
|
600
|
+
text: (.record.text // ""),
|
|
601
|
+
created_at: .indexedAt,
|
|
602
|
+
reason: .reason
|
|
603
|
+
}],
|
|
604
|
+
cursor: .cursor
|
|
605
|
+
}'
|
|
606
|
+
}
|
|
607
|
+
|
|
608
|
+
# --- Main ---
|
|
609
|
+
|
|
610
|
+
main() {
|
|
611
|
+
local command="${1:-}"
|
|
612
|
+
shift || true
|
|
613
|
+
|
|
614
|
+
if [[ -z "$command" ]]; then
|
|
615
|
+
echo "Usage: bsky-community.sh <command> [args]" >&2
|
|
616
|
+
echo "" >&2
|
|
617
|
+
echo "Commands:" >&2
|
|
618
|
+
echo " create-session - Test auth, output session info" >&2
|
|
619
|
+
echo " post <text> [reply flags] - Create a post" >&2
|
|
620
|
+
echo " get-metrics - Fetch profile stats" >&2
|
|
621
|
+
echo " get-notifications [--limit N] - Fetch mention notifications" >&2
|
|
622
|
+
exit 1
|
|
623
|
+
fi
|
|
624
|
+
|
|
625
|
+
require_jq
|
|
626
|
+
require_credentials
|
|
627
|
+
|
|
628
|
+
case "$command" in
|
|
629
|
+
create-session) cmd_create_session ;;
|
|
630
|
+
post) cmd_post "$@" ;;
|
|
631
|
+
get-metrics) cmd_get_metrics ;;
|
|
632
|
+
get-notifications) cmd_get_notifications "$@" ;;
|
|
633
|
+
*)
|
|
634
|
+
echo "Error: Unknown command '${command}'" >&2
|
|
635
|
+
echo "Run 'bsky-community.sh' without arguments for usage." >&2
|
|
636
|
+
exit 1
|
|
637
|
+
;;
|
|
638
|
+
esac
|
|
639
|
+
}
|
|
640
|
+
|
|
641
|
+
# Guard: allow sourcing without executing main (for test harness)
|
|
642
|
+
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
|
|
643
|
+
main "$@"
|
|
644
|
+
fi
|