@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,756 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# pipeline-tally.sh — running tally of autonomous-pipeline work units (#9403).
|
|
3
|
+
#
|
|
4
|
+
# WHAT IT COUNTS, AND WHY UNITS
|
|
5
|
+
#
|
|
6
|
+
# Autonomous loops (one-shot, work, review, test-fix-loop, drain-*, resolve-*,
|
|
7
|
+
# eval-harness) spend real work — review seats spawned, CI cycles, fix rounds,
|
|
8
|
+
# agent rounds — but print no running tally, so the cost shape of a run is only
|
|
9
|
+
# ever discovered post-hoc (inciting incident: PR #9339, an 11-seat review and
|
|
10
|
+
# ~8 CI cycles for a small fix). This script is the measuring instrument: a
|
|
11
|
+
# per-branch counter file under the session-state root, mutated only through
|
|
12
|
+
# the subcommands below.
|
|
13
|
+
#
|
|
14
|
+
# The counters are UNITS OF WORK, never money — the honest currency for
|
|
15
|
+
# zero-marginal Max-subscription runs (#5086 doctrine, ADR-056). No currency
|
|
16
|
+
# or price token appears in any output, by design and by sentinel.
|
|
17
|
+
#
|
|
18
|
+
# COUNTER FILE
|
|
19
|
+
#
|
|
20
|
+
# <session-state-root>/counters/<slug>
|
|
21
|
+
#
|
|
22
|
+
# <session-state-root> = _session_state_root() from scripts/lib/session-state.sh
|
|
23
|
+
# (SOLEUR_SESSION_STATE_ROOT override, else <git-common-dir>/
|
|
24
|
+
# soleur-session-state, else the /tmp/soleur-session-state-orphan fallback;
|
|
25
|
+
# under the orphan fallback the counters dir gains a -<repo-basename>
|
|
26
|
+
# suffix so two checkouts cannot collide).
|
|
27
|
+
# <slug> = branch name sanitized — every char outside [A-Za-z0-9._-] becomes
|
|
28
|
+
# '-' — PLUS `-<sha1-6>` of the RAW branch name: `feat/x` and `feat-x`
|
|
29
|
+
# sanitize identically and a shared ledger would let one branch's cap
|
|
30
|
+
# latch starve a sibling. Detached HEAD writes `HEAD-<hash>`.
|
|
31
|
+
# hooks/stop-hook.sh reads this ledger via `show` — no second path
|
|
32
|
+
# resolver exists.
|
|
33
|
+
#
|
|
34
|
+
# Flat key=value lines, rewritten wholesale under with_lock:
|
|
35
|
+
# seats / ci_cycles / fix_rounds / agent_rounds (counts, default 0)
|
|
36
|
+
# cap_<dim>=N (0 = unset — persisted at init so caps survive
|
|
37
|
+
# skill-to-skill handoff; argv dies at skill boundaries)
|
|
38
|
+
# warned_<dim>=N (level at which WARN first fired, ask included; 0 = never)
|
|
39
|
+
# capped=<dim> (empty, or the dim that hit its hard cap)
|
|
40
|
+
#
|
|
41
|
+
# CANONICAL PER-SKILL CALL-OUT BLOCK — the literal invocation every
|
|
42
|
+
# instrumented SKILL.md carries (the components.test.ts sentinel anchors on
|
|
43
|
+
# these call forms, comment-stripped — comment-only mentions do not satisfy it):
|
|
44
|
+
#
|
|
45
|
+
# # --- Pipeline tally (soleur #9403) ---
|
|
46
|
+
# bash "${CLAUDE_PLUGIN_ROOT}/scripts/pipeline-tally.sh" init # once, merge-safe
|
|
47
|
+
# bash "${CLAUDE_PLUGIN_ROOT}/scripts/pipeline-tally.sh" show # phase boundary
|
|
48
|
+
# bash "${CLAUDE_PLUGIN_ROOT}/scripts/pipeline-tally.sh" incr <dim> [n] # per op
|
|
49
|
+
# VERDICT="$(bash "${CLAUDE_PLUGIN_ROOT}/scripts/pipeline-tally.sh" gate <dim> [n])"
|
|
50
|
+
# # gate BEFORE each expensive step; [n] = the impending fan-out width so a
|
|
51
|
+
# # bulk spawn can't overshoot the cap unbounded (check-then-blast).
|
|
52
|
+
# # VERDICT == STOP → write
|
|
53
|
+
# # knowledge-base/project/specs/<feature>/session-state.md with
|
|
54
|
+
# # appended `status: budget-capped` + a `budget-capped: <dim>=<n>/<cap>`
|
|
55
|
+
# # line + resume prompt, then exit the phase cleanly — classified stop,
|
|
56
|
+
# # never a blocking prompt in an unattended run (#8611). A parent detects
|
|
57
|
+
# # it via `grep -q budget-capped` on that file.
|
|
58
|
+
# # VERDICT == WARN → continue; the crossing is recorded in the ledger.
|
|
59
|
+
# # VERDICT == UNKNOWN → substrate unreadable; caps unenforced (ship renders
|
|
60
|
+
# # `cap-unenforced`). Every call exits 0 — the tally is fail-open by
|
|
61
|
+
# # contract and must never red a pipeline.
|
|
62
|
+
#
|
|
63
|
+
# COUNTING CONVENTIONS: `seats` = review-panel seats actually spawned (design
|
|
64
|
+
# pass included — `gate seats <panel-size>` before dispatch). `agent_rounds` =
|
|
65
|
+
# orchestration dispatches (one-shot child skills, drain items, resolver
|
|
66
|
+
# fan-outs). `fix_rounds` = fix/retry iterations. `ci_cycles` = CI runs the run
|
|
67
|
+
# itself drove (each push to the PR head). Heterogeneous units land on one dim
|
|
68
|
+
# by design — a cap reads as "work units", not a strict taxonomy.
|
|
69
|
+
#
|
|
70
|
+
# DIMENSIONS: seats | ci_cycles | fix_rounds | agent_rounds
|
|
71
|
+
# (`ci-cycles` is accepted as an alias for `ci_cycles` everywhere a dim is
|
|
72
|
+
# taken). One writer per dimension per skill invocation — a prose `incr` and a
|
|
73
|
+
# workflow `counts:` post for the same dim never both fire.
|
|
74
|
+
#
|
|
75
|
+
# SUBCOMMANDS
|
|
76
|
+
#
|
|
77
|
+
# init [--reset] [--branch <b>]
|
|
78
|
+
# [--max-seats N] [--max-ci-cycles N] [--max-fix-rounds N]
|
|
79
|
+
# [--max-agent-rounds N]
|
|
80
|
+
# Idempotent MERGE: creates the file if absent, preserves counters, merges
|
|
81
|
+
# --max-* flags into cap_<dim>. Prints `tally-init: <slug> <outcome>` where
|
|
82
|
+
# outcome ∈ fresh | continued | reset | capped-reset | stale-reset |
|
|
83
|
+
# repaired:
|
|
84
|
+
# fresh no file existed; new ledger created
|
|
85
|
+
# continued existing ledger kept; argv caps merged. A capped ledger
|
|
86
|
+
# prints `continued capped=<dim>` — the latch is visible.
|
|
87
|
+
# reset --reset given: counts/warned/capped cleared
|
|
88
|
+
# capped-reset ledger carried capped AND new --max-* caps were supplied —
|
|
89
|
+
# the raised-cap resume path; latch AND warned_* cleared,
|
|
90
|
+
# counts preserved. Beats stale-reset: an explicit raised
|
|
91
|
+
# cap is operator intent to continue THIS run; a bare init
|
|
92
|
+
# on the same stale file still stale-resets.
|
|
93
|
+
# stale-reset ledger file untouched for >24h (mtime — inactivity, not
|
|
94
|
+
# age: every gate read and every write refreshes it, so a
|
|
95
|
+
# multi-day run still counting survives): fresh ledger —
|
|
96
|
+
# a stale-ledger continuation must not STOP a fresh run
|
|
97
|
+
# by accident.
|
|
98
|
+
# repaired existing file failed ledger validation — rewritten
|
|
99
|
+
# clean (fail-open) with SOLEUR_TALLY_ERROR
|
|
100
|
+
# reason=unreadable; NEVER reported `continued`, because
|
|
101
|
+
# nothing readable was preserved.
|
|
102
|
+
# CAP SEMANTICS: a ledger carrying `capped` is NOT reset by a bare `init` —
|
|
103
|
+
# it reports `continued` and `capped` persists, so the next `gate` still
|
|
104
|
+
# returns STOP (a budget-capped run cannot be accidentally resumed under
|
|
105
|
+
# the same caps; livelock impossible). `capped` clears only via an explicit
|
|
106
|
+
# `--reset` or by supplying new --max-* caps. Reset clears the LEDGER, never
|
|
107
|
+
# the budget: cap_<dim> values survive every reset form unless the argv
|
|
108
|
+
# overrides them; to drop caps entirely, remove the counter file. Also
|
|
109
|
+
# sweeps sibling counter files with mtime > 30 days.
|
|
110
|
+
# RATCHET GUARD: without --reset, a --max-* LOWER than a persisted nonzero
|
|
111
|
+
# cap is refused and surfaced as a `cap-kept:` line (`cap-kept: <dim>=<kept>`) — a forwarded
|
|
112
|
+
# or defaulted flag must not silently tighten the branch's budget.
|
|
113
|
+
# Armed caps print as `armed: cap:<dim>=<n> …` on every init — a persisted
|
|
114
|
+
# budget is never invisible.
|
|
115
|
+
# Flag validation: values must match ^[1-9][0-9]{0,9}$ — non-numeric,
|
|
116
|
+
# negative, zero, leading-zero forms (`08`), and digit strings that would
|
|
117
|
+
# wrap mod-2^64 are rejected with SOLEUR_TALLY_ERROR reason=bad-flag on
|
|
118
|
+
# stderr and exit 0. `--max-ci_cycles` (underscore) aliases --max-ci-cycles.
|
|
119
|
+
#
|
|
120
|
+
# incr <dim> [n] [--branch <b>]
|
|
121
|
+
# Adds n (default 1, ^[0-9]{1,10}$ validated and 10#-normalized) to <dim> under
|
|
122
|
+
# lock and prints the updated `tally:` line. Missing/unreadable file →
|
|
123
|
+
# stderr SOLEUR_TALLY_ERROR reason=missing-file, stdout UNKNOWN, exit 0 —
|
|
124
|
+
# NEVER auto-creates (auto-create would make an init-after-incr ordering
|
|
125
|
+
# defect undetectable). `--branch <b>` posts to another branch's ledger
|
|
126
|
+
# (fleet-skill item attribution).
|
|
127
|
+
#
|
|
128
|
+
# show [--branch <b>]
|
|
129
|
+
# Absent/unreadable file → UNKNOWN. Else prints
|
|
130
|
+
# `tally: seats=N ci_cycles=N fix_rounds=N agent_rounds=N`, a `cap:<dim>=<n>`
|
|
131
|
+
# token line when caps are set (the stop-hook floor reads this), and, when
|
|
132
|
+
# any is set, `warned:<dim>=<at>` / `capped:<dim>=<cap>` tokens.
|
|
133
|
+
#
|
|
134
|
+
# gate <dim> [n] [--branch <b>]
|
|
135
|
+
# Reads cap_<dim> from the FILE, never argv. Verdict on stdout:
|
|
136
|
+
# STOP capped is set (any dim), or count >= cap_<dim> (cap > 0);
|
|
137
|
+
# sets capped=<dim> when empty — first cap wins, it is sticky.
|
|
138
|
+
# With lookahead n: count+n > cap — STOP WITHOUT latching (a
|
|
139
|
+
# smaller ask may still fit).
|
|
140
|
+
# WARN count+n >= ceil(cap*0.8); records warned_<dim> at the projected
|
|
141
|
+
# level on first fire. (Caps <=4 warn and stop at the same count —
|
|
142
|
+
# the warn band is empty there by construction.)
|
|
143
|
+
# OK otherwise, including cap unset
|
|
144
|
+
# Substrate failure (missing file, unreadable, no flock, lock contention,
|
|
145
|
+
# SOLEUR_DISABLE_SESSION_STATE kill-switch) → stdout UNKNOWN + stderr
|
|
146
|
+
# SOLEUR_TALLY_ERROR reason=<k>. Exit 0 always.
|
|
147
|
+
# An UNKNOWN under configured caps is `cap-unenforced`, never a clean pass.
|
|
148
|
+
#
|
|
149
|
+
# selfcheck
|
|
150
|
+
# Prints SOLEUR_TALLY_OK, exits 0, writes NOTHING — handled before the lib
|
|
151
|
+
# is sourced (session-state.sh creates its state dirs at source time), so
|
|
152
|
+
# it is safe in a read-only sandbox with tmpfs HOME.
|
|
153
|
+
#
|
|
154
|
+
# STDERR DISCIPLINE: SOLEUR_TALLY_ERROR reason=<k> markers; reasons are
|
|
155
|
+
# bad-flag | bad-branch | missing-file | unreadable | no-flock | lock-failed |
|
|
156
|
+
# lock-substrate-disabled | write-failed | lib-missing. `bad-branch` is the
|
|
157
|
+
# _tally_paths refusal class (`--branch` token unsafe for a filename). Lock contention may
|
|
158
|
+
# also print the substrate's own `[warn] lock contended` notice.
|
|
159
|
+
# `unreadable` covers a file that exists but cannot be parsed as a ledger
|
|
160
|
+
# (no `seats=` key, a non-numeric count/cap/warned value, or a capped token
|
|
161
|
+
# outside the dim vocabulary) — a corrupt file must never render as the
|
|
162
|
+
# legitimate `tally: 0` ZERO state.
|
|
163
|
+
#
|
|
164
|
+
# EXIT: always 0 (fail-open — counters must never red a pipeline).
|
|
165
|
+
#
|
|
166
|
+
# macOS: util-linux flock is absent → with_lock unavailable → mutations and
|
|
167
|
+
# gates degrade to UNKNOWN (+reason=no-flock); `show` remains a pure read.
|
|
168
|
+
# Documented limitation until the session-state flock polyfill lands.
|
|
169
|
+
|
|
170
|
+
# xtrace refusal — REQUIRED FIRST EXECUTABLE STATEMENT (lint-shell-trace-
|
|
171
|
+
# credential-refusal, unconditional arm): `_tally_getf` reads via `${!_r}`
|
|
172
|
+
# indirection, which the linter treats as runtime-named credential access —
|
|
173
|
+
# and `-x` prints expanded values. exit 78 is a refusal, not a failure
|
|
174
|
+
# surface, and precedes even the selfcheck fast-path.
|
|
175
|
+
case "$-" in
|
|
176
|
+
*x*) printf '[FATAL] refusing to run under xtrace: this script handles a live credential and -x would print it (see #7797)\n' >&2; exit 78 ;;
|
|
177
|
+
esac
|
|
178
|
+
|
|
179
|
+
# selfcheck fast-path BEFORE sourcing the lib — see header (write-free).
|
|
180
|
+
if [[ "${1:-}" == "selfcheck" ]]; then
|
|
181
|
+
printf 'SOLEUR_TALLY_OK\n'
|
|
182
|
+
exit 0
|
|
183
|
+
fi
|
|
184
|
+
|
|
185
|
+
# Deliberately NOT `set -euo pipefail`: every subcommand is contractually
|
|
186
|
+
# fail-open (exit 0 even on internal error), so all failure surfaces below are
|
|
187
|
+
# explicit checks returning through the SOLEUR_TALLY_ERROR path instead.
|
|
188
|
+
# Every expansion that can be unset is defaulted (${var:-}).
|
|
189
|
+
|
|
190
|
+
TALLY_SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" 2>/dev/null && pwd -P || true)"
|
|
191
|
+
TALLY_LIB="${TALLY_SCRIPT_DIR}/lib/session-state.sh"
|
|
192
|
+
if [[ -r "$TALLY_LIB" ]]; then
|
|
193
|
+
# shellcheck source=lib/session-state.sh
|
|
194
|
+
. "$TALLY_LIB" || true
|
|
195
|
+
fi
|
|
196
|
+
|
|
197
|
+
_tally_err() { printf 'SOLEUR_TALLY_ERROR reason=%s\n' "$1" >&2; }
|
|
198
|
+
|
|
199
|
+
# Owning trap for _tally_write's mktemp allocation (lint-trap-ownership): the
|
|
200
|
+
# write is tmp+mv atomic; a die between alloc and mv would leak <$file>.tmp.*.
|
|
201
|
+
_TALLY_TMP=""
|
|
202
|
+
trap 'rm -f "${_TALLY_TMP:-}"' EXIT
|
|
203
|
+
|
|
204
|
+
# Every char outside [A-Za-z0-9._-] becomes '-'. Generalizes
|
|
205
|
+
# _safe_worktree_name (worktree-manager.sh) — NOT byte-identical to it
|
|
206
|
+
# (`tr '/' '-'` vs full-class), but leases and counters are disjoint
|
|
207
|
+
# namespaces so the divergence is safe.
|
|
208
|
+
_tally_slug() { printf '%s' "$1" | tr -c 'A-Za-z0-9._-' '-'; }
|
|
209
|
+
|
|
210
|
+
# Short discriminator appended to the slug: `feat/x` and `feat-x` slug identically,
|
|
211
|
+
# and a shared ledger would let one branch's cap latch starve a sibling. Hashing
|
|
212
|
+
# the RAW branch name keeps each branch's ledger its own.
|
|
213
|
+
_tally_shorthash() {
|
|
214
|
+
local h
|
|
215
|
+
h=$(printf '%s' "$1" | git hash-object --stdin 2>/dev/null | cut -c1-6)
|
|
216
|
+
# `cut` exits 0 on empty input, so `||` alone can never reach the fallback —
|
|
217
|
+
# test the captured hash instead (a git-less env would re-collide feat/x
|
|
218
|
+
# and feat-x onto `feat-x-`).
|
|
219
|
+
[[ -n "$h" ]] || h=$(printf '%s' "$1" | cksum | cut -d' ' -f1)
|
|
220
|
+
printf '%s' "$h"
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
|
|
224
|
+
# Map _tally_paths rc -> the right error reason (1=bad-branch, 2=lib-missing).
|
|
225
|
+
_tally_paths_err() { case "$1" in 1) _tally_err bad-branch ;; *) _tally_err lib-missing ;; esac; }
|
|
226
|
+
|
|
227
|
+
# Canonicalize a dim token -> seats|ci_cycles|fix_rounds|agent_rounds, or fail.
|
|
228
|
+
_tally_dim() {
|
|
229
|
+
case "$1" in
|
|
230
|
+
seats|ci_cycles|fix_rounds|agent_rounds) printf '%s' "$1" ;;
|
|
231
|
+
ci-cycles) printf 'ci_cycles' ;;
|
|
232
|
+
*) return 1 ;;
|
|
233
|
+
esac
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
# _tally_paths <branch-or-empty> -> T_SLUG T_COUNTERS_DIR T_FILE
|
|
237
|
+
# rc 1 = unsafe branch token refused; rc 2 = no session-state root.
|
|
238
|
+
# _tally_paths_err maps the rc to the right reason marker.
|
|
239
|
+
_tally_paths() {
|
|
240
|
+
local branch="${1:-}"
|
|
241
|
+
if [[ -z "$branch" ]]; then
|
|
242
|
+
branch=$(git branch --show-current 2>/dev/null || true)
|
|
243
|
+
[[ -n "$branch" ]] || branch="HEAD"
|
|
244
|
+
fi
|
|
245
|
+
T_SLUG=$(_tally_slug "$branch")-$(_tally_shorthash "$branch")
|
|
246
|
+
# `.`/`..` survive the slug transform and would compose a path outside
|
|
247
|
+
# counters/ (mv deposits the tmp file in the state root). Same refusal
|
|
248
|
+
# class _validate_worktree_name applies; `--branch '-x'` is flag-eating.
|
|
249
|
+
if [[ "$branch" == -* || "$T_SLUG" == .-* || "$T_SLUG" == ..-* ]]; then
|
|
250
|
+
T_COUNTERS_DIR=""; T_FILE=""; T_SLUG=""
|
|
251
|
+
return 1
|
|
252
|
+
fi
|
|
253
|
+
local root=""
|
|
254
|
+
if command -v _session_state_root >/dev/null 2>&1; then
|
|
255
|
+
root=$(_session_state_root 2>/dev/null || true)
|
|
256
|
+
fi
|
|
257
|
+
if [[ -z "$root" ]]; then
|
|
258
|
+
T_COUNTERS_DIR=""; T_FILE=""
|
|
259
|
+
return 2
|
|
260
|
+
fi
|
|
261
|
+
T_COUNTERS_DIR="$root/counters"
|
|
262
|
+
if [[ "$root" == "/tmp/soleur-session-state-orphan" ]]; then
|
|
263
|
+
# Orphan fallback (not a git repo): suffix the counters dir with the repo
|
|
264
|
+
# basename so counters from different checkouts cannot collide.
|
|
265
|
+
local base
|
|
266
|
+
base=$(basename "$(git rev-parse --show-toplevel 2>/dev/null || printf '%s' "$PWD")")
|
|
267
|
+
T_COUNTERS_DIR="$root/counters-$(_tally_slug "$base")"
|
|
268
|
+
fi
|
|
269
|
+
T_FILE="$T_COUNTERS_DIR/$T_SLUG"
|
|
270
|
+
return 0
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
# Field read: grep+cut, the substrate's own idiom (no jq). Always rc 0.
|
|
274
|
+
_tally_field() {
|
|
275
|
+
grep "^$2=" "$1" 2>/dev/null | head -1 | cut -d= -f2-
|
|
276
|
+
return 0
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
# Is this a parseable ledger? `seats=` is the first key every write emits; a
|
|
280
|
+
# file that lacks it is corrupt/partial and must be reported `unreadable`
|
|
281
|
+
# rather than silently re-read as an all-zero tally (which would masquerade as
|
|
282
|
+
# the legitimate "instrumented, nothing counted" ZERO state). Every count,
|
|
283
|
+
# cap_* and warned_* value must be PURE digits — a digit-prefixed corrupt like
|
|
284
|
+
# `cap_seats=5x` would pass a first-char check, load as 0, and render a budget
|
|
285
|
+
# that looks configured but silently never enforces. `capped=` is whitelisted
|
|
286
|
+
# to the dim vocabulary: a garbage latch would STOP every gate forever.
|
|
287
|
+
# Unknown keys (run_id, started_at from the old schema) are ignored.
|
|
288
|
+
_tally_ledger_ok() {
|
|
289
|
+
[[ -f "$1" && -r "$1" ]] || return 1
|
|
290
|
+
grep -q '^seats=' "$1" 2>/dev/null || return 1
|
|
291
|
+
if grep -qvE '=[0-9]{1,18}$' \
|
|
292
|
+
< <(grep -E '^(seats|ci_cycles|fix_rounds|agent_rounds|cap_[a-z_]+|warned_[a-z_]+)=' "$1" 2>/dev/null); then
|
|
293
|
+
return 1
|
|
294
|
+
fi
|
|
295
|
+
# EVERY capped= line must carry the dim vocabulary or be empty — a duplicate
|
|
296
|
+
# corrupt line after a clean one must not slip past a first-line read.
|
|
297
|
+
if grep -qvE '^capped=(|seats|ci_cycles|fix_rounds|agent_rounds)$' \
|
|
298
|
+
< <(grep -E '^capped=' "$1" 2>/dev/null); then
|
|
299
|
+
return 1
|
|
300
|
+
fi
|
|
301
|
+
return 0
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
# Indirect get/set on the T_* ledger vars (bash 3.2-safe; keys are whitelisted).
|
|
305
|
+
_tally_getf() { local _r="T_$1"; printf '%s' "${!_r}"; }
|
|
306
|
+
_tally_setf() { printf -v "T_$1" '%s' "$2"; }
|
|
307
|
+
|
|
308
|
+
# Load the ledger into T_* globals; missing/corrupt fields default to 0/empty.
|
|
309
|
+
_tally_load() {
|
|
310
|
+
local k v
|
|
311
|
+
for k in seats ci_cycles fix_rounds agent_rounds \
|
|
312
|
+
cap_seats cap_ci_cycles cap_fix_rounds cap_agent_rounds \
|
|
313
|
+
warned_seats warned_ci_cycles warned_fix_rounds warned_agent_rounds; do
|
|
314
|
+
v=""
|
|
315
|
+
[[ -r "$1" ]] && v=$(_tally_field "$1" "$k")
|
|
316
|
+
[[ "$v" =~ ^[0-9]+$ ]] || v=0
|
|
317
|
+
_tally_setf "$k" "$((10#$v))"
|
|
318
|
+
done
|
|
319
|
+
T_capped=""
|
|
320
|
+
if [[ -r "$1" ]]; then
|
|
321
|
+
T_capped=$(_tally_field "$1" capped)
|
|
322
|
+
# Sanitize: an unvetted latch value would reach indirect expansion in
|
|
323
|
+
# `show` (`cap_$T_capped` -> invalid variable name) and mis-STOP gates.
|
|
324
|
+
case "$T_capped" in
|
|
325
|
+
""|seats|ci_cycles|fix_rounds|agent_rounds) ;;
|
|
326
|
+
*) T_capped="" ;;
|
|
327
|
+
esac
|
|
328
|
+
fi
|
|
329
|
+
return 0
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
# Wholesale rewrite. tmp+mv in the same dir so a crash never leaves a torn
|
|
333
|
+
# ledger; the lock (held by callers) orders concurrent writers.
|
|
334
|
+
_tally_write() {
|
|
335
|
+
local tmp
|
|
336
|
+
mkdir -p "$(dirname "$1")" 2>/dev/null || true
|
|
337
|
+
tmp=$(mktemp "$1.tmp.XXXXXX" 2>/dev/null) || return 1
|
|
338
|
+
_TALLY_TMP="$tmp"
|
|
339
|
+
cat > "$tmp" <<EOF || { rm -f "$tmp"; _TALLY_TMP=""; return 1; }
|
|
340
|
+
seats=$(_tally_getf seats)
|
|
341
|
+
ci_cycles=$(_tally_getf ci_cycles)
|
|
342
|
+
fix_rounds=$(_tally_getf fix_rounds)
|
|
343
|
+
agent_rounds=$(_tally_getf agent_rounds)
|
|
344
|
+
cap_seats=$(_tally_getf cap_seats)
|
|
345
|
+
cap_ci_cycles=$(_tally_getf cap_ci_cycles)
|
|
346
|
+
cap_fix_rounds=$(_tally_getf cap_fix_rounds)
|
|
347
|
+
cap_agent_rounds=$(_tally_getf cap_agent_rounds)
|
|
348
|
+
warned_seats=$(_tally_getf warned_seats)
|
|
349
|
+
warned_ci_cycles=$(_tally_getf warned_ci_cycles)
|
|
350
|
+
warned_fix_rounds=$(_tally_getf warned_fix_rounds)
|
|
351
|
+
warned_agent_rounds=$(_tally_getf warned_agent_rounds)
|
|
352
|
+
capped=$T_capped
|
|
353
|
+
EOF
|
|
354
|
+
if ! mv "$tmp" "$1" 2>/dev/null; then
|
|
355
|
+
rm -f "$tmp" 2>/dev/null || true
|
|
356
|
+
_TALLY_TMP=""
|
|
357
|
+
return 1
|
|
358
|
+
fi
|
|
359
|
+
_TALLY_TMP=""
|
|
360
|
+
return 0
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
_tally_print_line() {
|
|
364
|
+
printf 'tally: seats=%s ci_cycles=%s fix_rounds=%s agent_rounds=%s\n' \
|
|
365
|
+
"$(_tally_getf seats)" "$(_tally_getf ci_cycles)" \
|
|
366
|
+
"$(_tally_getf fix_rounds)" "$(_tally_getf agent_rounds)"
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
# Reap sibling counter files older than 30 days (mtime) — opportunistic
|
|
370
|
+
# housekeeping inside init; never fatal, never the current file's problem.
|
|
371
|
+
# Runs under THIS slug's lock while touching sibling files — benign: only
|
|
372
|
+
# mtime>30d files die, and incr's in-lock existence re-check covers the race.
|
|
373
|
+
_tally_sweep() {
|
|
374
|
+
[[ -n "${T_COUNTERS_DIR:-}" && -d "$T_COUNTERS_DIR" ]] || return 0
|
|
375
|
+
find "$T_COUNTERS_DIR" -maxdepth 1 -type f -mtime +30 -delete 2>/dev/null || true
|
|
376
|
+
return 0
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
# Run an impl under the branch-scoped lock. rc 1 + UNKNOWN + marker on failure.
|
|
380
|
+
_tally_locked() {
|
|
381
|
+
if ! command -v flock >/dev/null 2>&1; then
|
|
382
|
+
_tally_err no-flock
|
|
383
|
+
printf 'UNKNOWN\n'
|
|
384
|
+
return 1
|
|
385
|
+
fi
|
|
386
|
+
if [[ "${SOLEUR_DISABLE_SESSION_STATE:-}" == "1" ]]; then
|
|
387
|
+
# Kill-switch sessions run with_lock's impl UNLOCKED (session-state.sh
|
|
388
|
+
# _acquire_lock_impl returns 0) — a racing read-modify-write would emit a
|
|
389
|
+
# confident tally of lost updates. UNKNOWN is the honest failure.
|
|
390
|
+
_tally_err lock-substrate-disabled
|
|
391
|
+
printf 'UNKNOWN\n'
|
|
392
|
+
return 1
|
|
393
|
+
fi
|
|
394
|
+
if ! command -v with_lock >/dev/null 2>&1; then
|
|
395
|
+
_tally_err lib-missing
|
|
396
|
+
printf 'UNKNOWN\n'
|
|
397
|
+
return 1
|
|
398
|
+
fi
|
|
399
|
+
if ! with_lock "pipeline-tally-$T_SLUG" 10 -- "$@"; then
|
|
400
|
+
_tally_err lock-failed
|
|
401
|
+
printf 'UNKNOWN\n'
|
|
402
|
+
return 1
|
|
403
|
+
fi
|
|
404
|
+
return 0
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
# Cap values: ^[1-9][0-9]{0,9}$ — rejects non-numeric, negative, 0, the
|
|
408
|
+
# leading-zero forms (`08`) that 10# would otherwise silently accept, AND
|
|
409
|
+
# digit strings that wrap mod-2^64 into a different cap than the one asked for.
|
|
410
|
+
_tally_norm_cap() {
|
|
411
|
+
[[ "$1" =~ ^[1-9][0-9]{0,9}$ ]] || return 1
|
|
412
|
+
printf '%s' "$((10#$1))"
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
# --- init -------------------------------------------------------------------
|
|
416
|
+
|
|
417
|
+
_tally_init_locked() {
|
|
418
|
+
local reset="$1" caps_given="$2"
|
|
419
|
+
local n_seats="$3" n_ci="$4" n_fix="$5" n_agent="$6"
|
|
420
|
+
local existed=0 ok=0 outcome
|
|
421
|
+
[[ -f "$T_FILE" ]] && existed=1
|
|
422
|
+
if (( existed )) && _tally_ledger_ok "$T_FILE"; then ok=1; fi
|
|
423
|
+
_tally_load "$T_FILE"
|
|
424
|
+
|
|
425
|
+
# Staleness = 24h of INACTIVITY, keyed on file mtime, not a written key:
|
|
426
|
+
# every incr/gate write bumps it (gate also refreshes it on read), so a
|
|
427
|
+
# multi-day pipeline that crosses the threshold while still counting never
|
|
428
|
+
# gets zeroed mid-run.
|
|
429
|
+
local stale=0 mtime=0
|
|
430
|
+
if (( existed && ok )); then
|
|
431
|
+
mtime=$(stat -c %Y "$T_FILE" 2>/dev/null || stat -f %m "$T_FILE" 2>/dev/null || echo 0)
|
|
432
|
+
[[ "$mtime" =~ ^[0-9]+$ ]] && (( $(date +%s) - 10#$mtime > 86400 )) && stale=1
|
|
433
|
+
fi
|
|
434
|
+
|
|
435
|
+
if (( ! existed )); then
|
|
436
|
+
outcome="fresh"
|
|
437
|
+
elif (( reset )); then
|
|
438
|
+
outcome="reset"
|
|
439
|
+
elif (( ! ok )); then
|
|
440
|
+
# Existing but unreadable/corrupt: rewrite a clean ledger (fail-open — the
|
|
441
|
+
# pipeline must never wedge on state) but do NOT report `continued` —
|
|
442
|
+
# nothing readable was preserved, and a repaired forensic record is not
|
|
443
|
+
# a continuation.
|
|
444
|
+
outcome="repaired"
|
|
445
|
+
_tally_err unreadable
|
|
446
|
+
elif [[ -n "$T_capped" ]] && (( caps_given )); then
|
|
447
|
+
# Raised-cap resume BEATS stale: an explicit `--max-*` argv is operator
|
|
448
|
+
# intent to continue THIS run under a new budget, and the counts are the
|
|
449
|
+
# forensic record the feature exists to keep. (A bare init on the same
|
|
450
|
+
# stale+capped file still stale-resets — argv intent is what disambiguates
|
|
451
|
+
# resume from a new run.)
|
|
452
|
+
outcome="capped-reset"
|
|
453
|
+
elif (( stale )); then
|
|
454
|
+
outcome="stale-reset"
|
|
455
|
+
elif [[ -n "$T_capped" ]]; then
|
|
456
|
+
# Budget-capped ledger + no raised caps: the ledger CONTINUES and `capped`
|
|
457
|
+
# persists, so the next `gate` still returns STOP. See CAP SEMANTICS above.
|
|
458
|
+
outcome="continued capped=$T_capped"
|
|
459
|
+
else
|
|
460
|
+
outcome="continued"
|
|
461
|
+
fi
|
|
462
|
+
|
|
463
|
+
case "$outcome" in
|
|
464
|
+
reset|stale-reset|repaired)
|
|
465
|
+
# Fresh ledger — counts, warnings, capped cleared. cap_<dim> survive:
|
|
466
|
+
# reset clears the ledger, never the budget.
|
|
467
|
+
_tally_setf seats 0; _tally_setf ci_cycles 0
|
|
468
|
+
_tally_setf fix_rounds 0; _tally_setf agent_rounds 0
|
|
469
|
+
_tally_setf warned_seats 0; _tally_setf warned_ci_cycles 0
|
|
470
|
+
_tally_setf warned_fix_rounds 0; _tally_setf warned_agent_rounds 0
|
|
471
|
+
T_capped=""
|
|
472
|
+
;;
|
|
473
|
+
capped-reset)
|
|
474
|
+
# Same run continuing under a raised budget: clear the latch AND the
|
|
475
|
+
# warned_* markers (they fired against the OLD cap and would annotate
|
|
476
|
+
# the new budget falsely). Counts persist — the branch's cost record is
|
|
477
|
+
# the tally the feature exists to report.
|
|
478
|
+
T_capped=""
|
|
479
|
+
_tally_setf warned_seats 0; _tally_setf warned_ci_cycles 0
|
|
480
|
+
_tally_setf warned_fix_rounds 0; _tally_setf warned_agent_rounds 0
|
|
481
|
+
;;
|
|
482
|
+
esac
|
|
483
|
+
|
|
484
|
+
# Merge argv caps — RATCHET GUARD: without --reset, a --max-* LOWER than a
|
|
485
|
+
# persisted nonzero cap is refused (a `cap-kept:` line surfaces it). A
|
|
486
|
+
# forwarded or defaulted flag would otherwise silently tighten this branch's
|
|
487
|
+
# budget and false-STOP a later unflagged run.
|
|
488
|
+
_TALLY_KEPT=""
|
|
489
|
+
_tally_merge_cap seats "$n_seats" "$reset"
|
|
490
|
+
_tally_merge_cap ci_cycles "$n_ci" "$reset"
|
|
491
|
+
_tally_merge_cap fix_rounds "$n_fix" "$reset"
|
|
492
|
+
_tally_merge_cap agent_rounds "$n_agent" "$reset"
|
|
493
|
+
|
|
494
|
+
_tally_write "$T_FILE" || { _tally_err write-failed; printf 'UNKNOWN\n'; return 0; }
|
|
495
|
+
_tally_sweep
|
|
496
|
+
printf 'tally-init: %s %s\n' "$T_SLUG" "$outcome"
|
|
497
|
+
# Armed-cap disclosure: a persisted cap from an earlier invocation is
|
|
498
|
+
# otherwise invisible until it stops a run.
|
|
499
|
+
local armed; armed=$(_tally_cap_tokens)
|
|
500
|
+
[[ -n "$armed" ]] && printf 'armed: %s\n' "${armed% }"
|
|
501
|
+
[[ -n "$_TALLY_KEPT" ]] && printf 'cap-kept: %s\n' "${_TALLY_KEPT% }"
|
|
502
|
+
return 0
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
# Trailing-space "cap:<d>=<n> ..." for the nonzero caps — shared by init's
|
|
506
|
+
# armed: line and show's cap: line so the two renderings cannot drift.
|
|
507
|
+
_tally_cap_tokens() {
|
|
508
|
+
local _d _c out=""
|
|
509
|
+
for _d in seats ci_cycles fix_rounds agent_rounds; do
|
|
510
|
+
_c=$(_tally_getf "cap_$_d")
|
|
511
|
+
(( _c > 0 )) && out="${out}cap:${_d}=${_c} "
|
|
512
|
+
done
|
|
513
|
+
printf '%s' "$out"
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
# Merge one --max-* value into cap_<dim>; refuses to lower a persisted nonzero
|
|
517
|
+
# cap unless --reset. Accumulates refusals in _TALLY_KEPT.
|
|
518
|
+
_tally_merge_cap() {
|
|
519
|
+
local dim="$1" newv="$2" reset="$3" old
|
|
520
|
+
[[ -n "$newv" ]] || return 0
|
|
521
|
+
old=$(_tally_getf "cap_$dim")
|
|
522
|
+
if (( ! reset )) && (( old > 0 )) && (( 10#$newv < old )); then
|
|
523
|
+
_TALLY_KEPT="${_TALLY_KEPT}${dim}=${old} "
|
|
524
|
+
return 0
|
|
525
|
+
fi
|
|
526
|
+
_tally_setf "cap_$dim" "$newv"
|
|
527
|
+
return 0
|
|
528
|
+
}
|
|
529
|
+
|
|
530
|
+
cmd_init() {
|
|
531
|
+
local reset=0 caps_given=0 branch="" flag=""
|
|
532
|
+
local n_seats="" n_ci="" n_fix="" n_agent="" v=""
|
|
533
|
+
while [[ $# -gt 0 ]]; do
|
|
534
|
+
# Underscored spellings of a flag alias to its hyphenated form —
|
|
535
|
+
# `--max-ci_cycles` would otherwise silently bad-flag the operator's budget.
|
|
536
|
+
flag=$(printf '%s' "$1" | tr '_' '-')
|
|
537
|
+
case "$flag" in
|
|
538
|
+
--reset) reset=1; shift ;;
|
|
539
|
+
--branch)
|
|
540
|
+
branch="${2:-}"
|
|
541
|
+
[[ -n "$branch" && "$branch" != -* ]] || { _tally_err bad-flag; printf 'UNKNOWN\n'; return 0; }
|
|
542
|
+
shift 2 ;;
|
|
543
|
+
--max-seats)
|
|
544
|
+
v=$(_tally_norm_cap "${2:-}") || { _tally_err bad-flag; printf 'UNKNOWN\n'; return 0; }
|
|
545
|
+
n_seats=$v; caps_given=1; shift 2 ;;
|
|
546
|
+
--max-ci-cycles)
|
|
547
|
+
v=$(_tally_norm_cap "${2:-}") || { _tally_err bad-flag; printf 'UNKNOWN\n'; return 0; }
|
|
548
|
+
n_ci=$v; caps_given=1; shift 2 ;;
|
|
549
|
+
--max-fix-rounds)
|
|
550
|
+
v=$(_tally_norm_cap "${2:-}") || { _tally_err bad-flag; printf 'UNKNOWN\n'; return 0; }
|
|
551
|
+
n_fix=$v; caps_given=1; shift 2 ;;
|
|
552
|
+
--max-agent-rounds)
|
|
553
|
+
v=$(_tally_norm_cap "${2:-}") || { _tally_err bad-flag; printf 'UNKNOWN\n'; return 0; }
|
|
554
|
+
n_agent=$v; caps_given=1; shift 2 ;;
|
|
555
|
+
*) _tally_err bad-flag; printf 'UNKNOWN\n'; return 0 ;;
|
|
556
|
+
esac
|
|
557
|
+
done
|
|
558
|
+
_tally_paths "$branch" || { _tally_paths_err $?; printf 'UNKNOWN\n'; return 0; }
|
|
559
|
+
_tally_locked _tally_init_locked "$reset" "$caps_given" "$n_seats" "$n_ci" "$n_fix" "$n_agent" || true
|
|
560
|
+
return 0
|
|
561
|
+
}
|
|
562
|
+
|
|
563
|
+
# --- incr -------------------------------------------------------------------
|
|
564
|
+
|
|
565
|
+
_tally_incr_locked() {
|
|
566
|
+
local dim="$1" n="$2"
|
|
567
|
+
if [[ ! -f "$T_FILE" ]]; then
|
|
568
|
+
_tally_err missing-file; printf 'UNKNOWN\n'; return 0
|
|
569
|
+
fi
|
|
570
|
+
if ! _tally_ledger_ok "$T_FILE"; then
|
|
571
|
+
_tally_err unreadable; printf 'UNKNOWN\n'; return 0
|
|
572
|
+
fi
|
|
573
|
+
_tally_load "$T_FILE"
|
|
574
|
+
_tally_setf "$dim" "$(( $(_tally_getf "$dim") + n ))"
|
|
575
|
+
_tally_write "$T_FILE" || { _tally_err write-failed; printf 'UNKNOWN\n'; return 0; }
|
|
576
|
+
_tally_print_line
|
|
577
|
+
return 0
|
|
578
|
+
}
|
|
579
|
+
|
|
580
|
+
cmd_incr() {
|
|
581
|
+
local dim="" n=1 n_set=0 branch=""
|
|
582
|
+
while [[ $# -gt 0 ]]; do
|
|
583
|
+
case "$1" in
|
|
584
|
+
--branch)
|
|
585
|
+
branch="${2:-}"
|
|
586
|
+
[[ -n "$branch" && "$branch" != -* ]] || { _tally_err bad-flag; printf 'UNKNOWN\n'; return 0; }
|
|
587
|
+
shift 2 ;;
|
|
588
|
+
-* ) _tally_err bad-flag; printf 'UNKNOWN\n'; return 0 ;;
|
|
589
|
+
*)
|
|
590
|
+
if [[ -z "$dim" ]]; then dim="$1"
|
|
591
|
+
elif (( ! n_set )); then n="$1"; n_set=1
|
|
592
|
+
else _tally_err bad-flag; printf 'UNKNOWN\n'; return 0; fi
|
|
593
|
+
shift ;;
|
|
594
|
+
esac
|
|
595
|
+
done
|
|
596
|
+
dim=$(_tally_dim "${dim:-}") || { _tally_err bad-flag; printf 'UNKNOWN\n'; return 0; }
|
|
597
|
+
if [[ ! "$n" =~ ^[0-9]{1,10}$ ]]; then
|
|
598
|
+
_tally_err bad-flag; printf 'UNKNOWN\n'; return 0
|
|
599
|
+
fi
|
|
600
|
+
n=$((10#$n))
|
|
601
|
+
_tally_paths "$branch" || { _tally_paths_err $?; printf 'UNKNOWN\n'; return 0; }
|
|
602
|
+
# Missing file is reported before any lock attempt: the error must fire even
|
|
603
|
+
# where flock is unavailable, and `incr` NEVER creates the ledger.
|
|
604
|
+
if [[ ! -f "$T_FILE" ]]; then
|
|
605
|
+
_tally_err missing-file; printf 'UNKNOWN\n'; return 0
|
|
606
|
+
fi
|
|
607
|
+
_tally_locked _tally_incr_locked "$dim" "$n" || true
|
|
608
|
+
return 0
|
|
609
|
+
}
|
|
610
|
+
|
|
611
|
+
# --- show -------------------------------------------------------------------
|
|
612
|
+
|
|
613
|
+
cmd_show() {
|
|
614
|
+
local branch=""
|
|
615
|
+
while [[ $# -gt 0 ]]; do
|
|
616
|
+
case "$1" in
|
|
617
|
+
--branch)
|
|
618
|
+
branch="${2:-}"
|
|
619
|
+
[[ -n "$branch" && "$branch" != -* ]] || { _tally_err bad-flag; printf 'UNKNOWN\n'; return 0; }
|
|
620
|
+
shift 2 ;;
|
|
621
|
+
*) _tally_err bad-flag; printf 'UNKNOWN\n'; return 0 ;;
|
|
622
|
+
esac
|
|
623
|
+
done
|
|
624
|
+
_tally_paths "$branch" || { _tally_paths_err $?; printf 'UNKNOWN\n'; return 0; }
|
|
625
|
+
if [[ ! -f "$T_FILE" ]]; then
|
|
626
|
+
_tally_err missing-file; printf 'UNKNOWN\n'; return 0
|
|
627
|
+
fi
|
|
628
|
+
if ! _tally_ledger_ok "$T_FILE"; then
|
|
629
|
+
_tally_err unreadable; printf 'UNKNOWN\n'; return 0
|
|
630
|
+
fi
|
|
631
|
+
_tally_load "$T_FILE"
|
|
632
|
+
_tally_print_line
|
|
633
|
+
# Second line: configured caps (the stop-hook floor and ship's render both
|
|
634
|
+
# consume this shape — `cap:<dim>=<n>` tokens, same helper init's armed: uses).
|
|
635
|
+
local caps d w
|
|
636
|
+
caps=$(_tally_cap_tokens)
|
|
637
|
+
[[ -n "$caps" ]] && printf '%s\n' "${caps% }"
|
|
638
|
+
# Third line: warned/capped annotations, only when set.
|
|
639
|
+
local ann=""
|
|
640
|
+
for d in seats ci_cycles fix_rounds agent_rounds; do
|
|
641
|
+
w=$(_tally_getf "warned_$d")
|
|
642
|
+
[[ "$w" != "0" ]] && ann="${ann}warned:${d}=${w} "
|
|
643
|
+
done
|
|
644
|
+
[[ -n "$T_capped" ]] && ann="${ann}capped:${T_capped}=$(_tally_getf "cap_$T_capped")"
|
|
645
|
+
ann="${ann% }"
|
|
646
|
+
[[ -n "$ann" ]] && printf '%s\n' "$ann"
|
|
647
|
+
return 0
|
|
648
|
+
}
|
|
649
|
+
|
|
650
|
+
# --- gate -------------------------------------------------------------------
|
|
651
|
+
|
|
652
|
+
_tally_gate_locked() {
|
|
653
|
+
local dim="$1" ask="${2:-0}"
|
|
654
|
+
if [[ ! -f "$T_FILE" ]]; then
|
|
655
|
+
_tally_err missing-file; printf 'UNKNOWN\n'; return 0
|
|
656
|
+
fi
|
|
657
|
+
if ! _tally_ledger_ok "$T_FILE"; then
|
|
658
|
+
_tally_err unreadable; printf 'UNKNOWN\n'; return 0
|
|
659
|
+
fi
|
|
660
|
+
_tally_load "$T_FILE"
|
|
661
|
+
# Refresh mtime on every successful gate read: staleness means "nothing
|
|
662
|
+
# touched the ledger in 24h", and a polling caller (ship's phase-7 gate)
|
|
663
|
+
# IS ledger activity — a quiet-but-live pipeline must not zero itself.
|
|
664
|
+
touch "$T_FILE" 2>/dev/null || true
|
|
665
|
+
# A set `capped` is sticky and global: STOP regardless of which dim is asked.
|
|
666
|
+
if [[ -n "$T_capped" ]]; then
|
|
667
|
+
printf 'STOP\n'; return 0
|
|
668
|
+
fi
|
|
669
|
+
local cap count
|
|
670
|
+
cap=$(_tally_getf "cap_$dim"); count=$(_tally_getf "$dim")
|
|
671
|
+
if (( cap <= 0 )); then
|
|
672
|
+
printf 'OK\n'; return 0
|
|
673
|
+
fi
|
|
674
|
+
if (( count >= cap )); then
|
|
675
|
+
T_capped="$dim"
|
|
676
|
+
# Best-effort persist: the verdict stands even if the write fails (the
|
|
677
|
+
# next gate re-derives STOP from count >= cap).
|
|
678
|
+
_tally_write "$T_FILE" || true
|
|
679
|
+
printf 'STOP\n'; return 0
|
|
680
|
+
fi
|
|
681
|
+
# Lookahead: `gate <dim> <n>` asks "does the impending n-unit step fit?"
|
|
682
|
+
# STOP without latching — a smaller ask may still fit.
|
|
683
|
+
if (( ask > 0 && count + ask > cap )); then
|
|
684
|
+
printf 'STOP\n'; return 0
|
|
685
|
+
fi
|
|
686
|
+
local warn_thresh=$(( (cap * 8 + 9) / 10 )) # ceil(cap * 0.8)
|
|
687
|
+
if (( count + ask >= warn_thresh )); then
|
|
688
|
+
if [[ "$(_tally_getf "warned_$dim")" == "0" ]]; then
|
|
689
|
+
_tally_setf "warned_$dim" "$((count + ask))" # first-fire level incl. the ask
|
|
690
|
+
_tally_write "$T_FILE" || true
|
|
691
|
+
fi
|
|
692
|
+
printf 'WARN\n'; return 0
|
|
693
|
+
fi
|
|
694
|
+
printf 'OK\n'
|
|
695
|
+
return 0
|
|
696
|
+
}
|
|
697
|
+
|
|
698
|
+
cmd_gate() {
|
|
699
|
+
local dim="" ask="" branch=""
|
|
700
|
+
while [[ $# -gt 0 ]]; do
|
|
701
|
+
case "$1" in
|
|
702
|
+
--branch)
|
|
703
|
+
branch="${2:-}"
|
|
704
|
+
[[ -n "$branch" && "$branch" != -* ]] || { _tally_err bad-flag; printf 'UNKNOWN\n'; return 0; }
|
|
705
|
+
shift 2 ;;
|
|
706
|
+
*)
|
|
707
|
+
if [[ -z "$dim" ]]; then dim="$1"
|
|
708
|
+
elif [[ -z "$ask" ]]; then ask="$1"
|
|
709
|
+
else _tally_err bad-flag; printf 'UNKNOWN\n'; return 0; fi
|
|
710
|
+
shift ;;
|
|
711
|
+
esac
|
|
712
|
+
done
|
|
713
|
+
dim=$(_tally_dim "${dim:-}") || { _tally_err bad-flag; printf 'UNKNOWN\n'; return 0; }
|
|
714
|
+
if [[ -n "$ask" ]]; then
|
|
715
|
+
[[ "$ask" =~ ^[0-9]{1,10}$ ]] || { _tally_err bad-flag; printf 'UNKNOWN\n'; return 0; }
|
|
716
|
+
ask=$((10#$ask))
|
|
717
|
+
else
|
|
718
|
+
ask=0
|
|
719
|
+
fi
|
|
720
|
+
_tally_paths "$branch" || { _tally_paths_err $?; printf 'UNKNOWN\n'; return 0; }
|
|
721
|
+
# Same ordering as cmd_incr: missing-file must win over no-flock.
|
|
722
|
+
if [[ ! -f "$T_FILE" ]]; then
|
|
723
|
+
_tally_err missing-file; printf 'UNKNOWN\n'; return 0
|
|
724
|
+
fi
|
|
725
|
+
_tally_locked _tally_gate_locked "$dim" "$ask" || true
|
|
726
|
+
return 0
|
|
727
|
+
}
|
|
728
|
+
|
|
729
|
+
# --- dispatch ---------------------------------------------------------------
|
|
730
|
+
|
|
731
|
+
_tally_usage() {
|
|
732
|
+
cat <<'EOF'
|
|
733
|
+
usage: pipeline-tally.sh <subcommand> [args]
|
|
734
|
+
|
|
735
|
+
init [--reset] [--branch <b>] [--max-seats N] [--max-ci-cycles N]
|
|
736
|
+
[--max-fix-rounds N] [--max-agent-rounds N]
|
|
737
|
+
incr <dim> [n] [--branch <b>]
|
|
738
|
+
show [--branch <b>]
|
|
739
|
+
gate <dim> [n] [--branch <b>]
|
|
740
|
+
selfcheck
|
|
741
|
+
|
|
742
|
+
dims: seats | ci_cycles (alias ci-cycles) | fix_rounds | agent_rounds
|
|
743
|
+
gate's optional [n] is a lookahead: STOP when count+n would exceed the cap.
|
|
744
|
+
fail-open: every subcommand exits 0; errors are SOLEUR_TALLY_ERROR on stderr.
|
|
745
|
+
EOF
|
|
746
|
+
}
|
|
747
|
+
|
|
748
|
+
case "${1:-}" in
|
|
749
|
+
init) shift; cmd_init "$@" ;;
|
|
750
|
+
incr) shift; cmd_incr "$@" ;;
|
|
751
|
+
show) shift; cmd_show "$@" ;;
|
|
752
|
+
gate) shift; cmd_gate "$@" ;;
|
|
753
|
+
-h|--help|"") _tally_usage ;;
|
|
754
|
+
*) _tally_err bad-flag; _tally_usage >&2 ;;
|
|
755
|
+
esac
|
|
756
|
+
exit 0
|