@playcraft/cli 0.1.49-beta → 0.1.51

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 (395) hide show
  1. package/README.md +3 -62
  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 -210
  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 -113
  50. package/dist/commands/video.js +0 -122
  51. package/dist/commands/workspace-runtime.js +0 -54
  52. package/dist/commands/workspace.js +0 -40
  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/error-diagnostics.js +0 -20
  75. package/dist/utils/tool-operation-journal.js +0 -124
  76. package/dist/utils/video-evidence-git.js +0 -81
  77. package/dist/video-replication/client.js +0 -234
  78. package/dist/video-replication/comparison-evidence.js +0 -149
  79. package/dist/video-replication/comparison-files.js +0 -57
  80. package/dist/video-replication/comparison-log.js +0 -72
  81. package/dist/video-replication/comparison-messages.js +0 -104
  82. package/dist/video-replication/comparison-output.js +0 -63
  83. package/dist/video-replication/comparison-preflight.js +0 -66
  84. package/dist/video-replication/comparison.js +0 -230
  85. package/dist/video-replication/diagnostics.js +0 -41
  86. package/dist/video-replication/evidence.js +0 -165
  87. package/dist/video-replication/media.js +0 -112
  88. package/dist/video-replication/messages.js +0 -97
  89. package/dist/workspace/messages.js +0 -67
  90. package/dist/workspace/transfer-client.js +0 -233
  91. package/dist/workspace/transfer-errors.js +0 -48
  92. package/dist/workspace-runtime/batch/content-changes.js +0 -30
  93. package/dist/workspace-runtime/batch/control.js +0 -86
  94. package/dist/workspace-runtime/batch/deliver.js +0 -173
  95. package/dist/workspace-runtime/batch/freeze.js +0 -101
  96. package/dist/workspace-runtime/batch/generate.js +0 -249
  97. package/dist/workspace-runtime/batch/git.js +0 -40
  98. package/dist/workspace-runtime/batch/occupancy.js +0 -8
  99. package/dist/workspace-runtime/batch/policy.js +0 -70
  100. package/dist/workspace-runtime/batch/prepare.js +0 -317
  101. package/dist/workspace-runtime/batch/processes.js +0 -72
  102. package/dist/workspace-runtime/batch/records.js +0 -113
  103. package/dist/workspace-runtime/batch/routes.js +0 -61
  104. package/dist/workspace-runtime/batch/source-candidate.js +0 -86
  105. package/dist/workspace-runtime/batch/source-capture.js +0 -146
  106. package/dist/workspace-runtime/batch/source-failure.js +0 -43
  107. package/dist/workspace-runtime/batch/source-publish.js +0 -130
  108. package/dist/workspace-runtime/codex/app-server.js +0 -1065
  109. package/dist/workspace-runtime/codex/compact.js +0 -46
  110. package/dist/workspace-runtime/codex/config-toml.js +0 -107
  111. package/dist/workspace-runtime/codex/delivery-tools.js +0 -144
  112. package/dist/workspace-runtime/codex/jsonrpc-stdio.js +0 -145
  113. package/dist/workspace-runtime/codex/launcher-client.js +0 -177
  114. package/dist/workspace-runtime/codex/loopback.js +0 -146
  115. package/dist/workspace-runtime/codex/mcp-config.js +0 -39
  116. package/dist/workspace-runtime/codex/model-broker.js +0 -263
  117. package/dist/workspace-runtime/codex/native-adapter.js +0 -9
  118. package/dist/workspace-runtime/codex/permissions.js +0 -79
  119. package/dist/workspace-runtime/codex/thread-image.js +0 -38
  120. package/dist/workspace-runtime/codex/tool-response.js +0 -10
  121. package/dist/workspace-runtime/codex/ui-instructions.js +0 -4
  122. package/dist/workspace-runtime/codex/ui-tools.js +0 -203
  123. package/dist/workspace-runtime/codex/work-mode.js +0 -15
  124. package/dist/workspace-runtime/main.js +0 -10
  125. package/dist/workspace-runtime/persistence/journal.js +0 -365
  126. package/dist/workspace-runtime/persistence/native-subagents.js +0 -162
  127. package/dist/workspace-runtime/persistence/sqlite-client.js +0 -77
  128. package/dist/workspace-runtime/persistence/sqlite-worker.js +0 -1161
  129. package/dist/workspace-runtime/persistence/stopped-execution.js +0 -77
  130. package/dist/workspace-runtime/previews/diagnostics.js +0 -44
  131. package/dist/workspace-runtime/previews/output.js +0 -36
  132. package/dist/workspace-runtime/previews/publish.js +0 -274
  133. package/dist/workspace-runtime/previews/single-file.js +0 -43
  134. package/dist/workspace-runtime/processes/managed-writes.js +0 -69
  135. package/dist/workspace-runtime/serve.js +0 -343
  136. package/dist/workspace-runtime/server/accept-operation.js +0 -61
  137. package/dist/workspace-runtime/server/auth.js +0 -21
  138. package/dist/workspace-runtime/server/connectivity.js +0 -209
  139. package/dist/workspace-runtime/server/desktop-host.js +0 -429
  140. package/dist/workspace-runtime/server/desktop-preview-config.js +0 -81
  141. package/dist/workspace-runtime/server/desktop-preview-service.js +0 -157
  142. package/dist/workspace-runtime/server/desktop-preview-static.js +0 -53
  143. package/dist/workspace-runtime/server/desktop-preview.js +0 -189
  144. package/dist/workspace-runtime/server/dispatch.js +0 -1393
  145. package/dist/workspace-runtime/server/endpoints.js +0 -21
  146. package/dist/workspace-runtime/server/execution-group.js +0 -90
  147. package/dist/workspace-runtime/server/http.js +0 -1316
  148. package/dist/workspace-runtime/server/lock.js +0 -53
  149. package/dist/workspace-runtime/server/operation-record.js +0 -33
  150. package/dist/workspace-runtime/server/rfb-watch-gate.js +0 -168
  151. package/dist/workspace-runtime/server/session-restore.js +0 -84
  152. package/dist/workspace-runtime/server/source-uploader.js +0 -138
  153. package/dist/workspace-runtime/server/submit-operation.js +0 -41
  154. package/dist/workspace-runtime/server/terminal-host.js +0 -366
  155. package/dist/workspace-runtime/server/types.js +0 -1
  156. package/dist/workspace-runtime/server/workspace-transfer.js +0 -168
  157. package/dist/workspace-runtime/verify-artifact.js +0 -59
  158. package/dist/workspace-runtime/workspaces/append-only-log.js +0 -62
  159. package/dist/workspace-runtime/workspaces/archive.js +0 -207
  160. package/dist/workspace-runtime/workspaces/artifact-events.js +0 -55
  161. package/dist/workspace-runtime/workspaces/artifact-files.js +0 -199
  162. package/dist/workspace-runtime/workspaces/artifact-receipts.js +0 -89
  163. package/dist/workspace-runtime/workspaces/artifacts.js +0 -282
  164. package/dist/workspace-runtime/workspaces/asset-library-import.js +0 -366
  165. package/dist/workspace-runtime/workspaces/attachment-content.js +0 -73
  166. package/dist/workspace-runtime/workspaces/attachments.js +0 -185
  167. package/dist/workspace-runtime/workspaces/batch-commit.js +0 -142
  168. package/dist/workspace-runtime/workspaces/binary-content.js +0 -65
  169. package/dist/workspace-runtime/workspaces/binary-write.js +0 -112
  170. package/dist/workspace-runtime/workspaces/cli-context.js +0 -23
  171. package/dist/workspace-runtime/workspaces/cli-credentials.js +0 -115
  172. package/dist/workspace-runtime/workspaces/composer-context.js +0 -147
  173. package/dist/workspace-runtime/workspaces/context-error.js +0 -2
  174. package/dist/workspace-runtime/workspaces/delivery-build.js +0 -331
  175. package/dist/workspace-runtime/workspaces/delivery-store.js +0 -168
  176. package/dist/workspace-runtime/workspaces/delivery.js +0 -64
  177. package/dist/workspace-runtime/workspaces/dependencies.js +0 -279
  178. package/dist/workspace-runtime/workspaces/developer-command.js +0 -98
  179. package/dist/workspace-runtime/workspaces/directories.js +0 -132
  180. package/dist/workspace-runtime/workspaces/directory-access.js +0 -37
  181. package/dist/workspace-runtime/workspaces/directory-attachments.js +0 -245
  182. package/dist/workspace-runtime/workspaces/directory-create.js +0 -57
  183. package/dist/workspace-runtime/workspaces/directory-maintenance.js +0 -111
  184. package/dist/workspace-runtime/workspaces/directory-stats.js +0 -49
  185. package/dist/workspace-runtime/workspaces/disk-snapshot.js +0 -31
  186. package/dist/workspace-runtime/workspaces/empty-template.js +0 -42
  187. package/dist/workspace-runtime/workspaces/file-content.js +0 -48
  188. package/dist/workspace-runtime/workspaces/files-search.js +0 -116
  189. package/dist/workspace-runtime/workspaces/files.js +0 -150
  190. package/dist/workspace-runtime/workspaces/git-credential-broker.js +0 -312
  191. package/dist/workspace-runtime/workspaces/git-credential-helper.js +0 -68
  192. package/dist/workspace-runtime/workspaces/git-direct-store.js +0 -155
  193. package/dist/workspace-runtime/workspaces/git.js +0 -670
  194. package/dist/workspace-runtime/workspaces/instructions.js +0 -56
  195. package/dist/workspace-runtime/workspaces/json5-edit.js +0 -170
  196. package/dist/workspace-runtime/workspaces/library-attachments.js +0 -268
  197. package/dist/workspace-runtime/workspaces/operation-log.js +0 -23
  198. package/dist/workspace-runtime/workspaces/optional-platform-skills.js +0 -14
  199. package/dist/workspace-runtime/workspaces/parameters.js +0 -272
  200. package/dist/workspace-runtime/workspaces/prepare.js +0 -278
  201. package/dist/workspace-runtime/workspaces/registry.js +0 -251
  202. package/dist/workspace-runtime/workspaces/remix-references.js +0 -301
  203. package/dist/workspace-runtime/workspaces/revisions.js +0 -31
  204. package/dist/workspace-runtime/workspaces/session-image.js +0 -104
  205. package/dist/workspace-runtime/workspaces/shared-git.js +0 -40
  206. package/dist/workspace-runtime/workspaces/skill-artifact-loader.js +0 -95
  207. package/dist/workspace-runtime/workspaces/skills.js +0 -191
  208. package/dist/workspace-runtime/workspaces/transfer-quota.js +0 -69
  209. package/dist/workspace-runtime/workspaces/transfer.js +0 -471
  210. package/dist/workspace-runtime/workspaces/turn-changes.js +0 -75
  211. package/dist/workspace-runtime/workspaces/video-attachments.js +0 -49
  212. package/project-template/.claude/skills/playcraft-replica-validation/SKILL.md +0 -25
  213. package/project-template/.claude/skills/playcraft-replica-validation/references/contracts.md +0 -79
  214. package/project-template/.claude/skills/playcraft-video-understanding/SKILL.md +0 -29
  215. package/project-template/.claude/skills/playcraft-video-understanding/references/contracts.md +0 -37
  216. package/project-template-v2/.claude/agents/artist.md +0 -82
  217. package/project-template-v2/.claude/agents/developer.md +0 -153
  218. package/project-template-v2/.claude/agents/game-designer.md +0 -264
  219. package/project-template-v2/.claude/agents/refs/artist-art-style-catalog.md +0 -533
  220. package/project-template-v2/.claude/agents/refs/artist-color-audio-recipes.md +0 -153
  221. package/project-template-v2/.claude/agents/refs/artist-dimension-axis.md +0 -27
  222. package/project-template-v2/.claude/agents/refs/artist-master-composite-recipes.md +0 -208
  223. package/project-template-v2/.claude/agents/refs/atom-skill-library.md +0 -81
  224. package/project-template-v2/.claude/agents/refs/developer-impl-cookbook.md +0 -432
  225. package/project-template-v2/.claude/agents/refs/framework-5-component-filter.md +0 -252
  226. package/project-template-v2/.claude/agents/refs/framework-game-feel-juice.md +0 -266
  227. package/project-template-v2/.claude/agents/refs/framework-mda.md +0 -147
  228. package/project-template-v2/.claude/agents/refs/game-designer-gameplay-sufficiency.md +0 -123
  229. package/project-template-v2/.claude/agents/refs/ta-3d-flip-recipe.md +0 -88
  230. package/project-template-v2/.claude/agents/refs/ta-atlas-deliverable-standard.md +0 -67
  231. package/project-template-v2/.claude/agents/refs/ta-batch-pipeline-recipes.md +0 -120
  232. package/project-template-v2/.claude/agents/refs/ta-image-generation-detail.md +0 -300
  233. package/project-template-v2/.claude/agents/refs/ta-image-ops-reference.md +0 -495
  234. package/project-template-v2/.claude/agents/refs/ta-pipeline-cookbook.md +0 -1141
  235. package/project-template-v2/.claude/agents/refs/ta-tools-reference.md +0 -111
  236. package/project-template-v2/.claude/agents/refs/ta-vfx-preset-catalog.md +0 -365
  237. package/project-template-v2/.claude/agents/refs/threejs-cannon-pitfalls.md +0 -412
  238. package/project-template-v2/.claude/agents/reviewer.md +0 -75
  239. package/project-template-v2/.claude/agents/technical-artist.md +0 -86
  240. package/project-template-v2/.claude/hooks/snapshot-milestone.mjs +0 -243
  241. package/project-template-v2/.claude/hooks/user-prompt.mjs +0 -133
  242. package/project-template-v2/.claude/settings.json +0 -33
  243. package/project-template-v2/.claude/skills/brainstorming/SKILL.md +0 -161
  244. package/project-template-v2/.claude/skills/brainstorming/scripts/frame-template.html +0 -270
  245. package/project-template-v2/.claude/skills/brainstorming/scripts/helper.js +0 -177
  246. package/project-template-v2/.claude/skills/brainstorming/scripts/server.cjs +0 -354
  247. package/project-template-v2/.claude/skills/brainstorming/scripts/start-server.sh +0 -148
  248. package/project-template-v2/.claude/skills/brainstorming/scripts/stop-server.sh +0 -56
  249. package/project-template-v2/.claude/skills/brainstorming/scripts/wait-for-selection.sh +0 -62
  250. package/project-template-v2/.claude/skills/brainstorming/spec-document-reviewer-prompt.md +0 -49
  251. package/project-template-v2/.claude/skills/brainstorming/visual-companion.md +0 -309
  252. package/project-template-v2/.claude/skills/playcraft-ad-psychology/SKILL.md +0 -182
  253. package/project-template-v2/.claude/skills/playcraft-art-style-guide/SKILL.md +0 -123
  254. package/project-template-v2/.claude/skills/playcraft-asset-state-sheet/SKILL.md +0 -205
  255. package/project-template-v2/.claude/skills/playcraft-audio-generation/SKILL.md +0 -280
  256. package/project-template-v2/.claude/skills/playcraft-batch-pipeline/SKILL.md +0 -184
  257. package/project-template-v2/.claude/skills/playcraft-build-optimizer/SKILL.md +0 -306
  258. package/project-template-v2/.claude/skills/playcraft-image-generation/SKILL.md +0 -298
  259. package/project-template-v2/.claude/skills/playcraft-image-generation/reference/build-sprite-sheet.template.mjs +0 -123
  260. package/project-template-v2/.claude/skills/playcraft-image-generation/reference/compare-style.template.mjs +0 -254
  261. package/project-template-v2/.claude/skills/playcraft-image-generation/reference/gen-batch-sprite.template.mjs +0 -324
  262. package/project-template-v2/.claude/skills/playcraft-image-generation/reference/gen-batch.template.mjs +0 -97
  263. package/project-template-v2/.claude/skills/playcraft-image-generation/reference/gen-edit-variants.template.mjs +0 -118
  264. package/project-template-v2/.claude/skills/playcraft-image-generation/reference/process-batch.template.mjs +0 -137
  265. package/project-template-v2/.claude/skills/playcraft-image-generation/reference/prompt-cookbook.md +0 -397
  266. package/project-template-v2/.claude/skills/playcraft-image-generation/reference/validate-sprite-sheet.template.mjs +0 -296
  267. package/project-template-v2/.claude/skills/playcraft-image-ops/SKILL.md +0 -122
  268. package/project-template-v2/.claude/skills/playcraft-image-processing/SKILL.md +0 -219
  269. package/project-template-v2/.claude/skills/playcraft-masking/SKILL.md +0 -373
  270. package/project-template-v2/.claude/skills/playcraft-playable-optimization/SKILL.md +0 -161
  271. package/project-template-v2/.claude/skills/playcraft-research/SKILL.md +0 -215
  272. package/project-template-v2/.claude/skills/playcraft-skill-recommender/SKILL.md +0 -382
  273. package/project-template-v2/.claude/skills/playcraft-sprite-generation/SKILL.md +0 -423
  274. package/project-template-v2/.claude/skills/playcraft-sprite-remix/SKILL.md +0 -158
  275. package/project-template-v2/.claude/skills/playcraft-sprite-sheet/SKILL.md +0 -100
  276. package/project-template-v2/.claude/skills/playcraft-storyboard/SKILL.md +0 -167
  277. package/project-template-v2/.claude/skills/playcraft-style-qa/SKILL.md +0 -270
  278. package/project-template-v2/.claude/skills/playcraft-text-rendering/SKILL.md +0 -236
  279. package/project-template-v2/.claude/skills/playcraft-vfx-animation/SKILL.md +0 -130
  280. package/project-template-v2/.claude/skills/playwright-cli/SKILL.md +0 -390
  281. package/project-template-v2/.claude/skills/playwright-cli/references/element-attributes.md +0 -23
  282. package/project-template-v2/.claude/skills/playwright-cli/references/playwright-tests.md +0 -39
  283. package/project-template-v2/.claude/skills/playwright-cli/references/request-mocking.md +0 -87
  284. package/project-template-v2/.claude/skills/playwright-cli/references/running-code.md +0 -240
  285. package/project-template-v2/.claude/skills/playwright-cli/references/session-management.md +0 -226
  286. package/project-template-v2/.claude/skills/playwright-cli/references/spec-driven-testing.md +0 -308
  287. package/project-template-v2/.claude/skills/playwright-cli/references/storage-state.md +0 -275
  288. package/project-template-v2/.claude/skills/playwright-cli/references/test-generation.md +0 -134
  289. package/project-template-v2/.claude/skills/playwright-cli/references/tracing.md +0 -142
  290. package/project-template-v2/.claude/skills/playwright-cli/references/video-recording.md +0 -153
  291. package/project-template-v2/.claude/skills/session-analyzer/SKILL.md +0 -386
  292. package/project-template-v2/.claude/skills/session-analyzer/scripts/execution-breakdown.mjs +0 -182
  293. package/project-template-v2/.claude/skills/session-analyzer/scripts/find-turns.mjs +0 -72
  294. package/project-template-v2/.claude/skills/session-analyzer/scripts/heavy-output.mjs +0 -121
  295. package/project-template-v2/.claude/skills/session-analyzer/scripts/resolve-session.mjs +0 -102
  296. package/project-template-v2/.claude/skills/session-analyzer/scripts/subagent-stats.mjs +0 -127
  297. package/project-template-v2/.claude/skills/session-analyzer/scripts/subagent-tool-timeline.mjs +0 -106
  298. package/project-template-v2/.claude/skills/session-analyzer/scripts/time-gaps.mjs +0 -128
  299. package/project-template-v2/.claude/skills/session-analyzer/scripts/turn-timeline.mjs +0 -67
  300. package/project-template-v2/.claude/snapshot.mjs +0 -263
  301. package/project-template-v2/.playcraft/skills.lock.json +0 -152
  302. package/project-template-v2/CLAUDE.md +0 -146
  303. package/project-template-v2/assets/audio/bgm/.gitkeep +0 -0
  304. package/project-template-v2/assets/audio/sfx/.gitkeep +0 -0
  305. package/project-template-v2/assets/bundles/.gitkeep +0 -0
  306. package/project-template-v2/assets/images/bg/.gitkeep +0 -0
  307. package/project-template-v2/assets/images/reference/.gitkeep +0 -0
  308. package/project-template-v2/assets/images/storyboard/.gitkeep +0 -0
  309. package/project-template-v2/assets/images/tiles/.gitkeep +0 -0
  310. package/project-template-v2/assets/images/ui/.gitkeep +0 -0
  311. package/project-template-v2/assets/images/vfx/.gitkeep +0 -0
  312. package/project-template-v2/assets/models/.gitkeep +0 -0
  313. package/project-template-v2/docs/harness/iteration-1/context-flow.md +0 -254
  314. package/project-template-v2/docs/harness/iteration-1/generate-flow.md +0 -91
  315. package/project-template-v2/docs/harness/iteration-1/ideate-flow.md +0 -214
  316. package/project-template-v2/docs/harness/iteration-1/optimize-flow.md +0 -75
  317. package/project-template-v2/docs/harness/iteration-1/wrapup-flow.md +0 -63
  318. package/project-template-v2/docs/harness/iteration-2/context-flow.md +0 -223
  319. package/project-template-v2/docs/harness/iteration-2/generate-flow.md +0 -129
  320. package/project-template-v2/docs/harness/iteration-2/ideate-flow.md +0 -267
  321. package/project-template-v2/docs/harness/iteration-2/optimize-flow.md +0 -164
  322. package/project-template-v2/docs/harness/iteration-2/wrapup-flow.md +0 -115
  323. package/project-template-v2/docs/harness/orchestrator-flow.md +0 -364
  324. package/project-template-v2/docs/project-state.json +0 -60
  325. package/project-template-v2/docs/project-state.md +0 -72
  326. package/project-template-v2/docs/standards/README.md +0 -225
  327. package/project-template-v2/docs/standards/agent-behavior-standards.md +0 -174
  328. package/project-template-v2/docs/standards/artifacts/design-brief.md +0 -19
  329. package/project-template-v2/docs/standards/artifacts/design.md +0 -22
  330. package/project-template-v2/docs/standards/artifacts/game-code.md +0 -41
  331. package/project-template-v2/docs/standards/artifacts/todo-list.md +0 -41
  332. package/project-template-v2/docs/standards/iter1-agent-behavior-standards.md +0 -343
  333. package/project-template-v2/game/index.ts +0 -18
  334. package/project-template-v2/globals.d.ts +0 -51
  335. package/project-template-v2/index.css +0 -34
  336. package/project-template-v2/index.html +0 -18
  337. package/project-template-v2/main.ts +0 -9
  338. package/project-template-v2/package.json +0 -46
  339. package/project-template-v2/skills/_shared/scripts/dispatch-clear.mjs +0 -31
  340. package/project-template-v2/skills/_shared/scripts/dispatch-set.mjs +0 -86
  341. package/project-template-v2/skills/_shared/scripts/dod-check.mjs +0 -153
  342. package/project-template-v2/skills/_shared/scripts/handoff-append.mjs +0 -70
  343. package/project-template-v2/skills/_shared/scripts/lib/validator-artifacts.mjs +0 -91
  344. package/project-template-v2/skills/_shared/scripts/pipeline/dod-config.mjs +0 -131
  345. package/project-template-v2/skills/_shared/scripts/pipeline/index.mjs +0 -80
  346. package/project-template-v2/skills/_shared/scripts/pipeline/iteration-1-core.mjs +0 -90
  347. package/project-template-v2/skills/_shared/scripts/pipeline/iteration-2-wrap.mjs +0 -93
  348. package/project-template-v2/skills/_shared/scripts/pipeline/iteration-3-visual.mjs +0 -23
  349. package/project-template-v2/skills/_shared/scripts/render-project-state.mjs +0 -230
  350. package/project-template-v2/skills/_shared/scripts/state-advance-stage.mjs +0 -58
  351. package/project-template-v2/skills/_shared/scripts/state-get.mjs +0 -339
  352. package/project-template-v2/skills/_shared/scripts/state-handoff.mjs +0 -39
  353. package/project-template-v2/skills/_shared/scripts/state-set.mjs +0 -94
  354. package/project-template-v2/skills/_shared/scripts/state-store.mjs +0 -783
  355. package/project-template-v2/skills/_shared/scripts/todo-add.mjs +0 -88
  356. package/project-template-v2/skills/_shared/scripts/todo-get.mjs +0 -130
  357. package/project-template-v2/skills/_shared/scripts/todo-remove.mjs +0 -33
  358. package/project-template-v2/skills/_shared/scripts/todo-set.mjs +0 -47
  359. package/project-template-v2/skills/_shared/scripts/verify-asset-code-sync.mjs +0 -268
  360. package/project-template-v2/skills/_shared/scripts/verify-env.mjs +0 -285
  361. package/project-template-v2/skills/_shared/scripts/verify-placeholders.mjs +0 -161
  362. package/project-template-v2/skills/playable-autoplay/SKILL.md +0 -176
  363. package/project-template-v2/skills/playable-autoplay/agents/openai.yaml +0 -4
  364. package/project-template-v2/skills/playable-debug/SKILL.md +0 -116
  365. package/project-template-v2/skills/playable-debug/agents/openai.yaml +0 -4
  366. package/project-template-v2/skills/playable-debug/references/debug-config.md +0 -40
  367. package/project-template-v2/skills/playable-record/SKILL.md +0 -140
  368. package/project-template-v2/skills/playable-record/scripts/lib/dev-server.mjs +0 -104
  369. package/project-template-v2/skills/playable-record/scripts/lib/record-audio-bridge.js +0 -141
  370. package/project-template-v2/skills/playable-record/scripts/record-playable.mjs +0 -425
  371. package/project-template-v2/skills/playable-record/scripts/verify-contract.mjs +0 -261
  372. package/project-template-v2/skills/playable-record/scripts/verify-firstwin.mjs +0 -398
  373. package/project-template-v2/skills/playable-record/scripts/verify-fusion.mjs +0 -322
  374. package/project-template-v2/skills/playable-record/scripts/verify-lifecycle.mjs +0 -105
  375. package/project-template-v2/skills/playable-record/scripts/verify-vlm-video.mjs +0 -230
  376. package/project-template-v2/skills/playable-validate/SKILL.md +0 -61
  377. package/project-template-v2/skills/playable-validate/validation-rules.md +0 -14
  378. package/project-template-v2/skills/playable-verify-ui/SKILL.md +0 -63
  379. package/project-template-v2/skills/playable-verify-ui/scripts/lib/__init__.py +0 -1
  380. package/project-template-v2/skills/playable-verify-ui/scripts/lib/config_expr.js +0 -218
  381. package/project-template-v2/skills/playable-verify-ui/scripts/lib/node_utils.js +0 -51
  382. package/project-template-v2/skills/playable-verify-ui/scripts/lib/profile_loader.py +0 -59
  383. package/project-template-v2/skills/playable-verify-ui/scripts/lib/report.py +0 -106
  384. package/project-template-v2/skills/playable-verify-ui/scripts/lib/runtime_contract.js +0 -116
  385. package/project-template-v2/skills/playable-verify-ui/scripts/verify_fetch_antipatterns.py +0 -59
  386. package/project-template-v2/skills/playable-verify-ui/scripts/verify_hardcoded_layout.js +0 -64
  387. package/project-template-v2/skills/playable-verify-ui/scripts/verify_runtime_contract.js +0 -58
  388. package/project-template-v2/skills/playable-verify-ui/scripts/verify_text_overlap.py +0 -333
  389. package/project-template-v2/ta-workspace/scripts/.gitkeep +0 -0
  390. package/project-template-v2/tsconfig.json +0 -20
  391. package/project-template-v2/vite.config.ts +0 -27
  392. package/project-templates/batch-locks/phaser.yaml +0 -922
  393. package/project-templates/batch-locks/threejs.yaml +0 -978
  394. package/project-templates/empty/AGENTS.md +0 -41
  395. package/project-templates/empty/gitignore +0 -33
@@ -1,77 +0,0 @@
1
- import { verifyLocalProjectSkills } from './validation.js';
2
- export { verifyLocalProjectSkills } from './validation.js';
3
- import { downloadLocalProjectSkillArtifacts } from './remote-cache.js';
4
- import { resolve } from 'node:path';
5
- import { inspectProjectSkills, } from '@playcraft/common/project-skills';
6
- import { syncLocalProjectSkills, enableLocalProjectSkill, installFrozenProjectSkills, explainLocalProjectSkills } from './local-store.js';
7
- import { runLocalProjectSkills, localProjectSkillUsage } from './local-run.js';
8
- import { projectSkillsMessage as t } from './messages.js';
9
- import { reconcileLocalProjectSkills } from './reconcile.js';
10
- import { importBuiltinProjectSkills } from './builtin-import.js';
11
- export async function inspectLocalProjectSkills(directory) {
12
- const inventory = await inspectProjectSkills(directory);
13
- // Report metadata only; never print complete skill bytes or project test data.
14
- return { declaration: inventory.declaration, discovered: inventory.discovered, issues: inventory.issues,
15
- sources: inventory.sources.map((source) => ({ entryKey: source.entryKey, root: source.root,
16
- sourceTreeHash: source.sourceTreeHash, files: source.files.map((file) => file.path) })) };
17
- }
18
- export function registerProjectSkillsCommands(skills) {
19
- const project = skills.command('project').description(t('description'));
20
- const output = async (action) => {
21
- try {
22
- process.stdout.write(`${JSON.stringify(await action(), null, 2)}\n`);
23
- }
24
- catch (error) {
25
- process.stderr.write(`${t('failed')}: ${error instanceof Error && error.message === 'workspace_skills_platform_required' ? t('platformRequired') : error instanceof Error ? error.message : String(error)}\n`);
26
- process.exitCode = 1;
27
- }
28
- };
29
- project.command('run <prompt>').description(t('run')).requiredOption('--model <provider/model>', t('model'))
30
- .option('--dir <path>', t('directory'), '.').action((prompt, options) => output(async () => {
31
- const result = await runLocalProjectSkills(resolve(options.dir), { prompt, model: options.model });
32
- if (result.exitCode !== 0)
33
- process.exitCode = result.exitCode;
34
- return result;
35
- }));
36
- project.command('usage').description(t('usage')).option('--dir <path>', t('directory'), '.')
37
- .action((options) => output(() => localProjectSkillUsage(resolve(options.dir))));
38
- project.command('sync').description(t('sync')).option('--dir <path>', t('directory'), '.')
39
- .action((options) => output(() => syncLocalProjectSkills(resolve(options.dir))));
40
- project.command('import-builtins <names...>').description(t('importBuiltins')).option('--dir <path>', t('directory'), '.')
41
- .requiredOption('--expected-declaration-hash <hash>', t('expectedDeclarationHash'))
42
- .requiredOption('--expected-lock-hash <hash>', t('expectedLockHash'))
43
- .action((names, options) => output(() => importBuiltinProjectSkills(resolve(options.dir), { ...options, names })));
44
- project.command('reconcile').description(t('reconcile')).option('--dir <path>', t('directory'), '.')
45
- .action((options) => output(() => reconcileLocalProjectSkills(resolve(options.dir), { write: true })));
46
- project.command('install').description(t('install')).requiredOption('--frozen', t('frozen')).option('--dir <path>', t('directory'), '.')
47
- .option('--online', t('online')).action((options) => output(async () => {
48
- const directory = resolve(options.dir);
49
- if (options.online)
50
- await downloadLocalProjectSkillArtifacts(directory);
51
- return installFrozenProjectSkills(directory);
52
- }));
53
- for (const enabled of [true, false])
54
- project.command(enabled ? 'enable <entryKey>' : 'disable <entryKey>')
55
- .description(t(enabled ? 'enable' : 'disable')).option('--dir <path>', t('directory'), '.')
56
- .action((entryKey, options) => output(() => enableLocalProjectSkill(resolve(options.dir), entryKey, enabled)));
57
- project.command('explain').description(t('explain')).option('--dir <path>', t('directory'), '.')
58
- .action((options) => output(() => explainLocalProjectSkills(resolve(options.dir))));
59
- project.command('inspect').description(t('inspect')).option('--dir <path>', t('directory'), '.')
60
- .action(async (options) => {
61
- const result = await inspectLocalProjectSkills(resolve(options.dir));
62
- process.stdout.write(`${JSON.stringify(result, null, 2)}\n`);
63
- if (result.issues.length)
64
- process.exitCode = 1;
65
- });
66
- project.command('verify').description(t('verify')).option('--dir <path>', t('directory'), '.')
67
- .option('--json', t('json')).action(async (options) => {
68
- try {
69
- const result = await verifyLocalProjectSkills(resolve(options.dir));
70
- process.stdout.write(`${options.json ? JSON.stringify(result) : t('verified')}\n`);
71
- }
72
- catch (error) {
73
- process.stderr.write(`${t('failed')}: ${error instanceof Error ? error.message : String(error)}\n`);
74
- process.exitCode = 1;
75
- }
76
- });
77
- }
@@ -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
- }