@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,670 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
#
|
|
3
|
+
# Tests for plugins/soleur/scripts/scan-ancestor-signal-helpers.py -- the inventory scan and
|
|
4
|
+
# shrink-only ratchet for shell test suites that contain a signal helper (an ancestor walk that
|
|
5
|
+
# signals, a signal to the parent, an all-process signal; targeted group and name-pattern signals
|
|
6
|
+
# are listed only). Guard 2 of the plan
|
|
7
|
+
# knowledge-base/project/plans/archive/20261013-062704-2026-10-10-chore-pid-namespace-guard-for-signal-helper-mutants-plan.md
|
|
8
|
+
#
|
|
9
|
+
# WHY NOTHING HERE SENDS A SIGNAL. The suite works on tracked DATA files (.txt, under
|
|
10
|
+
# plugins/soleur/test/fixtures/ancestor-signal/) that are passed to the scanner as explicit PATHs, and on a
|
|
11
|
+
# throwaway repository whose members are copies of those data files. The scanner only reads text.
|
|
12
|
+
# Walker-shaped text therefore never appears as a source line of this suite (the scan would find it in
|
|
13
|
+
# itself), and the walk over the whole tree is delegated to the scanner (the live row); this file keeps
|
|
14
|
+
# no tree walk of its own. The nonce walker data file that sits in the same fixture directory belongs to
|
|
15
|
+
# another suite and is never read or run here.
|
|
16
|
+
#
|
|
17
|
+
# Run: bash plugins/soleur/scripts/scan-ancestor-signal-helpers.test.sh
|
|
18
|
+
|
|
19
|
+
# shellcheck disable=SC2016 # single-quoted strings in this file are literal shell text under test, not expansions
|
|
20
|
+
set -uo pipefail
|
|
21
|
+
export TMPDIR="${TMPDIR:-/var/tmp}"
|
|
22
|
+
|
|
23
|
+
DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
24
|
+
REPO_ROOT="$(cd "$DIR/../../.." && pwd)"
|
|
25
|
+
SCAN="$DIR/scan-ancestor-signal-helpers.py"
|
|
26
|
+
BASELINE="$DIR/ancestor-signal-helpers.baseline.txt"
|
|
27
|
+
FIX="$REPO_ROOT/plugins/soleur/test/fixtures/ancestor-signal"
|
|
28
|
+
|
|
29
|
+
# Arms the git-location tripwire (a hook-exported GIT_DIR would redirect the fixture repository) and
|
|
30
|
+
# provides git_fixture_env for the throwaway repository.
|
|
31
|
+
# shellcheck source=/dev/null
|
|
32
|
+
source "$REPO_ROOT/plugins/soleur/test/lib/git-fixture-env.sh" || { echo "FATAL: could not source git-fixture-env.sh" >&2; exit 2; }
|
|
33
|
+
|
|
34
|
+
# Canonical fixture-dir guard (BYTE-IDENTICAL to plugins/soleur/test/test-helpers.sh; fixture-dir-operand-assert.test.sh compares every copy).
|
|
35
|
+
assert_fixture_dir() {
|
|
36
|
+
case "${1-}" in
|
|
37
|
+
"") printf 'FATAL: fixture dir is EMPTY; git -C "" would operate on %s\n' "$PWD" >&2; exit 2 ;;
|
|
38
|
+
*/../*|*/..) printf 'FATAL: fixture dir %s contains ..; refusing\n' "$1" >&2; exit 2 ;;
|
|
39
|
+
/proc/*|/sys/*|/dev/*) printf 'FATAL: fixture dir %s is a synthetic-fs path; refusing\n' "$1" >&2; exit 2 ;;
|
|
40
|
+
/|//|/.) printf 'FATAL: fixture dir resolves to the filesystem root; refusing\n' >&2; exit 2 ;;
|
|
41
|
+
/*) : ;;
|
|
42
|
+
*) printf 'FATAL: fixture dir %s is RELATIVE; refusing\n' "$1" >&2; exit 2 ;;
|
|
43
|
+
esac
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
TMP=""
|
|
47
|
+
cleanup_suite() {
|
|
48
|
+
[[ -n "${TMP:-}" ]] || return 0
|
|
49
|
+
assert_fixture_dir "$TMP"
|
|
50
|
+
rm -rf "$TMP"
|
|
51
|
+
}
|
|
52
|
+
trap cleanup_suite EXIT
|
|
53
|
+
|
|
54
|
+
TMP="$(mktemp -d "$TMPDIR/ancsig-scan.XXXXXXXX")" || { echo "FATAL: mktemp failed" >&2; exit 2; }
|
|
55
|
+
assert_fixture_dir "$TMP"
|
|
56
|
+
|
|
57
|
+
passes=0
|
|
58
|
+
fails=0
|
|
59
|
+
cases=0
|
|
60
|
+
skipped=0
|
|
61
|
+
PLANNED_TOTAL=148
|
|
62
|
+
|
|
63
|
+
pass() { passes=$((passes + 1)); printf '[ok] %s\n' "$1"; }
|
|
64
|
+
fail() { fails=$((fails + 1)); printf '[FAIL] %s\n' "$1"; }
|
|
65
|
+
|
|
66
|
+
# check <label> <command...>: one case; the counter moves at the call site, the verdict is separate.
|
|
67
|
+
check() {
|
|
68
|
+
local label="$1"; shift
|
|
69
|
+
cases=$((cases + 1))
|
|
70
|
+
if "$@"; then pass "$label"; else fail "$label"; fi
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
# --- instrument self-test: drive pass, fail and check once each, require each counter to move exactly as
|
|
74
|
+
# --- expected, and that check turns a failing command into a fail and a passing one into a pass ---
|
|
75
|
+
selftest_instrument() {
|
|
76
|
+
local p0="$passes" f0="$fails" c0="$cases" rc=0
|
|
77
|
+
pass "selftest" >/dev/null
|
|
78
|
+
fail "selftest" >/dev/null
|
|
79
|
+
if [[ "$passes" -ne $((p0 + 1)) || "$fails" -ne $((f0 + 1)) ]]; then rc=1; fi
|
|
80
|
+
check "selftest-true" true >/dev/null
|
|
81
|
+
check "selftest-false" false >/dev/null
|
|
82
|
+
if [[ "$passes" -ne $((p0 + 2)) || "$fails" -ne $((f0 + 2)) || "$cases" -ne $((c0 + 2)) ]]; then rc=1; fi
|
|
83
|
+
passes="$p0"; fails="$f0"; cases="$c0"
|
|
84
|
+
return "$rc"
|
|
85
|
+
}
|
|
86
|
+
selftest_instrument || { printf '[FATAL] instrument self-test: pass, fail and check did not each move their counters as expected\n' >&2; exit 1; }
|
|
87
|
+
|
|
88
|
+
# --- preconditions: a missing scanner is RED, a missing python3 is a visible SKIP ---
|
|
89
|
+
if ! command -v python3 >/dev/null 2>&1; then
|
|
90
|
+
printf 'SKIP scan suite: python3 not found (the scan needs python3; nothing was asserted)\n'
|
|
91
|
+
exit 0
|
|
92
|
+
fi
|
|
93
|
+
if [[ ! -f "$SCAN" ]]; then
|
|
94
|
+
printf '[FATAL] scanner missing at %s\n' "$SCAN" >&2
|
|
95
|
+
exit 1
|
|
96
|
+
fi
|
|
97
|
+
if [[ ! -d "$FIX" ]]; then
|
|
98
|
+
printf '[FATAL] fixture directory missing at %s\n' "$FIX" >&2
|
|
99
|
+
exit 1
|
|
100
|
+
fi
|
|
101
|
+
|
|
102
|
+
# --- helpers ---
|
|
103
|
+
T=$'\t'
|
|
104
|
+
SCAN_CWD="$FIX"
|
|
105
|
+
RC=0
|
|
106
|
+
run_scan() { # run_scan <args...> -> RC, $TMP/out, $TMP/err ; the scanner runs from SCAN_CWD
|
|
107
|
+
assert_fixture_dir "$TMP"
|
|
108
|
+
( cd "$SCAN_CWD" && timeout 60 python3 -I "$SCAN" "$@" ) >"$TMP/out" 2>"$TMP/err"
|
|
109
|
+
RC=$?
|
|
110
|
+
}
|
|
111
|
+
ncls() { awk -F'\t' -v c="$1" '$1==c{n++} END{print n+0}' "$TMP/out"; }
|
|
112
|
+
nall() { awk -F'\t' 'NF>=4{n++} END{print n+0}' "$TMP/out"; }
|
|
113
|
+
has_out() { grep -cE -- "$1" "$TMP/out" >/dev/null; }
|
|
114
|
+
has_err() { grep -cE -- "$1" "$TMP/err" >/dev/null; }
|
|
115
|
+
BL="$TMP/bl.txt"
|
|
116
|
+
bl_new() { assert_fixture_dir "$TMP"; printf '# test baseline\n' > "$BL"; }
|
|
117
|
+
bl_row() { assert_fixture_dir "$TMP"; printf '%s\t%s\t%s\n' "$1" "$2" "$3" >> "$BL"; }
|
|
118
|
+
SUMMARY_RE='^ancestor-signal scan: [0-9]+ files, [0-9]+ findings, [0-9]+ baselined, [0-9]+ new, [0-9]+ stale, [0-9]+ unbounded, [0-9]+ skipped$'
|
|
119
|
+
|
|
120
|
+
W_UNB="top=\$p; p=\$(awk '{print \$4}' \"/proc/\$p/stat\")"
|
|
121
|
+
W_BND="p=\$(awk '{print \$4}' \"/proc/\$p/stat\" 2>/dev/null)"
|
|
122
|
+
P_SITE='[ -f "$FX/x" ] && kill -9 "$PPID"'
|
|
123
|
+
P_TWO1='kill -9 "$PPID"'
|
|
124
|
+
|
|
125
|
+
# list_of <fixture-file>: the findings of one data file, every class, one line each
|
|
126
|
+
list_of() { run_scan --list "$1"; }
|
|
127
|
+
|
|
128
|
+
# ============================================================================================
|
|
129
|
+
# B. Detector classes on fixtures (list mode)
|
|
130
|
+
# ============================================================================================
|
|
131
|
+
list_of walker-bounded.txt
|
|
132
|
+
check "B1 bounded walker: one W, bounded=yes (S5 shape)" has_out "^W${T}yes${T}walker-bounded.txt${T}"
|
|
133
|
+
check "B1b bounded walker: exactly one finding and rc 0" test "$(nall)" -eq 1 -a "$RC" -eq 0
|
|
134
|
+
|
|
135
|
+
list_of walker-unbounded.txt
|
|
136
|
+
check "B2 unbounded walker: one W, bounded=no" has_out "^W${T}no${T}walker-unbounded.txt${T}"
|
|
137
|
+
|
|
138
|
+
list_of walker-ps-cursor.txt
|
|
139
|
+
check "B2b a cursor written with ps -o ppid= is a W" has_out "^W${T}no${T}walker-ps-cursor.txt${T}"
|
|
140
|
+
list_of walker-ppid-field-cursor.txt
|
|
141
|
+
check "B2c a cursor reading the PPid status field is a W" has_out "^W${T}no${T}walker-ppid-field-cursor.txt${T}"
|
|
142
|
+
|
|
143
|
+
list_of walker-comment-bound.txt
|
|
144
|
+
check "B3 a bound token only in comments reads bounded=no" has_out "^W${T}no${T}walker-comment-bound.txt${T}"
|
|
145
|
+
|
|
146
|
+
list_of walker-trailing-comment-bound.txt
|
|
147
|
+
check "B3b a bound token only in a trailing comment reads bounded=no" has_out "^W${T}no${T}walker-trailing-comment-bound.txt${T}"
|
|
148
|
+
|
|
149
|
+
list_of walker-echo-bound.txt
|
|
150
|
+
check "B4 a bound token only in echo and printf reads bounded=no" has_out "^W${T}no${T}walker-echo-bound.txt${T}"
|
|
151
|
+
|
|
152
|
+
for form in neq dbl-eq sgl-eq ne eq lt loop-cond; do
|
|
153
|
+
list_of "bound-$form.txt"
|
|
154
|
+
check "B5 bound form $form reads bounded=yes" has_out "^W${T}yes${T}bound-$form.txt${T}"
|
|
155
|
+
done
|
|
156
|
+
for form in n z regex-only; do
|
|
157
|
+
list_of "bound-$form.txt"
|
|
158
|
+
check "B5b a presence, emptiness or numeric-validation test ($form) is not a comparison: bounded=no" has_out "^W${T}no${T}bound-$form.txt${T}"
|
|
159
|
+
done
|
|
160
|
+
list_of bound-no-exit.txt
|
|
161
|
+
check "B6 a comparison with no exit/break/return reads bounded=no" has_out "^W${T}no${T}bound-no-exit.txt${T}"
|
|
162
|
+
list_of bound-no-comparator.txt
|
|
163
|
+
check "B7 the token without a comparison reads bounded=no" has_out "^W${T}no${T}bound-no-comparator.txt${T}"
|
|
164
|
+
|
|
165
|
+
# window edges: one fixture per edge
|
|
166
|
+
list_of edge-bound-above-15.txt
|
|
167
|
+
check "B8 bound token 15 lines above the cursor: bounded=yes" has_out "^W${T}yes${T}edge-bound-above-15.txt${T}"
|
|
168
|
+
list_of edge-bound-above-16.txt
|
|
169
|
+
check "B8 bound token 16 lines above the cursor: bounded=no" has_out "^W${T}no${T}edge-bound-above-16.txt${T}"
|
|
170
|
+
list_of edge-bound-below-3.txt
|
|
171
|
+
check "B8 bound token 3 lines below the cursor: bounded=yes" has_out "^W${T}yes${T}edge-bound-below-3.txt${T}"
|
|
172
|
+
list_of edge-bound-below-4.txt
|
|
173
|
+
check "B8 bound token 4 lines below the cursor: bounded=no" has_out "^W${T}no${T}edge-bound-below-4.txt${T}"
|
|
174
|
+
list_of edge-kill-below-40.txt
|
|
175
|
+
check "B9 kill 40 lines below the cursor is a W" test "$(ncls W)" -eq 1
|
|
176
|
+
list_of edge-kill-below-41.txt
|
|
177
|
+
check "B9 kill 41 lines below the cursor is no finding" test "$(nall)" -eq 0
|
|
178
|
+
list_of edge-kill-above-40.txt
|
|
179
|
+
check "B9 kill 40 lines above the cursor is a W" test "$(ncls W)" -eq 1
|
|
180
|
+
list_of edge-kill-above-41.txt
|
|
181
|
+
check "B9 kill 41 lines above the cursor is no finding" test "$(nall)" -eq 0
|
|
182
|
+
list_of edge-derived-20.txt
|
|
183
|
+
check "B10 parent variable assigned 20 lines before the kill is a P" test "$(ncls P)" -eq 1
|
|
184
|
+
list_of edge-derived-21.txt
|
|
185
|
+
check "B10 parent variable assigned 21 lines before the kill is no finding" test "$(nall)" -eq 0
|
|
186
|
+
|
|
187
|
+
# classes
|
|
188
|
+
list_of parent-direct.txt
|
|
189
|
+
check "B11 direct parent signals: three P" test "$(ncls P)" -eq 3 -a "$(nall)" -eq 3
|
|
190
|
+
list_of parent-derived.txt
|
|
191
|
+
check "B12 derived parent signal: one P, on the kill line" test "$(ncls P)" -eq 1 -a "$(nall)" -eq 1
|
|
192
|
+
check "B12b derived parent signal reports the kill line text" has_out "^P${T}-${T}parent-derived.txt${T}kill -9 \"\\\$shim\" 2>/dev/null\$"
|
|
193
|
+
list_of group-all.txt
|
|
194
|
+
check "B13 all-process and own-group signals: five G" test "$(ncls G)" -eq 5 -a "$(nall)" -eq 5
|
|
195
|
+
list_of listed-targeted-and-pattern.txt
|
|
196
|
+
check "B14 targeted group and name-pattern signals: six L, nothing else" test "$(ncls L)" -eq 6 -a "$(nall)" -eq 6
|
|
197
|
+
|
|
198
|
+
# must-PASS inputs, one fixture each so one mutant cannot hide behind another
|
|
199
|
+
for f in pass-comment pass-quoted pass-kill0 pass-kill-l pass-plain-pid; do
|
|
200
|
+
list_of "$f.txt"
|
|
201
|
+
check "B15 must-pass $f: no finding" test "$(nall)" -eq 0 -a "$RC" -eq 0
|
|
202
|
+
done
|
|
203
|
+
|
|
204
|
+
# ============================================================================================
|
|
205
|
+
# C. Baseline semantics (gated runs on explicit PATHs)
|
|
206
|
+
# ============================================================================================
|
|
207
|
+
bl_new
|
|
208
|
+
run_scan --baseline "$BL" walker-bounded.txt
|
|
209
|
+
check "C1 a W not in the baseline is NEW: rc 1" test "$RC" -eq 1
|
|
210
|
+
check "C1b the NEW line names the file and the class W" has_out "^NEW W walker-bounded.txt:[0-9]+: "
|
|
211
|
+
check "C1c a red verdict ends with the remedy footer" has_out "^ancestor-signal scan: remedy:"
|
|
212
|
+
check "C1d a red verdict never prints CLEAN" test "$(has_out '^ancestor-signal scan: CLEAN$' && echo y || echo n)" = n
|
|
213
|
+
|
|
214
|
+
bl_new; bl_row walker-bounded.txt W "$W_BND"
|
|
215
|
+
run_scan --baseline "$BL" walker-bounded.txt
|
|
216
|
+
check "C2 a baselined bounded W is clean: rc 0 and the CLEAN literal" test "$RC" -eq 0 -a "$(has_out '^ancestor-signal scan: CLEAN$' && echo y || echo n)" = y
|
|
217
|
+
check "C2b the summary line has the documented shape and counts" has_out "^ancestor-signal scan: 1 files, 1 findings, 1 baselined, 0 new, 0 stale, 0 unbounded, 0 skipped\$"
|
|
218
|
+
check "C2c the summary line matches the full format" has_out "$SUMMARY_RE"
|
|
219
|
+
check "C2d a clean verdict carries no remedy footer" test "$(has_out '^ancestor-signal scan: remedy:' && echo y || echo n)" = n
|
|
220
|
+
|
|
221
|
+
bl_new; bl_row walker-unbounded.txt W "$W_UNB"
|
|
222
|
+
run_scan --baseline "$BL" walker-unbounded.txt
|
|
223
|
+
check "C3 an unbounded W cannot be baselined: rc 1" test "$RC" -eq 1
|
|
224
|
+
check "C3b the UNBOUNDED line names the file" has_out "^UNBOUNDED W walker-unbounded.txt:[0-9]+: "
|
|
225
|
+
check "C3c the summary counts one unbounded and one baselined" has_out ", 1 baselined, 0 new, 0 stale, 1 unbounded, "
|
|
226
|
+
|
|
227
|
+
bl_new; bl_row two-sites.txt P "$P_TWO1"
|
|
228
|
+
run_scan --baseline "$BL" two-sites.txt
|
|
229
|
+
check "C4 two sites, the first baselined: rc 1" test "$RC" -eq 1
|
|
230
|
+
check "C4b the SECOND site is the one named NEW" has_out "^NEW P two-sites.txt:4: "
|
|
231
|
+
check "C4c the first site is not reported" test "$(has_out '^NEW P two-sites.txt:2: ' && echo y || echo n)" = n
|
|
232
|
+
|
|
233
|
+
bl_new
|
|
234
|
+
run_scan --baseline "$BL" site-base.txt
|
|
235
|
+
check "C5 deleting a baseline row of a live site is NEW: rc 1" test "$RC" -eq 1 -a "$(has_out '^NEW P site-base.txt:[0-9]+: ' && echo y || echo n)" = y
|
|
236
|
+
|
|
237
|
+
bl_new; bl_row site-base.txt P "$P_SITE"; bl_row site-base.txt P 'kill -9 "$GONE"'
|
|
238
|
+
run_scan --baseline "$BL" site-base.txt
|
|
239
|
+
check "C6 a baseline row with no live line is STALE: rc 1" test "$RC" -eq 1 -a "$(has_out '^STALE P site-base.txt: ' && echo y || echo n)" = y
|
|
240
|
+
check "C6b the summary counts one stale" has_out ", 1 baselined, 0 new, 1 stale, 0 unbounded, "
|
|
241
|
+
|
|
242
|
+
bl_new; bl_row dup-parent.txt P "$P_SITE"
|
|
243
|
+
run_scan --baseline "$BL" dup-parent.txt
|
|
244
|
+
check "C7 two identical lines against one row: one NEW (multiset)" test "$RC" -eq 1 -a "$(has_out ', 1 baselined, 1 new, 0 stale, ' && echo y || echo n)" = y
|
|
245
|
+
bl_new; bl_row dup-parent.txt P "$P_SITE"; bl_row dup-parent.txt P "$P_SITE"
|
|
246
|
+
run_scan --baseline "$BL" dup-parent.txt
|
|
247
|
+
check "C7b two identical lines against two rows: clean" test "$RC" -eq 0
|
|
248
|
+
bl_new; bl_row dup-parent.txt P "$P_SITE"; bl_row dup-parent.txt P "$P_SITE"; bl_row dup-parent.txt P "$P_SITE"
|
|
249
|
+
run_scan --baseline "$BL" dup-parent.txt
|
|
250
|
+
check "C7c two identical lines against three rows: one STALE" test "$RC" -eq 1 -a "$(has_out ', 2 baselined, 0 new, 1 stale, ' && echo y || echo n)" = y
|
|
251
|
+
|
|
252
|
+
bl_new; bl_row site-shifted.txt P "$P_SITE"
|
|
253
|
+
run_scan --baseline "$BL" site-shifted.txt
|
|
254
|
+
check "C8 a baselined line shifted by blank lines stays clean (content-keyed)" test "$RC" -eq 0
|
|
255
|
+
bl_new; bl_row site-reindented.txt P "$P_SITE"
|
|
256
|
+
run_scan --baseline "$BL" site-reindented.txt
|
|
257
|
+
check "C8b a baselined line re-indented and re-spaced stays clean (whitespace collapsed)" test "$RC" -eq 0
|
|
258
|
+
assert_fixture_dir "$TMP"; mkdir -p "$TMP/dp"; cp "$FIX/site-base.txt" "$TMP/dp/renamed.txt"
|
|
259
|
+
bl_new; bl_row site-base.txt P "$P_SITE"
|
|
260
|
+
SCAN_CWD="$TMP/dp" run_scan --baseline "$BL" renamed.txt
|
|
261
|
+
check "C8c the same content under a different path reads NEW (path-keyed)" test "$RC" -eq 1 -a "$(has_out '^NEW P renamed.txt:[0-9]+: ' && echo y || echo n)" = y
|
|
262
|
+
check "C8d only baseline rows of the scanned paths are judged: no STALE for the other path" has_out ", 0 baselined, 1 new, 0 stale, "
|
|
263
|
+
|
|
264
|
+
bl_new
|
|
265
|
+
run_scan --baseline "$BL" listed-targeted-and-pattern.txt
|
|
266
|
+
check "C9 class L is never gated: rc 0 and CLEAN against an empty baseline" test "$RC" -eq 0 -a "$(has_out '^ancestor-signal scan: CLEAN$' && echo y || echo n)" = y
|
|
267
|
+
|
|
268
|
+
run_scan walker-bounded.txt
|
|
269
|
+
check "C10 without a baseline the scan is list-only: rc 0 and the notice" test "$RC" -eq 0 -a "$(has_out 'no baseline: listing only' && echo y || echo n)" = y
|
|
270
|
+
check "C10b list-only mode never prints CLEAN" test "$(has_out '^ancestor-signal scan: CLEAN$' && echo y || echo n)" = n
|
|
271
|
+
|
|
272
|
+
# --write-baseline: refused with PATHs, a round trip over a tracked population, and the admissibility refusals
|
|
273
|
+
run_scan --write-baseline "$TMP/wb0.txt" parent-direct.txt
|
|
274
|
+
check "C11e --write-baseline with a PATH is refused: rc 2, nothing written" test "$RC" -eq 2 -a ! -e "$TMP/wb0.txt"
|
|
275
|
+
WBR="$TMP/wbrepo"
|
|
276
|
+
assert_fixture_dir "$WBR"
|
|
277
|
+
mkdir -p "$WBR"
|
|
278
|
+
cp "$FIX/parent-direct.txt" "$WBR/a.test.sh"
|
|
279
|
+
cp "$FIX/group-all.txt" "$WBR/b.test.sh"
|
|
280
|
+
cp "$FIX/walker-bounded.txt" "$WBR/c.test.sh"
|
|
281
|
+
( git_fixture_env "$WBR" && git -C "$WBR" init -q && git -C "$WBR" add -A && git -C "$WBR" commit -q -m seed ) >/dev/null 2>&1
|
|
282
|
+
run_scan --root "$WBR" --write-baseline "$TMP/wb.txt"
|
|
283
|
+
check "C11 --write-baseline succeeds: rc 0" test "$RC" -eq 0
|
|
284
|
+
check "C11b it wrote nine rows (3 P, 5 G, 1 W) beside its comment header" test "$(grep -cEv '^(#|$)' "$TMP/wb.txt")" -eq 9
|
|
285
|
+
check "C11c the header states that bounded=yes is lexical" test "$(grep -ci 'lexical' "$TMP/wb.txt")" -ge 1
|
|
286
|
+
run_scan --root "$WBR" --baseline "$TMP/wb.txt"
|
|
287
|
+
check "C11d the written baseline reads clean against the same files" test "$RC" -eq 0 -a "$(has_out '^ancestor-signal scan: CLEAN$' && echo y || echo n)" = y
|
|
288
|
+
WBR2="$TMP/wbrepo2"
|
|
289
|
+
assert_fixture_dir "$WBR2"
|
|
290
|
+
mkdir -p "$WBR2"
|
|
291
|
+
cp "$FIX/walker-unbounded.txt" "$WBR2/u.test.sh"
|
|
292
|
+
( git_fixture_env "$WBR2" && git -C "$WBR2" init -q && git -C "$WBR2" add -A && git -C "$WBR2" commit -q -m seed ) >/dev/null 2>&1
|
|
293
|
+
run_scan --root "$WBR2" --write-baseline "$TMP/wb2.txt"
|
|
294
|
+
check "C12 --write-baseline refuses an unbounded W: rc 1, no file" test "$RC" -eq 1 -a ! -e "$TMP/wb2.txt"
|
|
295
|
+
check "C12b the refusal says why (UNBOUNDED)" has_out "UNBOUNDED"
|
|
296
|
+
WBR3="$TMP/wbrepo3"
|
|
297
|
+
assert_fixture_dir "$WBR3"
|
|
298
|
+
mkdir -p "$WBR3"
|
|
299
|
+
cp "$FIX/parent-direct.txt" "$WBR3/a.test.sh"
|
|
300
|
+
ln -s a.test.sh "$WBR3/l.test.sh"
|
|
301
|
+
( git_fixture_env "$WBR3" && git -C "$WBR3" init -q && git -C "$WBR3" add -A && git -C "$WBR3" commit -q -m seed ) >/dev/null 2>&1
|
|
302
|
+
run_scan --root "$WBR3" --write-baseline "$TMP/wb3.txt"
|
|
303
|
+
check "C11f --write-baseline with a skipped member is refused: rc 3, no file" test "$RC" -eq 3 -a ! -e "$TMP/wb3.txt"
|
|
304
|
+
|
|
305
|
+
# --list scoped to one path names only that path
|
|
306
|
+
run_scan --list parent-direct.txt group-all.txt
|
|
307
|
+
check "C13 --list PATH scopes the listing to the given paths" test "$(awk -F'\t' 'NF>=4 && $3!="parent-direct.txt" && $3!="group-all.txt"{n++} END{print n+0}' "$TMP/out")" -eq 0 -a "$(nall)" -eq 8
|
|
308
|
+
|
|
309
|
+
# ============================================================================================
|
|
310
|
+
# D. UNRESOLVED (rc 3) is never a clean report
|
|
311
|
+
# ============================================================================================
|
|
312
|
+
R="$TMP/repo"
|
|
313
|
+
assert_fixture_dir "$R"
|
|
314
|
+
mkdir -p "$R/sub/deep"
|
|
315
|
+
cp "$FIX/walker-unbounded.txt" "$R/a.test.sh"
|
|
316
|
+
cp "$FIX/parent-direct.txt" "$R/sub/test-x.sh"
|
|
317
|
+
cp "$FIX/pass-comment.txt" "$R/sub/deep/b.test.sh"
|
|
318
|
+
cp "$FIX/walker-unbounded.txt" "$R/notes.txt"
|
|
319
|
+
ln -s a.test.sh "$R/link.test.sh"
|
|
320
|
+
BADNAME=$'bad\xff.test.sh'
|
|
321
|
+
NONUTF=1
|
|
322
|
+
if cp "$FIX/pass-plain-pid.txt" "$R/$BADNAME" 2>/dev/null; then :; else NONUTF=0; fi
|
|
323
|
+
|
|
324
|
+
E="$TMP/empty"
|
|
325
|
+
assert_fixture_dir "$E"
|
|
326
|
+
mkdir -p "$E"
|
|
327
|
+
cp "$FIX/walker-unbounded.txt" "$E/notes.txt"
|
|
328
|
+
( git_fixture_env "$E" && git -C "$E" init -q && git -C "$E" add -A && git -C "$E" commit -q -m seed ) >/dev/null 2>&1
|
|
329
|
+
|
|
330
|
+
run_scan --root "$E"
|
|
331
|
+
check "D1 a repository with no matching suites: rc 3 UNRESOLVED" test "$RC" -eq 3 -a "$(has_err 'UNRESOLVED' && echo y || echo n)" = y
|
|
332
|
+
check "D1b UNRESOLVED prints no CLEAN" test "$(has_out '^ancestor-signal scan: CLEAN$' && echo y || echo n)" = n
|
|
333
|
+
N="$TMP/no-such-dir"
|
|
334
|
+
assert_fixture_dir "$N"
|
|
335
|
+
run_scan --root "$N" --baseline "$FIX/site-base.txt"
|
|
336
|
+
check "D2 a root git cannot enter (the listing fails): rc 3 UNRESOLVED" test "$RC" -eq 3 -a "$(has_err 'UNRESOLVED' && echo y || echo n)" = y
|
|
337
|
+
run_scan --root "$WBR3" --baseline "$TMP/wb.txt"
|
|
338
|
+
check "D8 a skipped (symlinked) member under a baseline gate: rc 3 UNRESOLVED naming the skip, never CLEAN" test "$RC" -eq 3 -a "$(has_err 'UNRESOLVED: 1 listed member.*skipped' && echo y || echo n)" = y -a "$(has_out '^ancestor-signal scan: CLEAN$' && echo y || echo n)" = n
|
|
339
|
+
run_scan --baseline "$TMP/does-not-exist.txt" site-base.txt
|
|
340
|
+
check "D3 an unreadable (missing) baseline: rc 3 UNRESOLVED" test "$RC" -eq 3 -a "$(has_err 'UNRESOLVED' && echo y || echo n)" = y
|
|
341
|
+
run_scan --baseline "$TMP" site-base.txt
|
|
342
|
+
check "D4 a baseline that is a directory: rc 3 UNRESOLVED" test "$RC" -eq 3 -a "$(has_err 'UNRESOLVED' && echo y || echo n)" = y
|
|
343
|
+
assert_fixture_dir "$TMP"
|
|
344
|
+
printf 'only-one-field\n' > "$TMP/bad-bl.txt"
|
|
345
|
+
run_scan --baseline "$TMP/bad-bl.txt" site-base.txt
|
|
346
|
+
check "D5 a malformed baseline row: rc 3 UNRESOLVED" test "$RC" -eq 3 -a "$(has_err 'UNRESOLVED' && echo y || echo n)" = y
|
|
347
|
+
run_scan --list no-such-file.txt
|
|
348
|
+
check "D6 an explicit PATH that does not exist: rc 3 UNRESOLVED" test "$RC" -eq 3 -a "$(has_err 'UNRESOLVED' && echo y || echo n)" = y
|
|
349
|
+
if [[ -w /dev/full ]]; then
|
|
350
|
+
( cd "$FIX" && timeout 60 python3 -I "$SCAN" --list site-base.txt ) >/dev/full 2>"$TMP/err"
|
|
351
|
+
RC=$?
|
|
352
|
+
check "D7 an exception inside main (stdout is full): rc 3, never a traceback-only rc 1" test "$RC" -eq 3 -a "$(has_err 'UNRESOLVED' && echo y || echo n)" = y
|
|
353
|
+
check "D7b the swallowed flush error is noted by class name; the UNRESOLVED line and rc 3 are unchanged" test "$RC" -eq 3 -a "$(has_err ': swallowed [A-Za-z]+ at flush-stdout$' && echo y || echo n)" = y -a "$(has_err '^ancestor-signal scan: UNRESOLVED: ' && echo y || echo n)" = y
|
|
354
|
+
else
|
|
355
|
+
skipped=$((skipped + 1)); printf 'SKIP D7: /dev/full is not writable here\n'
|
|
356
|
+
fi
|
|
357
|
+
|
|
358
|
+
# ============================================================================================
|
|
359
|
+
# E. Producer, environment and reading model (throwaway repository, hostile inputs)
|
|
360
|
+
# ============================================================================================
|
|
361
|
+
( git_fixture_env "$R" && git -C "$R" init -q && git -C "$R" add -A && git -C "$R" commit -q -m seed ) >/dev/null 2>&1
|
|
362
|
+
SCAN_CWD="$TMP"
|
|
363
|
+
run_scan --list --root "$R"
|
|
364
|
+
cp "$TMP/out" "$TMP/out.plain"
|
|
365
|
+
check "E1 the producer reaches *.test.sh anywhere (a W in a.test.sh)" has_out "^W${T}no${T}a.test.sh${T}"
|
|
366
|
+
check "E1b the producer reaches test-*.sh in a subdirectory (P in sub/test-x.sh)" test "$(awk -F'\t' '$1=="P" && $3=="sub/test-x.sh"{n++} END{print n+0}' "$TMP/out")" -eq 3
|
|
367
|
+
check "E2 a tracked .txt copy of a walker is not scanned" test "$(has_out "${T}notes.txt${T}" && echo y || echo n)" = n
|
|
368
|
+
if [[ "$NONUTF" -eq 1 ]]; then EXPECT_FILES=4; else EXPECT_FILES=3; fi
|
|
369
|
+
check "E3 files read: the benign suites count, the symlink does not" has_out " ${EXPECT_FILES} files, "
|
|
370
|
+
check "E3b a symlinked member is counted skipped, not read" has_out " 1 skipped"
|
|
371
|
+
if [[ "$NONUTF" -eq 0 ]]; then
|
|
372
|
+
skipped=$((skipped + 1)); printf 'SKIP E4: this filesystem refused a non-UTF-8 file name\n'
|
|
373
|
+
else
|
|
374
|
+
check "E4 a non-UTF-8 path is in the population (not silently dropped)" has_out " ${EXPECT_FILES} files, "
|
|
375
|
+
fi
|
|
376
|
+
( cd "$TMP" && env GIT_DIR=/nonexistent/gitdir GIT_INDEX_FILE=/nonexistent/index GIT_WORK_TREE=/nonexistent timeout 60 python3 -I "$SCAN" --list --root "$R" ) >"$TMP/out" 2>"$TMP/err"
|
|
377
|
+
RC=$?
|
|
378
|
+
check "E5 bogus GIT_DIR/GIT_INDEX_FILE/GIT_WORK_TREE do not change the population" test "$RC" -eq 0 && cmp -s "$TMP/out" "$TMP/out.plain"
|
|
379
|
+
check "E5b the same listing byte for byte" cmp -s "$TMP/out" "$TMP/out.plain"
|
|
380
|
+
|
|
381
|
+
assert_fixture_dir "$TMP"
|
|
382
|
+
head -c 102400 /dev/zero | tr '\0' 'a' > "$TMP/big.txt"; printf '\n' >> "$TMP/big.txt"
|
|
383
|
+
SCAN_CWD="$TMP"
|
|
384
|
+
run_scan --list big.txt
|
|
385
|
+
check "E6 a 100 KB single line: no hang, no finding, rc 0" test "$RC" -eq 0 -a "$(nall)" -eq 0
|
|
386
|
+
check "E6b the overlong line is counted" has_out "overlong lines: 1"
|
|
387
|
+
{ head -c 102400 /dev/zero | tr '\0' 'a'; printf ' kill'; printf '\n'; } > "$TMP/big-kill.txt"
|
|
388
|
+
run_scan --list big-kill.txt
|
|
389
|
+
check "E7 an overlong line that carries a signal verb is still reported (G, fail closed)" test "$RC" -eq 0 -a "$(ncls G)" -eq 1
|
|
390
|
+
|
|
391
|
+
assert_fixture_dir "$TMP"
|
|
392
|
+
head -c 3000000 /dev/zero | tr '\0' 'a' > "$TMP/huge.txt"
|
|
393
|
+
run_scan --list huge.txt
|
|
394
|
+
check "E7b a file over 2 MB is skipped, not read" test "$RC" -eq 0 -a "$(nall)" -eq 0 -a "$(has_out ' 0 files, ' && echo y || echo n)" = y -a "$(has_out ' 1 skipped' && echo y || echo n)" = y
|
|
395
|
+
|
|
396
|
+
printf 'kill -9 "$PPID"\r\n' > "$TMP/crlf.txt"
|
|
397
|
+
run_scan --list crlf.txt
|
|
398
|
+
check "E8 a CRLF line is read without its carriage return" has_out "^P${T}-${T}crlf.txt${T}kill -9 \"\\\$PPID\"\$"
|
|
399
|
+
printf 'a\xe2\x80\xa8b\x0b\x0c\nkill -9 "$PPID"\n' > "$TMP/seps.txt"
|
|
400
|
+
bl_new
|
|
401
|
+
run_scan --baseline "$BL" seps.txt
|
|
402
|
+
check "E9 lines split on newline only (U+2028, VT, FF do not shift the line number)" has_out "^NEW P seps.txt:2: "
|
|
403
|
+
|
|
404
|
+
# ============================================================================================
|
|
405
|
+
# F. Live row: the whole tree, the committed baseline (the walk is the scanner's)
|
|
406
|
+
# ============================================================================================
|
|
407
|
+
SCAN_CWD="$REPO_ROOT"
|
|
408
|
+
T0="${EPOCHREALTIME:-0}"
|
|
409
|
+
run_scan --root "$REPO_ROOT" --baseline "$BASELINE"
|
|
410
|
+
T1="${EPOCHREALTIME:-0}"
|
|
411
|
+
cp "$TMP/out" "$TMP/out.live"
|
|
412
|
+
LIVE_RC="$RC"
|
|
413
|
+
LIVE_US=0
|
|
414
|
+
if [[ "$T0" != "0" ]]; then LIVE_US=$(( ${T1/./} - ${T0/./} )); fi
|
|
415
|
+
printf 'scan live run: %s ms (target under 5000, probe cap 15000)\n' "$((LIVE_US / 1000))"
|
|
416
|
+
check "F1 live scan with the committed baseline: rc 0" test "$LIVE_RC" -eq 0
|
|
417
|
+
check "F2 live scan: 0 new, 0 stale, 0 unbounded" has_out ", 0 new, 0 stale, 0 unbounded, "
|
|
418
|
+
check "F3 live scan prints the CLEAN literal the discoverability probe matches" has_out "^ancestor-signal scan: CLEAN\$"
|
|
419
|
+
LIVE_FILES="$(sed -n 's/^ancestor-signal scan: \([0-9][0-9]*\) files, .*/\1/p' "$TMP/out.live")"
|
|
420
|
+
check "F4 population floor: at least 600 files read" test "${LIVE_FILES:-0}" -ge 600
|
|
421
|
+
check "F5 root set covers .claude" has_out "^ancestor-signal scan: roots: (.* )?\.claude( |\$)"
|
|
422
|
+
for root in apps plugins scripts tests; do
|
|
423
|
+
check "F5 root set covers $root" has_out "^ancestor-signal scan: roots: (.* )?$root( |\$)"
|
|
424
|
+
done
|
|
425
|
+
check "F6 live run well inside the 15 s probe cap" test "$((LIVE_US / 1000))" -lt 15000
|
|
426
|
+
run_scan --list --root "$REPO_ROOT"
|
|
427
|
+
check "F7 the S5 helper is found as W bounded=yes" has_out "^W${T}yes${T}plugins/soleur/scripts/resolve-regenerable-conflicts\.test\.sh${T}"
|
|
428
|
+
check "F7b the roadmap-reconcile walker is found as W bounded=yes" has_out "^W${T}yes${T}plugins/soleur/test/roadmap-reconcile\.test\.sh${T}"
|
|
429
|
+
check "F7c no walker anywhere in the tree reads bounded=no" test "$(awk -F'\t' '$1=="W" && $2=="no"{n++} END{print n+0}' "$TMP/out")" -eq 0
|
|
430
|
+
check "F8 the listed-only class L is part of the listing" test "$(ncls L)" -ge 1
|
|
431
|
+
check "F9 this suite and the scanner are not findings of their own" test "$(awk -F'\t' '$3 ~ /scan-ancestor-signal-helpers/{n++} END{print n+0}' "$TMP/out")" -eq 0
|
|
432
|
+
BL_ROWS="$(grep -cEv '^(#|$)' "$BASELINE")"
|
|
433
|
+
check "F10 the committed baseline has rows and at least the two known walkers (F7 and F7b name them)" test "${BL_ROWS:-0}" -ge 1 -a "$(awk -F'\t' '$2=="W"{n++} END{print n+0}' "$BASELINE")" -ge 2
|
|
434
|
+
|
|
435
|
+
# Row 18: the original roadmap-reconcile walker must read unbounded, the bounded edit bounded
|
|
436
|
+
SCAN_CWD="$FIX"
|
|
437
|
+
list_of roadmap-walker-original.txt
|
|
438
|
+
check "G1 the original roadmap-reconcile walker reads bounded=no" has_out "^W${T}no${T}roadmap-walker-original.txt${T}"
|
|
439
|
+
list_of roadmap-walker-fixed.txt
|
|
440
|
+
check "G2 the bounded roadmap-reconcile walker reads bounded=yes" has_out "^W${T}yes${T}roadmap-walker-fixed.txt${T}"
|
|
441
|
+
|
|
442
|
+
# ============================================================================================
|
|
443
|
+
# H. Reading gaps closed after review (one fixture per shape)
|
|
444
|
+
# ============================================================================================
|
|
445
|
+
SCAN_CWD="$FIX"
|
|
446
|
+
list_of q-cursor.txt
|
|
447
|
+
check "H1 a double-quoted cursor substitution still reads W" has_out "^W${T}no${T}q-cursor.txt${T}"
|
|
448
|
+
list_of path-kill.txt
|
|
449
|
+
check "H2 kill invoked by absolute path is a P" has_out "^P${T}-${T}path-kill.txt${T}"
|
|
450
|
+
list_of prefix-env.txt
|
|
451
|
+
check "H3 kill behind env and an assignment prefix: two P" test "$(ncls P)" -eq 2
|
|
452
|
+
list_of prefix-timeout.txt
|
|
453
|
+
check "H4 kill behind timeout with an option is a P" has_out "^P${T}-${T}prefix-timeout.txt${T}"
|
|
454
|
+
list_of body-sh-c.txt
|
|
455
|
+
check "H5 a signal inside sh -c '...' is a P" has_out "^P${T}-${T}body-sh-c.txt${T}"
|
|
456
|
+
list_of body-trap.txt
|
|
457
|
+
check "H6 a signal inside trap '...' is a G" has_out "^G${T}-${T}body-trap.txt${T}"
|
|
458
|
+
list_of negated-derived.txt
|
|
459
|
+
check "H7 a negated derived parent variable (kill -9 -\$up) is a P" has_out "^P${T}-${T}negated-derived.txt${T}"
|
|
460
|
+
list_of ppid-upper.txt
|
|
461
|
+
check "H8 ps with the uppercase PPID header is a P" has_out "^P${T}-${T}ppid-upper.txt${T}"
|
|
462
|
+
list_of ppid-nested.txt
|
|
463
|
+
check "H10 a parent pid taken through a nested command substitution is a P" has_out "^P${T}-${T}ppid-nested.txt${T}"
|
|
464
|
+
awk 'BEGIN{for(i=0;i<60000;i++)print "p=$PPID"; for(i=0;i<60000;i++)print "kill $x"}' > "$TMP/stress.txt"
|
|
465
|
+
run_scan --list "$TMP/stress.txt"
|
|
466
|
+
check "H9 many parent assignments times many kills finish inside the 60 s cap (no quadratic stall)" test "$RC" -eq 0
|
|
467
|
+
|
|
468
|
+
# ============================================================================================
|
|
469
|
+
# F. Swallowed-exception note (PR2 of #10331): class name and a literal site label only, never raises
|
|
470
|
+
# ============================================================================================
|
|
471
|
+
assert_fixture_dir "$TMP"
|
|
472
|
+
python3 -I - "$SCAN" flush-stdout > "$TMP/note-probe.out" 2>&1 <<'PY' || true
|
|
473
|
+
import ast, importlib.util, io, os, sys
|
|
474
|
+
spec = importlib.util.spec_from_file_location("note_target", sys.argv[1])
|
|
475
|
+
mod = importlib.util.module_from_spec(spec)
|
|
476
|
+
spec.loader.exec_module(mod)
|
|
477
|
+
|
|
478
|
+
def say(ok, name):
|
|
479
|
+
print(("OK " if ok else "NOT-OK ") + name)
|
|
480
|
+
|
|
481
|
+
class Boom(OSError):
|
|
482
|
+
pass
|
|
483
|
+
|
|
484
|
+
def run_note(exc, stream):
|
|
485
|
+
real, sys.stderr = sys.stderr, stream
|
|
486
|
+
try:
|
|
487
|
+
mod._note(exc, "probe")
|
|
488
|
+
finally:
|
|
489
|
+
sys.stderr = real
|
|
490
|
+
|
|
491
|
+
buf = io.StringIO()
|
|
492
|
+
run_note(Boom("CANARY-7f3a"), buf)
|
|
493
|
+
line = buf.getvalue()
|
|
494
|
+
say(line.endswith(" swallowed Boom at probe\n") and line.count("\n") == 1, "line-shape")
|
|
495
|
+
say("CANARY" not in line, "canary-absent")
|
|
496
|
+
|
|
497
|
+
class Failing:
|
|
498
|
+
def __init__(self, exc):
|
|
499
|
+
self.exc = exc
|
|
500
|
+
def write(self, s):
|
|
501
|
+
raise self.exc
|
|
502
|
+
def flush(self):
|
|
503
|
+
raise self.exc
|
|
504
|
+
|
|
505
|
+
for name, exc in (("oserror-stderr", OSError("w")), ("valueerror-stderr", ValueError("w"))):
|
|
506
|
+
try:
|
|
507
|
+
run_note(Boom("x"), Failing(exc))
|
|
508
|
+
say(True, name)
|
|
509
|
+
except BaseException:
|
|
510
|
+
say(False, name)
|
|
511
|
+
|
|
512
|
+
try:
|
|
513
|
+
run_note(Boom("x"), None)
|
|
514
|
+
say(True, "none-stderr")
|
|
515
|
+
except BaseException:
|
|
516
|
+
say(False, "none-stderr")
|
|
517
|
+
|
|
518
|
+
closed = open(os.devnull, "w")
|
|
519
|
+
closed.close()
|
|
520
|
+
try:
|
|
521
|
+
run_note(Boom("x"), closed)
|
|
522
|
+
say(True, "closed-stderr")
|
|
523
|
+
except BaseException:
|
|
524
|
+
say(False, "closed-stderr")
|
|
525
|
+
|
|
526
|
+
def census(src):
|
|
527
|
+
calls, bad, labels = 0, [], set()
|
|
528
|
+
for node in ast.walk(ast.parse(src)):
|
|
529
|
+
if isinstance(node, ast.Call) and isinstance(node.func, ast.Name) and node.func.id == "_note":
|
|
530
|
+
calls += 1
|
|
531
|
+
lit = (len(node.args) == 2 and not node.keywords
|
|
532
|
+
and isinstance(node.args[0], ast.Name)
|
|
533
|
+
and isinstance(node.args[1], ast.Constant) and isinstance(node.args[1].value, str))
|
|
534
|
+
if lit:
|
|
535
|
+
labels.add(node.args[1].value)
|
|
536
|
+
else:
|
|
537
|
+
bad.append(node.lineno)
|
|
538
|
+
return calls, bad, labels
|
|
539
|
+
|
|
540
|
+
calls, bad, labels = census(open(sys.argv[1], encoding="utf-8").read())
|
|
541
|
+
say(calls >= 1 and not bad, "census-literal-labels")
|
|
542
|
+
say(labels == set(sys.argv[2].split(",")), "census-label-set")
|
|
543
|
+
say(census("_note(exc, site='x')")[1] != [], "census-rejects-keyword")
|
|
544
|
+
say(census("_note(str(exc), 'a')")[1] != [], "census-rejects-computed")
|
|
545
|
+
say(census("_note(exc, 'a')")[:2] == (1, []), "census-accepts-literal")
|
|
546
|
+
PY
|
|
547
|
+
for tok in line-shape canary-absent oserror-stderr valueerror-stderr none-stderr closed-stderr census-literal-labels census-label-set census-rejects-keyword census-rejects-computed census-accepts-literal; do
|
|
548
|
+
check "F-$tok the _note probe reports $tok" grep -qxF "OK $tok" "$TMP/note-probe.out"
|
|
549
|
+
done
|
|
550
|
+
|
|
551
|
+
# ============================================================================================
|
|
552
|
+
# G. Uncaught-exception exit contract (slice 1 of #10331): main() narrowed from BaseException to (Exception, KeyboardInterrupt);
|
|
553
|
+
# an uncaught exception of either class must still read as rc 3 UNRESOLVED, never rc 1 "findings".
|
|
554
|
+
# main() ends in os._exit(3), so each probe runs in its own subprocess. kill -INT is not used (non-interactive
|
|
555
|
+
# background jobs ignore SIGINT); the exception is raised from the replaced run() instead.
|
|
556
|
+
# ============================================================================================
|
|
557
|
+
assert_fixture_dir "$TMP"
|
|
558
|
+
for exc_name in KeyboardInterrupt RuntimeError; do
|
|
559
|
+
g_rc=0
|
|
560
|
+
python3 -I - "$SCAN" "$exc_name" > "$TMP/uncaught-$exc_name.out" 2>&1 <<'PY' || g_rc=$?
|
|
561
|
+
import importlib.util, sys
|
|
562
|
+
spec = importlib.util.spec_from_file_location("main_target", sys.argv[1])
|
|
563
|
+
mod = importlib.util.module_from_spec(spec)
|
|
564
|
+
spec.loader.exec_module(mod)
|
|
565
|
+
exc_name = sys.argv[2]
|
|
566
|
+
|
|
567
|
+
def boom(argv):
|
|
568
|
+
raise KeyboardInterrupt() if exc_name == "KeyboardInterrupt" else RuntimeError("synthetic")
|
|
569
|
+
|
|
570
|
+
mod.run = boom
|
|
571
|
+
mod.main()
|
|
572
|
+
sys.exit(0)
|
|
573
|
+
PY
|
|
574
|
+
check "G-$exc_name an uncaught $exc_name from run() exits 3 (UNRESOLVED), not 1 (findings)" test "$g_rc" -eq 3
|
|
575
|
+
check "G-$exc_name the UNRESOLVED line names $exc_name" grep -qF "UNRESOLVED: uncaught $exc_name" "$TMP/uncaught-$exc_name.out"
|
|
576
|
+
done
|
|
577
|
+
|
|
578
|
+
# GB2. The narrowing is deliberate: a BaseException subclass outside (Exception, KeyboardInterrupt) is not caught and exits 1
|
|
579
|
+
# with a traceback (the script docstring records it as unreachable from this synchronous scan). Pinned so a revert to
|
|
580
|
+
# `except BaseException` (rc 3) is a visible decision rather than a silent one.
|
|
581
|
+
g2_rc=0
|
|
582
|
+
python3 -I - "$SCAN" > "$TMP/uncaught-base.out" 2>&1 <<'PY' || g2_rc=$?
|
|
583
|
+
import importlib.util, sys
|
|
584
|
+
spec = importlib.util.spec_from_file_location("main_target", sys.argv[1])
|
|
585
|
+
mod = importlib.util.module_from_spec(spec)
|
|
586
|
+
spec.loader.exec_module(mod)
|
|
587
|
+
|
|
588
|
+
class OutsideBase(BaseException):
|
|
589
|
+
pass
|
|
590
|
+
|
|
591
|
+
def boom(argv):
|
|
592
|
+
raise OutsideBase("synthetic")
|
|
593
|
+
|
|
594
|
+
mod.run = boom
|
|
595
|
+
mod.main()
|
|
596
|
+
sys.exit(0)
|
|
597
|
+
PY
|
|
598
|
+
check "GB2 a BaseException subclass outside the narrowed tuple exits 1, not 3 (deliberate narrowing)" test "$g2_rc" -eq 1
|
|
599
|
+
check "GB2 that exit carries a traceback and no UNRESOLVED line" bash -c '! grep -qF "UNRESOLVED" "$1" && grep -qF "OutsideBase" "$1"' _ "$TMP/uncaught-base.out"
|
|
600
|
+
|
|
601
|
+
# GB3. The reconfigure capability probe is ONE suppress around both calls: a stdout without reconfigure() (an io.StringIO)
|
|
602
|
+
# skips the stderr call too, and main() still returns run()'s rc.
|
|
603
|
+
assert_fixture_dir "$TMP"
|
|
604
|
+
python3 -I - "$SCAN" > "$TMP/reconfigure-probe.out" 2>&1 <<'PY' || true
|
|
605
|
+
import importlib.util, io, sys
|
|
606
|
+
spec = importlib.util.spec_from_file_location("main_target", sys.argv[1])
|
|
607
|
+
mod = importlib.util.module_from_spec(spec)
|
|
608
|
+
spec.loader.exec_module(mod)
|
|
609
|
+
real_out = sys.stdout
|
|
610
|
+
|
|
611
|
+
class Err(io.StringIO):
|
|
612
|
+
calls = 0
|
|
613
|
+
def reconfigure(self, **kw):
|
|
614
|
+
Err.calls += 1
|
|
615
|
+
|
|
616
|
+
mod.run = lambda argv: 0
|
|
617
|
+
sys.stdout, sys.stderr = io.StringIO(), Err()
|
|
618
|
+
try:
|
|
619
|
+
rc = mod.main()
|
|
620
|
+
finally:
|
|
621
|
+
sys.stdout = real_out
|
|
622
|
+
print("RC=%s CALLS=%s" % (rc, Err.calls))
|
|
623
|
+
PY
|
|
624
|
+
check "GB3 a stdout without reconfigure() does not stop main() returning run()'s rc, and skips the stderr call" grep -qxF "RC=0 CALLS=0" "$TMP/reconfigure-probe.out"
|
|
625
|
+
|
|
626
|
+
# GB3 positive control: with reconfigure() present on both streams, main() calls both and asks for surrogateescape.
|
|
627
|
+
python3 -I - "$SCAN" > "$TMP/reconfigure-both.out" 2>&1 <<'PY' || true
|
|
628
|
+
import importlib.util, io, sys
|
|
629
|
+
spec = importlib.util.spec_from_file_location("main_target", sys.argv[1])
|
|
630
|
+
mod = importlib.util.module_from_spec(spec)
|
|
631
|
+
spec.loader.exec_module(mod)
|
|
632
|
+
real_out = sys.stdout
|
|
633
|
+
|
|
634
|
+
class Stream(io.StringIO):
|
|
635
|
+
def __init__(self):
|
|
636
|
+
super().__init__()
|
|
637
|
+
self.seen = []
|
|
638
|
+
def reconfigure(self, **kw):
|
|
639
|
+
self.seen.append(kw.get("errors"))
|
|
640
|
+
|
|
641
|
+
mod.run = lambda argv: 0
|
|
642
|
+
out, err = Stream(), Stream()
|
|
643
|
+
sys.stdout, sys.stderr = out, err
|
|
644
|
+
try:
|
|
645
|
+
mod.main()
|
|
646
|
+
finally:
|
|
647
|
+
sys.stdout = real_out
|
|
648
|
+
print("OUT=%s ERR=%s" % (out.seen, err.seen))
|
|
649
|
+
PY
|
|
650
|
+
check "GB3 control: stdout is reconfigured with errors=surrogateescape" grep -qF "OUT=['surrogateescape']" "$TMP/reconfigure-both.out"
|
|
651
|
+
check "GB3 control: stderr is reconfigured with errors=surrogateescape" grep -qF "ERR=['surrogateescape']" "$TMP/reconfigure-both.out"
|
|
652
|
+
|
|
653
|
+
# ============================================================================================
|
|
654
|
+
# Anti-vacuity and accounting (direct printf + exit, never through fail())
|
|
655
|
+
# ============================================================================================
|
|
656
|
+
if [[ "$cases" -lt 145 ]]; then
|
|
657
|
+
printf '[FATAL] anti-vacuity floor: only %s cases ran, floor is 145\n' "$cases" >&2
|
|
658
|
+
exit 1
|
|
659
|
+
fi
|
|
660
|
+
if [[ $((passes + fails)) -ne "$cases" ]]; then
|
|
661
|
+
printf '[FATAL] accounting: %s passed + %s failed != %s cases (verdicts were discarded)\n' "$passes" "$fails" "$cases" >&2
|
|
662
|
+
exit 1
|
|
663
|
+
fi
|
|
664
|
+
if [[ $((cases + skipped)) -ne "$PLANNED_TOTAL" ]]; then
|
|
665
|
+
printf '[FATAL] accounting: %s cases + %s skipped != planned total %s (a row was deleted or silently skipped)\n' "$cases" "$skipped" "$PLANNED_TOTAL" >&2
|
|
666
|
+
exit 1
|
|
667
|
+
fi
|
|
668
|
+
|
|
669
|
+
printf '\n%s passed, %s failed (%s cases, %s skipped, planned %s)\n' "$passes" "$fails" "$cases" "$skipped" "$PLANNED_TOTAL"
|
|
670
|
+
[[ "$fails" -eq 0 ]]
|