@prismer/runtime 2.0.7 → 2.2.55

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 (291) hide show
  1. package/CHANGELOG.md +3631 -0
  2. package/README.md +34 -12
  3. package/apc/skills/FIELD-DICTIONARY.md +111 -0
  4. package/apc/skills/bug-reproduce/SKILL.md +150 -0
  5. package/apc/skills/bug-reproduce/skill.json +96 -0
  6. package/apc/skills/code-review/SKILL.md +198 -0
  7. package/apc/skills/code-review/skill.json +124 -0
  8. package/apc/skills/design-review/SKILL.md +122 -0
  9. package/apc/skills/design-review/skill.json +88 -0
  10. package/apc/skills/doc-sync/SKILL.md +168 -0
  11. package/apc/skills/doc-sync/skill.json +81 -0
  12. package/apc/skills/env-doctor/SKILL.md +194 -0
  13. package/apc/skills/env-doctor/skill.json +209 -0
  14. package/apc/skills/git-ops/SKILL.md +189 -0
  15. package/apc/skills/git-ops/skill.json +94 -0
  16. package/apc/skills/impact-trace/SKILL.md +168 -0
  17. package/apc/skills/impact-trace/skill.json +104 -0
  18. package/apc/skills/observability/SKILL.md +195 -0
  19. package/apc/skills/observability/skill.json +116 -0
  20. package/apc/skills/release-db-config-sync/SKILL.md +186 -0
  21. package/apc/skills/release-db-config-sync/skill.json +109 -0
  22. package/apc/skills/release-ota-promote/SKILL.md +195 -0
  23. package/apc/skills/release-ota-promote/skill.json +176 -0
  24. package/apc/skills/release-preflight/SKILL.md +174 -0
  25. package/apc/skills/release-preflight/skill.json +175 -0
  26. package/apc/skills/release-rollback/SKILL.md +214 -0
  27. package/apc/skills/release-rollback/skill.json +230 -0
  28. package/apc/skills/release-tag/SKILL.md +194 -0
  29. package/apc/skills/release-tag/skill.json +94 -0
  30. package/apc/skills/releasing-prod/SKILL.md +49 -0
  31. package/apc/skills/releasing-test/SKILL.md +135 -0
  32. package/apc/skills/sdk-release/SKILL.md +200 -0
  33. package/apc/skills/spec-intake/SKILL.md +169 -0
  34. package/apc/skills/spec-intake/skill.json +93 -0
  35. package/apc/skills/test-result-feedback/SKILL.md +239 -0
  36. package/apc/skills/test-result-feedback/skill.json +193 -0
  37. package/apc/skills/test-runner/SKILL.md +169 -0
  38. package/apc/skills/test-runner/skill.json +103 -0
  39. package/apc/skills/ui-align/SKILL.md +209 -0
  40. package/apc/skills/ui-align/skill.json +114 -0
  41. package/apc/skills/ui-canvas/SKILL.md +148 -0
  42. package/apc/skills/ui-canvas/skill.json +127 -0
  43. package/built-in-skills/agent-coordination/SKILL.md +257 -0
  44. package/built-in-skills/agent-meta/SKILL.md +53 -0
  45. package/built-in-skills/assets/SKILL.md +133 -0
  46. package/built-in-skills/browser-use/SKILL.md +93 -0
  47. package/built-in-skills/canvas-design/LICENSE.txt +202 -0
  48. package/built-in-skills/canvas-design/SKILL.md +157 -0
  49. package/built-in-skills/canvas-design/canvas-fonts/ArsenalSC-OFL.txt +93 -0
  50. package/built-in-skills/canvas-design/canvas-fonts/ArsenalSC-Regular.ttf +0 -0
  51. package/built-in-skills/canvas-design/canvas-fonts/BigShoulders-Bold.ttf +0 -0
  52. package/built-in-skills/canvas-design/canvas-fonts/BigShoulders-OFL.txt +93 -0
  53. package/built-in-skills/canvas-design/canvas-fonts/BigShoulders-Regular.ttf +0 -0
  54. package/built-in-skills/canvas-design/canvas-fonts/Boldonse-OFL.txt +93 -0
  55. package/built-in-skills/canvas-design/canvas-fonts/Boldonse-Regular.ttf +0 -0
  56. package/built-in-skills/canvas-design/canvas-fonts/BricolageGrotesque-Bold.ttf +0 -0
  57. package/built-in-skills/canvas-design/canvas-fonts/BricolageGrotesque-OFL.txt +93 -0
  58. package/built-in-skills/canvas-design/canvas-fonts/BricolageGrotesque-Regular.ttf +0 -0
  59. package/built-in-skills/canvas-design/canvas-fonts/CrimsonPro-Bold.ttf +0 -0
  60. package/built-in-skills/canvas-design/canvas-fonts/CrimsonPro-Italic.ttf +0 -0
  61. package/built-in-skills/canvas-design/canvas-fonts/CrimsonPro-OFL.txt +93 -0
  62. package/built-in-skills/canvas-design/canvas-fonts/CrimsonPro-Regular.ttf +0 -0
  63. package/built-in-skills/canvas-design/canvas-fonts/DMMono-OFL.txt +93 -0
  64. package/built-in-skills/canvas-design/canvas-fonts/DMMono-Regular.ttf +0 -0
  65. package/built-in-skills/canvas-design/canvas-fonts/EricaOne-OFL.txt +94 -0
  66. package/built-in-skills/canvas-design/canvas-fonts/EricaOne-Regular.ttf +0 -0
  67. package/built-in-skills/canvas-design/canvas-fonts/GeistMono-Bold.ttf +0 -0
  68. package/built-in-skills/canvas-design/canvas-fonts/GeistMono-OFL.txt +93 -0
  69. package/built-in-skills/canvas-design/canvas-fonts/GeistMono-Regular.ttf +0 -0
  70. package/built-in-skills/canvas-design/canvas-fonts/Gloock-OFL.txt +93 -0
  71. package/built-in-skills/canvas-design/canvas-fonts/Gloock-Regular.ttf +0 -0
  72. package/built-in-skills/canvas-design/canvas-fonts/IBMPlexMono-Bold.ttf +0 -0
  73. package/built-in-skills/canvas-design/canvas-fonts/IBMPlexMono-OFL.txt +93 -0
  74. package/built-in-skills/canvas-design/canvas-fonts/IBMPlexMono-Regular.ttf +0 -0
  75. package/built-in-skills/canvas-design/canvas-fonts/IBMPlexSerif-Bold.ttf +0 -0
  76. package/built-in-skills/canvas-design/canvas-fonts/IBMPlexSerif-BoldItalic.ttf +0 -0
  77. package/built-in-skills/canvas-design/canvas-fonts/IBMPlexSerif-Italic.ttf +0 -0
  78. package/built-in-skills/canvas-design/canvas-fonts/IBMPlexSerif-Regular.ttf +0 -0
  79. package/built-in-skills/canvas-design/canvas-fonts/InstrumentSans-Bold.ttf +0 -0
  80. package/built-in-skills/canvas-design/canvas-fonts/InstrumentSans-BoldItalic.ttf +0 -0
  81. package/built-in-skills/canvas-design/canvas-fonts/InstrumentSans-Italic.ttf +0 -0
  82. package/built-in-skills/canvas-design/canvas-fonts/InstrumentSans-OFL.txt +93 -0
  83. package/built-in-skills/canvas-design/canvas-fonts/InstrumentSans-Regular.ttf +0 -0
  84. package/built-in-skills/canvas-design/canvas-fonts/InstrumentSerif-Italic.ttf +0 -0
  85. package/built-in-skills/canvas-design/canvas-fonts/InstrumentSerif-Regular.ttf +0 -0
  86. package/built-in-skills/canvas-design/canvas-fonts/Italiana-OFL.txt +93 -0
  87. package/built-in-skills/canvas-design/canvas-fonts/Italiana-Regular.ttf +0 -0
  88. package/built-in-skills/canvas-design/canvas-fonts/JetBrainsMono-Bold.ttf +0 -0
  89. package/built-in-skills/canvas-design/canvas-fonts/JetBrainsMono-OFL.txt +93 -0
  90. package/built-in-skills/canvas-design/canvas-fonts/JetBrainsMono-Regular.ttf +0 -0
  91. package/built-in-skills/canvas-design/canvas-fonts/Jura-Light.ttf +0 -0
  92. package/built-in-skills/canvas-design/canvas-fonts/Jura-Medium.ttf +0 -0
  93. package/built-in-skills/canvas-design/canvas-fonts/Jura-OFL.txt +93 -0
  94. package/built-in-skills/canvas-design/canvas-fonts/LibreBaskerville-OFL.txt +93 -0
  95. package/built-in-skills/canvas-design/canvas-fonts/LibreBaskerville-Regular.ttf +0 -0
  96. package/built-in-skills/canvas-design/canvas-fonts/Lora-Bold.ttf +0 -0
  97. package/built-in-skills/canvas-design/canvas-fonts/Lora-BoldItalic.ttf +0 -0
  98. package/built-in-skills/canvas-design/canvas-fonts/Lora-Italic.ttf +0 -0
  99. package/built-in-skills/canvas-design/canvas-fonts/Lora-OFL.txt +93 -0
  100. package/built-in-skills/canvas-design/canvas-fonts/Lora-Regular.ttf +0 -0
  101. package/built-in-skills/canvas-design/canvas-fonts/NationalPark-Bold.ttf +0 -0
  102. package/built-in-skills/canvas-design/canvas-fonts/NationalPark-OFL.txt +93 -0
  103. package/built-in-skills/canvas-design/canvas-fonts/NationalPark-Regular.ttf +0 -0
  104. package/built-in-skills/canvas-design/canvas-fonts/NothingYouCouldDo-OFL.txt +93 -0
  105. package/built-in-skills/canvas-design/canvas-fonts/NothingYouCouldDo-Regular.ttf +0 -0
  106. package/built-in-skills/canvas-design/canvas-fonts/Outfit-Bold.ttf +0 -0
  107. package/built-in-skills/canvas-design/canvas-fonts/Outfit-OFL.txt +93 -0
  108. package/built-in-skills/canvas-design/canvas-fonts/Outfit-Regular.ttf +0 -0
  109. package/built-in-skills/canvas-design/canvas-fonts/PixelifySans-Medium.ttf +0 -0
  110. package/built-in-skills/canvas-design/canvas-fonts/PixelifySans-OFL.txt +93 -0
  111. package/built-in-skills/canvas-design/canvas-fonts/PoiretOne-OFL.txt +93 -0
  112. package/built-in-skills/canvas-design/canvas-fonts/PoiretOne-Regular.ttf +0 -0
  113. package/built-in-skills/canvas-design/canvas-fonts/RedHatMono-Bold.ttf +0 -0
  114. package/built-in-skills/canvas-design/canvas-fonts/RedHatMono-OFL.txt +93 -0
  115. package/built-in-skills/canvas-design/canvas-fonts/RedHatMono-Regular.ttf +0 -0
  116. package/built-in-skills/canvas-design/canvas-fonts/Silkscreen-OFL.txt +93 -0
  117. package/built-in-skills/canvas-design/canvas-fonts/Silkscreen-Regular.ttf +0 -0
  118. package/built-in-skills/canvas-design/canvas-fonts/SmoochSans-Medium.ttf +0 -0
  119. package/built-in-skills/canvas-design/canvas-fonts/SmoochSans-OFL.txt +93 -0
  120. package/built-in-skills/canvas-design/canvas-fonts/Tektur-Medium.ttf +0 -0
  121. package/built-in-skills/canvas-design/canvas-fonts/Tektur-OFL.txt +93 -0
  122. package/built-in-skills/canvas-design/canvas-fonts/Tektur-Regular.ttf +0 -0
  123. package/built-in-skills/canvas-design/canvas-fonts/WorkSans-Bold.ttf +0 -0
  124. package/built-in-skills/canvas-design/canvas-fonts/WorkSans-BoldItalic.ttf +0 -0
  125. package/built-in-skills/canvas-design/canvas-fonts/WorkSans-Italic.ttf +0 -0
  126. package/built-in-skills/canvas-design/canvas-fonts/WorkSans-OFL.txt +93 -0
  127. package/built-in-skills/canvas-design/canvas-fonts/WorkSans-Regular.ttf +0 -0
  128. package/built-in-skills/canvas-design/canvas-fonts/YoungSerif-OFL.txt +93 -0
  129. package/built-in-skills/canvas-design/canvas-fonts/YoungSerif-Regular.ttf +0 -0
  130. package/built-in-skills/claim-agent-ownership/SKILL.md +255 -0
  131. package/built-in-skills/claude-api/LICENSE.txt +202 -0
  132. package/built-in-skills/claude-api/SKILL.md +325 -0
  133. package/built-in-skills/claude-api/csharp/claude-api.md +402 -0
  134. package/built-in-skills/claude-api/curl/examples.md +216 -0
  135. package/built-in-skills/claude-api/curl/managed-agents.md +336 -0
  136. package/built-in-skills/claude-api/go/claude-api.md +421 -0
  137. package/built-in-skills/claude-api/go/managed-agents/README.md +561 -0
  138. package/built-in-skills/claude-api/java/claude-api.md +432 -0
  139. package/built-in-skills/claude-api/java/managed-agents/README.md +442 -0
  140. package/built-in-skills/claude-api/php/claude-api.md +375 -0
  141. package/built-in-skills/claude-api/php/managed-agents/README.md +435 -0
  142. package/built-in-skills/claude-api/python/claude-api/README.md +420 -0
  143. package/built-in-skills/claude-api/python/claude-api/batches.md +185 -0
  144. package/built-in-skills/claude-api/python/claude-api/files-api.md +165 -0
  145. package/built-in-skills/claude-api/python/claude-api/streaming.md +162 -0
  146. package/built-in-skills/claude-api/python/claude-api/tool-use.md +590 -0
  147. package/built-in-skills/claude-api/python/managed-agents/README.md +332 -0
  148. package/built-in-skills/claude-api/ruby/claude-api.md +113 -0
  149. package/built-in-skills/claude-api/ruby/managed-agents/README.md +389 -0
  150. package/built-in-skills/claude-api/shared/agent-design.md +101 -0
  151. package/built-in-skills/claude-api/shared/error-codes.md +213 -0
  152. package/built-in-skills/claude-api/shared/live-sources.md +135 -0
  153. package/built-in-skills/claude-api/shared/managed-agents-api-reference.md +378 -0
  154. package/built-in-skills/claude-api/shared/managed-agents-client-patterns.md +209 -0
  155. package/built-in-skills/claude-api/shared/managed-agents-core.md +238 -0
  156. package/built-in-skills/claude-api/shared/managed-agents-environments.md +215 -0
  157. package/built-in-skills/claude-api/shared/managed-agents-events.md +195 -0
  158. package/built-in-skills/claude-api/shared/managed-agents-memory.md +197 -0
  159. package/built-in-skills/claude-api/shared/managed-agents-multiagent.md +99 -0
  160. package/built-in-skills/claude-api/shared/managed-agents-onboarding.md +114 -0
  161. package/built-in-skills/claude-api/shared/managed-agents-outcomes.md +106 -0
  162. package/built-in-skills/claude-api/shared/managed-agents-overview.md +68 -0
  163. package/built-in-skills/claude-api/shared/managed-agents-self-hosted-sandboxes.md +173 -0
  164. package/built-in-skills/claude-api/shared/managed-agents-tools.md +321 -0
  165. package/built-in-skills/claude-api/shared/managed-agents-webhooks.md +110 -0
  166. package/built-in-skills/claude-api/shared/model-migration.md +779 -0
  167. package/built-in-skills/claude-api/shared/models.md +121 -0
  168. package/built-in-skills/claude-api/shared/prompt-caching.md +171 -0
  169. package/built-in-skills/claude-api/shared/tool-use-concepts.md +327 -0
  170. package/built-in-skills/claude-api/typescript/claude-api/README.md +333 -0
  171. package/built-in-skills/claude-api/typescript/claude-api/batches.md +106 -0
  172. package/built-in-skills/claude-api/typescript/claude-api/files-api.md +98 -0
  173. package/built-in-skills/claude-api/typescript/claude-api/streaming.md +178 -0
  174. package/built-in-skills/claude-api/typescript/claude-api/tool-use.md +527 -0
  175. package/built-in-skills/claude-api/typescript/managed-agents/README.md +359 -0
  176. package/built-in-skills/codebase-design/DEEPENING.md +37 -0
  177. package/built-in-skills/codebase-design/DESIGN-IT-TWICE.md +44 -0
  178. package/built-in-skills/codebase-design/LICENSE +21 -0
  179. package/built-in-skills/codebase-design/SKILL.md +116 -0
  180. package/built-in-skills/conversation-compaction/SKILL.md +114 -0
  181. package/built-in-skills/council-creator/SKILL.md +426 -0
  182. package/built-in-skills/diagnosing-bugs/LICENSE +21 -0
  183. package/built-in-skills/diagnosing-bugs/SKILL.md +136 -0
  184. package/built-in-skills/diagnosing-bugs/scripts/hitl-loop.template.sh +41 -0
  185. package/built-in-skills/doc-coauthoring/SKILL.md +376 -0
  186. package/built-in-skills/document-generation/SKILL.md +105 -0
  187. package/built-in-skills/domain-modeling/ADR-FORMAT.md +47 -0
  188. package/built-in-skills/domain-modeling/CONTEXT-FORMAT.md +60 -0
  189. package/built-in-skills/domain-modeling/LICENSE +21 -0
  190. package/built-in-skills/domain-modeling/SKILL.md +76 -0
  191. package/built-in-skills/frontend-design/LICENSE.txt +177 -0
  192. package/built-in-skills/frontend-design/SKILL.md +43 -0
  193. package/built-in-skills/human-approval/SKILL.md +129 -0
  194. package/built-in-skills/image-generate/SKILL.md +128 -0
  195. package/built-in-skills/image-generate/scripts/generate-and-deliver.mjs +289 -0
  196. package/built-in-skills/ingest/SKILL.md +73 -0
  197. package/built-in-skills/internal-comms/LICENSE.txt +202 -0
  198. package/built-in-skills/internal-comms/SKILL.md +33 -0
  199. package/built-in-skills/internal-comms/examples/3p-updates.md +47 -0
  200. package/built-in-skills/internal-comms/examples/company-newsletter.md +65 -0
  201. package/built-in-skills/internal-comms/examples/faq-answers.md +30 -0
  202. package/built-in-skills/internal-comms/examples/general-comms.md +16 -0
  203. package/built-in-skills/liteparse/SKILL.md +176 -0
  204. package/built-in-skills/mcp-builder/LICENSE.txt +202 -0
  205. package/built-in-skills/mcp-builder/SKILL.md +237 -0
  206. package/built-in-skills/mcp-builder/reference/evaluation.md +602 -0
  207. package/built-in-skills/mcp-builder/reference/mcp_best_practices.md +249 -0
  208. package/built-in-skills/mcp-builder/reference/node_mcp_server.md +970 -0
  209. package/built-in-skills/mcp-builder/reference/python_mcp_server.md +719 -0
  210. package/built-in-skills/mcp-builder/scripts/connections.py +151 -0
  211. package/built-in-skills/mcp-builder/scripts/evaluation.py +373 -0
  212. package/built-in-skills/mcp-builder/scripts/example_evaluation.xml +22 -0
  213. package/built-in-skills/mcp-builder/scripts/requirements.txt +2 -0
  214. package/built-in-skills/memory/SKILL.md +471 -0
  215. package/built-in-skills/memory-dream/SKILL.md +339 -0
  216. package/built-in-skills/office-artifacts/SKILL.md +211 -0
  217. package/built-in-skills/okr/SKILL.md +154 -0
  218. package/built-in-skills/persona/SKILL.md +81 -0
  219. package/built-in-skills/persona-generator/SKILL.md +296 -0
  220. package/built-in-skills/pkf-svg/SKILL.md +253 -0
  221. package/built-in-skills/pkf-writing/SKILL.md +236 -0
  222. package/built-in-skills/prismer-im-collab/SKILL.md +168 -0
  223. package/built-in-skills/proactivity/SKILL.md +84 -0
  224. package/built-in-skills/remotion/SKILL.md +431 -0
  225. package/built-in-skills/role-builder/SKILL.md +203 -0
  226. package/built-in-skills/role-builder/scripts/author-role.mjs +334 -0
  227. package/built-in-skills/role-builder/scripts/ingest-role.mjs +223 -0
  228. package/built-in-skills/role-builder/scripts/instantiate-and-run.mjs +290 -0
  229. package/built-in-skills/role-builder/scripts/operation-harness.mjs +267 -0
  230. package/built-in-skills/skill-authoring/SKILL.md +134 -0
  231. package/built-in-skills/skill-authoring/skill.json +74 -0
  232. package/built-in-skills/skill-builder/SKILL.md +171 -0
  233. package/built-in-skills/skill-builder/scripts/ingest.mjs +265 -0
  234. package/built-in-skills/skill-creator/LICENSE.txt +202 -0
  235. package/built-in-skills/skill-creator/SKILL.md +227 -0
  236. package/built-in-skills/skill-creator/agents/analyzer.md +274 -0
  237. package/built-in-skills/skill-creator/agents/comparator.md +202 -0
  238. package/built-in-skills/skill-creator/agents/grader.md +223 -0
  239. package/built-in-skills/skill-creator/assets/eval_review.html +146 -0
  240. package/built-in-skills/skill-creator/eval-viewer/generate_review.py +471 -0
  241. package/built-in-skills/skill-creator/eval-viewer/viewer.html +1325 -0
  242. package/built-in-skills/skill-creator/references/external-library-import.md +110 -0
  243. package/built-in-skills/skill-creator/references/schemas.md +430 -0
  244. package/built-in-skills/skill-creator/scripts/__init__.py +0 -0
  245. package/built-in-skills/skill-creator/scripts/aggregate_benchmark.py +401 -0
  246. package/built-in-skills/skill-creator/scripts/generate_report.py +326 -0
  247. package/built-in-skills/skill-creator/scripts/import-library.mjs +475 -0
  248. package/built-in-skills/skill-creator/scripts/improve_description.py +247 -0
  249. package/built-in-skills/skill-creator/scripts/package_skill.py +136 -0
  250. package/built-in-skills/skill-creator/scripts/quick_validate.py +103 -0
  251. package/built-in-skills/skill-creator/scripts/run_eval.py +310 -0
  252. package/built-in-skills/skill-creator/scripts/run_loop.py +328 -0
  253. package/built-in-skills/skill-creator/scripts/utils.py +47 -0
  254. package/built-in-skills/slack-gif-creator/LICENSE.txt +202 -0
  255. package/built-in-skills/slack-gif-creator/SKILL.md +291 -0
  256. package/built-in-skills/slack-gif-creator/core/easing.py +234 -0
  257. package/built-in-skills/slack-gif-creator/core/frame_composer.py +176 -0
  258. package/built-in-skills/slack-gif-creator/core/gif_builder.py +269 -0
  259. package/built-in-skills/slack-gif-creator/core/validators.py +136 -0
  260. package/built-in-skills/slack-gif-creator/requirements.txt +4 -0
  261. package/built-in-skills/tasks/SKILL.md +413 -0
  262. package/built-in-skills/tdd/LICENSE +21 -0
  263. package/built-in-skills/tdd/SKILL.md +110 -0
  264. package/built-in-skills/tdd/mocking.md +59 -0
  265. package/built-in-skills/tdd/refactoring.md +10 -0
  266. package/built-in-skills/tdd/tests.md +61 -0
  267. package/built-in-skills/team/SKILL.md +77 -0
  268. package/built-in-skills/web-artifacts-builder/LICENSE.txt +202 -0
  269. package/built-in-skills/web-artifacts-builder/SKILL.md +105 -0
  270. package/built-in-skills/web-artifacts-builder/scripts/bundle-artifact.sh +54 -0
  271. package/built-in-skills/web-artifacts-builder/scripts/init-artifact.sh +334 -0
  272. package/built-in-skills/web-artifacts-builder/scripts/shadcn-components.tar.gz +0 -0
  273. package/built-in-skills/webapp-testing/LICENSE.txt +202 -0
  274. package/built-in-skills/webapp-testing/SKILL.md +97 -0
  275. package/built-in-skills/webapp-testing/examples/console_logging.py +35 -0
  276. package/built-in-skills/webapp-testing/examples/element_discovery.py +40 -0
  277. package/built-in-skills/webapp-testing/examples/static_html_automation.py +33 -0
  278. package/built-in-skills/webapp-testing/scripts/with_server.py +106 -0
  279. package/built-in-skills/wechat-pay/SKILL.md +59 -0
  280. package/dist/cli.cjs +72577 -16101
  281. package/dist/cli.js +72752 -16232
  282. package/dist/index.cjs +72632 -16024
  283. package/dist/index.d.cts +4956 -640
  284. package/dist/index.d.ts +4956 -640
  285. package/dist/index.js +72564 -15963
  286. package/package.json +39 -6
  287. package/plugins/memory/prismer/__init__.py +1211 -0
  288. package/plugins/memory/prismer/plugin.yaml +8 -0
  289. package/plugins/memory/prismer/tool-schemas.generated.json +249 -0
  290. package/plugins/tools/prismer-recall/__init__.py +282 -0
  291. package/plugins/tools/prismer-recall/plugin.yaml +15 -0
package/README.md CHANGED
@@ -12,7 +12,7 @@ The runtime opens **one WebSocket** to cloud, declares all hosted agents in a si
12
12
  ### macOS (LaunchAgent autostart)
13
13
 
14
14
  ```sh
15
- curl -fsSL https://prismer.cloud/install.sh | sh -s -- \
15
+ curl -fsSL https://prod.docbrew.cn/install.sh | sh -s -- \
16
16
  --component=daemon --adapters=claude-code,codex,hermes
17
17
  ```
18
18
 
@@ -41,20 +41,26 @@ Without LaunchAgent, you own daemon lifecycle (run under tmux / launchd / system
41
41
 
42
42
  ### Container (daemon-first sandbox image)
43
43
 
44
- The runtime is PID 1 of every Prismer sandbox pod. `infra/sandbox-image/daemon-entrypoint.sh` writes a flat `~/.prismer/config.toml` from controller-injected env, then `exec prismer daemon start --port=7878 --foreground`. Required env:
44
+ `tini` starts the resident Rust `sandbox-manager`. The manager exposes its
45
+ health endpoint before asking the dependency-free image bootstrapper to install
46
+ a verified signed bundle. That bundle contains Runtime, Cloud SDK/CLI, and AIP;
47
+ the manager prepends its `node_modules/.bin` and then supervises
48
+ `node <bundle>/dist/cli.js daemon start --port=7878 --foreground`. A fresh Pod
49
+ with no verified bundle stays manager-healthy with `daemonAlive:false` and
50
+ retries instead of falling back to image-builtin JavaScript. Required env:
45
51
 
46
52
  - `PRISMER_API_KEY` — required.
47
53
  - `PRISMER_DAEMON_ID` — required (else derived from hostname → `container:<podName>`).
48
- - `PRISMER_BASE_URL` (or `CLOUD_API_BASE`, `PRISMER_CLOUD_API_BASE`) — cloud URL; falls back to `https://prismer.cloud`.
54
+ - `PRISMER_BASE_URL` (or `CLOUD_API_BASE`, `PRISMER_CLOUD_API_BASE`) — cloud URL; falls back to `https://prod.docbrew.cn`.
49
55
  - `PRISMER_HOSTED_AGENT_FILE` / `PRISMER_HOSTED_AGENT_JSON` — static-binding payload (one-time agent install before first `host.declare`).
50
56
  - `PRISMER_STATIC_BINDING_REQUIRED=true` — make missing static binding fatal.
51
57
  - `PRISMER_USER_ID`, `PRISMER_TASK_ID`, `PRISMER_CONTAINER_ID` — audit-only.
52
58
 
53
59
  The container daemon binds `:7878` (controller proxy target) instead of the desktop default `:3210`, and starts `OutboxWatcher` to upload files dropped under `/workspace/_outbox/` as sandbox-output assets.
54
60
 
55
- ## CLI reference (16 verbs)
61
+ ## CLI reference
56
62
 
57
- `VERSION = '2.0.0'`. Each verb is a `commander` subcommand under `src/cli/commands/`. Output is JSON (`--json`) or human-friendly ANSI by default.
63
+ `VERSION = '2.2.4'`. Each verb is a `commander` subcommand under `src/cli/commands/`. Output is JSON (`--json`) or human-friendly ANSI by default. Repository environment diagnostics and test orchestration are exposed by the separate APC binary (`npm run apc`), not by the daemon runtime or general SDK.
58
64
 
59
65
  ### Lifecycle
60
66
 
@@ -176,8 +182,8 @@ Pure HTTP client of `hermes gateway` (Hermes 0.10+). All calls are HTTP — no `
176
182
 
177
183
  - `port` (1..65535, default `8642`), `apiKey` (required, from `~/.hermes/.env API_SERVER_KEY`).
178
184
  - `hermesProfileName` (default = first 8 chars of `profile.id`), `autoStart` (default `false`), `startupTimeoutMs` (default 30 000).
179
- - `configurePrismerProvider` (default `true`) — writes `custom_providers` + `model.provider='custom:prismer'` + `mcp_servers['prismer-tasks']` block into `~/.hermes/profiles/<name>/config.yaml`. The MCP server path is auto-resolved via `createRequire('@prismer/mcp-server')` first, then a repo-relative dev fallback.
180
- - `installPrismerMcpServer` (default `true`), `prismerMcpServerPath` (override).
185
+ - `configurePrismerProvider` (default `true`) — writes `custom_providers` + `model.provider='custom:prismer'` into `~/.hermes/profiles/<name>/config.yaml` (plus the `mcp_servers['prismer-tasks']` block only when `installPrismerMcpServer: true`). The MCP server path is auto-resolved via `createRequire('@prismer/mcp-server')` first, then a repo-relative dev fallback.
186
+ - `installPrismerMcpServer` (default `false` — retired for first-party agents 2026-07-19, skill+CLI is primary; explicit third-party opt-in only), `prismerMcpServerPath` (override).
181
187
  - `model` (default `us-kimi-k2.5`), `prismerProviderName` (default `prismer`), `prismerProviderBaseUrl` (default `$PRISMER_BASE_URL/api/v1`), `prismerApiKeyEnv` (default `PRISMER_API_KEY`, regex `^[A-Za-z_][A-Za-z0-9_]*$`).
182
188
  - `mirrorNativeKanban` (default `true`) — mirrors Prismer `work_item` projections into Hermes Kanban as triage cards via `hermes -p <profile> kanban create … --triage --idempotency-key prismer:<parentTaskId>`.
183
189
  - `mirrorNativeGoals` (default `true`) — writes Prismer standing objectives into Hermes' SQLite `state_meta["goal:<sessionId>"]` directly.
@@ -196,6 +202,20 @@ Dispatch flow:
196
202
 
197
203
  `claude --print --model <m> [--system-prompt …] [--allowed-tools …] <prompt>` per dispatch. `--cwd` removed (uses `child_process.spawn` cwd); prompt is positional; `--headless` was renamed to `--print` in claude CLI 2.x. Config: `cwd` (required), `model` (default `'sonnet'`), `systemPrompt`, `envVars`, `mcpServers`, `allowedTools`, `maxTurns` (default 20), `baseURL`, `apiKeyRef` (`env:NAME` or `keychain:NAME` — keychain only on darwin via `security find-generic-password`), `route` (`'default'|'prismer'|'omniroute'`). `stdio: ['ignore', 'pipe', 'pipe']` to close child stdin (claude ≥ 2.1.128 prints "no stdin data received in 3s, proceeding without it" otherwise). `task.signal` → `child.kill('SIGTERM')`; `task.timeoutMs` → SIGTERM via `setTimeout`.
198
204
 
205
+ The engine spawn path requires the exact Claude CLI `binaryPin` in
206
+ `src/adapters/known-versions.ts` (currently `2.1.179`, aligned with the sandbox
207
+ image). A mismatch raises `ADAPTER_BINARY_PIN_VIOLATION` before the SDK query
208
+ starts. `PRISMER_ALLOW_UNPINNED=1` is an explicit unverified escape hatch.
209
+
210
+ Claude Code runs with isolated `HOME` and `CLAUDE_CONFIG_DIR` rooted at
211
+ `~/.prismer/claude-config`, preventing user plugins, MCP servers, and settings
212
+ from entering daemon runs. Set `PRISMER_CC_NO_ISOLATION=1` only to opt back into
213
+ the legacy user config. **Not yet verified end-to-end**: the sentinel spawn
214
+ oracle (seed a marker in the real `~/.claude`, spawn, assert it is NOT loaded;
215
+ negative control = `PRISMER_CC_NO_ISOLATION=1` must load it) does not exist. The
216
+ current tests are pure-function assertions over the path resolver and never
217
+ spawn a process, so "isolation holds at spawn time" is unproven.
218
+
199
219
  ### `codex`
200
220
 
201
221
  `codex exec --model <m> --cd <cwd> --sandbox <level> --ephemeral --json <prompt>`. Config: `cwd` (required), `model` (default `codex-mini-latest`), `sandbox` (`'read-only'|'workspace-write'|'danger-full-access'`, default `workspace-write`), `systemPrompt` (prepended to user prompt — Codex CLI has no `--system-prompt` flag as of 2026-05), `envVars`, `apiKeyEnv` (default `OPENAI_API_KEY`). `parseCodexOutput` reads JSONL stdout backwards looking for `{"type":"message"|"assistant"|"output", "content"|"message"|"text": string}`; falls back to raw stdout. Outputs are capped at 64 KiB with `\n…[truncated]` suffix.
@@ -317,7 +337,7 @@ Operators run `hermes` in their own Python venv. Sample `~/.hermes/profiles/<nam
317
337
  custom_providers:
318
338
  prismer:
319
339
  type: openai
320
- base_url: https://prismer.cloud/api/v1
340
+ base_url: https://prod.docbrew.cn/api/v1
321
341
  api_key_env: PRISMER_API_KEY
322
342
  model:
323
343
  provider: custom:prismer
@@ -355,9 +375,9 @@ Bridge results are persisted on `IMTask.metadata.bridge.hermes` via the daemon's
355
375
  | Method | Path | Purpose |
356
376
  | ------ | ---- | ------- |
357
377
  | OPTIONS | `*` | CORS preflight |
358
- | GET | `/healthz` | `{status:'ok', daemonId, cloudBaseUrl, workspaceId, pid, startedAt, wsConnected, hostedAgents, observability}` |
378
+ | GET | `/healthz` | `{status:'ok', daemonId, cloudBaseUrl, workspaceId, pid, startedAt, wsConnected, hostedAgents, observability}`. Additive, **present only when the runner wires the subsystem** (spread — CLI/K8s shape unchanged): `assetOutbox {pending, uploaded, deadLetter, sampledAt}` (desktop205 W13; a SAMPLE pushed in by the drop-folder tick — this handler does zero I/O and the desktop Tray polls it), `recallStats`, `cloudReachable`/`pendingWrites`. |
359
379
  | GET | `/agents` | `{agents: [{imUserId, name, adapterName}]}` |
360
- | GET | `/tasks/running` | `{taskIds: string[]}` |
380
+ | GET | `/tasks/running` | `{taskIds: string[]}` + optional `tasks: [{taskId, agentName?, kind?, scopeLabel?, startedAt}]` (desktop205 W13 — descriptive rows for the desktop Tray; `taskIds` is unchanged for every existing consumer) |
361
381
  | POST | `/v1/runs` | Sandbox controller daemon-dispatch ack — `202 {runId, status:'accepted', taskId}`. Optional `payload.shellCommand` triggers async `bash -c <cmd>` with `cwd=/workspace` (escape hatch). |
362
382
  | POST | `/v1/agents/install` | **Cloud → daemon agent install RPC**: validates body via `validateInstallAgentPayload`, calls `runner.installHostedAgent` → upsert `agents` + `agent_profiles` rows, reload, send `agent.host.declare`, return `{ok, daemonId, installedAgent, hostedAgents}`. |
363
383
  | POST | `/v1/snapshot` | FS-manifest snapshot — walks `snapshotRoot` (default `/workspace`), computes per-file `{path, sha256, sizeBytes, mtime}`. Skips dotfiles + `_outbox/_uploaded`. 404 if root missing. |
@@ -378,6 +398,8 @@ The sandbox-controller's `installAgent` proxy at `POST /:id/installAgent` valida
378
398
  | `PRISMER_RUNTIME_MODE` | (empty) | `container` activates `OutboxWatcher` (alt to `PRISMER_CONTAINER_ID`) |
379
399
  | `PRISMER_DAEMON_URL` | `http://127.0.0.1:3210` | Loopback URL used by `prismer memory` and `agent doctor` |
380
400
  | `PRISMER_SHELL_ENABLED` | `false` | Override `[shell].enabled` in `config.toml` |
401
+ | `PRISMER_ALLOW_UNPINNED` | (empty) | `=1` bypasses exact Claude CLI binary pin enforcement; behavior is unverified |
402
+ | `PRISMER_CC_NO_ISOLATION` | (empty) | `=1` lets Claude Code inherit the user's real `HOME` / `~/.claude` instead of the isolated runtime config |
381
403
  | `LOCAL_ONLY` | (empty) | `=1` enables `--as-user` pair bypass |
382
404
  | `PRISMER_AUTH_TOKEN` | (empty) | Fallback for `prismer setup --token <jwt>` |
383
405
  | `EDITOR` | `vi` | Used by `prismer profile edit` |
@@ -386,7 +408,7 @@ The sandbox-controller's `installAgent` proxy at `POST /:id/installAgent` valida
386
408
 
387
409
  ```toml
388
410
  api_key = "sk-prismer-..."
389
- cloud_api_base = "https://cloud.prismer.dev"
411
+ cloud_api_base = "https://test.docbrew.cn"
390
412
  daemon_id = "..."
391
413
 
392
414
  [adapters.claude-code]
@@ -405,7 +427,7 @@ shell = "bash"
405
427
 
406
428
  ## Troubleshooting
407
429
 
408
- - **LaunchAgent respawn loop after install** — the plist must include `--foreground` in `ProgramArguments`. v2.0.0 installs do this automatically; if you're upgrading from 1.8.x re-run `curl -fsSL https://prismer.cloud/install.sh | sh -s -- --component=daemon` (the installer does `bootout` + `bootstrap` to reload).
430
+ - **LaunchAgent respawn loop after install** — the plist must include `--foreground` in `ProgramArguments`. v2.0.0 installs do this automatically; if you're upgrading from 1.8.x re-run `curl -fsSL https://prod.docbrew.cn/install.sh | sh -s -- --component=daemon` (the installer does `bootout` + `bootstrap` to reload).
409
431
  - **Daemon shows "waiting for ~/.prismer/config.toml"** — that's expected behavior pre-pair. Run `prismer pair` (or `prismer setup sk-prismer-...`) and the daemon snaps to attention within 5s.
410
432
  - **Cloud unreachable** — `prismer status` will print the failing base URL. Common causes: stale `cloud_api_base` after a tenant move (run `prismer setup --force <new-key> --cloud <url>`), or the API key was rotated (mint a new one with `prismer setup --token <jwt>`).
411
433
  - **Agent shows under `__unbound__` device in workspace runtime view** — the daemon's `agent.host.declare` is not stamping `daemonId`. Confirm you're on `@prismer/runtime@2.0.0` (the `daemonId` payload field is required as of v2.0.0).
@@ -0,0 +1,111 @@
1
+ <!-- APC skill authoring 参照:命令真产物的字段字典 -->
2
+ # APC skill 真产物字段字典
3
+
4
+ > **为什么存在**:M1-d/f 探路批(env-doctor + test-runner)4 轮返工里 **2 轮死在字段名漂移**——SKILL.md 照 doc 12 的抽象词("结构化 TierResult" / "doctor JSON")写,agent 照着解析真产物却对不上字段名。**写任何引用这些产物的 SKILL.md 前,字段名以本文件为准**(本文件由真跑命令抓取,非文档转述;schema 变了先更新这里)。
5
+ >
6
+ > 抓取方式(可复现):`npx tsx sdk/apc/bin/apc.ts env doctor` / `npx tsx scripts/test203/run.ts --tier=T0 --json`。
7
+
8
+ ## `apc env doctor` → stdout JSON
9
+
10
+ 顶层键:`envStatus` · `exitCode` · `generatedAt` · `items[]` · `summary` · `failed[]` · `undetected[]`
11
+
12
+ - `exitCode`:`0`=全绿 / `78`=env_blocked(**这是权威的 env 判据,不是自己数 items**)
13
+ - `envStatus`:`'ok'` | `'env_blocked'`
14
+ - `summary`:`{ pass, fail, skip, total }`(`total==pass+fail+skip==items.length`,一项崩不塌全轮)
15
+ - `failed[]`:失败项的 **id 字符串**数组(= 各 item 的 `item` 字段值)
16
+ - `items[]` 每项:`item`(**id,如 `toolchain.node`**)· `section`(**故障域:infra/toolchain/secrets/project**,分类按这个)· `status`(`'pass'|'fail'|'skip'`)· `label` · `detail` · `fixHint` · `strength` · `durationMs`
17
+
18
+ ⚠️ 字段名是 **`item` / `section` / `status`**,不是 `name` / `category`(首版踩过)。
19
+
20
+ ## `apc test`(= run.ts)`--json` → stdout JSON
21
+
22
+ 顶层键:`doctor` · `envStatus` · `exitCode` · `tiers[]` · `regressions[]` · `fixed[]` · `schema` · `timestamp`
23
+
24
+ - `doctor`:内嵌一份 doctor 段(同上结构)
25
+ - `exitCode`:`0`=通过 / `1`=SUT 红(`--diff` 下=有回归)/ `78`=env_blocked
26
+ - `regressions[]` / `fixed[]`:`--diff` 下 vs baseline 的**新增红 / 转绿**(顶层聚合,跨所有 tier)
27
+ - `tiers[]` 每项(TierResult):`tier` · `passed` · `failed` · `skipped` · `total` · **`failedNames`**(失败用例名数组)· `skippedNames` · `regressions` · `envStatus` · `durationMs`
28
+
29
+ ⚠️ 字段名是 **`failedNames`**(驼峰,非 "failed names");`command`/`exitCode` 在**顶层**不在每个 tier 内(首版踩过)。
30
+
31
+ ### ⚠️ 并行 flaky:单次 regression ≠ 真回归(2026-07-24 主会话查实)
32
+
33
+ T0 全量并发跑会偶发 flaky(资源竞争/端口/超时),**每次红的集合都不同**(探路批见 5 条、复查见 1 条 `web-rpc.test.ts`、再跑见 0 条;`web-rpc` 单独跑 10/10 绿)。baseline(26 条,均既有 ACP mock 债)**未被污染**。
34
+
35
+ ⇒ **test-runner skill 的验收 oracle 不能把"单次 `apc test` 出现 regression"直接判 skill 失败**。判据应是:
36
+ - regression 命中 baseline 已记的既有红 → 非新增,正常;
37
+ - regression 是新面孔 → **单独重跑该文件**确认;单跑绿=flaky(记录不 fail skill),单跑仍红=真回归(如实 `--outcome failed` 上报,是被测栈的红不是 skill 的红)。
38
+ - flaky 的签名 = 重跑红的集合漂移;真回归的签名 = 稳定复现同一批。
39
+
40
+ ## `cloud task verify-criterion <task-id> <criterion-id> --outcome <v>`
41
+
42
+ - `--outcome` 合法值**恰好四个**:`passed` | `failed` | `n/a` | `waived`(`task.ts:1374-1394`)
43
+ - 副作用 oracle:criterion 从 `pending` → 上报值,落 acceptance-view(读回确认)
44
+
45
+ ## `cloud skill ack <slug> --task <taskId>` 退出码
46
+
47
+ `0`=回执落库(`im_task_logs.action='skill_ack'`)/ `3`=无 task 上下文(**产不出回执,非失败;不许 `||true` 吞掉,按 3 分流**)/ `4`=调用身份≠task assignee / `1`=其它。
48
+
49
+ ## 端到端达标配方(env-doctor 2026-07-24 真跑 `ok:true` 验证过的黄金样板)
50
+
51
+ `cloud skill test <bundle> --agent <id> --json` 要拿 `ok:true`,skill.json 必须满足这些——**照 `sdk/apc/skills/env-doctor/skill.json` 抄**:
52
+
53
+ 1. **命令固化进 `sampleTasks[].prompt` 本体**:到达 agent 的是 prompt,**不是 SKILL.md**(SKILL.md 不进 dispatch 上下文)。prompt 里每条命令必须是 agent 在 cwd 真能跑的形态:
54
+ - **`apc` 不在 PATH** → 一律写 `npx tsx sdk/apc/bin/apc.ts <sub>`(不是裸 `apc`,不是 `npm run apc`)。
55
+ - 涉 `apc env up` → **强制 `--safe`**(bare `env up` 的 docker 步 `colima start` 在非交互 dispatch 里 block 数分钟 → reaper 杀)。prompt 里点明这一点。
56
+ 2. **`acceptanceCriteria` 必须机器可判 + 不可蒙混**:
57
+ - 用 `{label,match,type:"regex",required}` 对象,**不要**纯字符串(纯字符串走大小写敏感 substring = 要求 agent 逐字复述人话 → 假阴)。
58
+ - `match` 匹配 **agent 自然汇报里稳定出现的机器特征**(exit 码、`pass/fail/skip` 计数、字段值),**不是**要求贴原始 JSON。
59
+ - 正则要吃**多种合法排版**(inline `pass=15` / 表格 `| pass | 16 |` / dash)——否则同样正确的工作因排版一绿一红(脆性)。参考 env-doctor count 那条:`(pass|fail|skip)\w*\s*[:=|\-]*\s*\d+|\d+\s*[|:=\-]*\s*(pass|fail|skip)`。
60
+ - **必须自测负控**:蒙混文本("looks fine to me")喂 `matchAcceptanceCriteria` 要 `ok:false`;真汇报要 `ok:true`。放松到蒙混能过 = 作废。
61
+ 3. **写完立即端到端验**(daemon 活着时):`cloud skill test <bundle> --agent <id> --json` 看 `ok:true` + `taskStatus:completed`;再造蒙混 prompt 的临时 bundle 验 `ok:false`。**这是达标定义,不是可选。**
62
+
63
+ > harness 侧已修(`extractAgentReply` type 过滤 + 反向取最新 + `afterIso` 锚,只认比 prompt 发送时刻更新的 agent 回复)——authoring 不用管,但别写出依赖"首轮 poll"的假设。
64
+
65
+ ## 平台字段陷阱(authoring 必读)
66
+
67
+ - **`compatibility` ≠ `scope`**:`compatibility` 是枚举,合法值 `claude-code/codex/opencode/openclaw/prismer-sdk`——**不接受 `hermes`**(写进去 422 `STD_COMPATIBILITY_INVALID`)。hermes 可用性由 `scope: common` 授予。
68
+ - **⚠️ SKILL.md frontmatter 的 `scope:` 是描述性的、代码零消费**(2026-07-24 查实:`grep fm.scope` 全仓无命中)。真正决定"谁能装这个 skill"的 install-side 角色门是 **`role_scope`**(`built-in-skill.service.ts:354/467`),当前唯一约束值 = `orchestrator-only`(只装给 orchestrator)。约定(照 built-in `memory-dream`):**两个都写** —— `scope: common|coding` 给人读,`role_scope: orchestrator-only` 仅在该 skill 真要限制为 orchestrator-only 时加。
69
+ - **APC coding/common skill 默认不写 `role_scope`**:common 装给所有 agent(正确);coding 的限定靠 `platform-install` 的 agent 选择,**不是靠 frontmatter**。别以为写了 `scope: coding` 就把非 coding agent 挡在外面——那个字段没人读。若将来要"coding skill 只给 coding-role agent"的硬门,需在 `built-in-skill.service.ts` 扩 `role_scope` 值域(服务端改,不是 authoring)。
70
+ - **skill.json 无 `scope` 字段**:真实字段 = `schemaVersion/slug/name/description/category/version/license/compatibility/runtime/sampleTasks/security/provenance`。发布可见性(private/workspace/public)由 `platform-install` 的 `publishScope` 承载,不在 skill.json。
71
+ - **catalog slug 派生**:`platform-install` 后服务端 `toSlug(name,'community')` 把 slug 变成 `community-<name>`,与 bundle 目录名分叉——装载/查询按**返回的 slug**,不是 bundle 目录名。
72
+ - **双身份债**:同一 API key 在 `/api/im/me`、skills-install actor、task-event actor 可能解析成**不同 imUserId**(P0 验签债 `api-guard.validateJwt` 只解码不验签的下游症状)。task assignee 必须对齐 key 的**真** identity(task-event actor 那个),不是 me-endpoint 返回的。凡 coding-scope skill 涉 task 归属都会踩。
73
+
74
+ ## 发版 5 verb 真跑 `--json` 字段字典(§0.25 抓取,供发版 skill authoring)
75
+
76
+ `apc release <verb> --json` 输出形状(真跑抓取;退出码 green/staged/blocked ⇄ 0/3/1):
77
+
78
+ - **preflight** → `{decision, tier{tier,exitCode,envBlocked,regressions[]}, version{aligned,rootVersion,mismatches[]}, prisma{ok,stale[]}, blockers[], staged[]}`
79
+ - **db-config-sync** → `{decision, migration{exitCode,pending[],stderr}, keyDiff:{status:'skipped',reason}|{status:'computed',missing[],extra[],common}, blockers[], staged[]}`(真跑:本地 replica 217 pending、无 dump 时 keyDiff=skipped ⬜)
80
+ - **tag** → `{decision, tag, target, channel, tier{...}, approved, pushed, mirror, blockers[], notes[]}`(prod 拒时 `tier.exitCode=-1`,tag 算得出但 decision=blocked、pushed=false)
81
+ - **ota-promote** → `{decision, env, deliveryMode, k8s:{invoked,exitCode,rolledOut,output}|{skipped,reason}, desktop:{status:'not-wired',missing[],deliveryMode}, blockers[], notes[]}`(`k8s.invoked=true` 靠 `[runtime-ota]` banner 判真 spawn;桌面 not-wired=⬜;deliveryMode=line1-kill1 非 drain_respawn)
82
+ - **rollback** → `{decision, ledgerPath, plan:{ok:true,from,to,next[]}|{ok:false,reason}, approved, applied, mirrorRepointed, blockers[], notes[]}`
83
+
84
+ **真环境事实**:`/VERSION=2.2.4`(tag 算 v2.2.4);`prisma/schema.mysql.prisma` ⇄ generated client **真 drift** → preflight 真跑落 staged(非误报,与 §0.21 一致,需 `npm run prisma:generate:all`)。
85
+
86
+ ## 截图/资产 + 验收/观测 skill 字段(ui-canvas evidence + §0.33 S5b/S10 抓取)
87
+
88
+ **资产上传(ui-canvas/report-card 用)**:
89
+ - `POST /api/im/assets` 成功响应 asset id 在 **`data.id`**,不是 `data.assetId`(别处 `toAssetResponse` 用后者)。上传截图/产物一律 `data.assetId ?? data.id` 兜。
90
+ - 主题态截图:Playwright `addInitScript` 预置 `localStorage['prismer-theme']=light|dark|system`(`src/contexts/theme-context.tsx` 挂 `.dark`/`.light` 到 `<html>`),必须在页面脚本前种。目标必须是 registry 校验过的 `/ui-canvas?set=&version=&journey=&node=`;稳定锚是 `[data-testid="ui-canvas-overview"]` 或 `[data-testid="ui-canvas-viewport"]`。
91
+
92
+ **验收/观测(S5b/S10 用)**:
93
+ - `cloud task verify-criterion <task-id> <criterion-id> --outcome passed|failed|n/a|waived [--evidence <ref...>可重复 --note]`;`--evidence` 落 `criterion.evidence[]`(`taskRun:`/`asset:`/`url:`),`cloud task acceptance` 回读字段名 `evidence`;**任一 required criterion=failed → overall=failed**(别软化真红)。
94
+ - `cloud task add-criterion <taskId> --mode qualitative|quantitative|agent-self-check|manual --expectation <md> [--optional]` 返短 criterion id。criteria 存 **task metadata JSON 无专表**(仅 `im_task_criteria_templates`)。
95
+ - `cloud task create --kind work_item` → kind 存 `im_tasks.metadata.kind`(JSON),`--priority`→`metadata.priority`,`--json` 返 `data.id`。
96
+ - `scripts/debug/*`:`bundle.ts` 默认**写文件** `./debug-bundle-*.json`(打屏加 `--stdout`);`--env=local` 走 dev admin 短路免凭据。
97
+ - **harness `dispatch_not_created`(§0.29 修后的失败态)= 活 daemon 未为本 prompt 建 run(领养/路由层),非 criteria 失败**——真判据永远是 `im_task_runs` 真行,不是 skill-test output。
98
+
99
+ ### 结构化判据 checker(`type: "structured"` 的 `checker` 取值)
100
+
101
+ | checker | 真值来源 | 备注 |
102
+ | --- | --- | --- |
103
+ | `cited-evidence` | **磁盘**:每个 `path:line` 读回复核(存在/行范围/非空行/锚定命中) | 层 2 |
104
+ | `dimension-coverage` | **磁盘**:每维独占一行,答案是可复核引用或 `N/A — 理由` | 层 2;N/A 只校验长度不校验理由为真 |
105
+ | `doc-sync-obligations` | **磁盘**:从 delta 自行重算义务集与 gap 集再比对 | 层 2 |
106
+ | `json-claim` | **命令产物**:重解析 fenced JSON,钉 schema/算术/派生判定/baseline 重算/产物 mtime 新鲜度 | 层 3 |
107
+ | `declared-id-readback` | **云端真 API**:`TASK:/ASSET:/CRITERION:/META:` 声明的 id 回读比对(含存储 JS 类型) | 层 3 |
108
+ | `git-claim-readback` | **真 git 只读 plumbing**:commit 文件集/branch tip/bare 替身/`MERGE_HEAD` 仍在 | 层 3;硬拒 `.e2e-tmp/` 之外的仓库 |
109
+
110
+ > **层 2 = 复核报告关于「文件」的声称;层 3 = 复核关于「运行时副作用」的声称。**
111
+ > 共同边界:核的是**副作用存在性**不是**通道**;杀的是廉价伪造,不提供不可伪造性。
@@ -0,0 +1,150 @@
1
+ ---
2
+ name: bug-reproduce
3
+ description: Turn a known bug into a tight, red-capable reproducer, then prove the reproducer locks that bug with a reversal negative control (reintroduce the bug → reproducer must go red again). Use at the start of a bugfix, before theorizing about the cause.
4
+ license: MIT
5
+ scope: coding
6
+ compatibility:
7
+ - claude-code
8
+ allowed-tools:
9
+ - Bash
10
+ metadata:
11
+ category: diagnosis
12
+ ---
13
+
14
+ # bug-reproduce
15
+
16
+ 把一个**已知 bug** 变成**紧、可变红**的复现器(失败测试 / 脚本),然后用**反转负控**证明这个复现器真的锁住了那个 bug——**不是恰好绿着**(`apc/05` §2 S1 · `apc/12` bug-reproduce 行;纪律移植自 built-in `diagnosing-bugs` 的 Phase 1 复现 loop)。
17
+
18
+ **什么时候用**:一个 bugfix task 开工的**第一步**——在读代码建假设之前。`diagnosing-bugs` 的铁律:没有一个能对**这个** bug 变红的信号,再多盯代码也没用。本 skill 只补 `diagnosing-bugs` 缺的那一环:**负控——把 fix 撤掉/把 bug 注入回去,复现器必须变红**。
19
+
20
+ 铁律:一个复现器只有走完 **RED → GREEN → 反转 RED** 才算数。**只到 GREEN 不算**——一个无论 bug 在不在都绿的"复现器"是开卷考试,不是复现(`apc/12` §0 负控纪律)。
21
+
22
+ ## 复现器四判据(照 diagnosing-bugs Phase 1 完成标准)
23
+
24
+ 一个复现器必须是:
25
+
26
+ | 判据 | 含义 |
27
+ | --- | --- |
28
+ | **red-capable** | 它驱动**真正的 bug 代码路径**、断言**用户描述的确切症状**——能对这个 bug 变红,修好后变绿。不是"没崩就算过"。 |
29
+ | **deterministic** | 同一输入每次同一结论(非确定 bug:钉时间/种 RNG/隔离 FS,把复现率拉到可调试)。 |
30
+ | **fast** | 秒级不是分钟级。 |
31
+ | **agent-runnable** | 你能无人值守跑;一条命令(脚本/测试/curl)能贴出调用 + 输出。 |
32
+
33
+ ## Procedure
34
+
35
+ ### 1. 钉环境 + 建复现器(RED)
36
+
37
+ 在一个干净的、确定性的 workspace 里写出**最小失败测试/脚本**,然后跑它,**看它变红**:
38
+
39
+ ```bash
40
+ d=.e2e-tmp/apc/bug-reproduce && rm -rf "$d" && mkdir -p "$d" # repo-relative,已在 .gitignore
41
+ # …在 "$d" 里写 subject + repro…
42
+ node "$d"/repro.mjs; echo "exit=$?" # 或 apc test --tier=<T> --json / pytest / go test …
43
+ ```
44
+
45
+ **隔离场景的临时目录用 repo-relative 的 `.e2e-tmp/…`,不要用 `mktemp -d`**:复现器**本身就是证据**,判据在你跑完之后把你引用的 `path:line` **读回磁盘**——`/tmp` 从仓库根不可解析、收尾 `rm -rf` 更是把唯一产物销毁(test204「证据销毁反 pattern」的同一个坑)。本地真仓库里的 bug 则直接在真路径上做。
46
+
47
+ - 复现器必须断言**用户描述的症状本身**(`clamp(-5,0,10)` 应得 0 而非 -5),不是"没抛异常"。
48
+ - 记下**确切症状**:断言消息、错误、非零退出码。这就是 RED。
49
+ - 真仓库里的 bug:复现命令可以是选层的 `apc test --tier=<T> --json`(读 `exitCode`:`0` 绿 · `1` SUT 红 · `78` env_blocked)。**env_blocked 不是复现——是环境红,先 `apc env doctor`**。
50
+
51
+ ### 2. 最小 fix(GREEN)
52
+
53
+ 打**最小**修复(只改让复现器变绿所需的那一点),重跑复现器,**看它变绿**(`exit=0`)。**不顺手清理别的**——本步只证明"这个 fix 让这个复现器绿"。
54
+
55
+ ### 3. 反转负控(承重——RED again)
56
+
57
+ **这是本 skill 的命根子。** 把 fix 撤掉——把 bug 注入回去,**重跑同一条复现器命令**:
58
+
59
+ ```bash
60
+ # 首选:直接编辑源文件,把 buggy 的那一行 body 原样写回去
61
+ node "$d"/repro.mjs; echo "exit=$?" # 必须再次 RED(非零退出 / AssertionError)
62
+ ```
63
+
64
+ **反转手法只有一个首选:直接编辑源文件把 bug 写回去。**
65
+
66
+ > ⚠️ **`git stash` / `git checkout` 在共享工作树里是有害指令,默认不许用。** 本仓库常态是**多个并发 session 共用一个 working tree**、几百个未提交改动同时在飞——`git stash` 会把**别人正在做的改动**一起卷走,`git checkout <file>` 会**丢掉**别人对同一文件的未提交编辑。这类操作不可逆地毁坏他人工作,代价远大于它省下的那一次手工编辑。
67
+ >
68
+ > 只有在你**独占**这个 working tree(自己的 worktree / 一次性容器)**且已确认 `git status` 干净**时,`git stash` 才是等价手法;否则一律手工反转。反转的**语义**(把 bug 放回去)才是承重的,用什么手法不是。
69
+
70
+ - **复现器必须再次变红。** 这证明它**红在这个 bug 上**,不是恒绿的摆设。
71
+ - **若撤掉 fix 后复现器仍然绿 → 复现器是假的,任务失败**(`apc/12` bug-reproduce 负控)。不许放松断言让它"看起来锁住了"。
72
+
73
+ ### 4. 恢复 + 收尾(**不要删证据**)
74
+
75
+ 把 fix 放回去,确认最后一次 **GREEN**(`exit=0`)。**复现器留在盘上别删**——判据是在你跑完之后才读盘复核你引用的行的,`rm -rf` 掉复现器 = 自毁唯一产物。
76
+
77
+ ### 5. 写 BugfixCard(`repro` 阶段)
78
+
79
+ 复现 + 反转都拿到证据后,把这一阶段落成一张 **BugfixCard**——`repro` 是 BugfixCard 的**首阶段**,段锚是 `<h2 id="stage-repro">`(`src/lib/apc-cards/card-profile.ts` 的 `BUGFIX_STAGES[0].name = 'repro'`)。
80
+
81
+ > ⚠️ **段名是 `repro`,不是 `reproduce`。** `docs/apc/12` 那行写的 `stage-reproduce` 在实现里**不存在**,写成它会被 `card-stage-invalid` / `card-stage-section-missing` 挡下。以代码为准。
82
+
83
+ - `card` frontmatter:`{ kind: 'bugfix', stage: 'repro', taskId: <真 task id>, schemaRev: 1 }`——`taskId` 必填,**无 task 上下文时不要伪造绑定**:如实报告"本轮没有 task,卡未写",别硬造一张。
84
+ - `repro` 阶段的证据要求是 `asset`:段内要有 `prismer://…/asset/<id>` 链接,挂**复现器本体 + RED 输出 + 反转 RED 输出**三份证据(先 `cloud asset upload` 拿 id)。
85
+ - 段序检查只对**已过阶段**要求证据,当前阶段进行中不强求;但首阶段段锚 `stage-repro` 必须在场。
86
+
87
+ ## 输出契约(机器判据按这个复验,别自由发挥格式)
88
+
89
+ 旧判据全是关键词匹配("报告里出现过 `node`/`assert`/`exit=1`/`revert` 这些词")——**一篇一条命令都没跑过的报告照样满分**。现在多一条判据(`cited-evidence`)把复现器**读回磁盘**复核:复现器不存在、引用的行不存在、或者引用的行根本不含被测符号,当场判红。
90
+
91
+ **① 复现器锚点声明**(一行;符号会被复核确实出现在该文件里):
92
+
93
+ ```
94
+ CHANGE-POINT: <被测符号> @ <复现器/被测文件的 repo-relative 路径>
95
+ ```
96
+
97
+ **② RED→GREEN→反转 RED 相位表**(markdown 表,**首列是 `path:line`**):每相位一行,首列是该相位**转在哪一行**上。判据要求 **≥3 行**带可复核引用,且 **≥2 条引用所在的那一行真的含被测符号**。
98
+
99
+ ```
100
+ | path:line | phase | command | exit | observed |
101
+ | --- | --- | --- | --- | --- |
102
+ | .e2e-tmp/apc/bug-reproduce/repro.mjs:3 | 1 RED (buggy) | node .e2e-tmp/apc/bug-reproduce/repro.mjs | 1 | AssertionError: clamp must respect lower bound |
103
+ | .e2e-tmp/apc/bug-reproduce/clamp.mjs:1 | 2 GREEN (fixed) | node .e2e-tmp/apc/bug-reproduce/repro.mjs | 0 | REPRO OK |
104
+ | .e2e-tmp/apc/bug-reproduce/repro.mjs:3 | 3 REVERSAL RED | node .e2e-tmp/apc/bug-reproduce/repro.mjs | 1 | AssertionError: clamp must respect lower bound |
105
+ ```
106
+
107
+ **行号照抄 `cat -n` / `rg -n` 的真实输出**,不许凭印象写。引用必须 **repo-root-relative**(绝对路径与 `/tmp/...` 一律判红——这也是上面要求复现器落 `.e2e-tmp/` 且不删的原因)。产物存**可引用的扩展名**:引用解析器只认固定后缀集(`ts/tsx/js/jsx/mjs/cjs/prisma/sql/md/json/sh/py/yml/yaml`),存成 `.txt`/`.log` 的引用不会被解析。
108
+
109
+ ## 产出(副作用 oracle,报告里必须给)
110
+
111
+ 1. **复现器命令**:你**真跑过**的那一条(`node repro.mjs` / `apc test --tier=…` / pytest…),可贴调用。
112
+ 2. **初始 RED**:buggy 代码下复现器失败(AssertionError + 非零退出码)。
113
+ 3. **fix 后 GREEN**:`exit=0`。
114
+ 4. **反转 RED**(承重):把 bug 注入回去后复现器**再次变红**(非零退出码)——这是"锁住了"的唯一证明。
115
+ 5. **复现器本体留在盘上**(repo-relative 路径),锚点声明 + 相位表的每条引用都能读回。
116
+ 6.(有 task 上下文时)**BugfixCard `stage-repro` 段**:三份证据 asset link 挂上,卡可回读。
117
+
118
+ **不许**:只报到 GREEN 就收工(没有反转 = 没证明锁住);放松断言让恒绿脚本冒充复现器;把 `env_blocked`(exit 78)当作 bug 复现上报;凭推理宣称"应该能复现"而没真跑;**跑完 `rm -rf` 掉复现器**(证据必须留到判据读盘之后);**在共享工作树里用 `git stash`/`git checkout` 做反转**(会卷走别人的未提交改动)。
119
+
120
+ ## 诚实边界
121
+
122
+ - **本 skill 不保证任何 bug 都能建出紧复现器**:跨进程时序、真机才暴露、非确定性极低复现率的 bug,可能只能拉高复现率而非稳定复现(`diagnosing-bugs` Phase 1)。建不出就**显式停手说清楚**、列出试过什么、要人给可复现环境/捕获产物——**不许**无复现器就跳去建假设。
123
+ - **反转负控证明的是"复现器红在这个 bug 上",不是"这个 fix 是最终正解"**——正解由后续 fix + 评审 + test-runner 兜。
124
+ - **共享工作树是常态**:本仓库经常多个 session 同时在同一个 working tree 上飞着几百个未提交改动。因此反转 fix **默认手工编辑源文件**;`git stash`/`git checkout` 只在你确认独占该工作树、且 `git status` 干净时才等价可用。这不是洁癖——stash 卷走别人的改动是不可逆的破坏。
125
+ - **BugfixCard 的段名以实现为准(`repro`)**:`docs/apc/12` 里写的 `stage-reproduce` 是文档漂移,代码 `src/lib/apc-cards/card-profile.ts` 的 BugfixCard 首阶段叫 `repro`。无 `PRISMER_TASK_ID` 时 `card.taskId` 无法合法填写——**如实报告"卡未写"**,不要伪造一个绑定去凑一张卡。
126
+
127
+ <!-- APC-ACK:v1 -->
128
+
129
+ ## 调用回执(APC 平台方运营纪律 · 自动注入,勿手改)
130
+
131
+ 执行本 skill 的**第一步**,先落一条调用回执:
132
+
133
+ ```bash
134
+ cloud skill ack bug-reproduce --task "$PRISMER_TASK_ID"
135
+ ```
136
+
137
+ **按退出码分流**(这条命令的退出码是承重信息,禁止用 `||` 兜底、`; true`、
138
+ `set +e` 或重定向把它抹掉):
139
+
140
+ | exit | 含义 | 你要做的 |
141
+ | --- | --- | --- |
142
+ | `0` | 回执已落库(`im_task_logs.action='skill_ack'`) | 继续执行本 skill |
143
+ | `3` | **无 task 上下文**——本次运行没有 task,产不出回执 | 继续执行本 skill;但本次运行**没有回执**,任何报告里都不得声称已 ack |
144
+ | `4` | 你不是该 task 的 assignee,服务端拒绝 | 停下并上报:回执只能由执行该 task 的 agent 产生 |
145
+ | `1` | 其它失败(网络 / 服务端) | 重试一次;仍失败则继续执行,并在结果里显式标注「回执缺失」 |
146
+
147
+ 回执只证明本 skill **被调度**,不证明**执行正确**——效果证明由本 skill 自己的
148
+ acceptanceCriteria 副作用断言承担(apc/04 §2 层 1 诚实标注)。
149
+
150
+ <!-- /APC-ACK:v1 -->
@@ -0,0 +1,96 @@
1
+ {
2
+ "schemaVersion": 1,
3
+ "slug": "bug-reproduce",
4
+ "name": "Bug Reproduce",
5
+ "description": "Turn a known bug into a tight, red-capable reproducer (failing test / script), then PROVE the reproducer actually locks that bug with a reversal negative control: reintroduce the bug and the reproducer must go red again. A reproducer that stays green when the bug is put back is a fake and fails the task.",
6
+ "category": "diagnosis",
7
+ "version": "1.0.0",
8
+ "license": "MIT",
9
+ "compatibility": [
10
+ "claude-code"
11
+ ],
12
+ "runtime": {
13
+ "kind": "text-workflow",
14
+ "requires": {
15
+ "env": [],
16
+ "bins": [
17
+ "node",
18
+ "git"
19
+ ],
20
+ "capabilities": []
21
+ }
22
+ },
23
+ "sampleTasks": [
24
+ {
25
+ "title": "Reproduce a clamp() lower-bound bug and prove the lock with a reversal",
26
+ "prompt": "Run the bug-reproduce skill on this known bug. BUG: a `clamp(x, lo, hi)` helper ignores its lower bound — it returns `Math.min(x, hi)` so `clamp(-5, 0, 10)` wrongly returns -5 instead of 0. Build a tight, deterministic reproducer in a throwaway dir and PROVE it locks the bug with a reversal negative control. Run these exact steps and report the observed exit codes: (1) `d=.e2e-tmp/apc/bug-reproduce && rm -rf \"$d\" && mkdir -p \"$d\"` — a clean, deterministic workspace that is REPO-RELATIVE and SURVIVES the run. Do NOT use `mktemp -d`: the reproducer you build IS the evidence and it is re-read off disk after the run, so a temp dir you delete at the end destroys exactly the artifact the acceptance re-verifies (`.e2e-tmp/` is gitignored, so this pollutes nothing); (2) write `\"$d\"/clamp.mjs` containing the BUGGY version: `export const clamp = (x, lo, hi) => Math.min(x, hi);`; (3) write the reproducer `\"$d\"/repro.mjs`: `import assert from 'node:assert'; import { clamp } from './clamp.mjs'; assert.strictEqual(clamp(-5, 0, 10), 0, 'clamp must respect lower bound'); console.log('REPRO OK');`; (4) run the reproducer command `node \"$d\"/repro.mjs; echo \"exit=$?\"` — it MUST fail (AssertionError, non-zero exit): this is the bug reproduced RED; (5) apply the minimal fix — rewrite `\"$d\"/clamp.mjs` to `export const clamp = (x, lo, hi) => Math.max(lo, Math.min(x, hi));` — and re-run `node \"$d\"/repro.mjs; echo \"exit=$?\"`: it MUST now pass (exit 0) GREEN; (6) REVERSAL NEGATIVE CONTROL (load-bearing): revert the fix by EDITING `\"$d\"/clamp.mjs` DIRECTLY back to the buggy one-line body — do NOT use `git stash` / `git checkout` for this: you are in a SHARED working tree with other sessions' uncommitted changes, and stashing would revert THEIR work too. Re-run `node \"$d\"/repro.mjs; echo \"exit=$?\"` — it MUST go RED again (non-zero). This proves the reproducer is red-capable ON THIS bug, not accidentally green; (7) restore the fix, confirm GREEN one last time, and LEAVE `.e2e-tmp/apc/bug-reproduce/` in place — do not delete it.\n\n--- YOUR REPORT MUST USE THIS MACHINE-CHECKED OUTPUT CONTRACT (it is re-verified against the filesystem, so a reproducer you never actually wrote is caught):\n\nLine 1 — the reproducer anchor, exactly this shape (the symbol is re-read off disk and must really occur in that file):\n`CHANGE-POINT: clamp @ .e2e-tmp/apc/bug-reproduce/clamp.mjs`\n\nThen the RED→GREEN→REVERSAL phase table — one row per phase you actually ran, the FIRST CELL being the `path:line` in your reproducer/subject that the phase turns on (copy the line number from `cat -n` or `rg -n` over the files you just wrote; a missing file, an out-of-range line or a blank line FAILS the report):\n```\n| path:line | phase | command | exit | observed |\n| --- | --- | --- | --- | --- |\n| .e2e-tmp/apc/bug-reproduce/repro.mjs:3 | 1 RED (buggy) | node .e2e-tmp/apc/bug-reproduce/repro.mjs | 1 | AssertionError: clamp must respect lower bound |\n| .e2e-tmp/apc/bug-reproduce/clamp.mjs:1 | 2 GREEN (fixed) | node .e2e-tmp/apc/bug-reproduce/repro.mjs | 0 | REPRO OK |\n| .e2e-tmp/apc/bug-reproduce/repro.mjs:3 | 3 REVERSAL RED | node .e2e-tmp/apc/bug-reproduce/repro.mjs | 1 | AssertionError: clamp must respect lower bound |\n```\nYou need at least 3 phase rows carrying a verified `path:line`, and at least 2 of your citations must land on a line that LITERALLY CONTAINS `clamp` — a real line that is not a real hit in the reproducer is not evidence.\n\nHARD RULE: do not guess line numbers. Every `path:line` anywhere in your report is re-read off disk AFTER the run, so the files must still be there. Citations MUST be repo-root-relative (`.e2e-tmp/apc/bug-reproduce/repro.mjs:3`, never an absolute path and never a `/tmp/...` path, which cannot be resolved from the repo root).\n\nReport: the exact reproducer command you ran, the initial RED (exit code + the assertion that failed), the GREEN after the fix (exit 0), and the reversal RED after reintroducing the bug (exit code) — that reversal is the whole point: it is how you know the reproducer locks the bug.",
27
+ "expectedArtifacts": [
28
+ "the reproducer left on disk at `.e2e-tmp/apc/bug-reproduce/` (repo-relative, survives the run) + a `CHANGE-POINT: clamp @ .e2e-tmp/apc/bug-reproduce/clamp.mjs` declaration",
29
+ "RED→GREEN→REVERSAL phase table: ≥3 rows whose first cell is a `path:line` that resolves on disk, ≥2 landing on a line containing `clamp`",
30
+ "the exact reproducer command (a `node repro.mjs` invocation) that was actually run",
31
+ "initial RED: the reproducer failed on the buggy code (AssertionError, non-zero exit)",
32
+ "GREEN after the minimal fix (exit 0)",
33
+ "reversal negative control: reintroducing the bug makes the reproducer RED again (non-zero exit) — proves the lock"
34
+ ],
35
+ "acceptanceCriteria": [
36
+ {
37
+ "label": "the reproducer REALLY EXISTS on disk — anchored on `clamp @ .e2e-tmp/apc/bug-reproduce/clamp.mjs`, every path:line re-read off disk, ≥2 citations landing on a line that actually contains the subject symbol, ≥3 phase rows (RED/GREEN/REVERSAL) carrying a verified citation",
38
+ "type": "structured",
39
+ "checker": "cited-evidence",
40
+ "args": {
41
+ "minRows": 3,
42
+ "minAnchoredRows": 2,
43
+ "anchorMinLength": 4,
44
+ "expectedChangePoint": {
45
+ "symbol": "clamp",
46
+ "path": ".e2e-tmp/apc/bug-reproduce/clamp.mjs"
47
+ }
48
+ },
49
+ "match": "<structured:cited-evidence>",
50
+ "required": true
51
+ },
52
+ {
53
+ "label": "names a concrete runnable reproducer command (node/test invocation)",
54
+ "match": "\\b(node|npx|tsx|npm|pnpm|yarn|pytest|go\\s+test|cargo\\s+test|apc\\s+test)\\b",
55
+ "type": "regex",
56
+ "required": true
57
+ },
58
+ {
59
+ "label": "initial RED: reproducer fails on the bug (assertion / non-zero exit)",
60
+ "match": "(assert\\w*|assertionerror|❌|✗|fail\\w*|exit(\\s*code)?[^0-9]{0,6}[1-9])",
61
+ "type": "regex",
62
+ "required": true
63
+ },
64
+ {
65
+ "label": "GREEN after the fix (pass / exit 0)",
66
+ "match": "(pass\\w*|✓|✔|success\\w*|repro\\s*ok|green\\b|exit(\\s*code)?[^0-9]{0,6}0)\\b",
67
+ "type": "regex",
68
+ "required": true
69
+ },
70
+ {
71
+ "label": "REVERSAL negative control: reintroducing the bug makes the reproducer RED again (the lock)",
72
+ "match": "((revert|reversal|revers\\w*|reintroduc|re-?inject|re-?insert|put(ting)?\\s+(the\\s+)?bug\\s+back|remov\\w*\\s+the\\s+fix|back\\s?out|stash|undo\\s+the\\s+fix|buggy\\s*(version|body|one-?liner|代码|码|恢复|复原)|反转|复原|放回|重新(注入|引入)|注入回|撤(掉|回|销)\\s*(了\\s*)?(修复|fix))[\\s\\S]{0,220}(fail\\w*|red\\b|❌|✗|assert\\w*|non-?zero|exit(\\s*code)?[^0-9]{0,6}[1-9]))|((fail\\w*|red\\b|❌|✗|assert\\w*|non-?zero|exit(\\s*code)?[^0-9]{0,6}[1-9])[\\s\\S]{0,220}(revert|reversal|revers\\w*|reintroduc|re-?inject|re-?insert|put(ting)?\\s+(the\\s+)?bug\\s+back|remov\\w*\\s+the\\s+fix|back\\s?out|stash|undo\\s+the\\s+fix|buggy\\s*(version|body|one-?liner|代码|码|恢复|复原)|反转|复原|放回|重新(注入|引入)|注入回|撤(掉|回|销)\\s*(了\\s*)?(修复|fix)))",
73
+ "type": "regex",
74
+ "flags": "is",
75
+ "required": true
76
+ }
77
+ ]
78
+ }
79
+ ],
80
+ "security": {
81
+ "dataAccess": [
82
+ "local-filesystem"
83
+ ],
84
+ "humanApprovalRequiredFor": []
85
+ },
86
+ "provenance": {
87
+ "sourceKind": "inline-spec",
88
+ "sourceRefs": [
89
+ "docs/apc/12-skill-acceptance-tasks.md",
90
+ "docs/apc/05-devchain-gaps-and-skills.md",
91
+ "sdk/prismer-cloud/built-in-skills/diagnosing-bugs/SKILL.md"
92
+ ],
93
+ "authoredBy": "prismer-platform",
94
+ "authoredAt": "2026-07-24T00:00:00Z"
95
+ }
96
+ }