@playcraft/cli 0.1.40-beta → 0.1.42

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 (368) hide show
  1. package/README.md +3 -58
  2. package/dist/agent/local-backend.js +1 -1
  3. package/dist/cli-root-help.js +0 -2
  4. package/dist/commands/build-all.js +19 -5
  5. package/dist/commands/build.js +28 -15
  6. package/dist/commands/create.js +33 -26
  7. package/dist/commands/image.js +6 -2
  8. package/dist/commands/login.js +42 -84
  9. package/dist/commands/skills.js +0 -4
  10. package/dist/commands/tools-3d.js +0 -11
  11. package/dist/commands/tools-generation.js +137 -69
  12. package/dist/commands/tools-image-context.js +29 -0
  13. package/dist/commands/tools-utils.js +12 -0
  14. package/dist/commands/tools.js +2 -2
  15. package/dist/config.js +4 -59
  16. package/dist/index.js +3 -40
  17. package/dist/remix/clone.js +0 -2
  18. package/dist/remix/init-template.js +0 -2
  19. package/dist/remix/pull.js +0 -2
  20. package/dist/remix/push.js +1 -21
  21. package/dist/utils/agent-api-client.js +30 -185
  22. package/dist/utils/image-asset-context.js +228 -0
  23. package/dist/utils/playcraft-http-client.js +4 -6
  24. package/package.json +5 -15
  25. package/project-template/.claude/agents/refs/ta-image-generation-detail.md +67 -123
  26. package/project-template/.claude/skills/playcraft-image-generation/SKILL.md +135 -63
  27. package/project-template/.claude/skills/playcraft-image-generation/reference/gen-batch-sprite.template.mjs +42 -33
  28. package/project-template/.claude/skills/playcraft-image-generation/reference/gen-batch.template.mjs +18 -20
  29. package/project-template/.claude/skills/playcraft-image-generation/reference/process-batch.template.mjs +6 -7
  30. package/project-template/.claude/skills/playcraft-image-generation/reference/prompt-cookbook.md +39 -39
  31. package/project-templates/phaser/.claude/agents/refs/ta-image-generation-detail.md +59 -59
  32. package/project-templates/phaser/.claude/skills/playcraft-image-generation/SKILL.md +135 -63
  33. package/project-templates/phaser/.claude/skills/playcraft-image-generation/reference/gen-batch-sprite.template.mjs +42 -33
  34. package/project-templates/phaser/.claude/skills/playcraft-image-generation/reference/gen-batch.template.mjs +18 -20
  35. package/project-templates/phaser/.claude/skills/playcraft-image-generation/reference/process-batch.template.mjs +6 -7
  36. package/project-templates/phaser/.claude/skills/playcraft-image-generation/reference/prompt-cookbook.md +39 -39
  37. package/project-templates/threejs/.claude/agents/refs/ta-image-generation-detail.md +59 -59
  38. package/project-templates/threejs/.claude/skills/playcraft-image-generation/SKILL.md +135 -63
  39. package/project-templates/threejs/.claude/skills/playcraft-image-generation/reference/gen-batch-sprite.template.mjs +42 -33
  40. package/project-templates/threejs/.claude/skills/playcraft-image-generation/reference/gen-batch.template.mjs +18 -20
  41. package/project-templates/threejs/.claude/skills/playcraft-image-generation/reference/process-batch.template.mjs +6 -7
  42. package/project-templates/threejs/.claude/skills/playcraft-image-generation/reference/prompt-cookbook.md +39 -39
  43. package/SKILLS_REGISTRY.md +0 -149
  44. package/dist/auth/account-activation.js +0 -157
  45. package/dist/auth/messages.js +0 -30
  46. package/dist/commands/build-temp.js +0 -26
  47. package/dist/commands/platform-skills.generated.js +0 -19
  48. package/dist/commands/playable.js +0 -53
  49. package/dist/commands/tools-batch.js +0 -87
  50. package/dist/commands/video.js +0 -111
  51. package/dist/commands/workspace-runtime.js +0 -54
  52. package/dist/commands/workspace.js +0 -35
  53. package/dist/project-skills/builtin-import.js +0 -225
  54. package/dist/project-skills/commands.js +0 -77
  55. package/dist/project-skills/lifecycle.js +0 -28
  56. package/dist/project-skills/local-run.js +0 -112
  57. package/dist/project-skills/local-store.js +0 -221
  58. package/dist/project-skills/messages.js +0 -80
  59. package/dist/project-skills/reconcile.js +0 -62
  60. package/dist/project-skills/remote-cache.js +0 -51
  61. package/dist/project-skills/validation.js +0 -19
  62. package/dist/recording/messages.js +0 -40
  63. package/dist/recording/project-digest.js +0 -85
  64. package/dist/recording/recorder.js +0 -293
  65. package/dist/recording/scenario.js +0 -50
  66. package/dist/skill-registry/client.js +0 -345
  67. package/dist/skill-registry/commands.js +0 -180
  68. package/dist/skill-registry/evaluation-client.js +0 -156
  69. package/dist/skill-registry/evaluation-commands.js +0 -174
  70. package/dist/skill-registry/messages.js +0 -177
  71. package/dist/skill-registry/package.js +0 -275
  72. package/dist/skill-registry/platform-package.js +0 -100
  73. package/dist/utils/environment-endpoints.js +0 -17
  74. package/dist/utils/tool-operation-journal.js +0 -124
  75. package/dist/utils/video-evidence-git.js +0 -81
  76. package/dist/video-replication/client.js +0 -222
  77. package/dist/video-replication/comparison-evidence.js +0 -149
  78. package/dist/video-replication/comparison-files.js +0 -57
  79. package/dist/video-replication/comparison-log.js +0 -72
  80. package/dist/video-replication/comparison-messages.js +0 -104
  81. package/dist/video-replication/comparison-output.js +0 -63
  82. package/dist/video-replication/comparison-preflight.js +0 -66
  83. package/dist/video-replication/comparison.js +0 -216
  84. package/dist/video-replication/evidence.js +0 -165
  85. package/dist/video-replication/media.js +0 -111
  86. package/dist/video-replication/messages.js +0 -89
  87. package/dist/workspace/messages.js +0 -35
  88. package/dist/workspace/transfer-client.js +0 -174
  89. package/dist/workspace-runtime/codex/app-server.js +0 -1040
  90. package/dist/workspace-runtime/codex/compact.js +0 -46
  91. package/dist/workspace-runtime/codex/config-toml.js +0 -107
  92. package/dist/workspace-runtime/codex/jsonrpc-stdio.js +0 -145
  93. package/dist/workspace-runtime/codex/launcher-client.js +0 -177
  94. package/dist/workspace-runtime/codex/loopback.js +0 -146
  95. package/dist/workspace-runtime/codex/mcp-config.js +0 -39
  96. package/dist/workspace-runtime/codex/model-broker.js +0 -263
  97. package/dist/workspace-runtime/codex/native-adapter.js +0 -9
  98. package/dist/workspace-runtime/codex/permissions.js +0 -70
  99. package/dist/workspace-runtime/codex/thread-image.js +0 -38
  100. package/dist/workspace-runtime/codex/ui-instructions.js +0 -4
  101. package/dist/workspace-runtime/codex/ui-tools.js +0 -183
  102. package/dist/workspace-runtime/codex/work-mode.js +0 -15
  103. package/dist/workspace-runtime/main.js +0 -10
  104. package/dist/workspace-runtime/persistence/journal.js +0 -365
  105. package/dist/workspace-runtime/persistence/native-subagents.js +0 -162
  106. package/dist/workspace-runtime/persistence/sqlite-client.js +0 -77
  107. package/dist/workspace-runtime/persistence/sqlite-worker.js +0 -1161
  108. package/dist/workspace-runtime/persistence/stopped-execution.js +0 -77
  109. package/dist/workspace-runtime/previews/output.js +0 -36
  110. package/dist/workspace-runtime/previews/publish.js +0 -262
  111. package/dist/workspace-runtime/previews/single-file.js +0 -43
  112. package/dist/workspace-runtime/processes/managed-writes.js +0 -69
  113. package/dist/workspace-runtime/production/content-changes.js +0 -36
  114. package/dist/workspace-runtime/production/contracts.js +0 -19
  115. package/dist/workspace-runtime/production/controller.js +0 -218
  116. package/dist/workspace-runtime/production/dependencies.js +0 -60
  117. package/dist/workspace-runtime/production/native.js +0 -212
  118. package/dist/workspace-runtime/production/processes.js +0 -102
  119. package/dist/workspace-runtime/production/save-command.js +0 -35
  120. package/dist/workspace-runtime/production/source-archive.js +0 -137
  121. package/dist/workspace-runtime/production/source-copy.js +0 -91
  122. package/dist/workspace-runtime/production/stages.js +0 -334
  123. package/dist/workspace-runtime/production/storage.js +0 -75
  124. package/dist/workspace-runtime/serve.js +0 -214
  125. package/dist/workspace-runtime/server/auth.js +0 -21
  126. package/dist/workspace-runtime/server/connectivity.js +0 -201
  127. package/dist/workspace-runtime/server/desktop-host.js +0 -429
  128. package/dist/workspace-runtime/server/desktop-preview-config.js +0 -81
  129. package/dist/workspace-runtime/server/desktop-preview-service.js +0 -157
  130. package/dist/workspace-runtime/server/desktop-preview-static.js +0 -53
  131. package/dist/workspace-runtime/server/desktop-preview.js +0 -189
  132. package/dist/workspace-runtime/server/dispatch.js +0 -1217
  133. package/dist/workspace-runtime/server/endpoints.js +0 -21
  134. package/dist/workspace-runtime/server/execution-group.js +0 -90
  135. package/dist/workspace-runtime/server/http.js +0 -1243
  136. package/dist/workspace-runtime/server/lock.js +0 -53
  137. package/dist/workspace-runtime/server/rfb-watch-gate.js +0 -168
  138. package/dist/workspace-runtime/server/source-uploader.js +0 -138
  139. package/dist/workspace-runtime/server/terminal-host.js +0 -366
  140. package/dist/workspace-runtime/server/types.js +0 -1
  141. package/dist/workspace-runtime/server/workspace-transfer.js +0 -99
  142. package/dist/workspace-runtime/workspaces/archive.js +0 -207
  143. package/dist/workspace-runtime/workspaces/artifact-events.js +0 -55
  144. package/dist/workspace-runtime/workspaces/artifact-files.js +0 -197
  145. package/dist/workspace-runtime/workspaces/artifact-receipts.js +0 -89
  146. package/dist/workspace-runtime/workspaces/artifacts.js +0 -282
  147. package/dist/workspace-runtime/workspaces/attachment-content.js +0 -123
  148. package/dist/workspace-runtime/workspaces/attachments.js +0 -185
  149. package/dist/workspace-runtime/workspaces/batch-commit.js +0 -142
  150. package/dist/workspace-runtime/workspaces/cli-context.js +0 -23
  151. package/dist/workspace-runtime/workspaces/cli-credentials.js +0 -111
  152. package/dist/workspace-runtime/workspaces/composer-context.js +0 -147
  153. package/dist/workspace-runtime/workspaces/context-error.js +0 -2
  154. package/dist/workspace-runtime/workspaces/dependencies.js +0 -264
  155. package/dist/workspace-runtime/workspaces/developer-command.js +0 -64
  156. package/dist/workspace-runtime/workspaces/directories.js +0 -133
  157. package/dist/workspace-runtime/workspaces/directory-access.js +0 -37
  158. package/dist/workspace-runtime/workspaces/directory-attachments.js +0 -245
  159. package/dist/workspace-runtime/workspaces/directory-maintenance.js +0 -111
  160. package/dist/workspace-runtime/workspaces/directory-stats.js +0 -49
  161. package/dist/workspace-runtime/workspaces/disk-snapshot.js +0 -31
  162. package/dist/workspace-runtime/workspaces/empty-template.js +0 -42
  163. package/dist/workspace-runtime/workspaces/files-search.js +0 -116
  164. package/dist/workspace-runtime/workspaces/files.js +0 -138
  165. package/dist/workspace-runtime/workspaces/git-credential-broker.js +0 -312
  166. package/dist/workspace-runtime/workspaces/git-credential-helper.js +0 -68
  167. package/dist/workspace-runtime/workspaces/git-direct-store.js +0 -155
  168. package/dist/workspace-runtime/workspaces/git.js +0 -670
  169. package/dist/workspace-runtime/workspaces/instructions.js +0 -56
  170. package/dist/workspace-runtime/workspaces/json5-edit.js +0 -170
  171. package/dist/workspace-runtime/workspaces/library-attachments.js +0 -268
  172. package/dist/workspace-runtime/workspaces/optional-platform-skills.js +0 -14
  173. package/dist/workspace-runtime/workspaces/parameters.js +0 -272
  174. package/dist/workspace-runtime/workspaces/prepare.js +0 -278
  175. package/dist/workspace-runtime/workspaces/registry.js +0 -251
  176. package/dist/workspace-runtime/workspaces/remix-references.js +0 -301
  177. package/dist/workspace-runtime/workspaces/revisions.js +0 -31
  178. package/dist/workspace-runtime/workspaces/session-image.js +0 -104
  179. package/dist/workspace-runtime/workspaces/shared-git.js +0 -40
  180. package/dist/workspace-runtime/workspaces/skill-artifact-loader.js +0 -95
  181. package/dist/workspace-runtime/workspaces/skills.js +0 -191
  182. package/dist/workspace-runtime/workspaces/transfer.js +0 -288
  183. package/dist/workspace-runtime/workspaces/turn-changes.js +0 -75
  184. package/dist/workspace-runtime/workspaces/video-attachments.js +0 -49
  185. package/project-template/.claude/skills/playcraft-replica-validation/SKILL.md +0 -25
  186. package/project-template/.claude/skills/playcraft-replica-validation/references/contracts.md +0 -79
  187. package/project-template/.claude/skills/playcraft-video-understanding/SKILL.md +0 -29
  188. package/project-template/.claude/skills/playcraft-video-understanding/references/contracts.md +0 -37
  189. package/project-template-v2/.claude/agents/artist.md +0 -82
  190. package/project-template-v2/.claude/agents/developer.md +0 -153
  191. package/project-template-v2/.claude/agents/game-designer.md +0 -264
  192. package/project-template-v2/.claude/agents/refs/artist-art-style-catalog.md +0 -533
  193. package/project-template-v2/.claude/agents/refs/artist-color-audio-recipes.md +0 -153
  194. package/project-template-v2/.claude/agents/refs/artist-dimension-axis.md +0 -27
  195. package/project-template-v2/.claude/agents/refs/artist-master-composite-recipes.md +0 -208
  196. package/project-template-v2/.claude/agents/refs/atom-skill-library.md +0 -81
  197. package/project-template-v2/.claude/agents/refs/developer-impl-cookbook.md +0 -432
  198. package/project-template-v2/.claude/agents/refs/framework-5-component-filter.md +0 -252
  199. package/project-template-v2/.claude/agents/refs/framework-game-feel-juice.md +0 -266
  200. package/project-template-v2/.claude/agents/refs/framework-mda.md +0 -147
  201. package/project-template-v2/.claude/agents/refs/game-designer-gameplay-sufficiency.md +0 -123
  202. package/project-template-v2/.claude/agents/refs/ta-3d-flip-recipe.md +0 -88
  203. package/project-template-v2/.claude/agents/refs/ta-atlas-deliverable-standard.md +0 -67
  204. package/project-template-v2/.claude/agents/refs/ta-batch-pipeline-recipes.md +0 -120
  205. package/project-template-v2/.claude/agents/refs/ta-image-generation-detail.md +0 -300
  206. package/project-template-v2/.claude/agents/refs/ta-image-ops-reference.md +0 -495
  207. package/project-template-v2/.claude/agents/refs/ta-pipeline-cookbook.md +0 -1141
  208. package/project-template-v2/.claude/agents/refs/ta-tools-reference.md +0 -111
  209. package/project-template-v2/.claude/agents/refs/ta-vfx-preset-catalog.md +0 -365
  210. package/project-template-v2/.claude/agents/refs/threejs-cannon-pitfalls.md +0 -412
  211. package/project-template-v2/.claude/agents/reviewer.md +0 -75
  212. package/project-template-v2/.claude/agents/technical-artist.md +0 -86
  213. package/project-template-v2/.claude/hooks/snapshot-milestone.mjs +0 -243
  214. package/project-template-v2/.claude/hooks/user-prompt.mjs +0 -133
  215. package/project-template-v2/.claude/settings.json +0 -33
  216. package/project-template-v2/.claude/skills/brainstorming/SKILL.md +0 -161
  217. package/project-template-v2/.claude/skills/brainstorming/scripts/frame-template.html +0 -270
  218. package/project-template-v2/.claude/skills/brainstorming/scripts/helper.js +0 -177
  219. package/project-template-v2/.claude/skills/brainstorming/scripts/server.cjs +0 -354
  220. package/project-template-v2/.claude/skills/brainstorming/scripts/start-server.sh +0 -148
  221. package/project-template-v2/.claude/skills/brainstorming/scripts/stop-server.sh +0 -56
  222. package/project-template-v2/.claude/skills/brainstorming/scripts/wait-for-selection.sh +0 -62
  223. package/project-template-v2/.claude/skills/brainstorming/spec-document-reviewer-prompt.md +0 -49
  224. package/project-template-v2/.claude/skills/brainstorming/visual-companion.md +0 -309
  225. package/project-template-v2/.claude/skills/playcraft-ad-psychology/SKILL.md +0 -182
  226. package/project-template-v2/.claude/skills/playcraft-art-style-guide/SKILL.md +0 -123
  227. package/project-template-v2/.claude/skills/playcraft-asset-state-sheet/SKILL.md +0 -205
  228. package/project-template-v2/.claude/skills/playcraft-audio-generation/SKILL.md +0 -280
  229. package/project-template-v2/.claude/skills/playcraft-batch-pipeline/SKILL.md +0 -184
  230. package/project-template-v2/.claude/skills/playcraft-build-optimizer/SKILL.md +0 -306
  231. package/project-template-v2/.claude/skills/playcraft-image-generation/SKILL.md +0 -298
  232. package/project-template-v2/.claude/skills/playcraft-image-generation/reference/build-sprite-sheet.template.mjs +0 -123
  233. package/project-template-v2/.claude/skills/playcraft-image-generation/reference/compare-style.template.mjs +0 -254
  234. package/project-template-v2/.claude/skills/playcraft-image-generation/reference/gen-batch-sprite.template.mjs +0 -324
  235. package/project-template-v2/.claude/skills/playcraft-image-generation/reference/gen-batch.template.mjs +0 -97
  236. package/project-template-v2/.claude/skills/playcraft-image-generation/reference/gen-edit-variants.template.mjs +0 -118
  237. package/project-template-v2/.claude/skills/playcraft-image-generation/reference/process-batch.template.mjs +0 -137
  238. package/project-template-v2/.claude/skills/playcraft-image-generation/reference/prompt-cookbook.md +0 -397
  239. package/project-template-v2/.claude/skills/playcraft-image-generation/reference/validate-sprite-sheet.template.mjs +0 -296
  240. package/project-template-v2/.claude/skills/playcraft-image-ops/SKILL.md +0 -122
  241. package/project-template-v2/.claude/skills/playcraft-image-processing/SKILL.md +0 -219
  242. package/project-template-v2/.claude/skills/playcraft-masking/SKILL.md +0 -373
  243. package/project-template-v2/.claude/skills/playcraft-playable-optimization/SKILL.md +0 -161
  244. package/project-template-v2/.claude/skills/playcraft-research/SKILL.md +0 -215
  245. package/project-template-v2/.claude/skills/playcraft-skill-recommender/SKILL.md +0 -382
  246. package/project-template-v2/.claude/skills/playcraft-sprite-generation/SKILL.md +0 -423
  247. package/project-template-v2/.claude/skills/playcraft-sprite-remix/SKILL.md +0 -158
  248. package/project-template-v2/.claude/skills/playcraft-sprite-sheet/SKILL.md +0 -100
  249. package/project-template-v2/.claude/skills/playcraft-storyboard/SKILL.md +0 -167
  250. package/project-template-v2/.claude/skills/playcraft-style-qa/SKILL.md +0 -270
  251. package/project-template-v2/.claude/skills/playcraft-text-rendering/SKILL.md +0 -236
  252. package/project-template-v2/.claude/skills/playcraft-vfx-animation/SKILL.md +0 -130
  253. package/project-template-v2/.claude/skills/playwright-cli/SKILL.md +0 -390
  254. package/project-template-v2/.claude/skills/playwright-cli/references/element-attributes.md +0 -23
  255. package/project-template-v2/.claude/skills/playwright-cli/references/playwright-tests.md +0 -39
  256. package/project-template-v2/.claude/skills/playwright-cli/references/request-mocking.md +0 -87
  257. package/project-template-v2/.claude/skills/playwright-cli/references/running-code.md +0 -240
  258. package/project-template-v2/.claude/skills/playwright-cli/references/session-management.md +0 -226
  259. package/project-template-v2/.claude/skills/playwright-cli/references/spec-driven-testing.md +0 -308
  260. package/project-template-v2/.claude/skills/playwright-cli/references/storage-state.md +0 -275
  261. package/project-template-v2/.claude/skills/playwright-cli/references/test-generation.md +0 -134
  262. package/project-template-v2/.claude/skills/playwright-cli/references/tracing.md +0 -142
  263. package/project-template-v2/.claude/skills/playwright-cli/references/video-recording.md +0 -153
  264. package/project-template-v2/.claude/skills/session-analyzer/SKILL.md +0 -386
  265. package/project-template-v2/.claude/skills/session-analyzer/scripts/execution-breakdown.mjs +0 -182
  266. package/project-template-v2/.claude/skills/session-analyzer/scripts/find-turns.mjs +0 -72
  267. package/project-template-v2/.claude/skills/session-analyzer/scripts/heavy-output.mjs +0 -121
  268. package/project-template-v2/.claude/skills/session-analyzer/scripts/resolve-session.mjs +0 -102
  269. package/project-template-v2/.claude/skills/session-analyzer/scripts/subagent-stats.mjs +0 -127
  270. package/project-template-v2/.claude/skills/session-analyzer/scripts/subagent-tool-timeline.mjs +0 -106
  271. package/project-template-v2/.claude/skills/session-analyzer/scripts/time-gaps.mjs +0 -128
  272. package/project-template-v2/.claude/skills/session-analyzer/scripts/turn-timeline.mjs +0 -67
  273. package/project-template-v2/.claude/snapshot.mjs +0 -263
  274. package/project-template-v2/.playcraft/skills.lock.json +0 -152
  275. package/project-template-v2/CLAUDE.md +0 -146
  276. package/project-template-v2/assets/audio/bgm/.gitkeep +0 -0
  277. package/project-template-v2/assets/audio/sfx/.gitkeep +0 -0
  278. package/project-template-v2/assets/bundles/.gitkeep +0 -0
  279. package/project-template-v2/assets/images/bg/.gitkeep +0 -0
  280. package/project-template-v2/assets/images/reference/.gitkeep +0 -0
  281. package/project-template-v2/assets/images/storyboard/.gitkeep +0 -0
  282. package/project-template-v2/assets/images/tiles/.gitkeep +0 -0
  283. package/project-template-v2/assets/images/ui/.gitkeep +0 -0
  284. package/project-template-v2/assets/images/vfx/.gitkeep +0 -0
  285. package/project-template-v2/assets/models/.gitkeep +0 -0
  286. package/project-template-v2/docs/harness/iteration-1/context-flow.md +0 -254
  287. package/project-template-v2/docs/harness/iteration-1/generate-flow.md +0 -91
  288. package/project-template-v2/docs/harness/iteration-1/ideate-flow.md +0 -214
  289. package/project-template-v2/docs/harness/iteration-1/optimize-flow.md +0 -75
  290. package/project-template-v2/docs/harness/iteration-1/wrapup-flow.md +0 -63
  291. package/project-template-v2/docs/harness/iteration-2/context-flow.md +0 -223
  292. package/project-template-v2/docs/harness/iteration-2/generate-flow.md +0 -129
  293. package/project-template-v2/docs/harness/iteration-2/ideate-flow.md +0 -267
  294. package/project-template-v2/docs/harness/iteration-2/optimize-flow.md +0 -164
  295. package/project-template-v2/docs/harness/iteration-2/wrapup-flow.md +0 -115
  296. package/project-template-v2/docs/harness/orchestrator-flow.md +0 -364
  297. package/project-template-v2/docs/project-state.json +0 -60
  298. package/project-template-v2/docs/project-state.md +0 -72
  299. package/project-template-v2/docs/standards/README.md +0 -225
  300. package/project-template-v2/docs/standards/agent-behavior-standards.md +0 -174
  301. package/project-template-v2/docs/standards/artifacts/design-brief.md +0 -19
  302. package/project-template-v2/docs/standards/artifacts/design.md +0 -22
  303. package/project-template-v2/docs/standards/artifacts/game-code.md +0 -41
  304. package/project-template-v2/docs/standards/artifacts/todo-list.md +0 -41
  305. package/project-template-v2/docs/standards/iter1-agent-behavior-standards.md +0 -343
  306. package/project-template-v2/game/index.ts +0 -18
  307. package/project-template-v2/globals.d.ts +0 -51
  308. package/project-template-v2/index.css +0 -34
  309. package/project-template-v2/index.html +0 -18
  310. package/project-template-v2/main.ts +0 -9
  311. package/project-template-v2/package.json +0 -46
  312. package/project-template-v2/skills/_shared/scripts/dispatch-clear.mjs +0 -31
  313. package/project-template-v2/skills/_shared/scripts/dispatch-set.mjs +0 -86
  314. package/project-template-v2/skills/_shared/scripts/dod-check.mjs +0 -153
  315. package/project-template-v2/skills/_shared/scripts/handoff-append.mjs +0 -70
  316. package/project-template-v2/skills/_shared/scripts/lib/validator-artifacts.mjs +0 -91
  317. package/project-template-v2/skills/_shared/scripts/pipeline/dod-config.mjs +0 -131
  318. package/project-template-v2/skills/_shared/scripts/pipeline/index.mjs +0 -80
  319. package/project-template-v2/skills/_shared/scripts/pipeline/iteration-1-core.mjs +0 -90
  320. package/project-template-v2/skills/_shared/scripts/pipeline/iteration-2-wrap.mjs +0 -93
  321. package/project-template-v2/skills/_shared/scripts/pipeline/iteration-3-visual.mjs +0 -23
  322. package/project-template-v2/skills/_shared/scripts/render-project-state.mjs +0 -230
  323. package/project-template-v2/skills/_shared/scripts/state-advance-stage.mjs +0 -58
  324. package/project-template-v2/skills/_shared/scripts/state-get.mjs +0 -339
  325. package/project-template-v2/skills/_shared/scripts/state-handoff.mjs +0 -39
  326. package/project-template-v2/skills/_shared/scripts/state-set.mjs +0 -94
  327. package/project-template-v2/skills/_shared/scripts/state-store.mjs +0 -783
  328. package/project-template-v2/skills/_shared/scripts/todo-add.mjs +0 -88
  329. package/project-template-v2/skills/_shared/scripts/todo-get.mjs +0 -130
  330. package/project-template-v2/skills/_shared/scripts/todo-remove.mjs +0 -33
  331. package/project-template-v2/skills/_shared/scripts/todo-set.mjs +0 -47
  332. package/project-template-v2/skills/_shared/scripts/verify-asset-code-sync.mjs +0 -268
  333. package/project-template-v2/skills/_shared/scripts/verify-env.mjs +0 -285
  334. package/project-template-v2/skills/_shared/scripts/verify-placeholders.mjs +0 -161
  335. package/project-template-v2/skills/playable-autoplay/SKILL.md +0 -176
  336. package/project-template-v2/skills/playable-autoplay/agents/openai.yaml +0 -4
  337. package/project-template-v2/skills/playable-debug/SKILL.md +0 -116
  338. package/project-template-v2/skills/playable-debug/agents/openai.yaml +0 -4
  339. package/project-template-v2/skills/playable-debug/references/debug-config.md +0 -40
  340. package/project-template-v2/skills/playable-record/SKILL.md +0 -140
  341. package/project-template-v2/skills/playable-record/scripts/lib/dev-server.mjs +0 -104
  342. package/project-template-v2/skills/playable-record/scripts/lib/record-audio-bridge.js +0 -141
  343. package/project-template-v2/skills/playable-record/scripts/record-playable.mjs +0 -425
  344. package/project-template-v2/skills/playable-record/scripts/verify-contract.mjs +0 -261
  345. package/project-template-v2/skills/playable-record/scripts/verify-firstwin.mjs +0 -398
  346. package/project-template-v2/skills/playable-record/scripts/verify-fusion.mjs +0 -322
  347. package/project-template-v2/skills/playable-record/scripts/verify-lifecycle.mjs +0 -105
  348. package/project-template-v2/skills/playable-record/scripts/verify-vlm-video.mjs +0 -230
  349. package/project-template-v2/skills/playable-validate/SKILL.md +0 -61
  350. package/project-template-v2/skills/playable-validate/validation-rules.md +0 -14
  351. package/project-template-v2/skills/playable-verify-ui/SKILL.md +0 -63
  352. package/project-template-v2/skills/playable-verify-ui/scripts/lib/__init__.py +0 -1
  353. package/project-template-v2/skills/playable-verify-ui/scripts/lib/config_expr.js +0 -218
  354. package/project-template-v2/skills/playable-verify-ui/scripts/lib/node_utils.js +0 -51
  355. package/project-template-v2/skills/playable-verify-ui/scripts/lib/profile_loader.py +0 -59
  356. package/project-template-v2/skills/playable-verify-ui/scripts/lib/report.py +0 -106
  357. package/project-template-v2/skills/playable-verify-ui/scripts/lib/runtime_contract.js +0 -116
  358. package/project-template-v2/skills/playable-verify-ui/scripts/verify_fetch_antipatterns.py +0 -59
  359. package/project-template-v2/skills/playable-verify-ui/scripts/verify_hardcoded_layout.js +0 -64
  360. package/project-template-v2/skills/playable-verify-ui/scripts/verify_runtime_contract.js +0 -58
  361. package/project-template-v2/skills/playable-verify-ui/scripts/verify_text_overlap.py +0 -333
  362. package/project-template-v2/ta-workspace/scripts/.gitkeep +0 -0
  363. package/project-template-v2/tsconfig.json +0 -20
  364. package/project-template-v2/vite.config.ts +0 -27
  365. package/project-templates/batch-locks/phaser.yaml +0 -922
  366. package/project-templates/batch-locks/threejs.yaml +0 -978
  367. package/project-templates/empty/AGENTS.md +0 -41
  368. package/project-templates/empty/gitignore +0 -33
@@ -1,28 +0,0 @@
1
- import { spawnSync } from 'node:child_process';
2
- import { readProjectSkillsLockFile } from '@playcraft/common/project-skills';
3
- import { syncLocalProjectSkills, readLocalProjectSkillSnapshot, installFrozenProjectSkills } from './local-store.js';
4
- import { verifyLocalProjectSkills } from './validation.js';
5
- import { projectSkillsMessage as t } from './messages.js';
6
- /** Existing formats keep their legacy consumer; format 3 never silently downgrades. */
7
- export async function prepareLocalSkillLifecycle(directory, action, cache) {
8
- const raw = await readProjectSkillsLockFile(directory);
9
- const managed = raw !== null && JSON.parse(raw).lockVersion === 3;
10
- if (!managed && process.env.PROJECT_SKILLS_ADOPTION_ENABLED !== 'true')
11
- return { managed: false };
12
- if (raw !== null && !managed)
13
- return { managed: false, legacy: true };
14
- if (action === 'create' || action === 'push' || !managed)
15
- await syncLocalProjectSkills(directory, cache);
16
- await verifyLocalProjectSkills(directory);
17
- const snapshot = await readLocalProjectSkillSnapshot(directory);
18
- if (action === 'push') {
19
- const paths = ['.playcraft/skills.json', '.playcraft/skills.lock.json', ...snapshot.declaration.entries.flatMap(entry => entry.source.kind === 'repository' ? [entry.source.root, ...(entry.projectFiles ?? [])] : [])];
20
- const status = spawnSync('git', ['status', '--porcelain', '--', ...paths], { cwd: directory, encoding: 'utf8' });
21
- if (status.status !== 0 || status.stdout.trim())
22
- throw new Error(t('commitRequired'));
23
- }
24
- // Source-only checkouts work offline. Registry packages remain exact and require an authorized cache fill.
25
- if (!snapshot.lock.entries.some(entry => entry.revision.kind === 'release'))
26
- await installFrozenProjectSkills(directory, cache);
27
- return { managed: true, declarationHash: snapshot.lock.declarationHash };
28
- }
@@ -1,112 +0,0 @@
1
- import { spawn, execFileSync } from 'node:child_process';
2
- import { createHash, randomUUID } from 'node:crypto';
3
- import { createRequire } from 'node:module';
4
- import { readFile, writeFile, mkdir, readdir, realpath } from 'node:fs/promises';
5
- import { join } from 'node:path';
6
- import { pathToFileURL } from 'node:url';
7
- import { createInterface } from 'node:readline';
8
- import { effectiveProjectSkills, readManagedSkillEvidence } from '@playcraft/common/project-skills';
9
- import { installFrozenProjectSkills, readLocalProjectSkillSnapshot, projectSkillsCache } from './local-store.js';
10
- import { verifyLocalProjectSkills } from './validation.js';
11
- import { projectSkillsMessage as t } from './messages.js';
12
- const require = createRequire(import.meta.url);
13
- export async function localProjectSkillUsage(directory, cache = projectSkillsCache()) {
14
- const root = join(cache, 'usage', createHash('sha256').update(await realpath(directory)).digest('hex'));
15
- let files;
16
- try {
17
- files = await readdir(root);
18
- }
19
- catch (error) {
20
- if (error.code === 'ENOENT')
21
- return [];
22
- throw error;
23
- }
24
- return Promise.all(files.filter(file => /^[a-f0-9-]+\.json$/.test(file)).sort().map(async (file) => JSON.parse(await readFile(join(root, file), 'utf8'))));
25
- }
26
- /** Local evidence is explicitly client-reported; it never acts as a server evaluation or access grant. */
27
- export async function runLocalProjectSkills(directory, options, cache = projectSkillsCache()) {
28
- if (execFileSync('opencode', ['--version'], { encoding: 'utf8', timeout: 10000 }).trim() !== '1.18.31')
29
- throw new Error(t('runner'));
30
- const cwd = await realpath(directory);
31
- await verifyLocalProjectSkills(cwd);
32
- const snapshot = await readLocalProjectSkillSnapshot(cwd);
33
- const installed = await installFrozenProjectSkills(cwd, cache);
34
- const runId = randomUUID(), runtimeRoot = join(installed.generation, '.runtime');
35
- const home = join(runtimeRoot, 'home');
36
- await mkdir(home, { recursive: true, mode: 0o700 });
37
- const entries = await Promise.all(effectiveProjectSkills(snapshot.declaration, snapshot.lock, 'sandbox-agent').map(async (entry) => {
38
- const bodyFile = join(installed.generation, entry.entryKey, 'SKILL.md');
39
- return { name: entry.entryKey, skillRef: entry.revision.skillRef, revisionId: entry.revision.kind === 'source' ? entry.revision.sourceRevision : entry.revision.version,
40
- artifactHash: entry.revision.artifactHash, bodyFile, bodyHash: createHash('sha256').update(await readFile(bodyFile)).digest('hex'), description: entry.revision.skillRef };
41
- }));
42
- await writeFile(join(runtimeRoot, 'manifest.json'), JSON.stringify({ schemaVersion: 1, runtimeId: runId, lockId: snapshot.lock.declarationHash, entries }), { mode: 0o400 });
43
- await writeFile(join(runtimeRoot, 'opencode.json'), JSON.stringify({ model: options.model,
44
- plugin: [pathToFileURL(require.resolve('@playcraft/common/project-skills/runtime-plugin')).href] }), { mode: 0o400 });
45
- const usageRoot = join(cache, 'usage', createHash('sha256').update(cwd).digest('hex'));
46
- await mkdir(usageRoot, { recursive: true, mode: 0o700 });
47
- const evidence = new Map();
48
- const report = { schemaVersion: 1, runId, declarationHash: snapshot.lock.declarationHash, provenance: 'local-client-reported',
49
- runnerVersion: '1.18.31', model: options.model, startedAt: new Date().toISOString(), status: 'running', collectionStatus: 'collecting', loaded: [] };
50
- const reportPath = join(usageRoot, `${runId}.json`);
51
- await writeFile(reportPath, JSON.stringify(report), { mode: 0o600 });
52
- const environment = { ...process.env, HOME: home, XDG_CONFIG_HOME: join(home, '.config'), XDG_DATA_HOME: join(home, '.local/share'), XDG_STATE_HOME: join(home, '.local/state'), XDG_CACHE_HOME: join(home, '.cache'),
53
- OPENCODE_CONFIG: join(runtimeRoot, 'opencode.json'), OPENCODE_CONFIG_DIR: join(runtimeRoot, 'config'),
54
- OPENCODE_DISABLE_PROJECT_CONFIG: 'true', OPENCODE_DISABLE_CLAUDE_CODE: 'true', OPENCODE_DISABLE_DEFAULT_PLUGINS: 'true', OPENCODE_DISABLE_AUTOUPDATE: 'true',
55
- PLAYCRAFT_SKILL_RUNTIME_FILE: join(runtimeRoot, 'manifest.json') };
56
- delete environment.PLAYCRAFT_SKILL_RUNTIME_ROOT;
57
- delete environment.OPENCODE_CONFIG_CONTENT;
58
- let child;
59
- let cancelled = false, killTimer;
60
- const cancel = () => {
61
- cancelled = true;
62
- child?.kill('SIGTERM');
63
- killTimer ??= setTimeout(() => child?.kill('SIGKILL'), 5000);
64
- killTimer.unref();
65
- };
66
- process.once('SIGINT', cancel);
67
- process.once('SIGTERM', cancel);
68
- try {
69
- child = spawn('opencode', ['run', '--format', 'json', '--model', options.model, '--', options.prompt], { cwd, env: environment, stdio: ['ignore', 'pipe', 'inherit'] });
70
- // Resolve spawn failures so an early error cannot become an unhandled rejection while reading stdout.
71
- const finished = new Promise(resolve => {
72
- child.once('error', error => resolve({ code: 1, error }));
73
- child.once('close', code => resolve({ code: code ?? 1 }));
74
- });
75
- const lines = createInterface({ input: child.stdout });
76
- let partial = false;
77
- for await (const line of lines) {
78
- try {
79
- const event = JSON.parse(line);
80
- const parsed = readManagedSkillEvidence(event);
81
- if (parsed?.runtimeId === runId && parsed.lockId === report.declarationHash && entries.some(entry => entry.revisionId === parsed.skillVersionId && entry.artifactHash === parsed.artifactHash && entry.bodyHash === parsed.bodyHash)) {
82
- evidence.set(parsed.dedupeKey, parsed);
83
- report.loaded = [...evidence.values()];
84
- await writeFile(reportPath, JSON.stringify(report), { mode: 0o600 });
85
- }
86
- if (event.type === 'text' && typeof event.part?.text === 'string')
87
- process.stderr.write(event.part.text);
88
- }
89
- catch {
90
- partial = true;
91
- }
92
- }
93
- const result = await finished;
94
- if (result.error)
95
- throw result.error;
96
- const code = cancelled ? 130 : result.code;
97
- report.status = cancelled ? 'cancelled' : code === 0 ? 'completed' : 'failed';
98
- report.collectionStatus = code === 0 && !partial ? 'complete' : 'partial';
99
- return { ...report, reportPath, exitCode: code };
100
- }
101
- finally {
102
- if (killTimer)
103
- clearTimeout(killTimer);
104
- process.removeListener('SIGINT', cancel);
105
- process.removeListener('SIGTERM', cancel);
106
- if (report.status === 'running') {
107
- report.status = 'failed';
108
- report.collectionStatus = 'partial';
109
- }
110
- await writeFile(reportPath, JSON.stringify(report), { mode: 0o600 });
111
- }
112
- }
@@ -1,221 +0,0 @@
1
- import { createHash, randomUUID } from 'node:crypto';
2
- import { mkdir, readFile, rename, rm, writeFile, lstat } from 'node:fs/promises';
3
- import { join, resolve } from 'node:path';
4
- import { homedir } from 'node:os';
5
- import { projectSkillsMessage as t } from './messages.js';
6
- import { buildLocalProjectSkillsSnapshot, canonicalProjectSkillsJson, extractBundleArchive, createCanonicalBundleArchive, readProjectSkillSource, sourceTreeDigest, readProjectSkillsLockFile, inspectProjectSkills, setProjectSkillEnabled, validateProjectSkillsSnapshot, declarationDigest, effectiveProjectSkills, PROJECT_SKILLS_DECLARATION_PATH, PROJECT_SKILLS_LOCK_PATH, } from '@playcraft/common/project-skills';
7
- export const projectSkillsCache = () => process.env.PLAYCRAFT_SKILLS_CACHE_DIR
8
- ? resolve(process.env.PLAYCRAFT_SKILLS_CACHE_DIR) : join(homedir(), '.playcraft', 'skill-artifacts');
9
- export async function readLocalProjectSkillSnapshot(directory) {
10
- const inventory = await inspectProjectSkills(directory);
11
- if (inventory.issues.length)
12
- throw new Error(JSON.stringify(inventory.issues));
13
- return validateProjectSkillsSnapshot(inventory.declaration, await readProjectSkillsLockFile(directory));
14
- }
15
- /** Serializes local writers; an interrupted pair is diagnosed by the declaration digest. */
16
- async function change(directory, action) {
17
- const management = join(directory, '.playcraft');
18
- await mkdir(management, { recursive: true });
19
- if ((await lstat(management)).isSymbolicLink())
20
- throw new Error('Linked project management directory');
21
- const lease = join(management, 'skills-write.lock');
22
- await writeFile(lease, `${process.pid}\n`, { flag: 'wx', mode: 0o600 });
23
- try {
24
- return await action();
25
- }
26
- finally {
27
- await rm(lease);
28
- }
29
- }
30
- async function writeSnapshot(directory, snapshot) {
31
- validateProjectSkillsSnapshot(snapshot.declaration, snapshot.lock);
32
- for (const [file, value] of [[PROJECT_SKILLS_DECLARATION_PATH, snapshot.declaration], [PROJECT_SKILLS_LOCK_PATH, snapshot.lock]]) {
33
- const target = join(directory, file), temporary = `${target}.${randomUUID()}.tmp`;
34
- await writeFile(temporary, `${canonicalProjectSkillsJson(value)}\n`, { flag: 'wx', mode: 0o644 });
35
- await rename(temporary, target);
36
- }
37
- }
38
- /** Initializes an unmanaged checkout with one complete source and release snapshot under the existing writer lease. */
39
- export async function initializeLocalProjectSkills(directory, cache, options) {
40
- return change(directory, async () => {
41
- if (await readProjectSkillsLockFile(directory) !== null)
42
- throw new Error('skills_revision_conflict');
43
- const declarationPath = join(directory, PROJECT_SKILLS_DECLARATION_PATH);
44
- let originalDeclaration;
45
- try {
46
- const stat = await lstat(declarationPath);
47
- if (!stat.isFile() || stat.isSymbolicLink() || stat.size > 1024 * 1024)
48
- throw new Error('workspace_skills_invalid');
49
- originalDeclaration = await readFile(declarationPath);
50
- }
51
- catch (error) {
52
- if (error.code !== 'ENOENT')
53
- throw error;
54
- }
55
- let configurationWriteStarted = false;
56
- try {
57
- await options.prepareSources?.();
58
- const snapshot = buildLocalProjectSkillsSnapshot(await inspectProjectSkills(directory));
59
- for (const entry of snapshot.declaration.entries)
60
- if (entry.source.kind === 'repository' && options.enabledRoots.has(entry.source.root))
61
- entry.enabled = true;
62
- if (options.platform) {
63
- const platform = validateProjectSkillsSnapshot(options.platform.declaration, options.platform.lock);
64
- if (platform.declaration.entries.some(entry => entry.source.kind !== 'registry'))
65
- throw new Error('workspace_skills_invalid');
66
- snapshot.declaration.entries.push(...platform.declaration.entries);
67
- snapshot.lock.entries.push(...platform.lock.entries);
68
- }
69
- snapshot.lock.declarationHash = declarationDigest(snapshot.declaration);
70
- validateProjectSkillsSnapshot(snapshot.declaration, snapshot.lock);
71
- await mkdir(cache, { recursive: true, mode: 0o700 });
72
- // Every artifact is ready before the first configuration write; an input/output failure cannot leave a valid subset lock.
73
- for (const artifact of [...snapshot.artifacts, ...(options.platform?.artifacts ?? [])]) {
74
- if (createHash('sha256').update(artifact.archive).digest('hex') !== artifact.artifactHash)
75
- throw new Error('workspace_skills_digest_mismatch');
76
- const target = join(cache, `${artifact.artifactHash}.tar.gz`), temporary = `${target}.${randomUUID()}.tmp`;
77
- try {
78
- await writeFile(temporary, artifact.archive, { flag: 'wx', mode: 0o600 });
79
- await rename(temporary, target);
80
- }
81
- finally {
82
- await rm(temporary, { force: true });
83
- }
84
- }
85
- configurationWriteStarted = true;
86
- await writeSnapshot(directory, snapshot);
87
- return { declaration: snapshot.declaration, lock: snapshot.lock };
88
- }
89
- catch (error) {
90
- if (configurationWriteStarted) {
91
- if (originalDeclaration === undefined)
92
- await rm(declarationPath, { force: true });
93
- else {
94
- const temporary = `${declarationPath}.${randomUUID()}.tmp`;
95
- try {
96
- await writeFile(temporary, originalDeclaration, { flag: 'wx', mode: 0o644 });
97
- await rename(temporary, declarationPath);
98
- }
99
- finally {
100
- await rm(temporary, { force: true });
101
- }
102
- }
103
- await rm(join(directory, PROJECT_SKILLS_LOCK_PATH), { force: true });
104
- }
105
- await options.rollbackSources?.();
106
- throw error;
107
- }
108
- });
109
- }
110
- export async function syncLocalProjectSkills(directory, cache = projectSkillsCache()) {
111
- return change(directory, async () => {
112
- let previous;
113
- try {
114
- previous = await readProjectSkillsLockFile(directory) ?? undefined;
115
- }
116
- catch (error) {
117
- if (error.code !== 'ENOENT')
118
- throw error;
119
- }
120
- const snapshot = buildLocalProjectSkillsSnapshot(await inspectProjectSkills(directory), previous);
121
- await mkdir(cache, { recursive: true, mode: 0o700 });
122
- for (const artifact of snapshot.artifacts) {
123
- const target = join(cache, `${artifact.artifactHash}.tar.gz`);
124
- const temporary = `${target}.${randomUUID()}.tmp`;
125
- await writeFile(temporary, artifact.archive, { flag: 'wx', mode: 0o600 });
126
- await rename(temporary, target);
127
- }
128
- await writeSnapshot(directory, snapshot);
129
- return { declaration: snapshot.declaration, lock: snapshot.lock };
130
- });
131
- }
132
- export async function enableLocalProjectSkill(directory, entryKey, enabled) {
133
- return change(directory, async () => {
134
- const previous = await readLocalProjectSkillSnapshot(directory);
135
- const next = setProjectSkillEnabled(previous.declaration, previous.lock, entryKey, enabled);
136
- // Disabled required dependencies are shown immediately, before changing either file.
137
- for (const surface of ['portal-agent', 'sandbox-agent', 'build-time'])
138
- effectiveProjectSkills(next.declaration, next.lock, surface);
139
- await writeSnapshot(directory, next);
140
- return next;
141
- });
142
- }
143
- /** Restores exact cached bytes to a new generation. Never writes source directories. */
144
- export async function installFrozenProjectSkills(directory, cache = projectSkillsCache()) {
145
- const snapshot = await readLocalProjectSkillSnapshot(directory);
146
- const generation = join(cache, 'runs', randomUUID());
147
- const effective = effectiveProjectSkills(snapshot.declaration, snapshot.lock, 'sandbox-agent');
148
- try {
149
- await mkdir(generation, { recursive: true, mode: 0o700 });
150
- for (const entry of effective) {
151
- const cached = join(cache, `${entry.revision.artifactHash}.tar.gz`);
152
- let archive;
153
- try {
154
- archive = await readFile(cached);
155
- }
156
- catch (error) {
157
- if (error.code !== 'ENOENT' || entry.revision.kind !== 'source')
158
- throw error;
159
- const declaration = snapshot.declaration.entries.find(item => item.entryKey === entry.entryKey);
160
- const source = await readProjectSkillSource(directory, declaration);
161
- if (source.sourceTreeHash !== entry.sourceTreeHash)
162
- throw new Error(`Source digest mismatch: ${entry.entryKey}`);
163
- archive = createCanonicalBundleArchive(source.files.map(file => ({ path: file.path, data: Buffer.from(file.content) })));
164
- if (createHash('sha256').update(archive).digest('hex') !== entry.revision.artifactHash)
165
- throw new Error(`Artifact digest mismatch: ${entry.entryKey}`);
166
- await writeFile(cached, archive, { flag: 'wx', mode: 0o600 }).catch(error => { if (error.code !== 'EEXIST')
167
- throw error; });
168
- }
169
- if (createHash('sha256').update(archive).digest('hex') !== entry.revision.artifactHash)
170
- throw new Error(`Artifact digest mismatch: ${entry.entryKey}`);
171
- const extracted = extractBundleArchive(archive);
172
- if (extracted.issues.length)
173
- throw new Error(JSON.stringify(extracted.issues));
174
- if (entry.revision.kind === 'source' && sourceTreeDigest(extracted.files.map(file => ({ path: file.path, content: file.data }))) !== entry.sourceTreeHash)
175
- throw new Error(`Source digest mismatch: ${entry.entryKey}`);
176
- for (const file of extracted.files) {
177
- const target = join(generation, entry.entryKey, file.path);
178
- await mkdir(join(target, '..'), { recursive: true });
179
- await writeFile(target, file.data, { flag: 'wx', mode: 0o444 });
180
- }
181
- }
182
- return { generation, entries: effective.length, declarationHash: snapshot.lock.declarationHash };
183
- }
184
- catch (error) {
185
- await rm(generation, { recursive: true, force: true });
186
- throw error;
187
- }
188
- }
189
- export async function explainLocalProjectSkills(directory) {
190
- const { declaration, lock } = await readLocalProjectSkillSnapshot(directory);
191
- return declaration.entries.map((entry) => ({ ...entry, locked: lock.entries.find((locked) => locked.entryKey === entry.entryKey), reason: entry.enabled ? 'enabled_in_project' : 'disabled_in_project' }));
192
- }
193
- export async function adoptServerProjectSkillSnapshot(directory, expected, response, checkpoint) {
194
- const next = validateProjectSkillsSnapshot(response.declaration, response.lock);
195
- const withoutIdentity = (snapshot) => ({
196
- declaration: { ...snapshot.declaration, entries: snapshot.declaration.entries.map(entry => ({ ...entry,
197
- source: entry.source.kind === 'repository' ? { kind: entry.source.kind, root: entry.source.root } : entry.source })) },
198
- entries: snapshot.lock.entries.map(entry => ({ entryKey: entry.entryKey, sourceTreeHash: entry.sourceTreeHash,
199
- dependencies: entry.dependencies,
200
- revision: entry.revision.kind === 'source' ? { ...entry.revision, skillRef: undefined } : entry.revision })),
201
- });
202
- if (canonicalProjectSkillsJson(withoutIdentity(expected)) !== canonicalProjectSkillsJson(withoutIdentity(next)))
203
- throw new Error(t('reconcileChanged'));
204
- return change(directory, async () => {
205
- const current = await readLocalProjectSkillSnapshot(directory);
206
- if (canonicalProjectSkillsJson(current) !== canonicalProjectSkillsJson(expected))
207
- throw new Error(t('reconcileChanged'));
208
- for (const entry of current.declaration.entries) {
209
- if (entry.source.kind !== 'repository')
210
- continue;
211
- const source = await readProjectSkillSource(directory, entry);
212
- if (source.sourceTreeHash !== current.lock.entries.find(item => item.entryKey === entry.entryKey)?.sourceTreeHash)
213
- throw new Error(t('reconcileChanged'));
214
- }
215
- checkpoint();
216
- const changed = canonicalProjectSkillsJson(current) !== canonicalProjectSkillsJson(next);
217
- if (changed)
218
- await writeSnapshot(directory, next);
219
- return { changed };
220
- });
221
- }
@@ -1,80 +0,0 @@
1
- const messages = {
2
- en: {
3
- importBuiltins: 'Import published platform skills in Cloud Workspace; preserve exact existing revisions',
4
- platformRequired: 'Use Cloud Workspace’s Skills panel to import published platform skills. Local template import is unavailable.',
5
- expectedDeclarationHash: 'Expected declaration digest from the current skill lock',
6
- expectedLockHash: 'Expected digest of the canonical current skill lock',
7
- reconcile: 'Register the pushed commit and adopt verified platform skill identities',
8
- reconcileChanged: 'The branch, source bytes, or settings changed. Sync, commit and push the current project before reconciling.',
9
- reconcilePending: 'Indexing continues on the server. Retry reconcile later. Operation:',
10
- reconcileFailed: 'Skill indexing failed. Inspect the project adoption operation and retry it.',
11
- reconcileNext: 'Skills are registered. Run skills project reconcile to adopt the verified identities locally.',
12
- reconcileCommit: 'Verified skill identities saved. Commit the declaration and lock, then run remix push.',
13
- reconcileUnchanged: 'Local skills match the registered platform revisions.',
14
- pushIndexFailed: 'Git push succeeded, but skill indexing did not finish. Run skills project reconcile to retry.',
15
- unregistered: 'New skill sources are not in the project lock. Run skills project sync before starting a task.',
16
- online: 'Download missing exact artifacts using this Remix’s platform authorization',
17
- downloadMismatch: 'The server has no authorized artifact matching this local lock. Sync the project first.',
18
- commitRequired: 'Skill source or lock changes are ready. Commit them, then run remix push again.',
19
- run: 'Run a task with the frozen project skills in OpenCode 1.18.31',
20
- usage: 'Show locally reported skill deliveries (no chat upload)',
21
- model: 'OpenCode model identifier; credentials come from the local environment',
22
- runner: 'Managed skills require OpenCode 1.18.31.',
23
- sync: 'Save source revisions and cache their exact artifacts offline',
24
- install: 'Restore exactly the saved lock from the local cache',
25
- frozen: 'Require exact locked artifacts',
26
- enable: 'Enable a project skill for the next run',
27
- disable: 'Disable a project skill for the next run',
28
- explain: 'Explain configured revisions, sources and enablement',
29
- description: 'Inspect and validate this project’s managed skills',
30
- inspect: 'Inspect source directories and declarations without changing files',
31
- verify: 'Validate the saved lock and local source bytes',
32
- directory: 'Project directory',
33
- json: 'Print structured output',
34
- verified: 'Local skill sources and configuration match the lock. Server authorization and runner verification are separate checks.',
35
- failed: 'Skill verification failed',
36
- missing: 'The project does not have a managed declaration and lock yet.',
37
- changed: 'Source files have changed since the saved revision',
38
- },
39
- zh: {
40
- importBuiltins: '在云工作区导入已发布平台技能,保留已有精确修订',
41
- platformRequired: '请在云工作区的技能面板导入已发布平台技能;本地模板导入已停用。',
42
- expectedDeclarationHash: '当前技能锁中的声明摘要',
43
- expectedLockHash: '当前技能锁规范化内容的摘要',
44
- reconcile: '登记已推送的提交,并采用平台核验后的技能身份',
45
- reconcileChanged: '分支、源文件或配置发生变化,请同步、提交并推送当前项目后再对账。',
46
- reconcilePending: '服务端仍在登记,请稍后重新运行 reconcile。操作编号:',
47
- reconcileFailed: '技能登记失败,请检查项目接管操作并重试。',
48
- reconcileNext: '技能源已登记,请运行 skills project reconcile 在本地采用已核验的身份。',
49
- reconcileCommit: '已保存核验后的技能身份,请提交声明和锁文件,然后运行 remix push。',
50
- reconcileUnchanged: '本地技能与平台登记的修订一致。',
51
- pushIndexFailed: 'Git 推送成功,但技能登记未完成。请运行 skills project reconcile 重试。',
52
- unregistered: '发现尚未登记到项目锁的技能源,请先运行 skills project sync 再开始任务。',
53
- online: '使用此 Remix 的平台权限下载缺失的精确制品',
54
- downloadMismatch: '服务端没有与此本地锁匹配的授权制品,请先同步项目。',
55
- commitRequired: '技能源或锁文件已更新,请提交这些修改后再次运行 remix push。',
56
- run: '使用固定项目技能和 OpenCode 1.18.31 运行任务',
57
- usage: '查看本地自报的技能加载记录(不上传聊天)',
58
- model: 'OpenCode 模型标识;凭据使用本地环境',
59
- runner: '受控技能需要 OpenCode 1.18.31。',
60
- sync: '保存源修订并离线缓存精确制品',
61
- install: '按锁从本地缓存还原精确制品',
62
- frozen: '要求精确锁定制品',
63
- enable: '在下次运行中启用项目技能',
64
- disable: '在下次运行中停用项目技能',
65
- explain: '解释配置的修订、来源与启停状态',
66
- description: '检查和验证当前项目的受控技能',
67
- inspect: '检查技能源目录和声明,不修改文件',
68
- verify: '验证已保存的锁和本地源文件',
69
- directory: '项目目录',
70
- json: '输出结构化结果',
71
- verified: '本地技能源和配置与锁一致。服务端授权和运行器验证仍需单独检查。',
72
- failed: '技能验证失败',
73
- missing: '此项目还没有受控技能声明和锁。',
74
- changed: '源文件与已保存的修订不一致',
75
- },
76
- };
77
- export function projectSkillsMessage(key) {
78
- const locale = process.env.PLAYCRAFT_LANGUAGE || process.env.LANG || 'en';
79
- return messages[locale.startsWith('zh') ? 'zh' : 'en'][key];
80
- }
@@ -1,62 +0,0 @@
1
- import { spawnSync } from 'node:child_process';
2
- import { PlayCraftHttpClient } from '../utils/playcraft-http-client.js';
3
- import { readRemixLocalMeta } from '../remix/local-git.js';
4
- import { readLocalProjectSkillSnapshot, adoptServerProjectSkillSnapshot } from './local-store.js';
5
- import { projectSkillsMessage as t } from './messages.js';
6
- /** Register the saved commit, then adopt only identity changes for the same local bytes and settings. */
7
- export async function reconcileLocalProjectSkills(directory, options = {}) {
8
- const metadata = readRemixLocalMeta(directory);
9
- const git = (args) => {
10
- const result = spawnSync('git', args, { cwd: directory, encoding: 'utf8' });
11
- if (result.status !== 0)
12
- throw new Error(t('reconcileChanged'));
13
- return result.stdout.trim();
14
- };
15
- if (git(['branch', '--show-current']) !== metadata.branch)
16
- throw new Error(t('reconcileChanged'));
17
- const commit = git(['rev-parse', 'HEAD']);
18
- const snapshot = await readLocalProjectSkillSnapshot(directory);
19
- const paths = [
20
- '.playcraft/skills.json',
21
- '.playcraft/skills.lock.json',
22
- ...snapshot.declaration.entries.flatMap((entry) => entry.source.kind === 'repository' ? [entry.source.root, ...(entry.projectFiles ?? [])] : []),
23
- ];
24
- if (git(['status', '--porcelain', '--', ...paths]))
25
- throw new Error(t('commitRequired'));
26
- const client = new PlayCraftHttpClient(options);
27
- const base = `/projects/${encodeURIComponent(metadata.projectId)}/skills`;
28
- const query = new URLSearchParams({ branch: metadata.branch });
29
- const request = () => ({ signal: AbortSignal.timeout(30_000), redirect: 'error' });
30
- const view = await client.get(`${base}/config?${query}`, undefined, request());
31
- let operation = await client.post(`${base}/index`, { branch: metadata.branch, commit, expectedRevisionId: view.configuration?.id ?? null }, request());
32
- const deadline = Date.now() + 15 * 60_000;
33
- while (!['completed', 'failed', 'blocked', 'cancelled'].includes(operation.phase)) {
34
- if (Date.now() > deadline)
35
- throw new Error(`${t('reconcilePending')} ${operation.id}`);
36
- await new Promise((resolve) => setTimeout(resolve, 1000));
37
- operation = await client.get(`${base}/adoptions/${operation.id}?${query}`, undefined, request());
38
- }
39
- if (operation.phase !== 'completed')
40
- throw new Error(operation.issues?.[0]?.detail || t('reconcileFailed'));
41
- const updated = await client.get(`${base}/config?${query}`, undefined, request());
42
- if (!updated.configuration || updated.configuration.id !== operation.configRevisionId)
43
- throw new Error(t('reconcileChanged'));
44
- if (!options.write)
45
- return {
46
- operationId: operation.id,
47
- configRevisionId: operation.configRevisionId,
48
- commit,
49
- message: t('reconcileNext'),
50
- };
51
- const result = await adoptServerProjectSkillSnapshot(directory, snapshot, updated.configuration, () => {
52
- if (git(['rev-parse', 'HEAD']) !== commit || git(['status', '--porcelain', '--', ...paths]))
53
- throw new Error(t('reconcileChanged'));
54
- });
55
- return {
56
- ...result,
57
- operationId: operation.id,
58
- configRevisionId: operation.configRevisionId,
59
- commit,
60
- message: result.changed ? t('reconcileCommit') : t('reconcileUnchanged'),
61
- };
62
- }
@@ -1,51 +0,0 @@
1
- import { createHash, randomUUID } from 'node:crypto';
2
- import { mkdir, writeFile, rename, readFile } from 'node:fs/promises';
3
- import { join } from 'node:path';
4
- import { PlayCraftHttpClient } from '../utils/playcraft-http-client.js';
5
- import { readRemixLocalMeta } from '../remix/local-git.js';
6
- import { readLocalProjectSkillSnapshot, projectSkillsCache } from './local-store.js';
7
- import { projectSkillsMessage as t } from './messages.js';
8
- /** Only exact project-authorized revisions; identifiers inside Git never grant download access. */
9
- export async function downloadLocalProjectSkillArtifacts(directory, cache = projectSkillsCache()) {
10
- const meta = readRemixLocalMeta(directory), client = new PlayCraftHttpClient();
11
- const snapshot = await readLocalProjectSkillSnapshot(directory);
12
- const query = new URLSearchParams({ branch: meta.branch });
13
- const view = await client.get(`/projects/${encodeURIComponent(meta.projectId)}/skills/config?${query}`);
14
- await mkdir(cache, { recursive: true, mode: 0o700 });
15
- let downloaded = 0;
16
- for (const locked of snapshot.lock.entries) {
17
- const file = join(cache, `${locked.revision.artifactHash}.tar.gz`);
18
- try {
19
- if (createHash('sha256').update(await readFile(file)).digest('hex') === locked.revision.artifactHash)
20
- continue;
21
- }
22
- catch (error) {
23
- if (error.code !== 'ENOENT')
24
- throw error;
25
- }
26
- const authorized = view.entries?.find(entry => entry.entryKey === locked.entryKey && entry.artifactHash === locked.revision.artifactHash);
27
- if (!authorized)
28
- throw new Error(t('downloadMismatch'));
29
- const response = await fetch(client.url(`/projects/${encodeURIComponent(meta.projectId)}/skills/versions/${authorized.versionId}/archive?${query}`), {
30
- headers: { Authorization: `Bearer ${client.token}`, 'X-Request-Id': client.requestId }, redirect: 'error', signal: AbortSignal.timeout(60000),
31
- });
32
- if (!response.ok || !response.body)
33
- throw new Error(`${t('downloadMismatch')} (${response.status})`);
34
- const parts = [];
35
- let size = 0;
36
- for await (const chunk of response.body) {
37
- size += chunk.byteLength;
38
- if (size > 80 * 1024 * 1024)
39
- throw new Error(t('downloadMismatch'));
40
- parts.push(Buffer.from(chunk));
41
- }
42
- const archive = Buffer.concat(parts);
43
- if (createHash('sha256').update(archive).digest('hex') !== locked.revision.artifactHash)
44
- throw new Error(t('downloadMismatch'));
45
- const temporary = `${file}.${randomUUID()}.tmp`;
46
- await writeFile(temporary, archive, { mode: 0o600, flag: 'wx' });
47
- await rename(temporary, file);
48
- downloaded++;
49
- }
50
- return { downloaded };
51
- }
@@ -1,19 +0,0 @@
1
- import { readProjectSkillSource, inspectProjectSkills } from '@playcraft/common/project-skills';
2
- import { readLocalProjectSkillSnapshot } from './local-store.js';
3
- import { projectSkillsMessage as t } from './messages.js';
4
- export async function verifyLocalProjectSkills(directory) {
5
- const snapshot = await readLocalProjectSkillSnapshot(directory);
6
- const inventory = await inspectProjectSkills(directory);
7
- if (inventory.sources.length !== snapshot.declaration.entries.filter(entry => entry.source.kind === 'repository').length) {
8
- throw new Error(t('unregistered'));
9
- }
10
- for (const entry of snapshot.declaration.entries) {
11
- if (entry.source.kind !== 'repository')
12
- continue;
13
- const actual = await readProjectSkillSource(directory, entry);
14
- const expected = snapshot.lock.entries.find((locked) => locked.entryKey === entry.entryKey);
15
- if (actual.sourceTreeHash !== expected?.sourceTreeHash)
16
- throw new Error(`${t('changed')}: ${entry.entryKey}`);
17
- }
18
- return { valid: true, declarationHash: snapshot.lock.declarationHash, entries: snapshot.lock.entries.length, scope: 'local-source-and-config' };
19
- }
@@ -1,40 +0,0 @@
1
- const messages = {
2
- en: {
3
- topic: 'Record a playable with real browser input', record: 'Record a scenario and fresh-context interaction controls',
4
- url: 'Running playable URL on this workspace loopback interface', scenario: 'Validated scenario JSON file',
5
- out: 'Empty artifact directory', browser: 'Absolute Chromium executable path', timeout: 'Maximum recording time in seconds',
6
- invalidArguments: 'Invalid recording arguments or scenario.', invalidUrl: 'The playable URL must use HTTP on the workspace loopback interface without credentials.',
7
- browserUnavailable: 'Chromium or the Playwright video encoder is unavailable. Check the workspace image.',
8
- navigationFailed: 'The playable did not navigate successfully or left its authorized origin.',
9
- projectChanged: 'Project inputs changed while recording. Record the current project again.',
10
- projectUnavailable: 'The project input digest could not be completed safely.',
11
- recordingFailed: 'Recording failed. Inspect the partial recording and runtime logs.',
12
- outputConflict: 'The recording output directory must be empty.',
13
- recording: 'Recording the playable and interaction controls',
14
- timedOut: 'Recording timed out. Partial evidence was preserved.', interrupted: 'Recording was interrupted. Partial evidence was preserved.',
15
- },
16
- zh: {
17
- topic: '使用真实浏览器输入录制可玩作品', record: '录制操作场景和使用独立空上下文的交互对照',
18
- url: '当前工作区回环地址上的作品服务', scenario: '经过验证的操作场景文件', out: '空的证据输出目录',
19
- browser: 'Chromium 可执行文件的绝对路径', timeout: '录制最长秒数', invalidArguments: '录制参数或场景无效。',
20
- invalidUrl: '作品地址必须使用工作区回环接口的 HTTP 协议,不能包含凭据。',
21
- browserUnavailable: 'Chromium 或 Playwright 视频编码器不可用,请检查工作区镜像。',
22
- navigationFailed: '作品导航失败,或跳转离开了授权来源。', projectChanged: '录制时工程输入发生了变化,请基于当前工程重新录制。',
23
- projectUnavailable: '无法安全完成工程输入摘要。', recordingFailed: '录制失败,请检查保留的局部录像和运行日志。',
24
- outputConflict: '录制输出目录必须为空。', recording: '正在录制作品和交互对照',
25
- timedOut: '录制超时,已保留局部证据。', interrupted: '录制已中断,已保留局部证据。',
26
- },
27
- };
28
- export function recordingMessage(key) {
29
- const language = process.env.PLAYCRAFT_LANGUAGE || process.env.LANG || 'en';
30
- return messages[language.startsWith('zh') ? 'zh' : 'en'][key];
31
- }
32
- export class RecordingError extends Error {
33
- code;
34
- exitCode;
35
- constructor(code, exitCode = 4) {
36
- super(recordingMessage(code));
37
- this.code = code;
38
- this.exitCode = exitCode;
39
- }
40
- }