@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.
Files changed (832) hide show
  1. package/.claude-plugin/agents.manifest.json +476 -0
  2. package/.claude-plugin/plugin.json +42 -0
  3. package/README.md +44 -2
  4. package/agents/community/.gitkeep +0 -0
  5. package/agents/engineering/cto.md +87 -0
  6. package/agents/engineering/design/ddd-architect.md +95 -0
  7. package/agents/engineering/discovery/agent-finder.md +214 -0
  8. package/agents/engineering/discovery/functional-discovery.md +182 -0
  9. package/agents/engineering/infra/infra-security.md +151 -0
  10. package/agents/engineering/infra/platform-strategist.md +109 -0
  11. package/agents/engineering/infra/terraform-architect.md +171 -0
  12. package/agents/engineering/prompt-engineer.md +37 -0
  13. package/agents/engineering/research/best-practices-researcher.md +115 -0
  14. package/agents/engineering/research/framework-docs-researcher.md +93 -0
  15. package/agents/engineering/research/git-history-analyzer.md +53 -0
  16. package/agents/engineering/research/learnings-researcher.md +285 -0
  17. package/agents/engineering/research/repo-research-analyst.md +118 -0
  18. package/agents/engineering/review/agent-native-reviewer.md +279 -0
  19. package/agents/engineering/review/architecture-strategist.md +61 -0
  20. package/agents/engineering/review/code-quality-analyst.md +92 -0
  21. package/agents/engineering/review/code-simplicity-reviewer.md +109 -0
  22. package/agents/engineering/review/data-integrity-guardian.md +82 -0
  23. package/agents/engineering/review/data-migration-expert.md +98 -0
  24. package/agents/engineering/review/deployment-verification-agent.md +183 -0
  25. package/agents/engineering/review/dhh-rails-reviewer.md +46 -0
  26. package/agents/engineering/review/kieran-rails-reviewer.md +87 -0
  27. package/agents/engineering/review/legacy-code-expert.md +55 -0
  28. package/agents/engineering/review/observability-coverage-reviewer.md +147 -0
  29. package/agents/engineering/review/pattern-recognition-specialist.md +59 -0
  30. package/agents/engineering/review/performance-oracle.md +130 -0
  31. package/agents/engineering/review/security-sentinel.md +167 -0
  32. package/agents/engineering/review/semgrep-sast.md +36 -0
  33. package/agents/engineering/review/test-design-reviewer.md +150 -0
  34. package/agents/engineering/review/user-impact-reviewer.md +70 -0
  35. package/agents/engineering/workflow/pr-comment-resolver.md +69 -0
  36. package/agents/finance/budget-analyst.md +29 -0
  37. package/agents/finance/cfo.md +44 -0
  38. package/agents/finance/financial-reporter.md +30 -0
  39. package/agents/finance/revenue-analyst.md +30 -0
  40. package/agents/legal/clo.md +115 -0
  41. package/agents/legal/legal-compliance-auditor.md +110 -0
  42. package/agents/legal/legal-document-generator.md +134 -0
  43. package/agents/marketing/analytics-analyst.md +25 -0
  44. package/agents/marketing/brand-architect.md +181 -0
  45. package/agents/marketing/cmo.md +76 -0
  46. package/agents/marketing/conversion-optimizer.md +19 -0
  47. package/agents/marketing/copywriter.md +20 -0
  48. package/agents/marketing/fact-checker.md +70 -0
  49. package/agents/marketing/growth-strategist.md +145 -0
  50. package/agents/marketing/paid-media-strategist.md +28 -0
  51. package/agents/marketing/pricing-strategist.md +17 -0
  52. package/agents/marketing/programmatic-seo-specialist.md +25 -0
  53. package/agents/marketing/retention-strategist.md +23 -0
  54. package/agents/marketing/seo-aeo-analyst.md +164 -0
  55. package/agents/operations/coo.md +50 -0
  56. package/agents/operations/ops-advisor.md +78 -0
  57. package/agents/operations/ops-provisioner.md +101 -0
  58. package/agents/operations/ops-research.md +52 -0
  59. package/agents/operations/service-automator.md +278 -0
  60. package/agents/product/business-validator.md +206 -0
  61. package/agents/product/competitive-intelligence.md +89 -0
  62. package/agents/product/cpo.md +63 -0
  63. package/agents/product/design/ux-design-lead.md +209 -0
  64. package/agents/product/spec-flow-analyzer.md +122 -0
  65. package/agents/sales/cro.md +44 -0
  66. package/agents/sales/deal-architect.md +29 -0
  67. package/agents/sales/outbound-strategist.md +29 -0
  68. package/agents/sales/pipeline-analyst.md +29 -0
  69. package/agents/support/cco.md +48 -0
  70. package/agents/support/community-manager.md +570 -0
  71. package/agents/support/ticket-triage.md +70 -0
  72. package/bin/soleur-opencode.js +29 -0
  73. package/commands/go.md +660 -0
  74. package/commands/help.md +273 -0
  75. package/commands/sync.md +977 -0
  76. package/commands/version.md +103 -0
  77. package/hooks/antigravity-hooks.json +84 -0
  78. package/hooks/antigravity-session-start.sh +15 -0
  79. package/hooks/bare-root-cwd-guard.sh +131 -0
  80. package/hooks/browser-snapshot-credential-guard.sh +200 -0
  81. package/hooks/codex-session-start.sh +9 -0
  82. package/hooks/compaction-state.sh +525 -0
  83. package/hooks/destructive-command-guard.sh +1387 -0
  84. package/hooks/devin-session-start.sh +90 -0
  85. package/hooks/ext-filter-detect.sh +171 -0
  86. package/hooks/hooks.json +133 -0
  87. package/hooks/lib/hook-tool-kind.sh +24 -0
  88. package/hooks/lib/log-rotation.sh +176 -0
  89. package/hooks/lib/shell-argv.pl +576 -0
  90. package/hooks/memory-backstop.sh +1114 -0
  91. package/hooks/operator-stage-approval.sh +391 -0
  92. package/hooks/stop-hook.sh +367 -0
  93. package/hooks/unkept-promise-hook.sh +383 -0
  94. package/hooks/version-banner.sh +127 -0
  95. package/hooks/welcome-hook.sh +50 -0
  96. package/install.js +29 -0
  97. package/lib/agent-registry.ts +154 -0
  98. package/lib/c4-canonical-cli.mjs +34 -0
  99. package/lib/c4-canonical.mjs +46 -0
  100. package/lib/c4-from-components.ts +554 -0
  101. package/lib/go-routing.ts +81 -0
  102. package/lib/grok-inspect-contract.ts +311 -0
  103. package/lib/harness-model-map.ts +101 -0
  104. package/lib/harness-parity.ts +726 -0
  105. package/lib/harness-tool-map.ts +180 -0
  106. package/lib/harness.ts +716 -0
  107. package/lib/heartbeat-live-reconcile.ts +1153 -0
  108. package/lib/heartbeat-manifest.ts +361 -0
  109. package/lib/kb-coverage.ts +252 -0
  110. package/lib/pr-merge-poll.ts +103 -0
  111. package/lib/workflow-fidelity.ts +388 -0
  112. package/opencode/INSTRUCTIONS.md +171 -0
  113. package/opencode/agents/engineering/cto.md +10 -0
  114. package/opencode/agents/engineering/design/ddd-architect.md +10 -0
  115. package/opencode/agents/engineering/discovery/agent-finder.md +10 -0
  116. package/opencode/agents/engineering/discovery/functional-discovery.md +10 -0
  117. package/opencode/agents/engineering/infra/infra-security.md +10 -0
  118. package/opencode/agents/engineering/infra/platform-strategist.md +10 -0
  119. package/opencode/agents/engineering/infra/terraform-architect.md +10 -0
  120. package/opencode/agents/engineering/prompt-engineer.md +10 -0
  121. package/opencode/agents/engineering/research/best-practices-researcher.md +10 -0
  122. package/opencode/agents/engineering/research/framework-docs-researcher.md +10 -0
  123. package/opencode/agents/engineering/research/git-history-analyzer.md +10 -0
  124. package/opencode/agents/engineering/research/learnings-researcher.md +10 -0
  125. package/opencode/agents/engineering/research/repo-research-analyst.md +10 -0
  126. package/opencode/agents/engineering/review/agent-native-reviewer.md +10 -0
  127. package/opencode/agents/engineering/review/architecture-strategist.md +10 -0
  128. package/opencode/agents/engineering/review/code-quality-analyst.md +10 -0
  129. package/opencode/agents/engineering/review/code-simplicity-reviewer.md +10 -0
  130. package/opencode/agents/engineering/review/data-integrity-guardian.md +10 -0
  131. package/opencode/agents/engineering/review/data-migration-expert.md +10 -0
  132. package/opencode/agents/engineering/review/deployment-verification-agent.md +10 -0
  133. package/opencode/agents/engineering/review/dhh-rails-reviewer.md +10 -0
  134. package/opencode/agents/engineering/review/kieran-rails-reviewer.md +10 -0
  135. package/opencode/agents/engineering/review/legacy-code-expert.md +10 -0
  136. package/opencode/agents/engineering/review/observability-coverage-reviewer.md +10 -0
  137. package/opencode/agents/engineering/review/pattern-recognition-specialist.md +10 -0
  138. package/opencode/agents/engineering/review/performance-oracle.md +10 -0
  139. package/opencode/agents/engineering/review/security-sentinel.md +10 -0
  140. package/opencode/agents/engineering/review/semgrep-sast.md +10 -0
  141. package/opencode/agents/engineering/review/test-design-reviewer.md +10 -0
  142. package/opencode/agents/engineering/review/user-impact-reviewer.md +10 -0
  143. package/opencode/agents/engineering/workflow/pr-comment-resolver.md +10 -0
  144. package/opencode/agents/finance/budget-analyst.md +10 -0
  145. package/opencode/agents/finance/cfo.md +10 -0
  146. package/opencode/agents/finance/financial-reporter.md +10 -0
  147. package/opencode/agents/finance/revenue-analyst.md +10 -0
  148. package/opencode/agents/legal/clo.md +10 -0
  149. package/opencode/agents/legal/legal-compliance-auditor.md +10 -0
  150. package/opencode/agents/legal/legal-document-generator.md +10 -0
  151. package/opencode/agents/marketing/analytics-analyst.md +10 -0
  152. package/opencode/agents/marketing/brand-architect.md +10 -0
  153. package/opencode/agents/marketing/cmo.md +10 -0
  154. package/opencode/agents/marketing/conversion-optimizer.md +10 -0
  155. package/opencode/agents/marketing/copywriter.md +10 -0
  156. package/opencode/agents/marketing/fact-checker.md +10 -0
  157. package/opencode/agents/marketing/growth-strategist.md +10 -0
  158. package/opencode/agents/marketing/paid-media-strategist.md +10 -0
  159. package/opencode/agents/marketing/pricing-strategist.md +10 -0
  160. package/opencode/agents/marketing/programmatic-seo-specialist.md +10 -0
  161. package/opencode/agents/marketing/retention-strategist.md +10 -0
  162. package/opencode/agents/marketing/seo-aeo-analyst.md +10 -0
  163. package/opencode/agents/operations/coo.md +10 -0
  164. package/opencode/agents/operations/ops-advisor.md +10 -0
  165. package/opencode/agents/operations/ops-provisioner.md +10 -0
  166. package/opencode/agents/operations/ops-research.md +10 -0
  167. package/opencode/agents/operations/service-automator.md +10 -0
  168. package/opencode/agents/product/business-validator.md +10 -0
  169. package/opencode/agents/product/competitive-intelligence.md +10 -0
  170. package/opencode/agents/product/cpo.md +10 -0
  171. package/opencode/agents/product/design/ux-design-lead.md +10 -0
  172. package/opencode/agents/product/spec-flow-analyzer.md +10 -0
  173. package/opencode/agents/sales/cro.md +10 -0
  174. package/opencode/agents/sales/deal-architect.md +10 -0
  175. package/opencode/agents/sales/outbound-strategist.md +10 -0
  176. package/opencode/agents/sales/pipeline-analyst.md +10 -0
  177. package/opencode/agents/support/cco.md +10 -0
  178. package/opencode/agents/support/community-manager.md +10 -0
  179. package/opencode/agents/support/ticket-triage.md +10 -0
  180. package/opencode/commands/go.md +10 -0
  181. package/opencode/commands/help.md +10 -0
  182. package/opencode/commands/sync.md +10 -0
  183. package/opencode/commands/version.md +11 -0
  184. package/opencode/opencode.json +8 -0
  185. package/opencode/plugin.ts +818 -0
  186. package/package.json +36 -4
  187. package/scripts/admin-merge-ready.sh +545 -0
  188. package/scripts/admin-merge-ready.test.sh +753 -0
  189. package/scripts/affected-tests.sh +908 -0
  190. package/scripts/affected-tests.test.sh +1797 -0
  191. package/scripts/alpha-metrics.sh +78 -0
  192. package/scripts/alpha-metrics.test.sh +115 -0
  193. package/scripts/ancestor-signal-helpers.baseline.txt +16 -0
  194. package/scripts/audit-flag-flip.sh +107 -0
  195. package/scripts/check-red-on-main.sh +316 -0
  196. package/scripts/ci-head-verdict.sh +411 -0
  197. package/scripts/cloud-detect.sh +193 -0
  198. package/scripts/delegation-verify.sh +657 -0
  199. package/scripts/delegation-verify.test.sh +1424 -0
  200. package/scripts/deploy-arm.sh +475 -0
  201. package/scripts/domain-model-drift.sh +419 -0
  202. package/scripts/emit-decision.sh +144 -0
  203. package/scripts/emit-decision.test.sh +144 -0
  204. package/scripts/ext-filter-divergence-corpus.txt +15 -0
  205. package/scripts/ext-filter-divergence.sh +189 -0
  206. package/scripts/generate-c4-from-components.ts +442 -0
  207. package/scripts/grok-fidelity-gate.sh +68 -0
  208. package/scripts/grok-pre-push-gate.sh +232 -0
  209. package/scripts/harness-discovery-smoke.ts +906 -0
  210. package/scripts/harness-parity-census.ts +92 -0
  211. package/scripts/inngest-luks-alert-armed-probe.ts +29 -0
  212. package/scripts/install-opencode-adapter.ts +509 -0
  213. package/scripts/lib/affected-tests/common.sh +365 -0
  214. package/scripts/lib/affected-tests/go.sh +157 -0
  215. package/scripts/lib/affected-tests/js.sh +188 -0
  216. package/scripts/lib/affected-tests/nx-turbo.sh +98 -0
  217. package/scripts/lib/affected-tests/python.sh +185 -0
  218. package/scripts/lib/context-sanitize.sh +49 -0
  219. package/scripts/lib/domain-model-lib.sh +180 -0
  220. package/scripts/lib/ext-filter-grammar.tsv +34 -0
  221. package/scripts/lib/operator-script.sh +1236 -0
  222. package/scripts/lib/proc.sh +580 -0
  223. package/scripts/lib/session-state.sh +748 -0
  224. package/scripts/lib/tmp-classify.sh +843 -0
  225. package/scripts/lib/wrapper-boundary.sh +47 -0
  226. package/scripts/lint-ratchet.py +1547 -0
  227. package/scripts/monitor-pr-checks.sh +441 -0
  228. package/scripts/pipeline-tally.sh +756 -0
  229. package/scripts/pipeline-tally.test.sh +740 -0
  230. package/scripts/plugin-version.sh +528 -0
  231. package/scripts/precommit-guard.sh +115 -0
  232. package/scripts/precommit-guard.test.sh +254 -0
  233. package/scripts/reconcile-live-heartbeats.ts +705 -0
  234. package/scripts/render-c4-model.sh +217 -0
  235. package/scripts/resolve-git-root.sh +55 -0
  236. package/scripts/resolve-regenerable-conflicts.sh +363 -0
  237. package/scripts/resolve-regenerable-conflicts.test.sh +780 -0
  238. package/scripts/ruff-requirements.txt +22 -0
  239. package/scripts/run-in-pid-namespace.sh +98 -0
  240. package/scripts/run-in-pid-namespace.test.sh +290 -0
  241. package/scripts/scan-ancestor-signal-helpers.py +556 -0
  242. package/scripts/scan-ancestor-signal-helpers.test.sh +670 -0
  243. package/scripts/setup-ralph-loop.sh +238 -0
  244. package/scripts/sync-cursor-name-map.ts +316 -0
  245. package/scripts/sync-grok-agent-compat.ts +188 -0
  246. package/scripts/sync-npm-package.ts +165 -0
  247. package/scripts/sync-opencode-adapter.ts +498 -0
  248. package/scripts/sync-pr-behind.sh +647 -0
  249. package/scripts/sync-pr-behind.test.sh +252 -0
  250. package/scripts/taste-profile-update.sh +180 -0
  251. package/scripts/taste-profile-update.test.sh +167 -0
  252. package/scripts/write-budget-marker.sh +23 -0
  253. package/scripts/write-kb-coverage.ts +113 -0
  254. package/skills/admin-ip-refresh/SKILL.md +81 -0
  255. package/skills/admin-ip-refresh/references/admin-ip-refresh-procedure.md +201 -0
  256. package/skills/agent-browser/SKILL.md +698 -0
  257. package/skills/agent-browser/scripts/playwright-mcp-profile-slot.sh +304 -0
  258. package/skills/agent-browser/scripts/playwright-mcp-redact-proxy.py +964 -0
  259. package/skills/agent-browser/scripts/redact-a11y-snapshot.py +443 -0
  260. package/skills/agent-browser/test/fixtures/capture-playwright-mcp-fixtures.py +217 -0
  261. package/skills/agent-browser/test/fixtures/fake-passthrough-proxy.py +24 -0
  262. package/skills/agent-browser/test/fixtures/fake-playwright-mcp.py +131 -0
  263. package/skills/agent-browser/test/fixtures/make-proxy-mutant.py +48 -0
  264. package/skills/agent-browser/test/fixtures/odd-shapes/dialog-link-injection.json +10 -0
  265. package/skills/agent-browser/test/fixtures/odd-shapes/empty-content.json +5 -0
  266. package/skills/agent-browser/test/fixtures/odd-shapes/error-and-result.json +4 -0
  267. package/skills/agent-browser/test/fixtures/odd-shapes/error-code-bool.json +6 -0
  268. package/skills/agent-browser/test/fixtures/odd-shapes/error-code-string.json +6 -0
  269. package/skills/agent-browser/test/fixtures/odd-shapes/error-message-tree.json +6 -0
  270. package/skills/agent-browser/test/fixtures/odd-shapes/error-no-data.json +6 -0
  271. package/skills/agent-browser/test/fixtures/odd-shapes/error-string.json +4 -0
  272. package/skills/agent-browser/test/fixtures/odd-shapes/error-with-data.json +9 -0
  273. package/skills/agent-browser/test/fixtures/odd-shapes/evaluate-escaped-object.json +10 -0
  274. package/skills/agent-browser/test/fixtures/odd-shapes/invalid-utf8.json +4 -0
  275. package/skills/agent-browser/test/fixtures/odd-shapes/link-result.json +10 -0
  276. package/skills/agent-browser/test/fixtures/odd-shapes/list-two-results.json +6 -0
  277. package/skills/agent-browser/test/fixtures/odd-shapes/meta-in-result.json +13 -0
  278. package/skills/agent-browser/test/fixtures/odd-shapes/no-content.json +5 -0
  279. package/skills/agent-browser/test/fixtures/odd-shapes/quoted-key.json +10 -0
  280. package/skills/agent-browser/test/fixtures/odd-shapes/resource-block.json +18 -0
  281. package/skills/agent-browser/test/fixtures/odd-shapes/result-and-method.json +11 -0
  282. package/skills/agent-browser/test/fixtures/odd-shapes/result-string.json +3 -0
  283. package/skills/agent-browser/test/fixtures/odd-shapes/run-code-escaped-one-row.json +10 -0
  284. package/skills/agent-browser/test/fixtures/odd-shapes/run-code-escaped.json +10 -0
  285. package/skills/agent-browser/test/fixtures/odd-shapes/structured-content.json +13 -0
  286. package/skills/agent-browser/test/fixtures/odd-shapes/tools-list-no-tools.json +5 -0
  287. package/skills/agent-browser/test/fixtures/odd-shapes/tree-no-credential.json +10 -0
  288. package/skills/agent-browser/test/fixtures/odd-shapes/two-text-blocks.json +14 -0
  289. package/skills/agent-browser/test/fixtures/odd-shapes/unparsable-line.json +3 -0
  290. package/skills/agent-browser/test/fixtures/odd-shapes/value-contains-brace.json +10 -0
  291. package/skills/agent-browser/test/fixtures/odd-shapes/value-contains-link-substring.json +10 -0
  292. package/skills/agent-browser/test/fixtures/playwright-mcp-0.0.78/close.json +12 -0
  293. package/skills/agent-browser/test/fixtures/playwright-mcp-0.0.78/evaluate.json +12 -0
  294. package/skills/agent-browser/test/fixtures/playwright-mcp-0.0.78/find.json +12 -0
  295. package/skills/agent-browser/test/fixtures/playwright-mcp-0.0.78/framing.json +6 -0
  296. package/skills/agent-browser/test/fixtures/playwright-mcp-0.0.78/initialize.json +14 -0
  297. package/skills/agent-browser/test/fixtures/playwright-mcp-0.0.78/navigate-link.json +12 -0
  298. package/skills/agent-browser/test/fixtures/playwright-mcp-0.0.78/navigate.json +12 -0
  299. package/skills/agent-browser/test/fixtures/playwright-mcp-0.0.78/roots-list-request.json +5 -0
  300. package/skills/agent-browser/test/fixtures/playwright-mcp-0.0.78/screenshot.json +17 -0
  301. package/skills/agent-browser/test/fixtures/playwright-mcp-0.0.78/snapshot-filename.json +12 -0
  302. package/skills/agent-browser/test/fixtures/playwright-mcp-0.0.78/snapshot-meta-json.json +12 -0
  303. package/skills/agent-browser/test/fixtures/playwright-mcp-0.0.78/snapshot-meta-raw.json +12 -0
  304. package/skills/agent-browser/test/fixtures/playwright-mcp-0.0.78/snapshot.json +12 -0
  305. package/skills/agent-browser/test/fixtures/playwright-mcp-0.0.78/tools-list.json +827 -0
  306. package/skills/agent-browser/test/fixtures/proxy-session-driver.py +138 -0
  307. package/skills/agent-browser/test/fixtures/session-facts.py +102 -0
  308. package/skills/agent-browser/test/playwright-mcp-lifetime.test.sh +1620 -0
  309. package/skills/agent-browser/test/playwright-mcp-redact-proxy.test.sh +1599 -0
  310. package/skills/agent-browser/test/redact-a11y-snapshot.test.sh +527 -0
  311. package/skills/agent-native-architecture/SKILL.md +479 -0
  312. package/skills/agent-native-architecture/references/action-parity-discipline.md +430 -0
  313. package/skills/agent-native-architecture/references/agent-execution-patterns.md +483 -0
  314. package/skills/agent-native-architecture/references/agent-native-testing.md +605 -0
  315. package/skills/agent-native-architecture/references/architecture-patterns.md +493 -0
  316. package/skills/agent-native-architecture/references/dynamic-context-injection.md +358 -0
  317. package/skills/agent-native-architecture/references/files-universal-interface.md +314 -0
  318. package/skills/agent-native-architecture/references/from-primitives-to-domain-tools.md +381 -0
  319. package/skills/agent-native-architecture/references/mcp-tool-design.md +524 -0
  320. package/skills/agent-native-architecture/references/mobile-patterns.md +897 -0
  321. package/skills/agent-native-architecture/references/product-implications.md +478 -0
  322. package/skills/agent-native-architecture/references/refactoring-to-prompt-native.md +342 -0
  323. package/skills/agent-native-architecture/references/self-modification.md +294 -0
  324. package/skills/agent-native-architecture/references/shared-workspace-architecture.md +700 -0
  325. package/skills/agent-native-architecture/references/system-prompt-design.md +263 -0
  326. package/skills/agent-native-audit/SKILL.md +300 -0
  327. package/skills/agent-native-audit/workflows/agent-native-audit.workflow.js +423 -0
  328. package/skills/andrew-kane-gem-writer/SKILL.md +189 -0
  329. package/skills/andrew-kane-gem-writer/references/database-adapters.md +231 -0
  330. package/skills/andrew-kane-gem-writer/references/module-organization.md +121 -0
  331. package/skills/andrew-kane-gem-writer/references/rails-integration.md +183 -0
  332. package/skills/andrew-kane-gem-writer/references/resources.md +126 -0
  333. package/skills/andrew-kane-gem-writer/references/testing-patterns.md +261 -0
  334. package/skills/architecture/SKILL.md +436 -0
  335. package/skills/architecture/references/adr-template.md +154 -0
  336. package/skills/architecture/references/likec4-reference.md +136 -0
  337. package/skills/architecture/references/nfr-reference.md +126 -0
  338. package/skills/archive-kb/SKILL.md +86 -0
  339. package/skills/archive-kb/scripts/archive-kb.sh +300 -0
  340. package/skills/archive-kb/test/archive-kb-partial-run.test.sh +276 -0
  341. package/skills/atdd-developer/SKILL.md +65 -0
  342. package/skills/brainstorm/SKILL.md +701 -0
  343. package/skills/brainstorm/references/brainstorm-brand-workshop.md +153 -0
  344. package/skills/brainstorm/references/brainstorm-domain-config.md +63 -0
  345. package/skills/brainstorm/references/brainstorm-validation-workshop.md +65 -0
  346. package/skills/brainstorm/references/ui-surface-terms.md +42 -0
  347. package/skills/brainstorm-techniques/SKILL.md +231 -0
  348. package/skills/brainstorm-techniques/references/decision-principles.md +150 -0
  349. package/skills/brainstorm-techniques/references/phase-boundaries.md +103 -0
  350. package/skills/brainstorm-techniques/references/standing-delegation.md +407 -0
  351. package/skills/brainstorm-techniques/references/technical-ruling-delegation.md +174 -0
  352. package/skills/campaign-calendar/SKILL.md +145 -0
  353. package/skills/cf-token-scope/SKILL.md +164 -0
  354. package/skills/cf-token-scope/references/widen-playbook.md +114 -0
  355. package/skills/cf-token-scope/scripts/cf-token-scope.sh +253 -0
  356. package/skills/changelog/SKILL.md +142 -0
  357. package/skills/code-to-prd/SKILL.md +66 -0
  358. package/skills/code-to-prd/references/banner-template.md +12 -0
  359. package/skills/code-to-prd/references/prd-template.md +41 -0
  360. package/skills/code-to-prd/scripts/code-to-prd.sh +634 -0
  361. package/skills/code-to-prd/test/code-to-prd.test.sh +447 -0
  362. package/skills/code-to-prd/test/fixture/.env.example +7 -0
  363. package/skills/code-to-prd/test/fixture/app/about/page.tsx +11 -0
  364. package/skills/code-to-prd/test/fixture/app/api/health/route.ts +10 -0
  365. package/skills/code-to-prd/test/fixture/app/page.tsx +14 -0
  366. package/skills/code-to-prd/test/fixture/next.config.mjs +3 -0
  367. package/skills/code-to-prd/test/fixture/package.json +6 -0
  368. package/skills/cohort-status/SKILL.md +62 -0
  369. package/skills/community/SKILL.md +210 -0
  370. package/skills/community/scripts/bsky-community.sh +644 -0
  371. package/skills/community/scripts/bsky-setup.sh +631 -0
  372. package/skills/community/scripts/community-router.sh +93 -0
  373. package/skills/community/scripts/discord-community.sh +487 -0
  374. package/skills/community/scripts/discord-setup.sh +784 -0
  375. package/skills/community/scripts/github-community.sh +706 -0
  376. package/skills/community/scripts/hn-community.sh +233 -0
  377. package/skills/community/scripts/lib/hmac-sha1-b64.sh +126 -0
  378. package/skills/community/scripts/linkedin-community.sh +750 -0
  379. package/skills/community/scripts/linkedin-setup.sh +758 -0
  380. package/skills/community/scripts/x-community.sh +890 -0
  381. package/skills/community/scripts/x-setup.sh +713 -0
  382. package/skills/community/test/community-argv.test.sh +2922 -0
  383. package/skills/community/test/github-community.test.sh +981 -0
  384. package/skills/competitive-analysis/SKILL.md +69 -0
  385. package/skills/competitive-analysis/references/peer-plugin-audit.md +218 -0
  386. package/skills/compound/SKILL.md +673 -0
  387. package/skills/compound/scripts/token-efficiency-report.sh +334 -0
  388. package/skills/compound/test/phase-16.test.sh +379 -0
  389. package/skills/compound-capture/SKILL.md +791 -0
  390. package/skills/compound-capture/assets/critical-pattern-template.md +37 -0
  391. package/skills/compound-capture/assets/resolution-template.md +116 -0
  392. package/skills/compound-capture/references/yaml-schema.md +67 -0
  393. package/skills/compound-capture/schema.yaml +181 -0
  394. package/skills/constraint-scaffold/SKILL.md +175 -0
  395. package/skills/constraint-scaffold/references/boundary-readme.template +35 -0
  396. package/skills/constraint-scaffold/references/constraint-gates-workflow.template +69 -0
  397. package/skills/constraint-scaffold/references/depcruise-config.template +230 -0
  398. package/skills/constraint-scaffold/references/fix-constraints-stage-a.template +240 -0
  399. package/skills/constraint-scaffold/references/fix-constraints-stage-b.template +313 -0
  400. package/skills/constraint-scaffold/references/shared-runner.template +135 -0
  401. package/skills/constraint-scaffold/scripts/constraint-scaffold.sh +589 -0
  402. package/skills/constraint-scaffold/test/bite-proof.test.sh +1338 -0
  403. package/skills/constraint-scaffold/test/boundary.test.sh +734 -0
  404. package/skills/constraint-scaffold/test/emit-fix-constraints.test.sh +193 -0
  405. package/skills/constraint-scaffold/test/generator.test.sh +93 -0
  406. package/skills/constraint-scaffold/test/parity.test.sh +285 -0
  407. package/skills/content-writer/SKILL.md +242 -0
  408. package/skills/content-writer/scripts/blog-jargon-scan.sh +42 -0
  409. package/skills/cron-delete/SKILL.md +56 -0
  410. package/skills/cron-list/SKILL.md +54 -0
  411. package/skills/deepen-plan/SKILL.md +937 -0
  412. package/skills/deepen-plan/workflows/deepen-plan.workflow.js +488 -0
  413. package/skills/deploy/SKILL.md +115 -0
  414. package/skills/deploy/references/hetzner-setup.md +67 -0
  415. package/skills/deploy/scripts/deploy.sh +37 -0
  416. package/skills/deploy-docs/SKILL.md +95 -0
  417. package/skills/dhh-rails-style/SKILL.md +203 -0
  418. package/skills/dhh-rails-style/references/architecture.md +717 -0
  419. package/skills/dhh-rails-style/references/controllers.md +323 -0
  420. package/skills/dhh-rails-style/references/frontend.md +556 -0
  421. package/skills/dhh-rails-style/references/gems.md +316 -0
  422. package/skills/dhh-rails-style/references/models.md +388 -0
  423. package/skills/dhh-rails-style/references/testing.md +354 -0
  424. package/skills/discord-content/SKILL.md +126 -0
  425. package/skills/docs-site/SKILL.md +214 -0
  426. package/skills/drain-labeled-backlog/SKILL.md +203 -0
  427. package/skills/drain-labeled-backlog/scripts/group-by-area.sh +208 -0
  428. package/skills/drain-labeled-backlog/workflows/drain-labeled-backlog.workflow.js +433 -0
  429. package/skills/drain-prs/SKILL.md +143 -0
  430. package/skills/drain-prs/scripts/triage-prs.sh +192 -0
  431. package/skills/drain-prs/test/argv-ceiling.test.sh +183 -0
  432. package/skills/dspy-ruby/SKILL.md +634 -0
  433. package/skills/dspy-ruby/assets/config-template.rb +359 -0
  434. package/skills/dspy-ruby/assets/module-template.rb +326 -0
  435. package/skills/dspy-ruby/assets/signature-template.rb +143 -0
  436. package/skills/dspy-ruby/references/core-concepts.md +268 -0
  437. package/skills/dspy-ruby/references/optimization.md +623 -0
  438. package/skills/dspy-ruby/references/providers.md +335 -0
  439. package/skills/eval-harness/README.md +194 -0
  440. package/skills/eval-harness/SKILL.md +157 -0
  441. package/skills/eval-harness/enums/go-routes.json +13 -0
  442. package/skills/eval-harness/enums/incident-threshold.json +5 -0
  443. package/skills/eval-harness/enums/lane.json +5 -0
  444. package/skills/eval-harness/enums/tool-selection.json +20 -0
  445. package/skills/eval-harness/enums/triage-levels.json +5 -0
  446. package/skills/eval-harness/gated-skills.json +34 -0
  447. package/skills/eval-harness/models.generated.json +5 -0
  448. package/skills/eval-harness/promptfooconfig-go-routing.yaml +35 -0
  449. package/skills/eval-harness/promptfooconfig-incident-threshold.yaml +32 -0
  450. package/skills/eval-harness/promptfooconfig-lane-inference.yaml +33 -0
  451. package/skills/eval-harness/promptfooconfig-ticket-triage.yaml +34 -0
  452. package/skills/eval-harness/promptfooconfig-tool-selection.yaml +33 -0
  453. package/skills/eval-harness/prompts/go-baseline.txt +6 -0
  454. package/skills/eval-harness/prompts/go-skill.txt +21 -0
  455. package/skills/eval-harness/prompts/incident-threshold-baseline.txt +6 -0
  456. package/skills/eval-harness/prompts/incident-threshold-skill.txt +12 -0
  457. package/skills/eval-harness/prompts/lane-inference-baseline.txt +6 -0
  458. package/skills/eval-harness/prompts/lane-inference-skill.txt +15 -0
  459. package/skills/eval-harness/prompts/tool-selection-baseline.txt +19 -0
  460. package/skills/eval-harness/prompts/tool-selection-skill.txt +22 -0
  461. package/skills/eval-harness/prompts/triage-baseline.txt +7 -0
  462. package/skills/eval-harness/prompts/triage-skill.txt +10 -0
  463. package/skills/eval-harness/scripts/eval-gate.cjs +318 -0
  464. package/skills/eval-harness/scripts/extract-block.cjs +87 -0
  465. package/skills/eval-harness/scripts/gate-classification.cjs +28 -0
  466. package/skills/eval-harness/scripts/gen-models.sh +41 -0
  467. package/skills/eval-harness/scripts/gen-skill-prompt.cjs +177 -0
  468. package/skills/eval-harness/scripts/measure-classification.cjs +30 -0
  469. package/skills/eval-harness/scripts/parse-label.cjs +93 -0
  470. package/skills/eval-harness/scripts/verdict.cjs +132 -0
  471. package/skills/eval-harness/tasks/go-routing.jsonl +8 -0
  472. package/skills/eval-harness/tasks/incident-threshold.jsonl +7 -0
  473. package/skills/eval-harness/tasks/lane-inference.jsonl +7 -0
  474. package/skills/eval-harness/tasks/ticket-triage.jsonl +6 -0
  475. package/skills/eval-harness/tasks/tool-selection.jsonl +15 -0
  476. package/skills/eval-harness/test/eval-gate.test.sh +132 -0
  477. package/skills/eval-harness/test/extract-block.test.sh +87 -0
  478. package/skills/eval-harness/test/gate-classification.test.sh +77 -0
  479. package/skills/eval-harness/test/gen-models.test.sh +75 -0
  480. package/skills/eval-harness/test/measure-classification.test.sh +74 -0
  481. package/skills/eval-harness/test/parse-label.test.sh +129 -0
  482. package/skills/eval-harness/test/registry-completeness.test.sh +109 -0
  483. package/skills/eval-harness/test/verdict.test.sh +123 -0
  484. package/skills/every-style-editor/SKILL.md +142 -0
  485. package/skills/every-style-editor/references/EVERY_WRITE_STYLE.md +529 -0
  486. package/skills/feature-tweet/SKILL.md +199 -0
  487. package/skills/feature-video/SKILL.md +412 -0
  488. package/skills/feature-video/scripts/check_deps.sh +281 -0
  489. package/skills/file-todos/SKILL.md +267 -0
  490. package/skills/file-todos/assets/todo-template.md +166 -0
  491. package/skills/fix-issue/SKILL.md +278 -0
  492. package/skills/fix-issue/references/agent-authored-exclusion.md +120 -0
  493. package/skills/fix-issue/references/exclude-label-jq-snippet.md +97 -0
  494. package/skills/flag-bootstrap/SETUP.md +142 -0
  495. package/skills/flag-create/SKILL.md +145 -0
  496. package/skills/flag-create/scripts/create.sh +273 -0
  497. package/skills/flag-delete/SKILL.md +167 -0
  498. package/skills/flag-delete/scripts/delete.sh +288 -0
  499. package/skills/flag-list/SKILL.md +99 -0
  500. package/skills/flag-list/scripts/list.sh +275 -0
  501. package/skills/flag-set-role/SKILL.md +229 -0
  502. package/skills/flag-set-role/scripts/flip.sh +774 -0
  503. package/skills/frontend-anti-slop/SKILL.md +106 -0
  504. package/skills/frontend-anti-slop/references/anti-patterns.md +199 -0
  505. package/skills/frontend-anti-slop/references/slop-rules.md +65 -0
  506. package/skills/frontend-anti-slop/scripts/tier1-scan.ts +525 -0
  507. package/skills/frontend-design/SKILL.md +77 -0
  508. package/skills/gdpr-gate/NOTICE +136 -0
  509. package/skills/gdpr-gate/SKILL.md +341 -0
  510. package/skills/gdpr-gate/references/fields.md +160 -0
  511. package/skills/gdpr-gate/references/layers/api-layer.md +355 -0
  512. package/skills/gdpr-gate/references/layers/auth-sessions.md +290 -0
  513. package/skills/gdpr-gate/references/layers/data-in-transit.md +331 -0
  514. package/skills/gdpr-gate/references/layers/data-lifecycle.md +341 -0
  515. package/skills/gdpr-gate/references/layers/frontend.md +249 -0
  516. package/skills/gdpr-gate/references/layers/testing-seeding.md +256 -0
  517. package/skills/gdpr-gate/references/leakage-vectors.md +248 -0
  518. package/skills/gdpr-gate/references/legacy/legal-consent-v1-prose.md +48 -0
  519. package/skills/gdpr-gate/references/legal-consent.md +140 -0
  520. package/skills/gdpr-gate/references/non-negotiables.md +60 -0
  521. package/skills/gdpr-gate/scripts/gdpr-gate.sh +271 -0
  522. package/skills/gdpr-gate/scripts/notice-frontmatter.sh +337 -0
  523. package/skills/gdpr-gate/scripts/path-denylist.txt +39 -0
  524. package/skills/gdpr-gate/scripts/repo-scan.sh +158 -0
  525. package/skills/gdpr-gate/scripts/vendor-drift-classify.sh +120 -0
  526. package/skills/gdpr-gate/scripts/vendor-pin-integrity.sh +237 -0
  527. package/skills/gemini-imagegen/SKILL.md +283 -0
  528. package/skills/gemini-imagegen/requirements.txt +5 -0
  529. package/skills/gemini-imagegen/scripts/_error_handling.py +146 -0
  530. package/skills/gemini-imagegen/scripts/compose_images.py +150 -0
  531. package/skills/gemini-imagegen/scripts/edit_image.py +137 -0
  532. package/skills/gemini-imagegen/scripts/gemini_images.py +256 -0
  533. package/skills/gemini-imagegen/scripts/generate_image.py +147 -0
  534. package/skills/gemini-imagegen/scripts/multi_turn_chat.py +223 -0
  535. package/skills/gemini-imagegen/scripts/test_error_handling.py +179 -0
  536. package/skills/git-worktree/SKILL.md +534 -0
  537. package/skills/git-worktree/scripts/git-repo-readiness-diag.sh +98 -0
  538. package/skills/git-worktree/scripts/worktree-manager.sh +4773 -0
  539. package/skills/git-worktree/test/create-from-origin-main.test.sh +116 -0
  540. package/skills/git-worktree/test/lease-protects-active.test.sh +1056 -0
  541. package/skills/git-worktree/test/no-repo-fail-loud.test.sh +88 -0
  542. package/skills/git-worktree/test/orphan-reaper-honest-count.test.sh +379 -0
  543. package/skills/git-worktree/test/reap-archive-persistence.test.sh +725 -0
  544. package/skills/git-worktree/test/stale-lock-sweep.test.sh +176 -0
  545. package/skills/go/SKILL.md +54 -0
  546. package/skills/growth/SKILL.md +164 -0
  547. package/skills/harvest-debt/SKILL.md +78 -0
  548. package/skills/harvest-debt/scripts/harvest-debt.sh +114 -0
  549. package/skills/heal-skill/SKILL.md +173 -0
  550. package/skills/help/SKILL.md +46 -0
  551. package/skills/incident/NOTICE +39 -0
  552. package/skills/incident/SKILL.md +395 -0
  553. package/skills/incident/scripts/dry-run.sh +448 -0
  554. package/skills/incident/scripts/redact-engine.py +412 -0
  555. package/skills/incident/scripts/redact-sentinel.sh +44 -0
  556. package/skills/incident/templates/pir.md +139 -0
  557. package/skills/incident/test/fixtures/dry-run-incident.json +26 -0
  558. package/skills/incident/test/fixtures/dry-run-secret-leak.json +26 -0
  559. package/skills/incident/test/fixtures/legacy-bash-scanner.sh +82 -0
  560. package/skills/incident/test/fixtures/positive-corpus.md +87 -0
  561. package/skills/incident/test/redact-sentinel.test.sh +1420 -0
  562. package/skills/invoice/SKILL.md +206 -0
  563. package/skills/kb-glossary/SKILL.md +71 -0
  564. package/skills/kb-glossary/references/glossary-format.md +111 -0
  565. package/skills/kb-glossary/references/rejected-request-register.md +115 -0
  566. package/skills/kb-search/SKILL.md +276 -0
  567. package/skills/kb-search/scripts/kb-search-cache.sh +123 -0
  568. package/skills/legal-audit/SKILL.md +161 -0
  569. package/skills/legal-generate/NOTICE +242 -0
  570. package/skills/legal-generate/SKILL.md +244 -0
  571. package/skills/legal-generate/references/templates/advisor-agreement/template.md +12 -0
  572. package/skills/legal-generate/references/templates/business-associate-agreement/template.md +112 -0
  573. package/skills/legal-generate/references/templates/cookie-notice/template.md +82 -0
  574. package/skills/legal-generate/references/templates/dpa-global/template.md +439 -0
  575. package/skills/legal-generate/references/templates/dpa-us/template.md +222 -0
  576. package/skills/legal-generate/references/templates/employee-offer-letter/template.md +75 -0
  577. package/skills/legal-generate/references/templates/master-services-agreement/template.md +252 -0
  578. package/skills/legal-generate/references/templates/mutual-nda/template.md +66 -0
  579. package/skills/legal-generate/references/templates/one-way-nda/template.md +38 -0
  580. package/skills/legal-generate/references/templates/privacy-policy-gdpr/template.md +427 -0
  581. package/skills/legal-generate/references/templates/privacy-policy-us/template.md +313 -0
  582. package/skills/legal-generate/references/templates/terms-of-use/template.md +75 -0
  583. package/skills/legal-generate/scripts/strip-vendor-credit.sh +96 -0
  584. package/skills/linear-fetch/SKILL.md +247 -0
  585. package/skills/linear-fetch/scripts/assert-no-linear-telemetry.sh +66 -0
  586. package/skills/linear-fetch/scripts/redact-linear-urls.sh +51 -0
  587. package/skills/linear-fetch/scripts/render-caller-template.sh +36 -0
  588. package/skills/linear-fetch/test/assert-no-linear-telemetry.test.sh +113 -0
  589. package/skills/linear-fetch/test/parity.test.sh +112 -0
  590. package/skills/linear-fetch/test/persist-safe-integration.test.sh +191 -0
  591. package/skills/linear-fetch/test/redact-linear-urls.test.sh +226 -0
  592. package/skills/merge-pr/SKILL.md +670 -0
  593. package/skills/model-launch-review/SKILL.md +255 -0
  594. package/skills/model-launch-review/scripts/audit-models.sh +501 -0
  595. package/skills/one-shot/SKILL.md +316 -0
  596. package/skills/one-shot/references/token-discipline.md +74 -0
  597. package/skills/operator-bootstrap/SKILL.md +412 -0
  598. package/skills/operator-bootstrap/template.sh +439 -0
  599. package/skills/operator-digest/SKILL.md +287 -0
  600. package/skills/operator-digest/assets/operator-digest.workflow.yml +175 -0
  601. package/skills/operator-digest/scripts/digest-scrub.sh +119 -0
  602. package/skills/operator-digest/scripts/provision-operator-digest-repo.sh +147 -0
  603. package/skills/operator-rephrase/SKILL.md +98 -0
  604. package/skills/pencil-setup/SKILL.md +201 -0
  605. package/skills/pencil-setup/scripts/check_deps.sh +556 -0
  606. package/skills/pencil-setup/scripts/copy_adapter.sh +80 -0
  607. package/skills/pencil-setup/scripts/package-lock.json +1172 -0
  608. package/skills/pencil-setup/scripts/package.json +14 -0
  609. package/skills/pencil-setup/scripts/pencil-error-enrichment.mjs +21 -0
  610. package/skills/pencil-setup/scripts/pencil-mcp-adapter.mjs +733 -0
  611. package/skills/pencil-setup/scripts/pencil-response-classify.mjs +38 -0
  612. package/skills/pencil-setup/scripts/pencil-save-gate.mjs +26 -0
  613. package/skills/pencil-setup/scripts/sanitize-filename.mjs +25 -0
  614. package/skills/plan/SKILL.md +1140 -0
  615. package/skills/plan/references/differential-migration-testing.md +185 -0
  616. package/skills/plan/references/plan-community-discovery.md +42 -0
  617. package/skills/plan/references/plan-founder-check.md +137 -0
  618. package/skills/plan/references/plan-functional-overlap.md +25 -0
  619. package/skills/plan/references/plan-host-fanout.md +51 -0
  620. package/skills/plan/references/plan-issue-templates.md +779 -0
  621. package/skills/plan/references/plan-network-outage-checklist.md +131 -0
  622. package/skills/plan/references/plan-scope-check.md +126 -0
  623. package/skills/plan/references/plan-sharp-edges.md +331 -0
  624. package/skills/plan/references/plan-signoff-lifecycle.md +12 -0
  625. package/skills/plan/references/webapp-cwv-observability.md +143 -0
  626. package/skills/plan-review/SKILL.md +91 -0
  627. package/skills/plan-review/lib/named-panel.mjs +58 -0
  628. package/skills/plan-review/workflows/plan-review.workflow.js +477 -0
  629. package/skills/postmerge/SKILL.md +642 -0
  630. package/skills/postmerge/references/deploy-status-debugging.md +141 -0
  631. package/skills/postmerge/references/graceful-degradation.md +20 -0
  632. package/skills/postmerge/references/sentry-error-count-delta.md +137 -0
  633. package/skills/preflight/SKILL.md +1553 -0
  634. package/skills/preflight/references/check-13-founder-check.md +286 -0
  635. package/skills/preflight/scripts/founder-check.py +1640 -0
  636. package/skills/preflight/scripts/parse-form-a.awk +107 -0
  637. package/skills/preflight/scripts/probe-verb-gate.sh +108 -0
  638. package/skills/product-roadmap/SKILL.md +357 -0
  639. package/skills/product-roadmap/scripts/roadmap-reconcile.sh +327 -0
  640. package/skills/provision-cloudflare/SKILL.md +67 -0
  641. package/skills/provision-cloudflare/scripts/provision-cloudflare.sh +271 -0
  642. package/skills/provision-doppler/SKILL.md +58 -0
  643. package/skills/provision-doppler/scripts/provision-doppler.sh +358 -0
  644. package/skills/provision-github/SKILL.md +59 -0
  645. package/skills/provision-github/scripts/provision-github.sh +300 -0
  646. package/skills/provision-hetzner/SKILL.md +76 -0
  647. package/skills/provision-hetzner/scripts/provision-hetzner.sh +262 -0
  648. package/skills/provision-hetzner/test/fixture/knowledge-base/legal/tenant-dpa-register.md +26 -0
  649. package/skills/provision-hetzner/test/fixture/provision-hetzner-dry-run.golden +34 -0
  650. package/skills/provision-hetzner/test/provision-hetzner-characterization.test.sh +227 -0
  651. package/skills/qa/SKILL.md +263 -0
  652. package/skills/qa/references/browser-preflight.md +22 -0
  653. package/skills/questionnaire-generate/SKILL.md +328 -0
  654. package/skills/questionnaire-generate/references/questionnaire.template +60 -0
  655. package/skills/rclone/SKILL.md +162 -0
  656. package/skills/rclone/scripts/check_setup.sh +63 -0
  657. package/skills/release-announce/SKILL.md +65 -0
  658. package/skills/release-docs/SKILL.md +92 -0
  659. package/skills/reproduce-bug/SKILL.md +358 -0
  660. package/skills/resolve-debt/SKILL.md +85 -0
  661. package/skills/resolve-debt/scripts/resolve-debt.py +584 -0
  662. package/skills/resolve-parallel/SKILL.md +45 -0
  663. package/skills/resolve-parallel/workflows/resolve-parallel.workflow.js +415 -0
  664. package/skills/resolve-pr-parallel/SKILL.md +68 -0
  665. package/skills/resolve-pr-parallel/workflows/resolve-pr-parallel.workflow.js +419 -0
  666. package/skills/resolve-todo-parallel/SKILL.md +57 -0
  667. package/skills/resolve-todo-parallel/workflows/resolve-todo-parallel.workflow.js +398 -0
  668. package/skills/review/SKILL.md +1620 -0
  669. package/skills/review/references/anti-slop-scanner-hook.md +40 -0
  670. package/skills/review/references/defect-classes-migrations.md +9 -0
  671. package/skills/review/references/generated-input-oracle-surfaces.md +15 -0
  672. package/skills/review/references/review-e2e-testing.md +116 -0
  673. package/skills/review/references/review-evidence-comment.md +36 -0
  674. package/skills/review/references/review-todo-structure.md +165 -0
  675. package/skills/review/references/risk-tier-and-fix-rounds.md +97 -0
  676. package/skills/review/references/semgrep-custom-rules.yaml +174 -0
  677. package/skills/review/references/ultrathink-phases.md +98 -0
  678. package/skills/review/references/wfs.md +6 -0
  679. package/skills/review/scripts/emit-review-trailer.sh +499 -0
  680. package/skills/review/scripts/ensure-semgrep.sh +99 -0
  681. package/skills/review/scripts/fix-round-seats.sh +197 -0
  682. package/skills/review/test/emit-review-trailer.test.sh +387 -0
  683. package/skills/review/test/ensure-semgrep.test.sh +111 -0
  684. package/skills/review/test/fix-round-seats.test.sh +237 -0
  685. package/skills/review/workflows/README.md +147 -0
  686. package/skills/review/workflows/review.workflow.js +667 -0
  687. package/skills/schedule/SKILL.md +796 -0
  688. package/skills/seo-aeo/SKILL.md +139 -0
  689. package/skills/seo-aeo/scripts/validate-csp.sh +233 -0
  690. package/skills/seo-aeo/scripts/validate-seo.sh +262 -0
  691. package/skills/ship/SKILL.md +3023 -0
  692. package/skills/ship/references/adr-ordinal-collision.md +47 -0
  693. package/skills/ship/references/affected-gate-contract.md +115 -0
  694. package/skills/ship/references/ci-run-diagnosis.md +29 -0
  695. package/skills/ship/references/ci-workflow-authoring.md +68 -0
  696. package/skills/ship/references/cleanup-merged-archival.md +39 -0
  697. package/skills/ship/references/counsel-review-clo-attestation.md +38 -0
  698. package/skills/ship/references/cto-ruling-armed-push.md +5 -0
  699. package/skills/ship/references/decision-challenges-render.md +71 -0
  700. package/skills/ship/references/delegated-act-authoring-form.md +7 -0
  701. package/skills/ship/references/detached-battery-verdict.md +13 -0
  702. package/skills/ship/references/epic-close-sweep.md +62 -0
  703. package/skills/ship/references/feature-tweet-draft.md +42 -0
  704. package/skills/ship/references/followthrough-issue-body-template.md +47 -0
  705. package/skills/ship/references/followthrough-stub-template.sh +92 -0
  706. package/skills/ship/references/merge-queue-dequeue.md +39 -0
  707. package/skills/ship/references/operator-holds.md +179 -0
  708. package/skills/ship/references/pipeline-tally-render.md +43 -0
  709. package/skills/ship/references/pr-overlap.md +153 -0
  710. package/skills/ship/references/queue-mode.md +7 -0
  711. package/skills/ship/references/ready-run-wait.md +36 -0
  712. package/skills/ship/references/red-on-main-quarantine.md +110 -0
  713. package/skills/ship/references/register-update-pr-pattern.md +88 -0
  714. package/skills/ship/references/settle-then-admin-merge.md +130 -0
  715. package/skills/ship/references/supabase-column-probe.md +13 -0
  716. package/skills/ship/scripts/auto-close-scan.sh +76 -0
  717. package/skills/ship/scripts/battery-owed.sh +403 -0
  718. package/skills/ship/scripts/hold-gate-eval.sh +410 -0
  719. package/skills/ship/scripts/net-issue-flow.sh +665 -0
  720. package/skills/ship/scripts/pr-overlap-preflight.sh +483 -0
  721. package/skills/ship/scripts/ship-pir-action-items-gate.sh +246 -0
  722. package/skills/ship/scripts/technical-ruling-gate.sh +444 -0
  723. package/skills/skill-creator/SKILL.md +299 -0
  724. package/skills/skill-creator/references/api-security.md +248 -0
  725. package/skills/skill-creator/references/authoring-levers.md +110 -0
  726. package/skills/skill-creator/references/be-clear-and-direct.md +587 -0
  727. package/skills/skill-creator/references/best-practices.md +431 -0
  728. package/skills/skill-creator/references/common-patterns.md +639 -0
  729. package/skills/skill-creator/references/core-principles.md +193 -0
  730. package/skills/skill-creator/references/executable-code.md +188 -0
  731. package/skills/skill-creator/references/iteration-and-testing.md +509 -0
  732. package/skills/skill-creator/references/official-spec.md +193 -0
  733. package/skills/skill-creator/references/recommended-structure.md +180 -0
  734. package/skills/skill-creator/references/skill-structure.md +396 -0
  735. package/skills/skill-creator/references/using-scripts.md +122 -0
  736. package/skills/skill-creator/references/using-templates.md +120 -0
  737. package/skills/skill-creator/references/workflows-and-validation.md +541 -0
  738. package/skills/skill-creator/scripts/init_skill.py +322 -0
  739. package/skills/skill-creator/scripts/package_skill.py +110 -0
  740. package/skills/skill-creator/scripts/quick_validate.py +64 -0
  741. package/skills/skill-creator/templates/router-skill.md +73 -0
  742. package/skills/skill-creator/templates/simple-skill.md +34 -0
  743. package/skills/skill-creator/workflows/add-reference.md +96 -0
  744. package/skills/skill-creator/workflows/add-script.md +104 -0
  745. package/skills/skill-creator/workflows/add-template.md +83 -0
  746. package/skills/skill-creator/workflows/add-workflow.md +128 -0
  747. package/skills/skill-creator/workflows/audit-skill.md +159 -0
  748. package/skills/skill-creator/workflows/create-domain-expertise-skill.md +623 -0
  749. package/skills/skill-creator/workflows/create-new-skill.md +207 -0
  750. package/skills/skill-creator/workflows/get-guidance.md +134 -0
  751. package/skills/skill-creator/workflows/upgrade-to-router.md +170 -0
  752. package/skills/skill-creator/workflows/verify-skill.md +226 -0
  753. package/skills/skill-security-scan/SKILL.md +145 -0
  754. package/skills/skill-security-scan/references/disclaimer.md +21 -0
  755. package/skills/skill-security-scan/references/first-party-allowlist.yaml +38 -0
  756. package/skills/skill-security-scan/references/override-artifact-schema.json +68 -0
  757. package/skills/skill-security-scan/references/override-mechanism.md +171 -0
  758. package/skills/skill-security-scan/references/redirect-domains.yaml +27 -0
  759. package/skills/skill-security-scan/references/regex-patterns.md +136 -0
  760. package/skills/skill-security-scan/references/rules/code-exec.yaml +70 -0
  761. package/skills/skill-security-scan/references/rules/filesystem-boundary.yaml +29 -0
  762. package/skills/skill-security-scan/references/rules/manifest.yaml +44 -0
  763. package/skills/skill-security-scan/references/rules/supply-chain.yaml +36 -0
  764. package/skills/skill-security-scan/references/scan-meta-schema.json +63 -0
  765. package/skills/skill-security-scan/references/test-fixtures/clean-soleur-style.skill.md +23 -0
  766. package/skills/skill-security-scan/references/test-fixtures/clean-third-party.skill.md +26 -0
  767. package/skills/skill-security-scan/references/test-fixtures/malicious-codeexec.skill.md +23 -0
  768. package/skills/skill-security-scan/references/test-fixtures/malicious-curl-pipe-bash.skill.md +69 -0
  769. package/skills/skill-security-scan/references/test-fixtures/malicious-prompt-injection.skill.md +17 -0
  770. package/skills/skill-security-scan/references/test-fixtures/malicious-telemetry-beacon.skill.md +23 -0
  771. package/skills/skill-security-scan/references/typosquat-targets.yaml +65 -0
  772. package/skills/skill-security-scan/scripts/check-codeexec.sh +41 -0
  773. package/skills/skill-security-scan/scripts/check-filesystem-boundary.sh +19 -0
  774. package/skills/skill-security-scan/scripts/check-prompt-injection.sh +95 -0
  775. package/skills/skill-security-scan/scripts/check-supply-chain.sh +219 -0
  776. package/skills/skill-security-scan/scripts/check-telemetry-surface.sh +126 -0
  777. package/skills/skill-security-scan/scripts/lib.sh +197 -0
  778. package/skills/skill-security-scan/scripts/parse-override.sh +231 -0
  779. package/skills/skill-security-scan/scripts/run-scan.sh +342 -0
  780. package/skills/skill-security-scan/scripts/run-self-test.sh +95 -0
  781. package/skills/skill-security-scan/test/argv-ceiling.test.sh +180 -0
  782. package/skills/skill-security-scan/test/meta-dir-reap.test.sh +411 -0
  783. package/skills/skill-security-scan/test/parse-override.test.sh +607 -0
  784. package/skills/skill-security-scan/test/redact-pii-ghs-shape.test.sh +251 -0
  785. package/skills/social-distribute/SKILL.md +485 -0
  786. package/skills/spec-templates/SKILL.md +274 -0
  787. package/skills/sync/SKILL.md +49 -0
  788. package/skills/test-browser/SKILL.md +464 -0
  789. package/skills/test-browser/references/feature-map.md +161 -0
  790. package/skills/test-fix-loop/SKILL.md +159 -0
  791. package/skills/test-fix-loop/references/determinism-checklist.md +154 -0
  792. package/skills/triage/SKILL.md +402 -0
  793. package/skills/trigger-cron/SKILL.md +136 -0
  794. package/skills/trigger-cron/scripts/trigger.sh +198 -0
  795. package/skills/user-set-role/SKILL.md +147 -0
  796. package/skills/user-set-role/scripts/set-role.sh +218 -0
  797. package/skills/user-story-writer/SKILL.md +77 -0
  798. package/skills/ux-audit/SKILL.md +251 -0
  799. package/skills/ux-audit/references/finding.schema.json +62 -0
  800. package/skills/ux-audit/references/route-list.yaml +95 -0
  801. package/skills/ux-audit/scripts/bot-fixture.ts +270 -0
  802. package/skills/ux-audit/scripts/bot-signin.ts +135 -0
  803. package/skills/ux-audit/scripts/dedup-hash.ts +46 -0
  804. package/skills/verification-scaffold/SKILL.md +73 -0
  805. package/skills/verification-scaffold/references/gitleaks.toml.template +13 -0
  806. package/skills/verification-scaffold/references/guardrail-audit.md +156 -0
  807. package/skills/verification-scaffold/references/guards/block-stash-hook.sh.template +72 -0
  808. package/skills/verification-scaffold/references/guards/commit-on-main-hook.sh.template +82 -0
  809. package/skills/verification-scaffold/references/guards/orphan-test-check.sh.template +102 -0
  810. package/skills/verification-scaffold/references/guards/precommit-guard.sh.template +115 -0
  811. package/skills/verification-scaffold/references/guards/secret-scan-hook.sh.template +176 -0
  812. package/skills/verification-scaffold/references/guards/verification-gates.yml.template +49 -0
  813. package/skills/verification-scaffold/references/guards/wrapper-boundary.sh.template +47 -0
  814. package/skills/verification-scaffold/references/guards.tsv +21 -0
  815. package/skills/verification-scaffold/references/verification-readme.template +55 -0
  816. package/skills/verification-scaffold/scripts/verification-scaffold.sh +785 -0
  817. package/skills/verification-scaffold/test/bite-proof.test.sh +159 -0
  818. package/skills/verification-scaffold/test/generator.test.sh +319 -0
  819. package/skills/verification-scaffold/test/manifest.test.sh +144 -0
  820. package/skills/work/SKILL.md +1480 -0
  821. package/skills/work/references/end-of-work-resume.md +7 -0
  822. package/skills/work/references/hook-test-main-cwd.md +24 -0
  823. package/skills/work/references/key-principles.md +83 -0
  824. package/skills/work/references/property-testing.md +122 -0
  825. package/skills/work/references/sql-security-definer-rpc-scaffold.sql +78 -0
  826. package/skills/work/references/work-agent-teams.md +97 -0
  827. package/skills/work/references/work-lifecycle-parallel.md +147 -0
  828. package/skills/work/references/work-lockfile-bumps.md +97 -0
  829. package/skills/work/references/work-scratch-sandboxes.md +212 -0
  830. package/skills/work/references/work-subagent-fanout.md +61 -0
  831. package/skills/work/references/work-test-harness-sharp-edges.md +73 -0
  832. 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 ]]