@hasna/skills 0.1.62 → 0.1.63

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 (526) hide show
  1. package/README.md +10 -6
  2. package/bin/index.js +14271 -21602
  3. package/bin/mcp.js +3527 -11449
  4. package/bin/migrate.js +53 -3
  5. package/bin/server.js +5140 -2675
  6. package/bin/worker.js +4542 -2129
  7. package/dist/cli/commands/publish.d.ts +2 -0
  8. package/dist/cli/components/App.d.ts +2 -1
  9. package/dist/cli/components/CategorySelect.d.ts +2 -1
  10. package/dist/cli/components/Header.d.ts +2 -1
  11. package/dist/cli/components/InstallProgress.d.ts +2 -1
  12. package/dist/cli/components/SearchView.d.ts +2 -1
  13. package/dist/cli/components/SkillSelect.d.ts +2 -1
  14. package/dist/index.d.ts +4 -1
  15. package/dist/index.js +5094 -13755
  16. package/dist/lib/agent-sync.d.ts +38 -3
  17. package/dist/lib/home-adoption.d.ts +91 -0
  18. package/dist/lib/home-census.d.ts +22 -0
  19. package/dist/lib/home-migration.d.ts +61 -0
  20. package/dist/lib/portable-skills-files.d.ts +21 -1
  21. package/dist/lib/portable-skills-types.d.ts +46 -0
  22. package/dist/lib/pull.d.ts +66 -0
  23. package/dist/lib/remote-client.d.ts +6 -0
  24. package/dist/lib/run-state.d.ts +5 -0
  25. package/dist/lib/skill-bundles.d.ts +54 -0
  26. package/dist/lib/skill-contract.d.ts +35 -0
  27. package/dist/lib/skill-hash.d.ts +77 -0
  28. package/dist/sdk/cancel.d.ts +30 -0
  29. package/dist/sdk/dispatcher.d.ts +40 -0
  30. package/dist/sdk/event-sink.d.ts +2 -0
  31. package/dist/sdk/events.d.ts +79 -0
  32. package/dist/sdk/execution/admission.d.ts +44 -0
  33. package/dist/sdk/execution/dispatchers/e2b.d.ts +17 -0
  34. package/dist/sdk/execution/dispatchers/ecs.d.ts +151 -0
  35. package/dist/sdk/execution/image-profile.d.ts +73 -0
  36. package/dist/sdk/execution/index.d.ts +15 -0
  37. package/dist/sdk/execution/receipts.d.ts +44 -0
  38. package/dist/sdk/execution/state-machine.d.ts +38 -0
  39. package/dist/sdk/execution/storage.d.ts +158 -0
  40. package/dist/sdk/execution/types.d.ts +130 -0
  41. package/dist/sdk/executor.d.ts +17 -0
  42. package/dist/sdk/governance-store.d.ts +156 -0
  43. package/dist/sdk/governance.d.ts +92 -0
  44. package/dist/sdk/index.d.ts +26 -0
  45. package/dist/sdk/index.js +48730 -0
  46. package/dist/sdk/offline.d.ts +16 -0
  47. package/dist/sdk/outputs.d.ts +71 -0
  48. package/dist/sdk/registry.d.ts +28 -0
  49. package/dist/sdk/runs.d.ts +229 -0
  50. package/dist/sdk/server.d.ts +35 -0
  51. package/dist/sdk/spend.d.ts +36 -0
  52. package/dist/sdk/storage.d.ts +25 -0
  53. package/dist/server/app.d.ts +42 -0
  54. package/dist/server/artifact-storage.d.ts +102 -0
  55. package/dist/server/auth.d.ts +5 -0
  56. package/dist/server/config.d.ts +40 -0
  57. package/dist/server/database-url.d.ts +42 -0
  58. package/dist/server/handlers.d.ts +3 -0
  59. package/dist/server/index.d.ts +2 -0
  60. package/dist/server/migrate.d.ts +13 -0
  61. package/dist/server/migrations-dir.d.ts +18 -0
  62. package/dist/server/redaction.d.ts +1 -0
  63. package/dist/server/registry.d.ts +5 -0
  64. package/dist/server/rows.d.ts +23 -0
  65. package/dist/server/skills-api.d.ts +68 -0
  66. package/dist/server/sqlite-store.d.ts +114 -0
  67. package/dist/server/store-fixtures.d.ts +25 -0
  68. package/dist/server/store.d.ts +144 -0
  69. package/dist/server/types.d.ts +242 -0
  70. package/dist/server/worker.d.ts +4 -0
  71. package/dist/storage.js +32 -0
  72. package/docs/skill-standard.md +211 -39
  73. package/migrations/postgres/0003_run_outputs_governance.sql +83 -0
  74. package/migrations/sqlite/0003_run_outputs_governance.sql +58 -0
  75. package/package.json +11 -8
  76. package/schemas/skill.schema.json +181 -0
  77. package/agent-skills/README.md +0 -41
  78. package/agent-skills/fleet-package-rollout/SKILL.md +0 -169
  79. package/agent-skills/inbox/SKILL.md +0 -25
  80. package/agent-skills/inbox/scripts/inbox +0 -109
  81. package/agent-skills/inbox/tests/test_registered_sender_id.sh +0 -92
  82. package/agent-skills/inbox-monitor/SKILL.md +0 -41
  83. package/agent-skills/inbox-monitor/scripts/inbox_monitor.sh +0 -91
  84. package/agent-skills/inbox-monitor/scripts/test_inbox_monitor.sh +0 -71
  85. package/agent-skills/merge-pr/SKILL.md +0 -85
  86. package/agent-skills/merge-pr/references/merge-safety.md +0 -82
  87. package/agent-skills/merge-pr/scripts/merge_pr_guard.py +0 -694
  88. package/agent-skills/merge-pr/scripts/test_merge_pr_guard.py +0 -647
  89. package/agent-skills/merge-pr/tests/fixtures/multi-commit-synthesized.json +0 -28
  90. package/agent-skills/merge-pr/tests/fixtures/trailer-free-provider.json +0 -28
  91. package/agent-skills/skill-goal-execute/SKILL.md +0 -115
  92. package/agent-skills/skill-login/SKILL.md +0 -109
  93. package/agent-skills/skill-project-create/SKILL.md +0 -91
  94. package/agent-skills/skill-publish/SKILL.md +0 -254
  95. package/agent-skills/skill-publish/scripts/capture_registry.js +0 -47
  96. package/agent-skills/skill-publish/scripts/publish_with_git_head.sh +0 -143
  97. package/agent-skills/skill-publish/scripts/test_publish_with_git_head.sh +0 -231
  98. package/skills/_common/auth.ts +0 -45
  99. package/skills/_common/http-client.ts +0 -143
  100. package/skills/_common/index.ts +0 -26
  101. package/skills/_common/install.sh +0 -7
  102. package/skills/_common/installer.ts +0 -72
  103. package/skills/_common/skill-install.ts +0 -37
  104. package/skills/_common/vision.ts +0 -374
  105. package/skills/ad-creative-pack/SKILL.md +0 -55
  106. package/skills/ad-creative-pack/package.json +0 -10
  107. package/skills/analyze-data/CLAUDE.md +0 -16
  108. package/skills/analyze-data/SKILL.md +0 -112
  109. package/skills/analyze-data/package.json +0 -23
  110. package/skills/analyze-data/src/analysis.ts +0 -401
  111. package/skills/analyze-data/src/cli.ts +0 -66
  112. package/skills/analyze-data/src/formatters.ts +0 -235
  113. package/skills/analyze-data/src/index.ts +0 -74
  114. package/skills/analyze-data/src/logger.ts +0 -36
  115. package/skills/analyze-data/src/parsers.ts +0 -57
  116. package/skills/analyze-data/src/stats.ts +0 -151
  117. package/skills/analyze-data/src/types.ts +0 -85
  118. package/skills/analyze-data/tsconfig.json +0 -19
  119. package/skills/api-docs-portal/SKILL.md +0 -84
  120. package/skills/api-docs-portal/package.json +0 -35
  121. package/skills/api-docs-portal/src/index.ts +0 -919
  122. package/skills/api-docs-portal/tsconfig.json +0 -17
  123. package/skills/api-test-suite/CLAUDE.md +0 -19
  124. package/skills/api-test-suite/package.json +0 -27
  125. package/skills/api-test-suite/src/index.ts +0 -381
  126. package/skills/api-test-suite/tsconfig.json +0 -10
  127. package/skills/audio-extract/CLAUDE.md +0 -9
  128. package/skills/audio-extract/SKILL.md +0 -73
  129. package/skills/audio-extract/package.json +0 -23
  130. package/skills/audio-extract/src/index.ts +0 -323
  131. package/skills/audio-extract/tsconfig.json +0 -11
  132. package/skills/bio-sequence-tool/CLAUDE.md +0 -19
  133. package/skills/bio-sequence-tool/package.json +0 -27
  134. package/skills/bio-sequence-tool/src/index.ts +0 -85
  135. package/skills/bio-sequence-tool/tsconfig.json +0 -10
  136. package/skills/blog-article/CLAUDE.md +0 -12
  137. package/skills/blog-article/SKILL.md +0 -55
  138. package/skills/blog-article/package.json +0 -10
  139. package/skills/blog-article/tsconfig.json +0 -10
  140. package/skills/brand-assets/SKILL.md +0 -118
  141. package/skills/brand-assets/package.json +0 -35
  142. package/skills/brand-assets/src/cli.ts +0 -155
  143. package/skills/brand-assets/src/constants.ts +0 -8
  144. package/skills/brand-assets/src/extract.ts +0 -236
  145. package/skills/brand-assets/src/index.ts +0 -668
  146. package/skills/brand-assets/src/types.ts +0 -59
  147. package/skills/brand-assets/tsconfig.json +0 -17
  148. package/skills/brand-kit/SKILL.md +0 -54
  149. package/skills/brand-kit/package.json +0 -10
  150. package/skills/businessactivity/CLAUDE.md +0 -176
  151. package/skills/businessactivity/LICENSE +0 -192
  152. package/skills/businessactivity/README.md +0 -287
  153. package/skills/businessactivity/package.json +0 -25
  154. package/skills/businessactivity/scripts/publish.ts +0 -210
  155. package/skills/businessactivity/src/commands/activity.ts +0 -211
  156. package/skills/businessactivity/src/commands/function.ts +0 -227
  157. package/skills/businessactivity/src/commands/owner.ts +0 -193
  158. package/skills/businessactivity/src/commands/profile.ts +0 -121
  159. package/skills/businessactivity/src/commands/responsibility.ts +0 -264
  160. package/skills/businessactivity/src/commands/team.ts +0 -244
  161. package/skills/businessactivity/src/commands/workflow.ts +0 -359
  162. package/skills/businessactivity/src/index.ts +0 -3
  163. package/skills/businessactivity/src/lib/config.ts +0 -167
  164. package/skills/businessactivity/src/lib/output.ts +0 -76
  165. package/skills/businessactivity/src/lib/paths.ts +0 -79
  166. package/skills/businessactivity/src/lib/storage.ts +0 -95
  167. package/skills/businessactivity/src/types/index.ts +0 -86
  168. package/skills/businessactivity/tsconfig.json +0 -29
  169. package/skills/codefix/LICENSE +0 -192
  170. package/skills/codefix/README.md +0 -232
  171. package/skills/codefix/SKILL.md +0 -94
  172. package/skills/codefix/package.json +0 -21
  173. package/skills/codefix/src/fixers/batch.ts +0 -213
  174. package/skills/codefix/src/fixers/detector.ts +0 -160
  175. package/skills/codefix/src/fixers/index.ts +0 -7
  176. package/skills/codefix/src/fixers/runner.ts +0 -522
  177. package/skills/codefix/src/index-local.ts +0 -431
  178. package/skills/codefix/src/index.ts +0 -4
  179. package/skills/codefix/src/types.ts +0 -211
  180. package/skills/codefix/tsconfig.json +0 -15
  181. package/skills/commitpush/SKILL.md +0 -57
  182. package/skills/commitpush/package.json +0 -33
  183. package/skills/commitpush/src/index.ts +0 -34
  184. package/skills/commitpush/tsconfig.json +0 -17
  185. package/skills/commitpushpr/SKILL.md +0 -55
  186. package/skills/commitpushpr/package.json +0 -33
  187. package/skills/commitpushpr/src/index.ts +0 -34
  188. package/skills/commitpushpr/tsconfig.json +0 -17
  189. package/skills/compress-video/CLAUDE.md +0 -9
  190. package/skills/compress-video/SKILL.md +0 -79
  191. package/skills/compress-video/package.json +0 -23
  192. package/skills/compress-video/src/index.ts +0 -473
  193. package/skills/compress-video/tsconfig.json +0 -11
  194. package/skills/contract-review-report/SKILL.md +0 -52
  195. package/skills/contract-review-report/package.json +0 -10
  196. package/skills/customer-feedback-report/SKILL.md +0 -52
  197. package/skills/customer-feedback-report/package.json +0 -10
  198. package/skills/dashboard-builder/CLAUDE.md +0 -19
  199. package/skills/dashboard-builder/package.json +0 -29
  200. package/skills/dashboard-builder/src/index.ts +0 -150
  201. package/skills/dashboard-builder/tsconfig.json +0 -10
  202. package/skills/data-anonymizer/CLAUDE.md +0 -19
  203. package/skills/data-anonymizer/package.json +0 -27
  204. package/skills/data-anonymizer/src/index.ts +0 -183
  205. package/skills/data-anonymizer/tsconfig.json +0 -10
  206. package/skills/database-explorer/CLAUDE.md +0 -19
  207. package/skills/database-explorer/package.json +0 -29
  208. package/skills/database-explorer/src/index.ts +0 -95
  209. package/skills/database-explorer/tsconfig.json +0 -10
  210. package/skills/diff-viewer/CLAUDE.md +0 -19
  211. package/skills/diff-viewer/package.json +0 -30
  212. package/skills/diff-viewer/src/index.ts +0 -164
  213. package/skills/diff-viewer/tsconfig.json +0 -10
  214. package/skills/doc-read/SKILL.md +0 -45
  215. package/skills/doc-read/package.json +0 -29
  216. package/skills/doc-read/src/index.ts +0 -324
  217. package/skills/doc-read/tsconfig.json +0 -8
  218. package/skills/domainpurchase/LICENSE +0 -192
  219. package/skills/domainpurchase/SKILL.md +0 -29
  220. package/skills/domainpurchase/package.json +0 -30
  221. package/skills/domainpurchase/src/index.ts +0 -3
  222. package/skills/domainpurchase/tsconfig.json +0 -21
  223. package/skills/email-sequence/SKILL.md +0 -53
  224. package/skills/email-sequence/package.json +0 -10
  225. package/skills/experiment-power-calculator/CLAUDE.md +0 -19
  226. package/skills/experiment-power-calculator/package.json +0 -29
  227. package/skills/experiment-power-calculator/src/index.ts +0 -86
  228. package/skills/experiment-power-calculator/tsconfig.json +0 -10
  229. package/skills/extract-frames/CLAUDE.md +0 -19
  230. package/skills/extract-frames/package.json +0 -27
  231. package/skills/extract-frames/src/index.ts +0 -616
  232. package/skills/extract-frames/tsconfig.json +0 -10
  233. package/skills/file-organizer/CLAUDE.md +0 -19
  234. package/skills/file-organizer/package.json +0 -27
  235. package/skills/file-organizer/src/index.ts +0 -91
  236. package/skills/file-organizer/tsconfig.json +0 -10
  237. package/skills/folder-tree/CLAUDE.md +0 -19
  238. package/skills/folder-tree/package.json +0 -29
  239. package/skills/folder-tree/src/index.ts +0 -568
  240. package/skills/folder-tree/tsconfig.json +0 -10
  241. package/skills/form-filler/CLAUDE.md +0 -19
  242. package/skills/form-filler/package.json +0 -29
  243. package/skills/form-filler/src/index.ts +0 -81
  244. package/skills/form-filler/tsconfig.json +0 -10
  245. package/skills/generate-api-client/CLAUDE.md +0 -19
  246. package/skills/generate-api-client/package.json +0 -29
  247. package/skills/generate-api-client/src/generator.ts +0 -47
  248. package/skills/generate-api-client/src/index.ts +0 -92
  249. package/skills/generate-api-client/src/logger.ts +0 -34
  250. package/skills/generate-api-client/src/python-generator.ts +0 -245
  251. package/skills/generate-api-client/src/spec-loader.ts +0 -48
  252. package/skills/generate-api-client/src/type-mappers.ts +0 -79
  253. package/skills/generate-api-client/src/types.ts +0 -76
  254. package/skills/generate-api-client/src/typescript-generator.ts +0 -247
  255. package/skills/generate-api-client/tsconfig.json +0 -10
  256. package/skills/generate-chart/CLAUDE.md +0 -19
  257. package/skills/generate-chart/package.json +0 -27
  258. package/skills/generate-chart/src/index.ts +0 -510
  259. package/skills/generate-chart/tsconfig.json +0 -10
  260. package/skills/generate-dockerfile/CLAUDE.md +0 -19
  261. package/skills/generate-dockerfile/package.json +0 -27
  262. package/skills/generate-dockerfile/src/cli.ts +0 -78
  263. package/skills/generate-dockerfile/src/dockerfile-templates.ts +0 -392
  264. package/skills/generate-dockerfile/src/index.ts +0 -81
  265. package/skills/generate-dockerfile/src/logger.ts +0 -30
  266. package/skills/generate-dockerfile/src/project-detection.ts +0 -68
  267. package/skills/generate-dockerfile/src/support-files.ts +0 -171
  268. package/skills/generate-dockerfile/src/types.ts +0 -29
  269. package/skills/generate-dockerfile/tsconfig.json +0 -10
  270. package/skills/generate-env/CLAUDE.md +0 -19
  271. package/skills/generate-env/package.json +0 -29
  272. package/skills/generate-env/src/cli.ts +0 -85
  273. package/skills/generate-env/src/detection.ts +0 -161
  274. package/skills/generate-env/src/env-data.ts +0 -66
  275. package/skills/generate-env/src/generators.ts +0 -240
  276. package/skills/generate-env/src/index.ts +0 -120
  277. package/skills/generate-env/src/runtime.ts +0 -30
  278. package/skills/generate-env/src/types.ts +0 -32
  279. package/skills/generate-env/tsconfig.json +0 -10
  280. package/skills/generate-favicon/CLAUDE.md +0 -19
  281. package/skills/generate-favicon/package.json +0 -29
  282. package/skills/generate-favicon/src/index.ts +0 -421
  283. package/skills/generate-favicon/tsconfig.json +0 -10
  284. package/skills/generate-qrcode/CLAUDE.md +0 -19
  285. package/skills/generate-qrcode/package.json +0 -30
  286. package/skills/generate-qrcode/src/index.ts +0 -584
  287. package/skills/generate-qrcode/tsconfig.json +0 -10
  288. package/skills/generate-resume/CLAUDE.md +0 -19
  289. package/skills/generate-resume/package.json +0 -27
  290. package/skills/generate-resume/src/cli.ts +0 -157
  291. package/skills/generate-resume/src/index.ts +0 -178
  292. package/skills/generate-resume/src/parsers.ts +0 -95
  293. package/skills/generate-resume/src/renderers.ts +0 -538
  294. package/skills/generate-resume/src/security.ts +0 -39
  295. package/skills/generate-resume/src/types.ts +0 -86
  296. package/skills/generate-resume/tsconfig.json +0 -10
  297. package/skills/generate-sitemap/CLAUDE.md +0 -19
  298. package/skills/generate-sitemap/package.json +0 -27
  299. package/skills/generate-sitemap/src/index.ts +0 -626
  300. package/skills/generate-sitemap/tsconfig.json +0 -10
  301. package/skills/gif-maker/CLAUDE.md +0 -19
  302. package/skills/gif-maker/package.json +0 -30
  303. package/skills/gif-maker/src/index.ts +0 -600
  304. package/skills/gif-maker/tsconfig.json +0 -10
  305. package/skills/hook/LICENSE +0 -192
  306. package/skills/hook/README.md +0 -74
  307. package/skills/hook/SKILL.md +0 -85
  308. package/skills/hook/bunfig.toml +0 -5
  309. package/skills/hook/package.json +0 -28
  310. package/skills/hook/src/commands/create.ts +0 -112
  311. package/skills/hook/src/commands/events.ts +0 -37
  312. package/skills/hook/src/commands/validate.ts +0 -117
  313. package/skills/hook/src/index.ts +0 -118
  314. package/skills/hook/src/templates/root.ts +0 -196
  315. package/skills/hook/src/templates/source.ts +0 -647
  316. package/skills/hook/tsconfig.json +0 -18
  317. package/skills/http-server/CLAUDE.md +0 -19
  318. package/skills/http-server/package.json +0 -29
  319. package/skills/http-server/src/index.ts +0 -51
  320. package/skills/http-server/tsconfig.json +0 -10
  321. package/skills/implementation/LICENSE +0 -192
  322. package/skills/implementation/README.md +0 -53
  323. package/skills/implementation/SKILL.md +0 -57
  324. package/skills/implementation/bunfig.toml +0 -5
  325. package/skills/implementation/package.json +0 -28
  326. package/skills/implementation/src/commands/create.ts +0 -187
  327. package/skills/implementation/src/index.ts +0 -62
  328. package/skills/implementation/tsconfig.json +0 -18
  329. package/skills/implementation-plan/CLAUDE.md +0 -19
  330. package/skills/implementation-plan/package.json +0 -29
  331. package/skills/implementation-plan/src/index.ts +0 -520
  332. package/skills/implementation-plan/tsconfig.json +0 -10
  333. package/skills/implementation-todo/CLAUDE.md +0 -19
  334. package/skills/implementation-todo/package.json +0 -29
  335. package/skills/implementation-todo/src/index.ts +0 -429
  336. package/skills/implementation-todo/tsconfig.json +0 -10
  337. package/skills/invoice/.env.example +0 -3
  338. package/skills/invoice/CLAUDE.md +0 -31
  339. package/skills/invoice/LICENSE +0 -192
  340. package/skills/invoice/README.md +0 -70
  341. package/skills/invoice/package.json +0 -26
  342. package/skills/invoice/src/commands/companies.ts +0 -202
  343. package/skills/invoice/src/commands/config.ts +0 -132
  344. package/skills/invoice/src/commands/generate.ts +0 -177
  345. package/skills/invoice/src/commands/invoices.ts +0 -218
  346. package/skills/invoice/src/index.ts +0 -3
  347. package/skills/invoice/src/lib/api.ts +0 -124
  348. package/skills/invoice/src/lib/storage.ts +0 -171
  349. package/skills/invoice/src/types/index.ts +0 -86
  350. package/skills/invoice/src/utils/logger.ts +0 -33
  351. package/skills/invoice/src/utils/paths.ts +0 -25
  352. package/skills/invoice/tsconfig.json +0 -23
  353. package/skills/invoice-reconciliation/SKILL.md +0 -98
  354. package/skills/invoice-reconciliation/package.json +0 -36
  355. package/skills/invoice-reconciliation/src/index.ts +0 -743
  356. package/skills/invoice-reconciliation/tsconfig.json +0 -17
  357. package/skills/landing-page-pack/SKILL.md +0 -55
  358. package/skills/landing-page-pack/package.json +0 -10
  359. package/skills/latex-table-generator/CLAUDE.md +0 -19
  360. package/skills/latex-table-generator/package.json +0 -29
  361. package/skills/latex-table-generator/src/index.ts +0 -113
  362. package/skills/latex-table-generator/tsconfig.json +0 -10
  363. package/skills/logo-design/SKILL.md +0 -94
  364. package/skills/logo-design/package.json +0 -35
  365. package/skills/logo-design/src/cli.ts +0 -132
  366. package/skills/logo-design/src/constants.ts +0 -5
  367. package/skills/logo-design/src/docs.ts +0 -102
  368. package/skills/logo-design/src/geometry.ts +0 -324
  369. package/skills/logo-design/src/index.ts +0 -212
  370. package/skills/logo-design/src/palette.ts +0 -258
  371. package/skills/logo-design/src/types.ts +0 -50
  372. package/skills/logo-design/tsconfig.json +0 -17
  373. package/skills/lorem-generator/CLAUDE.md +0 -19
  374. package/skills/lorem-generator/package.json +0 -29
  375. package/skills/lorem-generator/src/index.ts +0 -59
  376. package/skills/lorem-generator/tsconfig.json +0 -10
  377. package/skills/managemcp/CLAUDE.md +0 -14
  378. package/skills/managemcp/README.md +0 -24
  379. package/skills/managemcp/package.json +0 -16
  380. package/skills/managemcp/src/index.ts +0 -3
  381. package/skills/managemcp/tsconfig.json +0 -27
  382. package/skills/markdown-validator/CLAUDE.md +0 -19
  383. package/skills/markdown-validator/package.json +0 -29
  384. package/skills/markdown-validator/src/index.ts +0 -92
  385. package/skills/markdown-validator/tsconfig.json +0 -10
  386. package/skills/market-research-report/SKILL.md +0 -51
  387. package/skills/market-research-report/package.json +0 -10
  388. package/skills/meeting-pack/SKILL.md +0 -52
  389. package/skills/meeting-pack/package.json +0 -10
  390. package/skills/merge-pdfs/CLAUDE.md +0 -19
  391. package/skills/merge-pdfs/package.json +0 -31
  392. package/skills/merge-pdfs/src/index.ts +0 -427
  393. package/skills/merge-pdfs/tsconfig.json +0 -10
  394. package/skills/migration-plan-pack/SKILL.md +0 -56
  395. package/skills/migration-plan-pack/package.json +0 -10
  396. package/skills/monitor/SKILL.md +0 -69
  397. package/skills/monitor/package.json +0 -33
  398. package/skills/monitor/src/index.ts +0 -34
  399. package/skills/monitor/tsconfig.json +0 -17
  400. package/skills/one-page-website/SKILL.md +0 -128
  401. package/skills/one-page-website/package.json +0 -34
  402. package/skills/one-page-website/src/design.ts +0 -336
  403. package/skills/one-page-website/src/docs.ts +0 -159
  404. package/skills/one-page-website/src/index.ts +0 -357
  405. package/skills/one-page-website/src/page.ts +0 -340
  406. package/skills/one-page-website/src/styles.ts +0 -508
  407. package/skills/one-page-website/src/types.ts +0 -78
  408. package/skills/one-page-website/tsconfig.json +0 -17
  409. package/skills/pdf-generate/CLAUDE.md +0 -19
  410. package/skills/pdf-generate/SKILL.md +0 -86
  411. package/skills/pdf-generate/package.json +0 -21
  412. package/skills/pdf-generate/src/cli.ts +0 -162
  413. package/skills/pdf-generate/src/html.ts +0 -84
  414. package/skills/pdf-generate/src/index.ts +0 -62
  415. package/skills/pdf-generate/src/markdown.ts +0 -27
  416. package/skills/pdf-generate/src/pdf-writer.ts +0 -78
  417. package/skills/pdf-generate/src/runtime.ts +0 -34
  418. package/skills/pdf-generate/src/security.ts +0 -37
  419. package/skills/pdf-generate/src/templates.ts +0 -311
  420. package/skills/pdf-generate/src/types.ts +0 -28
  421. package/skills/pdf-generate/tsconfig.json +0 -16
  422. package/skills/pdf-to-dataset/SKILL.md +0 -88
  423. package/skills/pdf-to-dataset/package.json +0 -37
  424. package/skills/pdf-to-dataset/src/index.ts +0 -790
  425. package/skills/pdf-to-dataset/tsconfig.json +0 -17
  426. package/skills/pdf-to-markdown/SKILL.md +0 -81
  427. package/skills/pdf-to-markdown/package.json +0 -35
  428. package/skills/pdf-to-markdown/src/index.ts +0 -694
  429. package/skills/pdf-to-markdown/tsconfig.json +0 -17
  430. package/skills/performance-audit-report/SKILL.md +0 -49
  431. package/skills/performance-audit-report/package.json +0 -10
  432. package/skills/pitch-deck/SKILL.md +0 -51
  433. package/skills/pitch-deck/package.json +0 -10
  434. package/skills/product-mockup/SKILL.md +0 -107
  435. package/skills/product-mockup/package.json +0 -32
  436. package/skills/product-mockup/src/cli.ts +0 -150
  437. package/skills/product-mockup/src/design.ts +0 -151
  438. package/skills/product-mockup/src/docs.ts +0 -134
  439. package/skills/product-mockup/src/index.ts +0 -182
  440. package/skills/product-mockup/src/render.ts +0 -407
  441. package/skills/product-mockup/src/types.ts +0 -66
  442. package/skills/product-mockup/tsconfig.json +0 -17
  443. package/skills/proposal-pack/SKILL.md +0 -53
  444. package/skills/proposal-pack/package.json +0 -10
  445. package/skills/read-csv/SKILL.md +0 -62
  446. package/skills/read-csv/package.json +0 -37
  447. package/skills/read-csv/src/index.ts +0 -356
  448. package/skills/read-csv/tsconfig.json +0 -17
  449. package/skills/read-excel/SKILL.md +0 -64
  450. package/skills/read-excel/package.json +0 -36
  451. package/skills/read-excel/src/index.ts +0 -266
  452. package/skills/read-excel/tsconfig.json +0 -17
  453. package/skills/regex-tester/CLAUDE.md +0 -19
  454. package/skills/regex-tester/package.json +0 -27
  455. package/skills/regex-tester/src/index.ts +0 -183
  456. package/skills/regex-tester/tsconfig.json +0 -10
  457. package/skills/repo-onboarding-report/SKILL.md +0 -52
  458. package/skills/repo-onboarding-report/package.json +0 -10
  459. package/skills/scancommitpr/SKILL.md +0 -178
  460. package/skills/scancommitpr/package.json +0 -34
  461. package/skills/scancommitpr/src/index.ts +0 -44
  462. package/skills/scancommitpr/tsconfig.json +0 -13
  463. package/skills/scancommitpush/SKILL.md +0 -174
  464. package/skills/scancommitpush/package.json +0 -32
  465. package/skills/scancommitpush/src/index.ts +0 -44
  466. package/skills/scancommitpush/tsconfig.json +0 -13
  467. package/skills/scientific-figure-check/CLAUDE.md +0 -19
  468. package/skills/scientific-figure-check/package.json +0 -29
  469. package/skills/scientific-figure-check/src/index.ts +0 -83
  470. package/skills/scientific-figure-check/tsconfig.json +0 -10
  471. package/skills/security-audit/CLAUDE.md +0 -19
  472. package/skills/security-audit/package.json +0 -27
  473. package/skills/security-audit/src/index.ts +0 -145
  474. package/skills/security-audit/tsconfig.json +0 -10
  475. package/skills/security-audit-report/SKILL.md +0 -52
  476. package/skills/security-audit-report/package.json +0 -10
  477. package/skills/seo-content-pack/SKILL.md +0 -54
  478. package/skills/seo-content-pack/package.json +0 -10
  479. package/skills/siteanalyze/SKILL.md +0 -25
  480. package/skills/siteanalyze/package.json +0 -27
  481. package/skills/siteanalyze/src/index.ts +0 -592
  482. package/skills/slide-deck-generator/SKILL.md +0 -93
  483. package/skills/slide-deck-generator/package.json +0 -38
  484. package/skills/slide-deck-generator/src/cli.ts +0 -133
  485. package/skills/slide-deck-generator/src/index.ts +0 -148
  486. package/skills/slide-deck-generator/src/model.ts +0 -307
  487. package/skills/slide-deck-generator/src/pptx.ts +0 -143
  488. package/skills/slide-deck-generator/src/render.ts +0 -248
  489. package/skills/slide-deck-generator/src/types.ts +0 -114
  490. package/skills/slide-deck-generator/src/utils.ts +0 -53
  491. package/skills/slide-deck-generator/tsconfig.json +0 -17
  492. package/skills/social-content-calendar/SKILL.md +0 -54
  493. package/skills/social-content-calendar/package.json +0 -10
  494. package/skills/split-pdf/CLAUDE.md +0 -19
  495. package/skills/split-pdf/package.json +0 -30
  496. package/skills/split-pdf/src/index.ts +0 -301
  497. package/skills/split-pdf/tsconfig.json +0 -10
  498. package/skills/statistical-test-selector/CLAUDE.md +0 -19
  499. package/skills/statistical-test-selector/package.json +0 -27
  500. package/skills/statistical-test-selector/src/index.ts +0 -75
  501. package/skills/statistical-test-selector/tsconfig.json +0 -10
  502. package/skills/test-suite-generator/SKILL.md +0 -51
  503. package/skills/test-suite-generator/package.json +0 -10
  504. package/skills/tmux-session/SKILL.md +0 -109
  505. package/skills/tmux-session/package.json +0 -33
  506. package/skills/tmux-session/src/index.ts +0 -34
  507. package/skills/tmux-session/tsconfig.json +0 -17
  508. package/skills/todos-plan/SKILL.md +0 -363
  509. package/skills/todos-plan/agents/openai.yaml +0 -4
  510. package/skills/todos-plan/package.json +0 -9
  511. package/skills/todos-plan/src/index.ts +0 -68
  512. package/skills/tsconfig.base.json +0 -12
  513. package/skills/validate-config/CLAUDE.md +0 -19
  514. package/skills/validate-config/package.json +0 -29
  515. package/skills/validate-config/src/index.ts +0 -56
  516. package/skills/validate-config/tsconfig.json +0 -10
  517. package/skills/video-downloader/CLAUDE.md +0 -19
  518. package/skills/video-downloader/package.json +0 -29
  519. package/skills/video-downloader/src/index.ts +0 -561
  520. package/skills/video-downloader/tsconfig.json +0 -10
  521. package/skills/video-highlight-pack/SKILL.md +0 -54
  522. package/skills/video-highlight-pack/package.json +0 -10
  523. package/skills/watermark/CLAUDE.md +0 -19
  524. package/skills/watermark/package.json +0 -32
  525. package/skills/watermark/src/index.ts +0 -587
  526. package/skills/watermark/tsconfig.json +0 -10
@@ -1,647 +0,0 @@
1
- #!/usr/bin/env python3
2
-
3
- from __future__ import annotations
4
-
5
- import importlib.util
6
- import json
7
- import subprocess
8
- import sys
9
- import tempfile
10
- import unittest
11
- from datetime import datetime, timezone
12
- from pathlib import Path
13
-
14
-
15
- SCRIPT = Path(__file__).with_name("merge_pr_guard.py")
16
- FIXTURES = Path(__file__).parents[1] / "tests" / "fixtures"
17
- sys.dont_write_bytecode = True
18
- SPEC = importlib.util.spec_from_file_location("merge_pr_guard", SCRIPT)
19
- assert SPEC and SPEC.loader
20
- GUARD = importlib.util.module_from_spec(SPEC)
21
- SPEC.loader.exec_module(GUARD)
22
-
23
- REPO = "hasna/tai"
24
- PR_NUMBER = 4
25
- HEAD_SHA = "2797e3264c416018c06608434c0c57340f647330"
26
- ACCEPTANCE_SCOPE = "skills-merge-trailer-hardening-v1"
27
- TASK_ID = "fae9ac3b-5af9-4f15-aaca-748e2a5da394"
28
-
29
-
30
- def artifact(identity: str) -> dict[str, object]:
31
- return {
32
- "repository": REPO,
33
- "pr_number": PR_NUMBER,
34
- "head_sha": HEAD_SHA,
35
- "acceptance_scope": ACCEPTANCE_SCOPE,
36
- "reviewer_identity": identity,
37
- "timestamp": datetime.now(timezone.utc).isoformat(),
38
- "verdict": "approved",
39
- "checked_risks_summary": "Checked exact-head merge and message provenance.",
40
- "blocking_findings": [],
41
- }
42
-
43
-
44
- def preflight(mode: str = "immediate-merge", verdict: str = "mergeable") -> dict[str, object]:
45
- snapshot: dict[str, object] = {
46
- "task_id": TASK_ID,
47
- "mode": mode,
48
- "risk_tier": {"declared": "elevated", "effective": "elevated", "source": "explicit"},
49
- "acceptance_scope": ACCEPTANCE_SCOPE,
50
- "required_reviewer_artifacts": 2,
51
- "repair_cycles": {"count": 0, "cap": 2},
52
- "verdict": verdict,
53
- "repo": REPO,
54
- "pr_number": PR_NUMBER,
55
- "pr_url": "https://github.com/hasna/tai/pull/4",
56
- "base": "main",
57
- "head": "hasna:ci/provider-native-validation",
58
- "head_sha": HEAD_SHA,
59
- "merge_state": {
60
- "state": "OPEN",
61
- "is_draft": False,
62
- "mergeable": "MERGEABLE",
63
- "merge_state_status": "CLEAN",
64
- "review_decision": "APPROVED",
65
- },
66
- "checks": [{"name": "ci", "bucket": "pass", "state": "SUCCESS"}],
67
- "reviews": [{"author": {"login": "reviewer-a"}, "state": "APPROVED"}],
68
- "reviewer_artifacts": [artifact("reviewer-a"), artifact("reviewer-b")],
69
- "worker_identity": "worker",
70
- "executor_identity": "executor",
71
- "branch_policy": {"protected": True, "queue_required": mode == "merge-queue"},
72
- "blocking_reasons": [],
73
- "warnings": [],
74
- "observed_at": datetime.now(timezone.utc).isoformat(),
75
- }
76
- if verdict == "pending":
77
- snapshot["merge_state"]["merge_state_status"] = "UNSTABLE"
78
- snapshot["checks"] = [{"name": "ci", "bucket": "pending", "state": "PENDING"}]
79
- return snapshot
80
-
81
-
82
- class GuardCliTests(unittest.TestCase):
83
- def run_cli(self, *args: str) -> subprocess.CompletedProcess[str]:
84
- return subprocess.run(
85
- [sys.executable, str(SCRIPT), *args],
86
- check=False,
87
- text=True,
88
- stdout=subprocess.PIPE,
89
- stderr=subprocess.PIPE,
90
- )
91
-
92
- def build(
93
- self,
94
- directory: Path,
95
- *args: str,
96
- snapshot: dict[str, object] | None = None,
97
- expected_scope: str = ACCEPTANCE_SCOPE,
98
- expected_repair_cycle_count: int = 0,
99
- ):
100
- snapshot_path = directory / "preflight.json"
101
- snapshot_path.write_text(json.dumps(snapshot or preflight()), encoding="utf-8")
102
- result = self.run_cli(
103
- "build",
104
- "--preflight",
105
- str(snapshot_path),
106
- "--task-id",
107
- TASK_ID,
108
- "--acceptance-scope",
109
- expected_scope,
110
- "--repair-cycle-count",
111
- str(expected_repair_cycle_count),
112
- *args,
113
- )
114
- return result, json.loads(result.stdout) if result.stdout else None
115
-
116
- def provenance(
117
- self, directory: Path, body: str = ""
118
- ) -> tuple[Path, Path, dict[str, object]]:
119
- result, plan = self.build(
120
- directory,
121
- "--strategy",
122
- "squash",
123
- "--subject",
124
- "fix: safe",
125
- f"--body={body}",
126
- )
127
- if result.returncode != 0 or not isinstance(plan, dict):
128
- raise AssertionError(result.stderr)
129
- plan_path = directory / "command-plan.json"
130
- plan_path.write_text(json.dumps(plan), encoding="utf-8")
131
- return directory / "preflight.json", plan_path, plan
132
-
133
- def postverify_contract_args(
134
- self,
135
- preflight_path: Path,
136
- plan_path: Path,
137
- plan: dict[str, object],
138
- repo: str = REPO,
139
- pr_number: int = PR_NUMBER,
140
- ) -> list[str]:
141
- return [
142
- "--repo",
143
- repo,
144
- "--pr",
145
- str(pr_number),
146
- "--task-id",
147
- TASK_ID,
148
- "--mode",
149
- "immediate-merge",
150
- "--acceptance-scope",
151
- ACCEPTANCE_SCOPE,
152
- "--repair-cycle-count",
153
- "0",
154
- "--expected-base",
155
- "main",
156
- "--expected-head-sha",
157
- HEAD_SHA,
158
- "--preflight-sha256",
159
- str(plan["preflight_sha256"]),
160
- "--command-argv-sha256",
161
- str(plan["command_argv_sha256"]),
162
- "--preflight",
163
- str(preflight_path),
164
- "--command-plan",
165
- str(plan_path),
166
- ]
167
-
168
- def test_multi_commit_squash_builds_explicit_message_and_exact_head_cas(self) -> None:
169
- raw = json.loads((FIXTURES / "multi-commit-synthesized.json").read_text(encoding="utf-8"))
170
- self.assertEqual(len(raw["source_commits"]), 2)
171
- self.assertTrue(all(not GUARD.forbidden_trailer_lines(commit["message"]) for commit in raw["source_commits"]))
172
- with tempfile.TemporaryDirectory() as temporary:
173
- result, plan = self.build(
174
- Path(temporary),
175
- "--strategy",
176
- "squash",
177
- "--subject",
178
- "ci: add provider-native validation workflow",
179
- )
180
- self.assertEqual(result.returncode, 0, result.stderr)
181
- argv = plan["argv"]
182
- self.assertEqual(argv[:3], ["gh", "pr", "merge"])
183
- self.assertIn("--squash", argv)
184
- self.assertEqual(argv[argv.index("--subject") + 1], "ci: add provider-native validation workflow")
185
- self.assertEqual(argv[argv.index("--body") + 1], "")
186
- self.assertEqual(argv[argv.index("--match-head-commit") + 1], HEAD_SHA)
187
- self.assertEqual(plan["base"], "main")
188
- self.assertEqual(len(plan["preflight_sha256"]), 64)
189
- self.assertEqual(len(plan["command_argv_sha256"]), 64)
190
- self.assertTrue({"--admin", "--force", "--delete-branch"}.isdisjoint(argv))
191
- self.assertNotIn("push", argv)
192
-
193
- def test_omitted_and_explicit_empty_body_are_identical(self) -> None:
194
- with tempfile.TemporaryDirectory() as temporary:
195
- directory = Path(temporary)
196
- omitted, omitted_plan = self.build(directory, "--strategy", "squash", "--subject", "fix: safe")
197
- explicit, explicit_plan = self.build(
198
- directory, "--strategy", "squash", "--subject", "fix: safe", "--body", ""
199
- )
200
- self.assertEqual(omitted.returncode, 0)
201
- self.assertEqual(explicit.returncode, 0)
202
- self.assertEqual(omitted_plan["argv"], explicit_plan["argv"])
203
-
204
- def test_custom_body_normalizes_line_endings_deterministically(self) -> None:
205
- with tempfile.TemporaryDirectory() as temporary:
206
- result, plan = self.build(
207
- Path(temporary),
208
- "--strategy",
209
- "squash",
210
- "--subject",
211
- "fix: safe",
212
- "--body",
213
- "first\r\nsecond\rthird",
214
- )
215
- self.assertEqual(result.returncode, 0, result.stderr)
216
- self.assertEqual(plan["argv"][plan["argv"].index("--body") + 1], "first\nsecond\nthird")
217
-
218
- def test_co_authored_by_case_and_whitespace_variants_are_rejected(self) -> None:
219
- variants = [
220
- "Co-Authored-By: person <person@example.invalid>",
221
- "co-authored-by : person <person@example.invalid>",
222
- "\tCO - AUTHORED - BY\t: person <person@example.invalid>",
223
- "Co Authored By: person <person@example.invalid>",
224
- ]
225
- for variant in variants:
226
- with self.subTest(variant=variant), tempfile.TemporaryDirectory() as temporary:
227
- result, _ = self.build(
228
- Path(temporary),
229
- "--strategy",
230
- "squash",
231
- "--subject",
232
- "fix: safe",
233
- "--body",
234
- f"Summary\n\n{variant}",
235
- )
236
- self.assertEqual(result.returncode, 2)
237
- self.assertIn("forbidden Co-Authored-By trailer", result.stderr)
238
-
239
- def test_co_authored_by_subject_is_rejected(self) -> None:
240
- with tempfile.TemporaryDirectory() as temporary:
241
- result, _ = self.build(
242
- Path(temporary),
243
- "--strategy",
244
- "squash",
245
- "--subject",
246
- "CO - AUTHORED - BY : person <person@example.invalid>",
247
- )
248
- self.assertEqual(result.returncode, 2)
249
- self.assertIn("forbidden Co-Authored-By trailer", result.stderr)
250
-
251
- def test_auto_merge_requires_explicit_delayed_intent(self) -> None:
252
- with tempfile.TemporaryDirectory() as temporary:
253
- directory = Path(temporary)
254
- rejected, _ = self.build(
255
- directory,
256
- "--strategy",
257
- "squash",
258
- "--subject",
259
- "fix: safe",
260
- snapshot=preflight("auto-merge"),
261
- )
262
- accepted, plan = self.build(
263
- directory,
264
- "--strategy",
265
- "squash",
266
- "--subject",
267
- "fix: safe",
268
- "--delayed-intent",
269
- snapshot=preflight("auto-merge"),
270
- )
271
- self.assertEqual(rejected.returncode, 2)
272
- self.assertEqual(accepted.returncode, 0, accepted.stderr)
273
- self.assertIn("--auto", plan["argv"])
274
-
275
- def test_non_mergeable_or_identity_colliding_preflight_fails_closed(self) -> None:
276
- blocked = preflight()
277
- blocked["verdict"] = "not_mergeable"
278
- collision = preflight()
279
- collision["reviewer_artifacts"][0]["reviewer_identity"] = "executor"
280
- for snapshot in (blocked, collision):
281
- with tempfile.TemporaryDirectory() as temporary:
282
- result, _ = self.build(
283
- Path(temporary),
284
- "--strategy",
285
- "squash",
286
- "--subject",
287
- "fix: safe",
288
- snapshot=snapshot,
289
- )
290
- self.assertEqual(result.returncode, 2)
291
-
292
- def test_missing_worker_or_branch_policy_evidence_fails_closed(self) -> None:
293
- missing_worker = preflight()
294
- del missing_worker["worker_identity"]
295
- missing_policy = preflight()
296
- del missing_policy["branch_policy"]
297
- for snapshot in (missing_worker, missing_policy):
298
- with tempfile.TemporaryDirectory() as temporary:
299
- result, _ = self.build(
300
- Path(temporary),
301
- "--strategy",
302
- "squash",
303
- "--subject",
304
- "fix: safe",
305
- snapshot=snapshot,
306
- )
307
- self.assertEqual(result.returncode, 2)
308
-
309
- def test_missing_review_decision_and_stateless_check_fail_closed(self) -> None:
310
- missing_decision = preflight()
311
- del missing_decision["merge_state"]["review_decision"]
312
- blank_decision = preflight()
313
- blank_decision["merge_state"]["review_decision"] = ""
314
- invented_decision = preflight()
315
- invented_decision["merge_state"]["review_decision"] = "INVENTED"
316
- stateless_check = preflight()
317
- stateless_check["checks"] = [{}]
318
- completed_without_conclusion = preflight()
319
- completed_without_conclusion["checks"] = [{"state": "COMPLETED"}]
320
- for snapshot in (
321
- missing_decision,
322
- blank_decision,
323
- invented_decision,
324
- stateless_check,
325
- completed_without_conclusion,
326
- ):
327
- with tempfile.TemporaryDirectory() as temporary:
328
- result, _ = self.build(
329
- Path(temporary),
330
- "--strategy",
331
- "squash",
332
- "--subject",
333
- "fix: safe",
334
- snapshot=snapshot,
335
- )
336
- self.assertEqual(result.returncode, 2)
337
-
338
- def test_empty_or_conflicting_check_and_review_evidence_fails_closed(self) -> None:
339
- empty_checks = preflight()
340
- empty_checks["checks"] = []
341
- conflicting_check = preflight()
342
- conflicting_check["checks"] = [{"bucket": "pass", "state": "invented"}]
343
- empty_reviews = preflight()
344
- empty_reviews["reviews"] = []
345
- malformed_review = preflight()
346
- malformed_review["reviews"] = [{"state": "APPROVED"}]
347
- blocking_review = preflight()
348
- blocking_review["reviews"] = [
349
- {"author": {"login": "reviewer-a"}, "state": "CHANGES_REQUESTED"}
350
- ]
351
- for snapshot in (
352
- empty_checks,
353
- conflicting_check,
354
- empty_reviews,
355
- malformed_review,
356
- blocking_review,
357
- ):
358
- with tempfile.TemporaryDirectory() as temporary:
359
- result, _ = self.build(
360
- Path(temporary),
361
- "--strategy",
362
- "squash",
363
- "--subject",
364
- "fix: safe",
365
- snapshot=snapshot,
366
- )
367
- self.assertEqual(result.returncode, 2)
368
-
369
- def test_merge_and_rebase_strategies_have_no_bypass(self) -> None:
370
- for strategy in ("merge", "rebase"):
371
- with self.subTest(strategy=strategy), tempfile.TemporaryDirectory() as temporary:
372
- result, _ = self.build(
373
- Path(temporary),
374
- "--strategy",
375
- strategy,
376
- "--subject",
377
- "fix: safe",
378
- )
379
- self.assertEqual(result.returncode, 2)
380
-
381
- def test_scope_cycle_and_freshness_are_executor_bound(self) -> None:
382
- changed_scope = preflight()
383
- changed_scope["acceptance_scope"] = "changed-scope"
384
- changed_scope["reviewer_artifacts"][0]["acceptance_scope"] = "changed-scope"
385
- changed_scope["reviewer_artifacts"][1]["acceptance_scope"] = "changed-scope"
386
- changed_cycle = preflight()
387
- changed_cycle["repair_cycles"]["count"] = 1
388
- stale = preflight()
389
- stale["observed_at"] = "2020-01-01T00:00:00Z"
390
- for snapshot in (changed_scope, changed_cycle, stale):
391
- with tempfile.TemporaryDirectory() as temporary:
392
- result, _ = self.build(
393
- Path(temporary),
394
- "--strategy",
395
- "squash",
396
- "--subject",
397
- "fix: safe",
398
- snapshot=snapshot,
399
- )
400
- self.assertEqual(result.returncode, 2)
401
-
402
- def test_boolean_counts_and_unicode_equivalent_reviewers_fail_closed(self) -> None:
403
- boolean_count = preflight()
404
- boolean_count["risk_tier"] = {"declared": "routine", "effective": "routine", "source": "explicit"}
405
- boolean_count["required_reviewer_artifacts"] = True
406
- boolean_count["repair_cycles"]["cap"] = 1
407
- boolean_count["reviewer_artifacts"] = boolean_count["reviewer_artifacts"][:1]
408
- boolean_cap = preflight()
409
- boolean_cap["risk_tier"] = {"declared": "routine", "effective": "routine", "source": "explicit"}
410
- boolean_cap["required_reviewer_artifacts"] = 1
411
- boolean_cap["repair_cycles"]["cap"] = True
412
- boolean_cap["reviewer_artifacts"] = boolean_cap["reviewer_artifacts"][:1]
413
- duplicate_reviewer = preflight()
414
- duplicate_reviewer["reviewer_artifacts"][0]["reviewer_identity"] = "reviewer-\u212a"
415
- duplicate_reviewer["reviewer_artifacts"][1]["reviewer_identity"] = "reviewer-K"
416
- for snapshot in (boolean_count, boolean_cap, duplicate_reviewer):
417
- with tempfile.TemporaryDirectory() as temporary:
418
- result, _ = self.build(
419
- Path(temporary),
420
- "--strategy",
421
- "squash",
422
- "--subject",
423
- "fix: safe",
424
- snapshot=snapshot,
425
- )
426
- self.assertEqual(result.returncode, 2)
427
-
428
- def test_stale_artifact_and_failed_check_fail_closed(self) -> None:
429
- stale = preflight()
430
- stale["reviewer_artifacts"][0]["timestamp"] = "2020-01-01T00:00:00Z"
431
- failed_check = preflight()
432
- failed_check["checks"] = [{"name": "ci", "bucket": "fail", "state": "FAILURE"}]
433
- for snapshot in (stale, failed_check):
434
- with tempfile.TemporaryDirectory() as temporary:
435
- result, _ = self.build(
436
- Path(temporary),
437
- "--strategy",
438
- "squash",
439
- "--subject",
440
- "fix: safe",
441
- snapshot=snapshot,
442
- )
443
- self.assertEqual(result.returncode, 2)
444
-
445
- def test_merge_queue_has_exact_head_cas_and_no_strategy_or_mutation_flags(self) -> None:
446
- with tempfile.TemporaryDirectory() as temporary:
447
- result, plan = self.build(Path(temporary), snapshot=preflight("merge-queue"))
448
- self.assertEqual(result.returncode, 0, result.stderr)
449
- argv = plan["argv"]
450
- self.assertEqual(argv[argv.index("--match-head-commit") + 1], HEAD_SHA)
451
- self.assertTrue(
452
- {"--squash", "--merge", "--rebase", "--admin", "--force", "--delete-branch", "--auto"}.isdisjoint(argv)
453
- )
454
-
455
- def test_pending_merge_queue_requires_delayed_intent_without_auto_flag(self) -> None:
456
- pending = preflight("merge-queue", "pending")
457
- with tempfile.TemporaryDirectory() as temporary:
458
- directory = Path(temporary)
459
- rejected, _ = self.build(directory, snapshot=pending)
460
- accepted, plan = self.build(directory, "--delayed-intent", snapshot=pending)
461
- self.assertEqual(rejected.returncode, 2)
462
- self.assertEqual(accepted.returncode, 0, accepted.stderr)
463
- self.assertNotIn("--auto", plan["argv"])
464
- self.assertIn("--match-head-commit", plan["argv"])
465
-
466
- def test_synthesized_provider_trailer_writes_failed_receipt(self) -> None:
467
- with tempfile.TemporaryDirectory() as temporary:
468
- directory = Path(temporary)
469
- preflight_path, plan_path, plan = self.provenance(directory)
470
- receipt = directory / "postverify.json"
471
- result = self.run_cli(
472
- "postverify",
473
- *self.postverify_contract_args(preflight_path, plan_path, plan),
474
- "--fixture",
475
- str(FIXTURES / "multi-commit-synthesized.json"),
476
- "--receipt",
477
- str(receipt),
478
- )
479
- durable = json.loads(receipt.read_text(encoding="utf-8"))
480
- self.assertEqual(result.returncode, 1)
481
- self.assertEqual(durable["outcome"], "failed")
482
- self.assertIn("forbidden_co_authored_by_trailer", durable["failure_reasons"])
483
- self.assertTrue(durable["forbidden_trailer_line_numbers"])
484
- self.assertNotIn("message", durable)
485
- self.assertEqual(durable["evidence_source"], "fixture")
486
- self.assertIs(durable["authoritative"], False)
487
-
488
- def test_trailer_free_fixture_is_clean_but_cannot_complete_live_postverify(self) -> None:
489
- with tempfile.TemporaryDirectory() as temporary:
490
- directory = Path(temporary)
491
- preflight_path, plan_path, plan = self.provenance(directory)
492
- receipt = directory / "postverify.json"
493
- result = self.run_cli(
494
- "postverify",
495
- *self.postverify_contract_args(preflight_path, plan_path, plan),
496
- "--fixture",
497
- str(FIXTURES / "trailer-free-provider.json"),
498
- "--receipt",
499
- str(receipt),
500
- )
501
- durable = json.loads(receipt.read_text(encoding="utf-8"))
502
- self.assertEqual(result.returncode, 1, result.stderr)
503
- self.assertEqual(durable["outcome"], "fixture_clean")
504
- self.assertEqual(durable["forbidden_trailer_line_numbers"], [])
505
- self.assertEqual(durable["message_policy"], "forbidden_co_authored_by_trailer_absent")
506
- self.assertEqual(durable["task_id"], TASK_ID)
507
- self.assertEqual(durable["mode"], "immediate-merge")
508
- self.assertEqual(durable["acceptance_scope"], ACCEPTANCE_SCOPE)
509
- self.assertEqual(durable["repair_cycle_count"], 0)
510
- self.assertEqual(durable["preflight_sha256"], plan["preflight_sha256"])
511
- self.assertEqual(durable["command_argv_sha256"], plan["command_argv_sha256"])
512
- self.assertEqual(durable["provider_url"], "https://github.com/hasna/tai/pull/4")
513
- self.assertEqual(durable["provider_base"], "main")
514
- self.assertEqual(durable["evidence_source"], "fixture")
515
- self.assertIs(durable["authoritative"], False)
516
-
517
- def test_fixture_target_mismatch_writes_failed_non_authoritative_receipt(self) -> None:
518
- with tempfile.TemporaryDirectory() as temporary:
519
- directory = Path(temporary)
520
- preflight_path, plan_path, plan = self.provenance(directory)
521
- receipt = directory / "postverify.json"
522
- result = self.run_cli(
523
- "postverify",
524
- *self.postverify_contract_args(
525
- preflight_path,
526
- plan_path,
527
- plan,
528
- repo="hasna/not-tai",
529
- pr_number=999,
530
- ),
531
- "--fixture",
532
- str(FIXTURES / "trailer-free-provider.json"),
533
- "--receipt",
534
- str(receipt),
535
- )
536
- durable = json.loads(receipt.read_text(encoding="utf-8"))
537
- self.assertEqual(result.returncode, 1)
538
- self.assertEqual(durable["outcome"], "failed")
539
- self.assertNotEqual(durable.get("authoritative"), True)
540
-
541
- def test_postverify_recomputes_preflight_and_rejects_plan_provenance_mismatch(self) -> None:
542
- with tempfile.TemporaryDirectory() as temporary:
543
- directory = Path(temporary)
544
- preflight_path, plan_path, plan = self.provenance(directory)
545
- plan["preflight_sha256"] = "f" * 64
546
- plan_path.write_text(json.dumps(plan), encoding="utf-8")
547
- receipt = directory / "postverify.json"
548
- result = self.run_cli(
549
- "postverify",
550
- *self.postverify_contract_args(preflight_path, plan_path, plan),
551
- "--fixture",
552
- str(FIXTURES / "trailer-free-provider.json"),
553
- "--receipt",
554
- str(receipt),
555
- )
556
- durable = json.loads(receipt.read_text(encoding="utf-8"))
557
- self.assertEqual(result.returncode, 1)
558
- self.assertEqual(durable["outcome"], "failed")
559
- self.assertIs(durable["authoritative"], False)
560
-
561
- def test_postverify_rejects_command_plan_argv_mutation(self) -> None:
562
- with tempfile.TemporaryDirectory() as temporary:
563
- directory = Path(temporary)
564
- preflight_path, plan_path, plan = self.provenance(directory)
565
- plan["argv"].append("--admin")
566
- plan_path.write_text(json.dumps(plan), encoding="utf-8")
567
- receipt = directory / "postverify.json"
568
- result = self.run_cli(
569
- "postverify",
570
- *self.postverify_contract_args(preflight_path, plan_path, plan),
571
- "--fixture",
572
- str(FIXTURES / "trailer-free-provider.json"),
573
- "--receipt",
574
- str(receipt),
575
- )
576
- durable = json.loads(receipt.read_text(encoding="utf-8"))
577
- self.assertEqual(result.returncode, 1)
578
- self.assertEqual(durable["outcome"], "failed")
579
- self.assertIs(durable["authoritative"], False)
580
-
581
- def test_postverify_rejects_saved_subject_or_body_mutation(self) -> None:
582
- for option in ("--subject", "--body"):
583
- with self.subTest(option=option), tempfile.TemporaryDirectory() as temporary:
584
- directory = Path(temporary)
585
- preflight_path, plan_path, plan = self.provenance(directory)
586
- option_index = plan["argv"].index(option)
587
- plan["argv"][option_index + 1] = "changed but trailer-free"
588
- plan_path.write_text(json.dumps(plan), encoding="utf-8")
589
- receipt = directory / "postverify.json"
590
- result = self.run_cli(
591
- "postverify",
592
- *self.postverify_contract_args(preflight_path, plan_path, plan),
593
- "--fixture",
594
- str(FIXTURES / "trailer-free-provider.json"),
595
- "--receipt",
596
- str(receipt),
597
- )
598
- durable = json.loads(receipt.read_text(encoding="utf-8"))
599
- self.assertEqual(result.returncode, 1)
600
- self.assertEqual(durable["outcome"], "failed")
601
- self.assertTrue(
602
- any("command argv digest mismatch" in reason for reason in durable["failure_reasons"])
603
- )
604
- self.assertIs(durable["authoritative"], False)
605
-
606
- def test_postverify_persists_failed_receipt_for_non_utf8_plan(self) -> None:
607
- with tempfile.TemporaryDirectory() as temporary:
608
- directory = Path(temporary)
609
- preflight_path, plan_path, plan = self.provenance(directory)
610
- plan_path.write_bytes(b"\xff")
611
- receipt = directory / "postverify.json"
612
- result = self.run_cli(
613
- "postverify",
614
- *self.postverify_contract_args(preflight_path, plan_path, plan),
615
- "--fixture",
616
- str(FIXTURES / "trailer-free-provider.json"),
617
- "--receipt",
618
- str(receipt),
619
- )
620
- durable = json.loads(receipt.read_text(encoding="utf-8"))
621
- self.assertEqual(result.returncode, 1)
622
- self.assertEqual(durable["outcome"], "failed")
623
- self.assertIs(durable["authoritative"], False)
624
- self.assertNotIn("Traceback", result.stderr)
625
-
626
- def test_literal_command_words_remain_custom_body_data(self) -> None:
627
- for body in ("push", "--admin"):
628
- with self.subTest(body=body), tempfile.TemporaryDirectory() as temporary:
629
- directory = Path(temporary)
630
- preflight_path, plan_path, plan = self.provenance(directory, body)
631
- receipt = directory / "postverify.json"
632
- result = self.run_cli(
633
- "postverify",
634
- *self.postverify_contract_args(preflight_path, plan_path, plan),
635
- "--fixture",
636
- str(FIXTURES / "trailer-free-provider.json"),
637
- "--receipt",
638
- str(receipt),
639
- )
640
- durable = json.loads(receipt.read_text(encoding="utf-8"))
641
- self.assertEqual(result.returncode, 1)
642
- self.assertEqual(durable["outcome"], "fixture_clean")
643
- self.assertIs(durable["authoritative"], False)
644
-
645
-
646
- if __name__ == "__main__":
647
- unittest.main()
@@ -1,28 +0,0 @@
1
- {
2
- "pr_view": {
3
- "state": "MERGED",
4
- "mergedAt": "2026-07-23T15:36:23Z",
5
- "mergeCommit": {
6
- "oid": "03b55df060fa034ad31a67fa14d35be81297f59c"
7
- },
8
- "headRefOid": "2797e3264c416018c06608434c0c57340f647330",
9
- "baseRefName": "main",
10
- "url": "https://github.com/hasna/tai/pull/4"
11
- },
12
- "source_commits": [
13
- {
14
- "oid": "5d38cd4fe95556a06f7d9f31481ce88c8bb78e85",
15
- "message": "ci: add provider-native validation workflow"
16
- },
17
- {
18
- "oid": "2797e3264c416018c06608434c0c57340f647330",
19
- "message": "ci: disable setup action cache and token"
20
- }
21
- ],
22
- "commit": {
23
- "sha": "03b55df060fa034ad31a67fa14d35be81297f59c",
24
- "commit": {
25
- "message": "ci: add provider-native validation workflow (#4)\n\n* ci: add provider-native validation workflow\n\n* ci: disable setup action cache and token\n\n---------\n\nCo-authored-by: fixture-user <fixture@example.invalid>"
26
- }
27
- }
28
- }