@playcraft/cli 0.1.54 → 0.1.55-beta

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 (453) hide show
  1. package/README.md +83 -15
  2. package/SKILLS_REGISTRY.md +149 -0
  3. package/dist/agent/local-backend.js +1 -1
  4. package/dist/assets/client.js +157 -0
  5. package/dist/assets/messages.js +48 -0
  6. package/dist/auth/account-activation.js +157 -0
  7. package/dist/auth/messages.js +30 -0
  8. package/dist/cli-root-help.js +4 -0
  9. package/dist/commands/assets.js +123 -0
  10. package/dist/commands/build-all.js +5 -19
  11. package/dist/commands/build-temp.js +26 -0
  12. package/dist/commands/build.js +15 -28
  13. package/dist/commands/create.js +26 -33
  14. package/dist/commands/image-layer-messages.js +37 -0
  15. package/dist/commands/image-layer-tools.js +185 -0
  16. package/dist/commands/image.js +2 -73
  17. package/dist/commands/library-messages.js +46 -0
  18. package/dist/commands/library.js +130 -0
  19. package/dist/commands/login.js +84 -42
  20. package/dist/commands/platform-skills.generated.js +19 -0
  21. package/dist/commands/playable.js +53 -0
  22. package/dist/commands/preview-runtime.js +21 -0
  23. package/dist/commands/skills.js +4 -0
  24. package/dist/commands/tools-3d.js +11 -0
  25. package/dist/commands/tools-batch.js +113 -0
  26. package/dist/commands/tools-generation.js +6 -0
  27. package/dist/commands/tools.js +2 -0
  28. package/dist/commands/video.js +122 -0
  29. package/dist/commands/workspace-runtime.js +54 -0
  30. package/dist/commands/workspace.js +40 -0
  31. package/dist/config.js +59 -4
  32. package/dist/index.js +47 -3
  33. package/dist/preview-runtime/distribution.js +77 -0
  34. package/dist/project-skills/builtin-import.js +225 -0
  35. package/dist/project-skills/commands.js +77 -0
  36. package/dist/project-skills/lifecycle.js +28 -0
  37. package/dist/project-skills/local-run.js +112 -0
  38. package/dist/project-skills/local-store.js +221 -0
  39. package/dist/project-skills/messages.js +80 -0
  40. package/dist/project-skills/reconcile.js +62 -0
  41. package/dist/project-skills/remote-cache.js +51 -0
  42. package/dist/project-skills/validation.js +19 -0
  43. package/dist/recording/messages.js +40 -0
  44. package/dist/recording/project-digest.js +85 -0
  45. package/dist/recording/recorder.js +293 -0
  46. package/dist/recording/scenario.js +50 -0
  47. package/dist/remix/clone.js +2 -0
  48. package/dist/remix/init-template.js +2 -0
  49. package/dist/remix/pull.js +2 -0
  50. package/dist/remix/push.js +21 -1
  51. package/dist/skill-registry/client.js +345 -0
  52. package/dist/skill-registry/commands.js +180 -0
  53. package/dist/skill-registry/evaluation-client.js +156 -0
  54. package/dist/skill-registry/evaluation-commands.js +174 -0
  55. package/dist/skill-registry/messages.js +177 -0
  56. package/dist/skill-registry/package.js +275 -0
  57. package/dist/skill-registry/platform-package.js +100 -0
  58. package/dist/utils/agent-api-client.js +245 -30
  59. package/dist/utils/environment-endpoints.js +17 -0
  60. package/dist/utils/error-diagnostics.js +20 -0
  61. package/dist/utils/playcraft-http-client.js +6 -4
  62. package/dist/utils/tool-operation-journal.js +124 -0
  63. package/dist/utils/video-evidence-git.js +81 -0
  64. package/dist/video-replication/client.js +234 -0
  65. package/dist/video-replication/comparison-evidence.js +149 -0
  66. package/dist/video-replication/comparison-files.js +57 -0
  67. package/dist/video-replication/comparison-log.js +72 -0
  68. package/dist/video-replication/comparison-messages.js +104 -0
  69. package/dist/video-replication/comparison-output.js +63 -0
  70. package/dist/video-replication/comparison-preflight.js +66 -0
  71. package/dist/video-replication/comparison.js +230 -0
  72. package/dist/video-replication/diagnostics.js +41 -0
  73. package/dist/video-replication/evidence.js +165 -0
  74. package/dist/video-replication/media.js +112 -0
  75. package/dist/video-replication/messages.js +97 -0
  76. package/dist/workspace/messages.js +67 -0
  77. package/dist/workspace/transfer-client.js +237 -0
  78. package/dist/workspace/transfer-errors.js +48 -0
  79. package/dist/workspace-runtime/batch/content-changes.js +30 -0
  80. package/dist/workspace-runtime/batch/control.js +86 -0
  81. package/dist/workspace-runtime/batch/deliver.js +173 -0
  82. package/dist/workspace-runtime/batch/freeze.js +101 -0
  83. package/dist/workspace-runtime/batch/generate.js +249 -0
  84. package/dist/workspace-runtime/batch/git.js +40 -0
  85. package/dist/workspace-runtime/batch/occupancy.js +8 -0
  86. package/dist/workspace-runtime/batch/policy.js +70 -0
  87. package/dist/workspace-runtime/batch/prepare.js +317 -0
  88. package/dist/workspace-runtime/batch/processes.js +72 -0
  89. package/dist/workspace-runtime/batch/records.js +113 -0
  90. package/dist/workspace-runtime/batch/routes.js +61 -0
  91. package/dist/workspace-runtime/batch/source-candidate.js +86 -0
  92. package/dist/workspace-runtime/batch/source-capture.js +146 -0
  93. package/dist/workspace-runtime/batch/source-failure.js +43 -0
  94. package/dist/workspace-runtime/batch/source-publish.js +130 -0
  95. package/dist/workspace-runtime/codex/app-server.js +1065 -0
  96. package/dist/workspace-runtime/codex/compact.js +46 -0
  97. package/dist/workspace-runtime/codex/config-toml.js +107 -0
  98. package/dist/workspace-runtime/codex/delivery-tools.js +144 -0
  99. package/dist/workspace-runtime/codex/jsonrpc-stdio.js +145 -0
  100. package/dist/workspace-runtime/codex/launcher-client.js +177 -0
  101. package/dist/workspace-runtime/codex/loopback.js +146 -0
  102. package/dist/workspace-runtime/codex/mcp-config.js +39 -0
  103. package/dist/workspace-runtime/codex/model-broker.js +263 -0
  104. package/dist/workspace-runtime/codex/native-adapter.js +9 -0
  105. package/dist/workspace-runtime/codex/permissions.js +79 -0
  106. package/dist/workspace-runtime/codex/thread-image.js +38 -0
  107. package/dist/workspace-runtime/codex/tool-response.js +10 -0
  108. package/dist/workspace-runtime/codex/ui-instructions.js +4 -0
  109. package/dist/workspace-runtime/codex/ui-tools.js +203 -0
  110. package/dist/workspace-runtime/codex/work-mode.js +15 -0
  111. package/dist/workspace-runtime/main.js +10 -0
  112. package/dist/workspace-runtime/persistence/journal.js +365 -0
  113. package/dist/workspace-runtime/persistence/native-subagents.js +162 -0
  114. package/dist/workspace-runtime/persistence/sqlite-client.js +77 -0
  115. package/dist/workspace-runtime/persistence/sqlite-worker.js +1161 -0
  116. package/dist/workspace-runtime/persistence/stopped-execution.js +77 -0
  117. package/dist/workspace-runtime/previews/diagnostics.js +44 -0
  118. package/dist/workspace-runtime/previews/output.js +36 -0
  119. package/dist/workspace-runtime/previews/publish.js +283 -0
  120. package/dist/workspace-runtime/previews/runtime-preview.js +251 -0
  121. package/dist/workspace-runtime/previews/single-file.js +43 -0
  122. package/dist/workspace-runtime/processes/managed-writes.js +69 -0
  123. package/dist/workspace-runtime/serve.js +441 -0
  124. package/dist/workspace-runtime/server/accept-operation.js +61 -0
  125. package/dist/workspace-runtime/server/asset-transfers.js +63 -0
  126. package/dist/workspace-runtime/server/auth.js +21 -0
  127. package/dist/workspace-runtime/server/connectivity.js +211 -0
  128. package/dist/workspace-runtime/server/desktop-host.js +429 -0
  129. package/dist/workspace-runtime/server/desktop-preview-config.js +81 -0
  130. package/dist/workspace-runtime/server/desktop-preview-service.js +157 -0
  131. package/dist/workspace-runtime/server/desktop-preview-static.js +53 -0
  132. package/dist/workspace-runtime/server/desktop-preview.js +189 -0
  133. package/dist/workspace-runtime/server/dispatch.js +1655 -0
  134. package/dist/workspace-runtime/server/endpoints.js +21 -0
  135. package/dist/workspace-runtime/server/execution-group.js +90 -0
  136. package/dist/workspace-runtime/server/http.js +1363 -0
  137. package/dist/workspace-runtime/server/lock.js +53 -0
  138. package/dist/workspace-runtime/server/operation-record.js +33 -0
  139. package/dist/workspace-runtime/server/rfb-watch-gate.js +168 -0
  140. package/dist/workspace-runtime/server/session-restore.js +84 -0
  141. package/dist/workspace-runtime/server/source-uploader.js +138 -0
  142. package/dist/workspace-runtime/server/submit-operation.js +41 -0
  143. package/dist/workspace-runtime/server/terminal-host.js +366 -0
  144. package/dist/workspace-runtime/server/types.js +1 -0
  145. package/dist/workspace-runtime/server/workspace-transfer.js +168 -0
  146. package/dist/workspace-runtime/verify-artifact.js +59 -0
  147. package/dist/workspace-runtime/workspaces/append-only-log.js +62 -0
  148. package/dist/workspace-runtime/workspaces/archive.js +207 -0
  149. package/dist/workspace-runtime/workspaces/artifact-events.js +55 -0
  150. package/dist/workspace-runtime/workspaces/artifact-files.js +199 -0
  151. package/dist/workspace-runtime/workspaces/artifact-receipts.js +89 -0
  152. package/dist/workspace-runtime/workspaces/artifacts.js +282 -0
  153. package/dist/workspace-runtime/workspaces/asset-library-import.js +387 -0
  154. package/dist/workspace-runtime/workspaces/asset-publication-access.js +25 -0
  155. package/dist/workspace-runtime/workspaces/asset-transfer-dependencies.js +81 -0
  156. package/dist/workspace-runtime/workspaces/asset-transfer-publish.js +438 -0
  157. package/dist/workspace-runtime/workspaces/asset-transfer-storage.js +389 -0
  158. package/dist/workspace-runtime/workspaces/attachment-content.js +73 -0
  159. package/dist/workspace-runtime/workspaces/attachments.js +185 -0
  160. package/dist/workspace-runtime/workspaces/batch-commit.js +142 -0
  161. package/dist/workspace-runtime/workspaces/binary-content.js +65 -0
  162. package/dist/workspace-runtime/workspaces/binary-write.js +117 -0
  163. package/dist/workspace-runtime/workspaces/cli-context.js +23 -0
  164. package/dist/workspace-runtime/workspaces/cli-credentials.js +115 -0
  165. package/dist/workspace-runtime/workspaces/composer-context.js +147 -0
  166. package/dist/workspace-runtime/workspaces/context-error.js +2 -0
  167. package/dist/workspace-runtime/workspaces/delivery-build.js +331 -0
  168. package/dist/workspace-runtime/workspaces/delivery-store.js +168 -0
  169. package/dist/workspace-runtime/workspaces/delivery.js +64 -0
  170. package/dist/workspace-runtime/workspaces/dependencies.js +279 -0
  171. package/dist/workspace-runtime/workspaces/developer-command.js +98 -0
  172. package/dist/workspace-runtime/workspaces/directories.js +135 -0
  173. package/dist/workspace-runtime/workspaces/directory-access.js +37 -0
  174. package/dist/workspace-runtime/workspaces/directory-attachments.js +245 -0
  175. package/dist/workspace-runtime/workspaces/directory-create.js +57 -0
  176. package/dist/workspace-runtime/workspaces/directory-maintenance.js +111 -0
  177. package/dist/workspace-runtime/workspaces/directory-mutations.js +238 -0
  178. package/dist/workspace-runtime/workspaces/directory-revisions.js +56 -0
  179. package/dist/workspace-runtime/workspaces/directory-stats.js +49 -0
  180. package/dist/workspace-runtime/workspaces/disk-snapshot.js +31 -0
  181. package/dist/workspace-runtime/workspaces/empty-template.js +43 -0
  182. package/dist/workspace-runtime/workspaces/file-content.js +48 -0
  183. package/dist/workspace-runtime/workspaces/files-search.js +116 -0
  184. package/dist/workspace-runtime/workspaces/files.js +150 -0
  185. package/dist/workspace-runtime/workspaces/git-credential-broker.js +312 -0
  186. package/dist/workspace-runtime/workspaces/git-credential-helper.js +68 -0
  187. package/dist/workspace-runtime/workspaces/git-direct-store.js +155 -0
  188. package/dist/workspace-runtime/workspaces/git.js +670 -0
  189. package/dist/workspace-runtime/workspaces/instructions.js +56 -0
  190. package/dist/workspace-runtime/workspaces/json5-edit.js +313 -0
  191. package/dist/workspace-runtime/workspaces/library-attachments.js +268 -0
  192. package/dist/workspace-runtime/workspaces/operation-log.js +23 -0
  193. package/dist/workspace-runtime/workspaces/optional-platform-skills.js +14 -0
  194. package/dist/workspace-runtime/workspaces/parameter-agent-inputs.js +97 -0
  195. package/dist/workspace-runtime/workspaces/parameter-agent-protocol.js +40 -0
  196. package/dist/workspace-runtime/workspaces/parameter-agent-store.js +58 -0
  197. package/dist/workspace-runtime/workspaces/parameter-agent.js +284 -0
  198. package/dist/workspace-runtime/workspaces/parameter-assets.js +189 -0
  199. package/dist/workspace-runtime/workspaces/parameters.js +329 -0
  200. package/dist/workspace-runtime/workspaces/prepare.js +284 -0
  201. package/dist/workspace-runtime/workspaces/registry.js +251 -0
  202. package/dist/workspace-runtime/workspaces/remix-references.js +301 -0
  203. package/dist/workspace-runtime/workspaces/revisions.js +31 -0
  204. package/dist/workspace-runtime/workspaces/session-image.js +104 -0
  205. package/dist/workspace-runtime/workspaces/shared-git.js +40 -0
  206. package/dist/workspace-runtime/workspaces/skill-artifact-loader.js +95 -0
  207. package/dist/workspace-runtime/workspaces/skills.js +191 -0
  208. package/dist/workspace-runtime/workspaces/theme-asset-index.js +157 -0
  209. package/dist/workspace-runtime/workspaces/transfer-quota.js +69 -0
  210. package/dist/workspace-runtime/workspaces/transfer.js +471 -0
  211. package/dist/workspace-runtime/workspaces/turn-changes.js +75 -0
  212. package/dist/workspace-runtime/workspaces/video-attachments.js +49 -0
  213. package/dist/workspace-runtime/workspaces/worktree-attachments.js +74 -0
  214. package/dist/workspace-runtime/workspaces/worktree-checkout.js +67 -0
  215. package/dist/workspace-runtime/workspaces/worktrees.js +73 -0
  216. package/package.json +16 -5
  217. package/project-template/.claude/skills/playcraft-audio-generation/SKILL.md +31 -4
  218. package/project-template/.claude/skills/playcraft-image-generation/SKILL.md +36 -5
  219. package/project-template/.claude/skills/playcraft-image-generation/reference/build-sprite-sheet.template.mjs +1 -1
  220. package/project-template/.claude/skills/playcraft-image-generation/reference/compare-style.template.mjs +1 -1
  221. package/project-template/.claude/skills/playcraft-image-generation/reference/gen-batch-sprite.template.mjs +1 -1
  222. package/project-template/.claude/skills/playcraft-image-generation/reference/gen-batch.template.mjs +1 -1
  223. package/project-template/.claude/skills/playcraft-image-generation/reference/gen-edit-variants.template.mjs +1 -1
  224. package/project-template/.claude/skills/playcraft-image-generation/reference/process-batch.template.mjs +1 -1
  225. package/project-template/.claude/skills/playcraft-image-generation/reference/ta-image-generation-detail.md +300 -0
  226. package/project-template/.claude/skills/playcraft-image-generation/reference/validate-sprite-sheet.template.mjs +1 -1
  227. package/project-template/.claude/skills/playcraft-image-processing/SKILL.md +50 -25
  228. package/project-template/.claude/skills/playcraft-replica-validation/SKILL.md +25 -0
  229. package/project-template/.claude/skills/playcraft-replica-validation/references/contracts.md +79 -0
  230. package/project-template/.claude/skills/playcraft-video-understanding/SKILL.md +29 -0
  231. package/project-template/.claude/skills/playcraft-video-understanding/references/contracts.md +37 -0
  232. package/project-template/.claude/skills/playcraft-workspace-assets/SKILL.md +53 -0
  233. package/project-template/.claude/skills/playcraft-workspace-assets/references/requests.json +32 -0
  234. package/project-template-v2/.claude/agents/artist.md +82 -0
  235. package/project-template-v2/.claude/agents/developer.md +153 -0
  236. package/project-template-v2/.claude/agents/game-designer.md +264 -0
  237. package/project-template-v2/.claude/agents/refs/artist-art-style-catalog.md +533 -0
  238. package/project-template-v2/.claude/agents/refs/artist-color-audio-recipes.md +153 -0
  239. package/project-template-v2/.claude/agents/refs/artist-dimension-axis.md +27 -0
  240. package/project-template-v2/.claude/agents/refs/artist-master-composite-recipes.md +208 -0
  241. package/project-template-v2/.claude/agents/refs/atom-skill-library.md +81 -0
  242. package/project-template-v2/.claude/agents/refs/developer-impl-cookbook.md +432 -0
  243. package/project-template-v2/.claude/agents/refs/framework-5-component-filter.md +252 -0
  244. package/project-template-v2/.claude/agents/refs/framework-game-feel-juice.md +266 -0
  245. package/project-template-v2/.claude/agents/refs/framework-mda.md +147 -0
  246. package/project-template-v2/.claude/agents/refs/game-designer-gameplay-sufficiency.md +123 -0
  247. package/project-template-v2/.claude/agents/refs/ta-3d-flip-recipe.md +88 -0
  248. package/project-template-v2/.claude/agents/refs/ta-atlas-deliverable-standard.md +67 -0
  249. package/project-template-v2/.claude/agents/refs/ta-batch-pipeline-recipes.md +120 -0
  250. package/project-template-v2/.claude/agents/refs/ta-image-generation-detail.md +300 -0
  251. package/project-template-v2/.claude/agents/refs/ta-image-ops-reference.md +495 -0
  252. package/project-template-v2/.claude/agents/refs/ta-pipeline-cookbook.md +1141 -0
  253. package/project-template-v2/.claude/agents/refs/ta-tools-reference.md +111 -0
  254. package/project-template-v2/.claude/agents/refs/ta-vfx-preset-catalog.md +365 -0
  255. package/project-template-v2/.claude/agents/refs/threejs-cannon-pitfalls.md +412 -0
  256. package/project-template-v2/.claude/agents/reviewer.md +75 -0
  257. package/project-template-v2/.claude/agents/technical-artist.md +86 -0
  258. package/project-template-v2/.claude/hooks/snapshot-milestone.mjs +243 -0
  259. package/project-template-v2/.claude/hooks/user-prompt.mjs +133 -0
  260. package/project-template-v2/.claude/settings.json +33 -0
  261. package/project-template-v2/.claude/skills/brainstorming/SKILL.md +161 -0
  262. package/project-template-v2/.claude/skills/brainstorming/scripts/frame-template.html +270 -0
  263. package/project-template-v2/.claude/skills/brainstorming/scripts/helper.js +177 -0
  264. package/project-template-v2/.claude/skills/brainstorming/scripts/server.cjs +354 -0
  265. package/project-template-v2/.claude/skills/brainstorming/scripts/start-server.sh +148 -0
  266. package/project-template-v2/.claude/skills/brainstorming/scripts/stop-server.sh +56 -0
  267. package/project-template-v2/.claude/skills/brainstorming/scripts/wait-for-selection.sh +62 -0
  268. package/project-template-v2/.claude/skills/brainstorming/spec-document-reviewer-prompt.md +49 -0
  269. package/project-template-v2/.claude/skills/brainstorming/visual-companion.md +309 -0
  270. package/project-template-v2/.claude/skills/playcraft-ad-psychology/SKILL.md +182 -0
  271. package/project-template-v2/.claude/skills/playcraft-art-style-guide/SKILL.md +123 -0
  272. package/project-template-v2/.claude/skills/playcraft-asset-state-sheet/SKILL.md +205 -0
  273. package/project-template-v2/.claude/skills/playcraft-audio-generation/SKILL.md +307 -0
  274. package/project-template-v2/.claude/skills/playcraft-batch-pipeline/SKILL.md +184 -0
  275. package/project-template-v2/.claude/skills/playcraft-build-optimizer/SKILL.md +306 -0
  276. package/project-template-v2/.claude/skills/playcraft-image-generation/SKILL.md +401 -0
  277. package/project-template-v2/.claude/skills/playcraft-image-generation/reference/build-sprite-sheet.template.mjs +123 -0
  278. package/project-template-v2/.claude/skills/playcraft-image-generation/reference/compare-style.template.mjs +254 -0
  279. package/project-template-v2/.claude/skills/playcraft-image-generation/reference/gen-batch-sprite.template.mjs +333 -0
  280. package/project-template-v2/.claude/skills/playcraft-image-generation/reference/gen-batch.template.mjs +95 -0
  281. package/project-template-v2/.claude/skills/playcraft-image-generation/reference/gen-edit-variants.template.mjs +118 -0
  282. package/project-template-v2/.claude/skills/playcraft-image-generation/reference/process-batch.template.mjs +136 -0
  283. package/project-template-v2/.claude/skills/playcraft-image-generation/reference/prompt-cookbook.md +397 -0
  284. package/project-template-v2/.claude/skills/playcraft-image-generation/reference/ta-image-generation-detail.md +300 -0
  285. package/project-template-v2/.claude/skills/playcraft-image-generation/reference/validate-sprite-sheet.template.mjs +296 -0
  286. package/project-template-v2/.claude/skills/playcraft-image-ops/SKILL.md +122 -0
  287. package/project-template-v2/.claude/skills/playcraft-image-processing/SKILL.md +244 -0
  288. package/project-template-v2/.claude/skills/playcraft-masking/SKILL.md +373 -0
  289. package/project-template-v2/.claude/skills/playcraft-playable-optimization/SKILL.md +161 -0
  290. package/project-template-v2/.claude/skills/playcraft-research/SKILL.md +215 -0
  291. package/project-template-v2/.claude/skills/playcraft-skill-recommender/SKILL.md +382 -0
  292. package/project-template-v2/.claude/skills/playcraft-sprite-generation/SKILL.md +423 -0
  293. package/project-template-v2/.claude/skills/playcraft-sprite-remix/SKILL.md +158 -0
  294. package/project-template-v2/.claude/skills/playcraft-sprite-sheet/SKILL.md +100 -0
  295. package/project-template-v2/.claude/skills/playcraft-storyboard/SKILL.md +167 -0
  296. package/project-template-v2/.claude/skills/playcraft-style-qa/SKILL.md +270 -0
  297. package/project-template-v2/.claude/skills/playcraft-text-rendering/SKILL.md +236 -0
  298. package/project-template-v2/.claude/skills/playcraft-vfx-animation/SKILL.md +130 -0
  299. package/project-template-v2/.claude/skills/playcraft-workspace-assets/SKILL.md +53 -0
  300. package/project-template-v2/.claude/skills/playcraft-workspace-assets/references/requests.json +32 -0
  301. package/project-template-v2/.claude/skills/playwright-cli/SKILL.md +390 -0
  302. package/project-template-v2/.claude/skills/playwright-cli/references/element-attributes.md +23 -0
  303. package/project-template-v2/.claude/skills/playwright-cli/references/playwright-tests.md +39 -0
  304. package/project-template-v2/.claude/skills/playwright-cli/references/request-mocking.md +87 -0
  305. package/project-template-v2/.claude/skills/playwright-cli/references/running-code.md +240 -0
  306. package/project-template-v2/.claude/skills/playwright-cli/references/session-management.md +226 -0
  307. package/project-template-v2/.claude/skills/playwright-cli/references/spec-driven-testing.md +308 -0
  308. package/project-template-v2/.claude/skills/playwright-cli/references/storage-state.md +275 -0
  309. package/project-template-v2/.claude/skills/playwright-cli/references/test-generation.md +134 -0
  310. package/project-template-v2/.claude/skills/playwright-cli/references/tracing.md +142 -0
  311. package/project-template-v2/.claude/skills/playwright-cli/references/video-recording.md +153 -0
  312. package/project-template-v2/.claude/skills/session-analyzer/SKILL.md +386 -0
  313. package/project-template-v2/.claude/skills/session-analyzer/scripts/execution-breakdown.mjs +182 -0
  314. package/project-template-v2/.claude/skills/session-analyzer/scripts/find-turns.mjs +72 -0
  315. package/project-template-v2/.claude/skills/session-analyzer/scripts/heavy-output.mjs +121 -0
  316. package/project-template-v2/.claude/skills/session-analyzer/scripts/resolve-session.mjs +102 -0
  317. package/project-template-v2/.claude/skills/session-analyzer/scripts/subagent-stats.mjs +127 -0
  318. package/project-template-v2/.claude/skills/session-analyzer/scripts/subagent-tool-timeline.mjs +106 -0
  319. package/project-template-v2/.claude/skills/session-analyzer/scripts/time-gaps.mjs +128 -0
  320. package/project-template-v2/.claude/skills/session-analyzer/scripts/turn-timeline.mjs +67 -0
  321. package/project-template-v2/.claude/snapshot.mjs +263 -0
  322. package/project-template-v2/.playcraft/skills.lock.json +152 -0
  323. package/project-template-v2/CLAUDE.md +146 -0
  324. package/project-template-v2/assets/audio/bgm/.gitkeep +0 -0
  325. package/project-template-v2/assets/audio/sfx/.gitkeep +0 -0
  326. package/project-template-v2/assets/bundles/.gitkeep +0 -0
  327. package/project-template-v2/assets/images/bg/.gitkeep +0 -0
  328. package/project-template-v2/assets/images/reference/.gitkeep +0 -0
  329. package/project-template-v2/assets/images/storyboard/.gitkeep +0 -0
  330. package/project-template-v2/assets/images/tiles/.gitkeep +0 -0
  331. package/project-template-v2/assets/images/ui/.gitkeep +0 -0
  332. package/project-template-v2/assets/images/vfx/.gitkeep +0 -0
  333. package/project-template-v2/assets/models/.gitkeep +0 -0
  334. package/project-template-v2/docs/harness/iteration-1/context-flow.md +254 -0
  335. package/project-template-v2/docs/harness/iteration-1/generate-flow.md +91 -0
  336. package/project-template-v2/docs/harness/iteration-1/ideate-flow.md +214 -0
  337. package/project-template-v2/docs/harness/iteration-1/optimize-flow.md +75 -0
  338. package/project-template-v2/docs/harness/iteration-1/wrapup-flow.md +63 -0
  339. package/project-template-v2/docs/harness/iteration-2/context-flow.md +223 -0
  340. package/project-template-v2/docs/harness/iteration-2/generate-flow.md +129 -0
  341. package/project-template-v2/docs/harness/iteration-2/ideate-flow.md +267 -0
  342. package/project-template-v2/docs/harness/iteration-2/optimize-flow.md +164 -0
  343. package/project-template-v2/docs/harness/iteration-2/wrapup-flow.md +115 -0
  344. package/project-template-v2/docs/harness/orchestrator-flow.md +364 -0
  345. package/project-template-v2/docs/project-state.json +60 -0
  346. package/project-template-v2/docs/project-state.md +72 -0
  347. package/project-template-v2/docs/standards/README.md +225 -0
  348. package/project-template-v2/docs/standards/agent-behavior-standards.md +174 -0
  349. package/project-template-v2/docs/standards/artifacts/design-brief.md +19 -0
  350. package/project-template-v2/docs/standards/artifacts/design.md +22 -0
  351. package/project-template-v2/docs/standards/artifacts/game-code.md +41 -0
  352. package/project-template-v2/docs/standards/artifacts/todo-list.md +41 -0
  353. package/project-template-v2/docs/standards/iter1-agent-behavior-standards.md +343 -0
  354. package/project-template-v2/game/index.ts +18 -0
  355. package/project-template-v2/globals.d.ts +51 -0
  356. package/project-template-v2/index.css +34 -0
  357. package/project-template-v2/index.html +18 -0
  358. package/project-template-v2/main.ts +9 -0
  359. package/project-template-v2/package.json +46 -0
  360. package/project-template-v2/skills/_shared/scripts/dispatch-clear.mjs +31 -0
  361. package/project-template-v2/skills/_shared/scripts/dispatch-set.mjs +86 -0
  362. package/project-template-v2/skills/_shared/scripts/dod-check.mjs +153 -0
  363. package/project-template-v2/skills/_shared/scripts/handoff-append.mjs +70 -0
  364. package/project-template-v2/skills/_shared/scripts/lib/validator-artifacts.mjs +91 -0
  365. package/project-template-v2/skills/_shared/scripts/pipeline/dod-config.mjs +131 -0
  366. package/project-template-v2/skills/_shared/scripts/pipeline/index.mjs +80 -0
  367. package/project-template-v2/skills/_shared/scripts/pipeline/iteration-1-core.mjs +90 -0
  368. package/project-template-v2/skills/_shared/scripts/pipeline/iteration-2-wrap.mjs +93 -0
  369. package/project-template-v2/skills/_shared/scripts/pipeline/iteration-3-visual.mjs +23 -0
  370. package/project-template-v2/skills/_shared/scripts/render-project-state.mjs +230 -0
  371. package/project-template-v2/skills/_shared/scripts/state-advance-stage.mjs +58 -0
  372. package/project-template-v2/skills/_shared/scripts/state-get.mjs +339 -0
  373. package/project-template-v2/skills/_shared/scripts/state-handoff.mjs +39 -0
  374. package/project-template-v2/skills/_shared/scripts/state-set.mjs +94 -0
  375. package/project-template-v2/skills/_shared/scripts/state-store.mjs +783 -0
  376. package/project-template-v2/skills/_shared/scripts/todo-add.mjs +88 -0
  377. package/project-template-v2/skills/_shared/scripts/todo-get.mjs +130 -0
  378. package/project-template-v2/skills/_shared/scripts/todo-remove.mjs +33 -0
  379. package/project-template-v2/skills/_shared/scripts/todo-set.mjs +47 -0
  380. package/project-template-v2/skills/_shared/scripts/verify-asset-code-sync.mjs +268 -0
  381. package/project-template-v2/skills/_shared/scripts/verify-env.mjs +285 -0
  382. package/project-template-v2/skills/_shared/scripts/verify-placeholders.mjs +161 -0
  383. package/project-template-v2/skills/playable-autoplay/SKILL.md +176 -0
  384. package/project-template-v2/skills/playable-autoplay/agents/openai.yaml +4 -0
  385. package/project-template-v2/skills/playable-debug/SKILL.md +116 -0
  386. package/project-template-v2/skills/playable-debug/agents/openai.yaml +4 -0
  387. package/project-template-v2/skills/playable-debug/references/debug-config.md +40 -0
  388. package/project-template-v2/skills/playable-record/SKILL.md +140 -0
  389. package/project-template-v2/skills/playable-record/scripts/lib/dev-server.mjs +104 -0
  390. package/project-template-v2/skills/playable-record/scripts/lib/record-audio-bridge.js +141 -0
  391. package/project-template-v2/skills/playable-record/scripts/record-playable.mjs +425 -0
  392. package/project-template-v2/skills/playable-record/scripts/verify-contract.mjs +261 -0
  393. package/project-template-v2/skills/playable-record/scripts/verify-firstwin.mjs +398 -0
  394. package/project-template-v2/skills/playable-record/scripts/verify-fusion.mjs +322 -0
  395. package/project-template-v2/skills/playable-record/scripts/verify-lifecycle.mjs +105 -0
  396. package/project-template-v2/skills/playable-record/scripts/verify-vlm-video.mjs +230 -0
  397. package/project-template-v2/skills/playable-validate/SKILL.md +61 -0
  398. package/project-template-v2/skills/playable-validate/validation-rules.md +14 -0
  399. package/project-template-v2/skills/playable-verify-ui/SKILL.md +63 -0
  400. package/project-template-v2/skills/playable-verify-ui/scripts/lib/__init__.py +1 -0
  401. package/project-template-v2/skills/playable-verify-ui/scripts/lib/config_expr.js +218 -0
  402. package/project-template-v2/skills/playable-verify-ui/scripts/lib/node_utils.js +51 -0
  403. package/project-template-v2/skills/playable-verify-ui/scripts/lib/profile_loader.py +59 -0
  404. package/project-template-v2/skills/playable-verify-ui/scripts/lib/report.py +106 -0
  405. package/project-template-v2/skills/playable-verify-ui/scripts/lib/runtime_contract.js +116 -0
  406. package/project-template-v2/skills/playable-verify-ui/scripts/verify_fetch_antipatterns.py +59 -0
  407. package/project-template-v2/skills/playable-verify-ui/scripts/verify_hardcoded_layout.js +64 -0
  408. package/project-template-v2/skills/playable-verify-ui/scripts/verify_runtime_contract.js +58 -0
  409. package/project-template-v2/skills/playable-verify-ui/scripts/verify_text_overlap.py +333 -0
  410. package/project-template-v2/ta-workspace/scripts/.gitkeep +0 -0
  411. package/project-template-v2/tsconfig.json +20 -0
  412. package/project-template-v2/vite.config.ts +27 -0
  413. package/project-templates/batch-locks/phaser.yaml +922 -0
  414. package/project-templates/batch-locks/threejs.yaml +978 -0
  415. package/project-templates/empty/AGENTS.md +53 -0
  416. package/project-templates/empty/gitignore +33 -0
  417. package/project-templates/phaser/.claude/skills/playcraft-audio-generation/SKILL.md +31 -4
  418. package/project-templates/phaser/.claude/skills/playcraft-image-generation/SKILL.md +36 -5
  419. package/project-templates/phaser/.claude/skills/playcraft-image-generation/reference/build-sprite-sheet.template.mjs +1 -1
  420. package/project-templates/phaser/.claude/skills/playcraft-image-generation/reference/compare-style.template.mjs +1 -1
  421. package/project-templates/phaser/.claude/skills/playcraft-image-generation/reference/gen-batch-sprite.template.mjs +1 -1
  422. package/project-templates/phaser/.claude/skills/playcraft-image-generation/reference/gen-batch.template.mjs +1 -1
  423. package/project-templates/phaser/.claude/skills/playcraft-image-generation/reference/gen-edit-variants.template.mjs +1 -1
  424. package/project-templates/phaser/.claude/skills/playcraft-image-generation/reference/process-batch.template.mjs +1 -1
  425. package/project-templates/phaser/.claude/skills/playcraft-image-generation/reference/ta-image-generation-detail.md +300 -0
  426. package/project-templates/phaser/.claude/skills/playcraft-image-generation/reference/validate-sprite-sheet.template.mjs +1 -1
  427. package/project-templates/phaser/.claude/skills/playcraft-image-processing/SKILL.md +50 -25
  428. package/project-templates/phaser/.claude/skills/playcraft-workspace-assets/SKILL.md +53 -0
  429. package/project-templates/phaser/.claude/skills/playcraft-workspace-assets/references/requests.json +32 -0
  430. package/project-templates/threejs/.claude/skills/playcraft-audio-generation/SKILL.md +31 -4
  431. package/project-templates/threejs/.claude/skills/playcraft-image-generation/SKILL.md +36 -5
  432. package/project-templates/threejs/.claude/skills/playcraft-image-generation/reference/build-sprite-sheet.template.mjs +1 -1
  433. package/project-templates/threejs/.claude/skills/playcraft-image-generation/reference/compare-style.template.mjs +1 -1
  434. package/project-templates/threejs/.claude/skills/playcraft-image-generation/reference/gen-batch-sprite.template.mjs +1 -1
  435. package/project-templates/threejs/.claude/skills/playcraft-image-generation/reference/gen-batch.template.mjs +1 -1
  436. package/project-templates/threejs/.claude/skills/playcraft-image-generation/reference/gen-edit-variants.template.mjs +1 -1
  437. package/project-templates/threejs/.claude/skills/playcraft-image-generation/reference/process-batch.template.mjs +1 -1
  438. package/project-templates/threejs/.claude/skills/playcraft-image-generation/reference/ta-image-generation-detail.md +300 -0
  439. package/project-templates/threejs/.claude/skills/playcraft-image-generation/reference/validate-sprite-sheet.template.mjs +1 -1
  440. package/project-templates/threejs/.claude/skills/playcraft-image-processing/SKILL.md +50 -25
  441. package/project-templates/threejs/.claude/skills/playcraft-workspace-assets/SKILL.md +53 -0
  442. package/project-templates/threejs/.claude/skills/playcraft-workspace-assets/references/requests.json +32 -0
  443. package/templates/preview-runtime/v1/README.md +71 -0
  444. package/templates/preview-runtime/v1/build-preview.mjs +1324 -0
  445. package/templates/preview-runtime/v1/manifest.json +17 -0
  446. package/templates/preview-runtime/v1/release-guard.mjs +87 -0
  447. package/templates/preview-runtime/v1/runtime.d.mts +3 -0
  448. package/templates/preview-runtime/v1/runtime.d.ts +3 -0
  449. package/templates/preview-runtime/v1/runtime.mjs +1121 -0
  450. package/templates/preview-runtime/v1/types/adapters.d.ts +26 -0
  451. package/templates/preview-runtime/v1/types/preview.d.ts +23 -0
  452. package/templates/preview-runtime/v1/types/protocol.d.ts +94 -0
  453. package/templates/preview-runtime/v1/types/runtime.d.ts +14 -0
@@ -0,0 +1,174 @@
1
+ import { constants, promises as fs } from 'node:fs';
2
+ import { EvaluationClient, validatePollOptions } from './evaluation-client.js';
3
+ import { parseSkillReference } from './package.js';
4
+ import { packNativePlatformSource } from './platform-package.js';
5
+ import { message, RegistryError } from './messages.js';
6
+ async function readInput(file, keys) {
7
+ const maximum = 2 * 1024 * 1024;
8
+ const handle = await fs.open(file, constants.O_RDONLY | constants.O_NOFOLLOW);
9
+ try {
10
+ const stat = await handle.stat();
11
+ if (!stat.isFile() || stat.size > maximum)
12
+ throw new RegistryError('invalid_evaluation_input', message('invalidEvaluationInput'));
13
+ const buffer = Buffer.alloc(stat.size + 1);
14
+ let length = 0;
15
+ while (length < buffer.length) {
16
+ const read = await handle.read(buffer, length, buffer.length - length, null);
17
+ if (!read.bytesRead)
18
+ break;
19
+ length += read.bytesRead;
20
+ }
21
+ if (length !== stat.size)
22
+ throw new RegistryError('invalid_evaluation_input', message('invalidEvaluationInput'));
23
+ let value;
24
+ try {
25
+ value = JSON.parse(buffer.subarray(0, length).toString('utf8'));
26
+ }
27
+ catch {
28
+ throw new RegistryError('invalid_evaluation_input', message('invalidEvaluationInput'));
29
+ }
30
+ if (!value ||
31
+ typeof value !== 'object' ||
32
+ Array.isArray(value) ||
33
+ Object.keys(value).some((key) => !keys.includes(key)) ||
34
+ keys.some((key) => !(key in value)))
35
+ throw new RegistryError('invalid_evaluation_input', message('invalidEvaluationInput'));
36
+ return value;
37
+ }
38
+ finally {
39
+ await handle.close();
40
+ }
41
+ }
42
+ function completed(run) {
43
+ if (run.phase !== 'completed' || run.verdict !== 'passed')
44
+ throw new RegistryError('evaluation_not_passed', message('evaluationNotPassed'), { run });
45
+ return run;
46
+ }
47
+ export function registerEvaluationCommands(registry, dependencies = {}) {
48
+ const stdout = dependencies.stdout ?? ((text) => console.log(text));
49
+ const stderr = dependencies.stderr ?? ((text) => console.error(text));
50
+ function action(command, callback) {
51
+ command.action(async (...values) => {
52
+ const options = values.at(-1).optsWithGlobals();
53
+ try {
54
+ const scope = options.scope ?? 'private';
55
+ if (!['private', 'team', 'platform'].includes(scope) ||
56
+ (scope === 'team' ? !options.team?.trim() : Boolean(options.team)))
57
+ throw new RegistryError('invalid_scope', message('invalidScope'));
58
+ const client = dependencies.evaluationClient?.(options) ??
59
+ new EvaluationClient({ url: options.url, token: options.token });
60
+ const result = await callback(client, options, values.slice(0, -2));
61
+ stdout(JSON.stringify(result, null, options.json ? undefined : 2));
62
+ }
63
+ catch (error) {
64
+ const failure = error instanceof RegistryError
65
+ ? error
66
+ : new RegistryError('operation_failed', message('requestFailed'));
67
+ (options.json ? stdout : stderr)(JSON.stringify({
68
+ error: {
69
+ code: failure.code,
70
+ message: failure.message,
71
+ status: failure.status,
72
+ details: failure.details,
73
+ },
74
+ }));
75
+ if (dependencies.failure)
76
+ dependencies.failure();
77
+ else
78
+ process.exitCode = 1;
79
+ }
80
+ });
81
+ }
82
+ async function exact(client, input, options) {
83
+ const ref = parseSkillReference(input, true);
84
+ return client.info(ref.skillRef, ref.version, {
85
+ scope: (options.scope ?? 'private'),
86
+ ...(options.team ? { teamId: options.team } : {}),
87
+ });
88
+ }
89
+ function polling(command) {
90
+ return command
91
+ .option('--timeout <seconds>', message('pollTimeout'), '600')
92
+ .option('--interval <seconds>', message('pollInterval'), '3');
93
+ }
94
+ function pollOptions(options) {
95
+ return { timeoutSeconds: Number(options.timeout), intervalSeconds: Number(options.interval) };
96
+ }
97
+ const platform = registry.command('platform').description(message('platform'));
98
+ action(platform
99
+ .command('push <source>')
100
+ .description(message('platformPush'))
101
+ .option('--ref <ref>', message('ref'))
102
+ .option('--version <version>', message('version'))
103
+ .requiredOption('--changelog <text>', message('changelog'))
104
+ .option('--evaluation-template <templateId>', message('evaluationTemplate')), async (client, options, [source]) => {
105
+ if (options.team || options.scope === 'team')
106
+ throw new RegistryError('invalid_scope', message('invalidScope'));
107
+ const bundle = await packNativePlatformSource(source, options);
108
+ return client.importPlatform(bundle, options.changelog, options.evaluationTemplate);
109
+ });
110
+ const evaluation = registry.command('evaluation').description(message('evaluation'));
111
+ const templates = evaluation.command('templates').description(message('evaluationTemplates'));
112
+ action(templates.command('list').description(message('evaluationTemplates')), (client) => client.templates());
113
+ action(templates
114
+ .command('create')
115
+ .description(message('createTemplate'))
116
+ .requiredOption('--input <file>', message('inputFile')), async (client, options) => {
117
+ const input = await readInput(options.input, ['key', 'name', 'spec']);
118
+ if (typeof input.key !== 'string' ||
119
+ typeof input.name !== 'string' ||
120
+ !input.spec ||
121
+ typeof input.spec !== 'object')
122
+ throw new RegistryError('invalid_evaluation_input', message('invalidEvaluationInput'));
123
+ return client.createTemplate(input);
124
+ });
125
+ for (const state of ['enable', 'disable'])
126
+ action(templates.command(`${state} <templateId>`).description(message(state)), (client, _options, [id]) => client.templateState(id, state === 'enable' ? 'enabled' : 'disabled'));
127
+ action(evaluation
128
+ .command('models')
129
+ .description(message('evaluationModels'))
130
+ .requiredOption('--workspace <workspaceId>', message('workspace')), (client, options) => client.models(options.workspace));
131
+ const config = evaluation.command('config').description(message('evaluationConfig'));
132
+ action(config.command('get <reference>').description(message('readConfig')), async (client, options, [input]) => client.config(await exact(client, input, options)));
133
+ action(config
134
+ .command('set <reference>')
135
+ .description(message('saveConfig'))
136
+ .requiredOption('--input <file>', message('inputFile')), async (client, options, [input]) => {
137
+ const data = await readInput(options.input, ['templateId', 'expectedRevision', 'spec']);
138
+ if (typeof data.templateId !== 'string' ||
139
+ typeof data.expectedRevision !== 'number' ||
140
+ !data.spec ||
141
+ typeof data.spec !== 'object')
142
+ throw new RegistryError('invalid_evaluation_input', message('invalidEvaluationInput'));
143
+ return client.saveConfig(await exact(client, input, options), data);
144
+ });
145
+ action(polling(evaluation
146
+ .command('run <reference>')
147
+ .description(message('evaluationRun'))
148
+ .requiredOption('--workspace <workspaceId>', message('workspace'))
149
+ .requiredOption('--config <configId>', message('configId'))
150
+ .requiredOption('--request-key <key>', message('requestKey'))
151
+ .option('--compare', message('compare'))
152
+ .option('--wait', message('wait'))), async (client, options, [input]) => {
153
+ if (options.wait)
154
+ validatePollOptions(pollOptions(options));
155
+ const run = await client.createRun(await exact(client, input, options), {
156
+ workspaceId: options.workspace,
157
+ configId: options.config,
158
+ compare: Boolean(options.compare),
159
+ requestKey: options.requestKey,
160
+ });
161
+ return options.wait ? completed(await client.wait(run.id, pollOptions(options))) : run;
162
+ });
163
+ action(evaluation.command('status <runId>').description(message('evaluationStatus')), (client, _options, [id]) => client.run(id));
164
+ action(evaluation
165
+ .command('runs <reference>')
166
+ .description(message('evaluationRuns'))
167
+ .requiredOption('--workspace <workspaceId>', message('workspace')), async (client, options, [input]) => client.runs(await exact(client, input, options), options.workspace));
168
+ action(evaluation
169
+ .command('evidence <runId>')
170
+ .description(message('evaluationEvidence'))
171
+ .requiredOption('--case <caseResultId>', message('caseResult')), (client, options, [id]) => client.evidence(id, options.case));
172
+ action(polling(evaluation.command('wait <runId>').description(message('wait'))), async (client, options, [id]) => completed(await client.wait(id, pollOptions(options))));
173
+ action(evaluation.command('cancel <runId>').description(message('evaluationCancel')), (client, _options, [id]) => client.cancel(id));
174
+ }
@@ -0,0 +1,177 @@
1
+ const messages = {
2
+ en: {
3
+ group: 'Manage remote skill versions and releases',
4
+ url: 'Deployment address (including any environment prefix)',
5
+ token: 'Personal access token (prefer PLAYCRAFT_TOKEN)',
6
+ json: 'Print one JSON (JavaScript Object Notation) result',
7
+ scope: 'Release scope: private, team, platform',
8
+ team: 'Target team identifier',
9
+ list: 'List accessible skills in a release scope',
10
+ query: 'Search names and descriptions',
11
+ limit: 'Page size (1–100)',
12
+ cursor: 'Continue from the returned cursor',
13
+ info: 'Read a skill or an exact version',
14
+ versions: 'List accessible versions',
15
+ files: 'Include the file inventory',
16
+ pull: 'Download and verify one exact version',
17
+ out: 'Destination directory (must be absent or empty)',
18
+ push: 'Upload an immutable draft version',
19
+ publish: 'Publish an exact version or upload and publish a directory',
20
+ update: 'Upload a new version with an explicit base version',
21
+ ref: 'Canonical skill identity (namespace/slug)',
22
+ version: 'Exact new semantic version',
23
+ base: 'Exact previous version for conflict detection',
24
+ changelog: 'Describe the version changes',
25
+ from: 'Directory containing SKILL.md and resources',
26
+ check: 'Check publish requirements for an exact version',
27
+ history: 'Read release history',
28
+ rollback: 'Move the release pointer to an existing exact version',
29
+ reason: 'Reason for the decision',
30
+ review: 'Manage release review requests',
31
+ submit: 'Submit an exact version for review',
32
+ approve: 'Approve a review as an authorized administrator',
33
+ reject: 'Reject a review as an authorized administrator',
34
+ login: 'Log in to this environment with playcraft login --url first.',
35
+ invalidUrl: 'Invalid environment address.',
36
+ invalidRef: 'Use a lowercase namespace/slug identity and an exact x.y.z release version (at most 32 characters) when required.',
37
+ invalidScope: 'Choose private, team, or platform; team requires --team and other scopes forbid it.',
38
+ invalidBundle: 'Invalid skill bundle.',
39
+ invalidResponse: 'The registry returned an invalid or mismatched response.',
40
+ tooLarge: 'The request or response exceeds the size limit.',
41
+ destination: 'Destination must be an absent or empty directory without symbolic links.',
42
+ network: 'The request could not complete. Retry the same command to recover its result.',
43
+ requestFailed: 'The registry rejected this request.',
44
+ missingVersion: 'Directory uploads require --version (or manifest.version), and --ref (or manifest.skillRef).',
45
+ missingBase: 'Updates require --base-version and a different --version.',
46
+ manifestConflict: 'Explicit identity/version conflicts with manifest.json. Update the manifest first.',
47
+ uploadOptionsOnly: '--ref, --version, --base-version and --changelog apply only to directory uploads; an exact reference already selects the version to publish.',
48
+ invalidReceipt: 'The pending release receipt is invalid. Inspect the registry history before attempting a new publication.',
49
+ platform: 'Register native platform skill bundles',
50
+ platformPush: 'Register a native platform draft from a directory or archive without publishing',
51
+ evaluationTemplate: 'Optional evaluation template identifier for the draft',
52
+ invalidPlatformBundle: 'Expected an unchanged native platform video skill bundle with an aligned manifest and SKILL.md.',
53
+ evaluation: 'Configure and run real skill evaluations',
54
+ evaluationTemplates: 'List evaluation runtime templates',
55
+ createTemplate: 'Create an evaluation template draft from a file',
56
+ enable: 'Enable an evaluation template',
57
+ disable: 'Disable an evaluation template',
58
+ inputFile: 'Input JSON (JavaScript Object Notation) file with the documented request fields',
59
+ evaluationModels: 'List evaluation models available to the workspace',
60
+ workspace: 'Workspace identifier authorized for this account',
61
+ evaluationConfig: 'Read and save exact-version evaluation configuration',
62
+ readConfig: 'Read the current configuration and revision',
63
+ saveConfig: 'Save configuration with an explicit expected revision',
64
+ evaluationRun: 'Enqueue a real evaluation of an exact skill version and configuration',
65
+ configId: 'Exact saved evaluation configuration identifier',
66
+ requestKey: 'Unique run key (8–128 letters, digits, underscores or hyphens); reuse only to recover the same run',
67
+ compare: 'Also evaluate the current stable version as baseline',
68
+ wait: 'Poll the run until terminal; fail unless its verdict is passed',
69
+ pollTimeout: 'Maximum polling duration in seconds (default 600; does not cancel the run)',
70
+ pollInterval: 'Polling interval in seconds (default 3; maximum 60)',
71
+ evaluationStatus: 'Read run state, verdict and case results',
72
+ evaluationRuns: 'List runs for an exact version in one workspace',
73
+ evaluationEvidence: 'Read archived evidence for one case result',
74
+ caseResult: 'Case result identifier from run.results[].id (not the logical case name)',
75
+ evaluationCancel: 'Request cancellation of a run',
76
+ invalidIdentifier: 'Expected a valid resource identifier.',
77
+ invalidEvaluationInput: 'Invalid evaluation input; use the documented fields and explicit identifiers/revision.',
78
+ invalidPollOptions: 'Polling timeout must be greater than 0 and at most 86400 seconds; interval must be greater than 0 and at most 60 seconds.',
79
+ waitTimeout: 'Polling timed out. The run is still active; use status or wait with its identifier.',
80
+ evaluationNotPassed: 'Evaluation ended without a passed verdict. Inspect the returned run and its evidence.',
81
+ },
82
+ zh: {
83
+ group: '管理远程技能版本与发行',
84
+ url: '部署地址(保留环境路径前缀)',
85
+ token: '个人访问令牌(建议使用 PLAYCRAFT_TOKEN)',
86
+ json: '输出单个 JSON (JavaScript Object Notation, JavaScript 对象表示法) 结果',
87
+ scope: '发行范围:private、team、platform',
88
+ team: '目标团队标识',
89
+ list: '列出发行范围内可访问的技能',
90
+ query: '搜索名称与描述',
91
+ limit: '每页数量(1–100)',
92
+ cursor: '使用返回的游标继续查询',
93
+ info: '读取技能或精确版本',
94
+ versions: '列出可访问版本',
95
+ files: '包括文件清单',
96
+ pull: '下载并校验一个精确版本',
97
+ out: '目标目录(必须不存在或为空)',
98
+ push: '上传不可变的草稿版本',
99
+ publish: '发布精确版本,或上传目录后发布',
100
+ update: '基于明确旧版本上传新版本',
101
+ ref: '规范技能标识(namespace/slug)',
102
+ version: '明确的新语义版本',
103
+ base: '用于冲突检测的明确旧版本',
104
+ changelog: '版本变更说明',
105
+ from: '包含 SKILL.md 和资源的目录',
106
+ check: '检查精确版本的发布条件',
107
+ history: '读取发行历史',
108
+ rollback: '将发行指针切换到已有精确版本',
109
+ reason: '操作原因',
110
+ review: '管理发行审核申请',
111
+ submit: '提交精确版本审核',
112
+ approve: '由有权限的管理员批准审核',
113
+ reject: '由有权限的管理员拒绝审核',
114
+ login: '请先使用 playcraft login --url 登录该环境。',
115
+ invalidUrl: '环境地址无效。',
116
+ invalidRef: '请使用小写 namespace/slug 标识,需要版本时必须给出精确 x.y.z 发行版本(最多 32 字符)。',
117
+ invalidScope: '范围须为 private、team 或 platform;team 必须提供 --team,其他范围不能提供。',
118
+ invalidBundle: '技能包无效。',
119
+ invalidResponse: '注册表返回了无效或不匹配的结果。',
120
+ tooLarge: '请求或响应超出大小上限。',
121
+ destination: '目标目录必须不存在或为空,路径不能包含符号链接。',
122
+ network: '请求未能完成。重新执行相同命令可恢复结果。',
123
+ requestFailed: '注册表拒绝了此请求。',
124
+ missingVersion: '上传目录需要 --version(或 manifest.version)及 --ref(或 manifest.skillRef)。',
125
+ missingBase: '更新需要 --base-version 和不同的 --version。',
126
+ manifestConflict: '参数中的标识或版本与 manifest.json 冲突,请先修改清单。',
127
+ uploadOptionsOnly: '--ref、--version、--base-version 和 --changelog 仅用于上传目录;精确引用已明确要发布的版本。',
128
+ invalidReceipt: '待恢复的发行回执无效。请先核对注册表发行历史,再发起新的发布。',
129
+ platform: '登记原生平台技能包',
130
+ platformPush: '从目录或压缩包登记原生平台草稿,不执行发布',
131
+ evaluationTemplate: '草稿可选使用的评估模板标识',
132
+ invalidPlatformBundle: '需要原生平台视频技能包,且清单与 SKILL.md 信息一致;不自动改写清单。',
133
+ evaluation: '配置并执行真实技能评估',
134
+ evaluationTemplates: '列出评估运行模板',
135
+ createTemplate: '根据文件创建评估模板草稿',
136
+ enable: '启用评估模板',
137
+ disable: '停用评估模板',
138
+ inputFile: '包含约定请求字段的 JSON (JavaScript Object Notation, JavaScript 对象表示法) 文件',
139
+ evaluationModels: '列出工作区可用的评估模型',
140
+ workspace: '当前账号有权限使用的工作区标识',
141
+ evaluationConfig: '读取和保存精确版本的评估配置',
142
+ readConfig: '读取当前配置和修订号',
143
+ saveConfig: '提供明确的预期修订号保存配置',
144
+ evaluationRun: '为精确技能版本和配置发起真实评估',
145
+ configId: '已保存评估配置的精确标识',
146
+ requestKey: '评估唯一请求键(8–128 位字母、数字、下划线或连字符);仅恢复同一评估时复用',
147
+ compare: '同时评估当前稳定版本作为基线',
148
+ wait: '轮询至评估终态;判定未通过时以失败状态退出',
149
+ pollTimeout: '最长轮询秒数(默认 600;超时不取消评估)',
150
+ pollInterval: '轮询间隔秒数(默认 3;最多 60)',
151
+ evaluationStatus: '读取评估状态、判定和用例结果',
152
+ evaluationRuns: '列出工作区内精确版本的评估记录',
153
+ evaluationEvidence: '读取单个用例结果的归档证据',
154
+ caseResult: '使用 run.results[].id 用例结果标识,不使用逻辑用例名称',
155
+ evaluationCancel: '请求取消评估',
156
+ invalidIdentifier: '资源标识无效。',
157
+ invalidEvaluationInput: '评估输入无效;请使用文档约定字段及明确的标识和修订号。',
158
+ invalidPollOptions: '轮询时限须大于 0 且不超过 86400 秒,间隔须大于 0 且不超过 60 秒。',
159
+ waitTimeout: '轮询超时,评估仍在运行;可用评估标识继续查询或等待。',
160
+ evaluationNotPassed: '评估已结束但未通过,请查看返回的评估记录和证据。',
161
+ },
162
+ };
163
+ export function message(key) {
164
+ return messages[(process.env.PLAYCRAFT_LANGUAGE || process.env.LANG || 'en').startsWith('zh') ? 'zh' : 'en'][key];
165
+ }
166
+ export class RegistryError extends Error {
167
+ code;
168
+ details;
169
+ status;
170
+ constructor(code, text, details, status) {
171
+ super(text);
172
+ this.code = code;
173
+ this.details = details;
174
+ this.status = status;
175
+ this.name = 'RegistryError';
176
+ }
177
+ }
@@ -0,0 +1,275 @@
1
+ import { constants, promises as fs } from 'node:fs';
2
+ import path from 'node:path';
3
+ import { createHash } from 'node:crypto';
4
+ import yaml from 'js-yaml';
5
+ import { createCanonicalBundleArchive, extractBundleArchive, } from '@playcraft/common/project-skills';
6
+ import { message, RegistryError } from './messages.js';
7
+ export const MAX_BUNDLE_BYTES = 64 * 1024 * 1024;
8
+ const MAX_FILE_BYTES = 16 * 1024 * 1024;
9
+ const MAX_FILES = 512;
10
+ const RECEIPT = '.playcraft-skill.json';
11
+ const SEMVER = /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)$/;
12
+ export function parseSkillReference(value, exact = false) {
13
+ const [skillRef, version, extra] = value.split('@');
14
+ if (!/^[a-z0-9][a-z0-9_-]{0,95}\/[a-z0-9][a-z0-9._-]{0,159}$/.test(skillRef) ||
15
+ extra !== undefined ||
16
+ (version !== undefined && (!SEMVER.test(version) || version.length > 32)) ||
17
+ (exact && !version)) {
18
+ throw new RegistryError('invalid_reference', message('invalidRef'));
19
+ }
20
+ return { skillRef, version };
21
+ }
22
+ export function sha256(data) {
23
+ return createHash('sha256').update(data).digest('hex');
24
+ }
25
+ function bundleError(details) {
26
+ throw new RegistryError('invalid_bundle', message('invalidBundle'), details);
27
+ }
28
+ function safePath(value) {
29
+ return (value === value.trim() &&
30
+ !/[\\:\x00-\x1f\x7f]/.test(value) &&
31
+ !value.startsWith('/') &&
32
+ value
33
+ .split('/')
34
+ .every((part) => Boolean(part) &&
35
+ part !== '.' &&
36
+ part !== '..' &&
37
+ !/[. ]$/.test(part) &&
38
+ !/^(con|prn|aux|nul|com[1-9]|lpt[1-9])(?:\.|$)/i.test(part)));
39
+ }
40
+ function validateFiles(files) {
41
+ if (files.length > MAX_FILES)
42
+ bundleError({ maxFiles: MAX_FILES });
43
+ const names = new Set();
44
+ let size = 0;
45
+ for (const file of files) {
46
+ const normalized = file.path.normalize('NFC').toLowerCase();
47
+ if (!safePath(file.path) || names.has(normalized) || file.path === RECEIPT)
48
+ bundleError({ path: file.path });
49
+ names.add(normalized);
50
+ size += file.data.length;
51
+ if (file.data.length > MAX_FILE_BYTES || size > MAX_BUNDLE_BYTES)
52
+ bundleError({
53
+ path: file.path,
54
+ maxFileBytes: MAX_FILE_BYTES,
55
+ maxBundleBytes: MAX_BUNDLE_BYTES,
56
+ });
57
+ }
58
+ for (const name of names) {
59
+ const parts = name.split('/');
60
+ for (let index = 1; index < parts.length; index++)
61
+ if (names.has(parts.slice(0, index).join('/')))
62
+ bundleError({ path: name });
63
+ }
64
+ if (!files
65
+ .find((file) => file.path === 'SKILL.md')
66
+ ?.data.toString('utf8')
67
+ .trim())
68
+ bundleError({ path: 'SKILL.md' });
69
+ }
70
+ function readManifest(file) {
71
+ if (!file)
72
+ return {};
73
+ try {
74
+ const value = JSON.parse(file.toString('utf8'));
75
+ if (value && typeof value === 'object' && !Array.isArray(value))
76
+ return value;
77
+ }
78
+ catch {
79
+ /* Report a structured validation error below. */
80
+ }
81
+ return bundleError({ path: 'manifest.json' });
82
+ }
83
+ function validateReferences(manifest, files) {
84
+ if (manifest.files === undefined)
85
+ return;
86
+ if (!Array.isArray(manifest.files))
87
+ bundleError({ path: 'manifest.json:files' });
88
+ for (const reference of manifest.files) {
89
+ if (!reference ||
90
+ typeof reference !== 'object' ||
91
+ typeof reference.path !== 'string' ||
92
+ !safePath(reference.path))
93
+ bundleError({ reference });
94
+ const file = files.find((item) => item.path === reference.path);
95
+ if (!file || (reference.hash !== undefined && reference.hash !== sha256(file.data)))
96
+ bundleError({ reference });
97
+ }
98
+ }
99
+ export async function packSkillDirectory(directory, options) {
100
+ const root = path.resolve(directory);
101
+ const rootStat = await fs.lstat(root);
102
+ if (!rootStat.isDirectory() || rootStat.isSymbolicLink())
103
+ bundleError({ path: root });
104
+ const files = [];
105
+ let total = 0;
106
+ let entries = 0;
107
+ async function walk(relative = '') {
108
+ for (const entry of (await fs.readdir(path.join(root, relative))).sort()) {
109
+ if (!relative && ['.git', 'node_modules', RECEIPT].includes(entry))
110
+ continue;
111
+ const name = relative ? `${relative}/${entry}` : entry;
112
+ if (!safePath(name) || ++entries > 2048)
113
+ bundleError({ path: name });
114
+ const fullPath = path.join(root, name);
115
+ const stat = await fs.lstat(fullPath);
116
+ if (stat.isSymbolicLink())
117
+ bundleError({ path: name });
118
+ if (stat.isDirectory()) {
119
+ await walk(name);
120
+ continue;
121
+ }
122
+ if (!stat.isFile() ||
123
+ stat.nlink !== 1 ||
124
+ stat.size > MAX_FILE_BYTES ||
125
+ files.length >= MAX_FILES ||
126
+ total + stat.size > MAX_BUNDLE_BYTES)
127
+ bundleError({ path: name });
128
+ const handle = await fs.open(fullPath, constants.O_RDONLY | constants.O_NOFOLLOW);
129
+ try {
130
+ const opened = await handle.stat();
131
+ if (!opened.isFile() ||
132
+ opened.ino !== stat.ino ||
133
+ opened.dev !== stat.dev ||
134
+ opened.size !== stat.size)
135
+ bundleError({ path: name });
136
+ // A bounded read also prevents concurrently growing files from allocating unbounded memory.
137
+ const data = Buffer.alloc(stat.size + 1);
138
+ let length = 0;
139
+ while (length < data.length) {
140
+ const chunk = await handle.read(data, length, data.length - length, null);
141
+ if (!chunk.bytesRead)
142
+ break;
143
+ length += chunk.bytesRead;
144
+ }
145
+ if (length !== stat.size)
146
+ bundleError({ path: name });
147
+ files.push({ path: name, data: data.subarray(0, length) });
148
+ total += length;
149
+ }
150
+ finally {
151
+ await handle.close();
152
+ }
153
+ }
154
+ }
155
+ await walk();
156
+ validateFiles(files);
157
+ const manifest = readManifest(files.find((file) => file.path === 'manifest.json')?.data);
158
+ const ref = options.ref ?? manifest.skillRef;
159
+ const version = options.version ?? manifest.version;
160
+ if (typeof ref !== 'string' || typeof version !== 'string')
161
+ throw new RegistryError('missing_version', message('missingVersion'));
162
+ const identity = parseSkillReference(`${ref}@${version}`, true);
163
+ if ((manifest.skillRef !== undefined && manifest.skillRef !== ref) ||
164
+ (manifest.version !== undefined && manifest.version !== version)) {
165
+ throw new RegistryError('manifest_conflict', message('manifestConflict'));
166
+ }
167
+ const markdown = files.find((file) => file.path === 'SKILL.md').data.toString('utf8');
168
+ let frontmatter = {};
169
+ const match = markdown.match(/^---\r?\n([\s\S]*?)\r?\n---(?:\r?\n|$)/);
170
+ if (match) {
171
+ try {
172
+ const parsed = yaml.load(match[1]);
173
+ if (parsed && typeof parsed === 'object' && !Array.isArray(parsed))
174
+ frontmatter = parsed;
175
+ }
176
+ catch {
177
+ bundleError({ path: 'SKILL.md:frontmatter' });
178
+ }
179
+ }
180
+ const output = {
181
+ schemaVersion: 2,
182
+ category: 'general',
183
+ kind: 'markdown',
184
+ bundleType: 'markdown',
185
+ name: frontmatter.name ?? ref.split('/')[1],
186
+ description: frontmatter.description ?? '',
187
+ ...manifest,
188
+ skillRef: identity.skillRef,
189
+ version,
190
+ files: manifest.files ??
191
+ files.filter((file) => file.path !== 'manifest.json').map((file) => ({ path: file.path })),
192
+ };
193
+ const packaged = options.preserveManifest
194
+ ? files
195
+ : files.filter((file) => file.path !== 'manifest.json');
196
+ if (!options.preserveManifest)
197
+ packaged.push({ path: 'manifest.json', data: Buffer.from(`${JSON.stringify(output)}\n`) });
198
+ else if (manifest.skillRef !== ref || manifest.version !== version)
199
+ bundleError({ path: 'manifest.json' });
200
+ validateFiles(packaged);
201
+ validateReferences(options.preserveManifest ? manifest : output, packaged);
202
+ const archive = createCanonicalBundleArchive(packaged);
203
+ if (archive.length > MAX_BUNDLE_BYTES)
204
+ throw new RegistryError('bundle_too_large', message('tooLarge'));
205
+ return {
206
+ skillRef: identity.skillRef,
207
+ version,
208
+ archive,
209
+ uploadHash: sha256(archive),
210
+ files: packaged.map((file) => ({ path: file.path, size: file.data.length })),
211
+ };
212
+ }
213
+ async function assertDestination(target) {
214
+ for (let current = target;; current = path.dirname(current)) {
215
+ const stat = await fs.lstat(current).catch((error) => {
216
+ if (error.code === 'ENOENT')
217
+ return null;
218
+ throw error;
219
+ });
220
+ if (stat && (!stat.isDirectory() || stat.isSymbolicLink()))
221
+ throw new RegistryError('unsafe_destination', message('destination'));
222
+ if (current === path.dirname(current))
223
+ break;
224
+ }
225
+ const existing = await fs.readdir(target).catch((error) => {
226
+ if (error.code === 'ENOENT')
227
+ return null;
228
+ throw error;
229
+ });
230
+ if (existing?.length)
231
+ throw new RegistryError('destination_not_empty', message('destination'));
232
+ return existing !== null;
233
+ }
234
+ export async function unpackSkillArchive(archive, destination, expected) {
235
+ if (!/^[a-f0-9]{64}$/.test(expected.artifactHash) || sha256(archive) !== expected.artifactHash)
236
+ throw new RegistryError('artifact_hash_mismatch', message('invalidResponse'));
237
+ const extracted = extractBundleArchive(archive, {
238
+ maxArchiveBytes: MAX_BUNDLE_BYTES,
239
+ maxExpandedBytes: MAX_BUNDLE_BYTES + 8 * 1024 * 1024,
240
+ });
241
+ if (extracted.issues.length)
242
+ bundleError(extracted.issues);
243
+ validateFiles(extracted.files);
244
+ const manifestFile = extracted.files.find((file) => file.path === 'manifest.json');
245
+ if (!manifestFile)
246
+ bundleError({ path: 'manifest.json' });
247
+ const manifest = readManifest(manifestFile.data);
248
+ // Historical artifacts predate these declarations; their exact bytes remain pinned by the server hash.
249
+ if ((manifest.skillRef !== undefined && manifest.skillRef !== expected.skillRef) ||
250
+ (manifest.version !== undefined && manifest.version !== expected.version))
251
+ throw new RegistryError('artifact_identity_mismatch', message('invalidResponse'));
252
+ validateReferences(manifest, extracted.files);
253
+ const target = path.resolve(destination);
254
+ await assertDestination(target);
255
+ await fs.mkdir(path.dirname(target), { recursive: true });
256
+ const temporary = await fs.mkdtemp(path.join(path.dirname(target), '.playcraft-skill-'));
257
+ try {
258
+ for (const file of extracted.files) {
259
+ const fullPath = path.join(temporary, file.path);
260
+ await fs.mkdir(path.dirname(fullPath), { recursive: true });
261
+ await fs.writeFile(fullPath, file.data, { flag: 'wx', mode: 0o644 });
262
+ }
263
+ await fs.writeFile(path.join(temporary, RECEIPT), `${JSON.stringify(expected, null, 2)}\n`, {
264
+ flag: 'wx',
265
+ mode: 0o600,
266
+ });
267
+ if (await assertDestination(target))
268
+ await fs.rmdir(target);
269
+ await fs.rename(temporary, target);
270
+ }
271
+ finally {
272
+ await fs.rm(temporary, { recursive: true, force: true });
273
+ }
274
+ return { directory: target, files: extracted.files.length };
275
+ }