@playcraft/cli 0.1.33 → 0.1.35-prod

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 (346) hide show
  1. package/README.md +3 -56
  2. package/dist/agent/local-backend.js +1 -1
  3. package/dist/cli-root-help.js +0 -2
  4. package/dist/commands/build.js +4 -9
  5. package/dist/commands/create.js +33 -26
  6. package/dist/commands/image.js +6 -2
  7. package/dist/commands/login.js +42 -84
  8. package/dist/commands/skills.js +0 -2
  9. package/dist/commands/tools-3d.js +0 -11
  10. package/dist/commands/tools-generation.js +109 -68
  11. package/dist/commands/tools-image-context.js +23 -0
  12. package/dist/commands/tools.js +2 -2
  13. package/dist/config.js +4 -59
  14. package/dist/index.js +3 -36
  15. package/dist/remix/clone.js +0 -2
  16. package/dist/remix/init-template.js +0 -2
  17. package/dist/remix/pull.js +0 -2
  18. package/dist/remix/push.js +1 -21
  19. package/dist/utils/agent-api-client.js +30 -185
  20. package/dist/utils/image-asset-context.js +105 -0
  21. package/dist/utils/playcraft-http-client.js +4 -6
  22. package/package.json +5 -14
  23. package/project-template/.claude/agents/refs/ta-image-generation-detail.md +67 -123
  24. package/project-template/.claude/skills/playcraft-image-generation/SKILL.md +105 -44
  25. package/project-template/.claude/skills/playcraft-image-generation/reference/gen-batch-sprite.template.mjs +42 -33
  26. package/project-template/.claude/skills/playcraft-image-generation/reference/gen-batch.template.mjs +18 -20
  27. package/project-template/.claude/skills/playcraft-image-generation/reference/process-batch.template.mjs +6 -7
  28. package/project-template/.claude/skills/playcraft-image-generation/reference/prompt-cookbook.md +36 -39
  29. package/project-templates/phaser/.claude/agents/refs/ta-image-generation-detail.md +59 -59
  30. package/project-templates/phaser/.claude/skills/playcraft-image-generation/SKILL.md +105 -44
  31. package/project-templates/phaser/.claude/skills/playcraft-image-generation/reference/gen-batch-sprite.template.mjs +42 -33
  32. package/project-templates/phaser/.claude/skills/playcraft-image-generation/reference/gen-batch.template.mjs +18 -20
  33. package/project-templates/phaser/.claude/skills/playcraft-image-generation/reference/process-batch.template.mjs +6 -7
  34. package/project-templates/phaser/.claude/skills/playcraft-image-generation/reference/prompt-cookbook.md +36 -39
  35. package/project-templates/threejs/.claude/agents/refs/ta-image-generation-detail.md +59 -59
  36. package/project-templates/threejs/.claude/skills/playcraft-image-generation/SKILL.md +105 -44
  37. package/project-templates/threejs/.claude/skills/playcraft-image-generation/reference/gen-batch-sprite.template.mjs +42 -33
  38. package/project-templates/threejs/.claude/skills/playcraft-image-generation/reference/gen-batch.template.mjs +18 -20
  39. package/project-templates/threejs/.claude/skills/playcraft-image-generation/reference/process-batch.template.mjs +6 -7
  40. package/project-templates/threejs/.claude/skills/playcraft-image-generation/reference/prompt-cookbook.md +36 -39
  41. package/dist/auth/account-activation.js +0 -157
  42. package/dist/auth/messages.js +0 -30
  43. package/dist/commands/platform-skills.generated.js +0 -19
  44. package/dist/commands/playable.js +0 -53
  45. package/dist/commands/tools-batch.js +0 -87
  46. package/dist/commands/video.js +0 -111
  47. package/dist/commands/workspace-runtime.js +0 -54
  48. package/dist/commands/workspace.js +0 -35
  49. package/dist/project-skills/builtin-import.js +0 -225
  50. package/dist/project-skills/commands.js +0 -77
  51. package/dist/project-skills/lifecycle.js +0 -28
  52. package/dist/project-skills/local-run.js +0 -112
  53. package/dist/project-skills/local-store.js +0 -221
  54. package/dist/project-skills/messages.js +0 -80
  55. package/dist/project-skills/reconcile.js +0 -62
  56. package/dist/project-skills/remote-cache.js +0 -51
  57. package/dist/project-skills/validation.js +0 -19
  58. package/dist/recording/messages.js +0 -40
  59. package/dist/recording/project-digest.js +0 -85
  60. package/dist/recording/recorder.js +0 -293
  61. package/dist/recording/scenario.js +0 -50
  62. package/dist/utils/environment-endpoints.js +0 -17
  63. package/dist/utils/tool-operation-journal.js +0 -124
  64. package/dist/utils/video-evidence-git.js +0 -81
  65. package/dist/video-replication/client.js +0 -222
  66. package/dist/video-replication/comparison-evidence.js +0 -149
  67. package/dist/video-replication/comparison-files.js +0 -57
  68. package/dist/video-replication/comparison-log.js +0 -72
  69. package/dist/video-replication/comparison-messages.js +0 -104
  70. package/dist/video-replication/comparison-output.js +0 -63
  71. package/dist/video-replication/comparison-preflight.js +0 -66
  72. package/dist/video-replication/comparison.js +0 -216
  73. package/dist/video-replication/evidence.js +0 -165
  74. package/dist/video-replication/media.js +0 -111
  75. package/dist/video-replication/messages.js +0 -89
  76. package/dist/workspace/messages.js +0 -35
  77. package/dist/workspace/transfer-client.js +0 -174
  78. package/dist/workspace-runtime/codex/app-server.js +0 -965
  79. package/dist/workspace-runtime/codex/compact.js +0 -46
  80. package/dist/workspace-runtime/codex/config-toml.js +0 -107
  81. package/dist/workspace-runtime/codex/jsonrpc-stdio.js +0 -145
  82. package/dist/workspace-runtime/codex/launcher-client.js +0 -177
  83. package/dist/workspace-runtime/codex/loopback.js +0 -146
  84. package/dist/workspace-runtime/codex/mcp-config.js +0 -39
  85. package/dist/workspace-runtime/codex/model-broker.js +0 -263
  86. package/dist/workspace-runtime/codex/native-adapter.js +0 -9
  87. package/dist/workspace-runtime/codex/permissions.js +0 -70
  88. package/dist/workspace-runtime/codex/work-mode.js +0 -15
  89. package/dist/workspace-runtime/main.js +0 -10
  90. package/dist/workspace-runtime/persistence/journal.js +0 -355
  91. package/dist/workspace-runtime/persistence/native-subagents.js +0 -162
  92. package/dist/workspace-runtime/persistence/sqlite-client.js +0 -77
  93. package/dist/workspace-runtime/persistence/sqlite-worker.js +0 -1096
  94. package/dist/workspace-runtime/previews/output.js +0 -36
  95. package/dist/workspace-runtime/previews/publish.js +0 -262
  96. package/dist/workspace-runtime/previews/single-file.js +0 -43
  97. package/dist/workspace-runtime/processes/managed-writes.js +0 -69
  98. package/dist/workspace-runtime/production/contracts.js +0 -17
  99. package/dist/workspace-runtime/production/controller.js +0 -207
  100. package/dist/workspace-runtime/production/dependencies.js +0 -60
  101. package/dist/workspace-runtime/production/native.js +0 -203
  102. package/dist/workspace-runtime/production/processes.js +0 -86
  103. package/dist/workspace-runtime/production/save-command.js +0 -35
  104. package/dist/workspace-runtime/production/source-copy.js +0 -91
  105. package/dist/workspace-runtime/production/stages.js +0 -205
  106. package/dist/workspace-runtime/production/storage.js +0 -60
  107. package/dist/workspace-runtime/serve.js +0 -207
  108. package/dist/workspace-runtime/server/auth.js +0 -21
  109. package/dist/workspace-runtime/server/connectivity.js +0 -201
  110. package/dist/workspace-runtime/server/desktop-host.js +0 -429
  111. package/dist/workspace-runtime/server/desktop-preview-config.js +0 -81
  112. package/dist/workspace-runtime/server/desktop-preview-service.js +0 -157
  113. package/dist/workspace-runtime/server/desktop-preview-static.js +0 -53
  114. package/dist/workspace-runtime/server/desktop-preview.js +0 -189
  115. package/dist/workspace-runtime/server/dispatch.js +0 -1174
  116. package/dist/workspace-runtime/server/endpoints.js +0 -19
  117. package/dist/workspace-runtime/server/execution-group.js +0 -85
  118. package/dist/workspace-runtime/server/http.js +0 -1127
  119. package/dist/workspace-runtime/server/lock.js +0 -53
  120. package/dist/workspace-runtime/server/rfb-watch-gate.js +0 -168
  121. package/dist/workspace-runtime/server/terminal-host.js +0 -366
  122. package/dist/workspace-runtime/server/types.js +0 -1
  123. package/dist/workspace-runtime/server/workspace-transfer.js +0 -99
  124. package/dist/workspace-runtime/workspaces/archive.js +0 -207
  125. package/dist/workspace-runtime/workspaces/artifact-events.js +0 -55
  126. package/dist/workspace-runtime/workspaces/artifact-files.js +0 -197
  127. package/dist/workspace-runtime/workspaces/artifact-receipts.js +0 -89
  128. package/dist/workspace-runtime/workspaces/artifacts.js +0 -282
  129. package/dist/workspace-runtime/workspaces/attachment-content.js +0 -123
  130. package/dist/workspace-runtime/workspaces/attachments.js +0 -181
  131. package/dist/workspace-runtime/workspaces/batch-commit.js +0 -142
  132. package/dist/workspace-runtime/workspaces/cli-context.js +0 -23
  133. package/dist/workspace-runtime/workspaces/cli-credentials.js +0 -111
  134. package/dist/workspace-runtime/workspaces/composer-context.js +0 -125
  135. package/dist/workspace-runtime/workspaces/context-error.js +0 -2
  136. package/dist/workspace-runtime/workspaces/dependencies.js +0 -264
  137. package/dist/workspace-runtime/workspaces/developer-command.js +0 -64
  138. package/dist/workspace-runtime/workspaces/directories.js +0 -123
  139. package/dist/workspace-runtime/workspaces/directory-access.js +0 -37
  140. package/dist/workspace-runtime/workspaces/directory-attachments.js +0 -245
  141. package/dist/workspace-runtime/workspaces/directory-maintenance.js +0 -111
  142. package/dist/workspace-runtime/workspaces/directory-stats.js +0 -49
  143. package/dist/workspace-runtime/workspaces/disk-snapshot.js +0 -31
  144. package/dist/workspace-runtime/workspaces/empty-template.js +0 -40
  145. package/dist/workspace-runtime/workspaces/files-search.js +0 -116
  146. package/dist/workspace-runtime/workspaces/files.js +0 -120
  147. package/dist/workspace-runtime/workspaces/git-credential-broker.js +0 -312
  148. package/dist/workspace-runtime/workspaces/git-credential-helper.js +0 -68
  149. package/dist/workspace-runtime/workspaces/git-direct-store.js +0 -155
  150. package/dist/workspace-runtime/workspaces/git.js +0 -658
  151. package/dist/workspace-runtime/workspaces/instructions.js +0 -56
  152. package/dist/workspace-runtime/workspaces/json5-edit.js +0 -170
  153. package/dist/workspace-runtime/workspaces/library-attachments.js +0 -268
  154. package/dist/workspace-runtime/workspaces/parameters.js +0 -272
  155. package/dist/workspace-runtime/workspaces/prepare.js +0 -264
  156. package/dist/workspace-runtime/workspaces/registry.js +0 -236
  157. package/dist/workspace-runtime/workspaces/revisions.js +0 -31
  158. package/dist/workspace-runtime/workspaces/skill-artifact-loader.js +0 -91
  159. package/dist/workspace-runtime/workspaces/skills.js +0 -189
  160. package/dist/workspace-runtime/workspaces/transfer.js +0 -288
  161. package/dist/workspace-runtime/workspaces/turn-changes.js +0 -72
  162. package/dist/workspace-runtime/workspaces/video-attachments.js +0 -49
  163. package/project-template/.claude/skills/playcraft-replica-validation/SKILL.md +0 -25
  164. package/project-template/.claude/skills/playcraft-replica-validation/references/contracts.md +0 -79
  165. package/project-template/.claude/skills/playcraft-video-understanding/SKILL.md +0 -29
  166. package/project-template/.claude/skills/playcraft-video-understanding/references/contracts.md +0 -37
  167. package/project-template-v2/.claude/agents/artist.md +0 -82
  168. package/project-template-v2/.claude/agents/developer.md +0 -153
  169. package/project-template-v2/.claude/agents/game-designer.md +0 -264
  170. package/project-template-v2/.claude/agents/refs/artist-art-style-catalog.md +0 -533
  171. package/project-template-v2/.claude/agents/refs/artist-color-audio-recipes.md +0 -153
  172. package/project-template-v2/.claude/agents/refs/artist-dimension-axis.md +0 -27
  173. package/project-template-v2/.claude/agents/refs/artist-master-composite-recipes.md +0 -208
  174. package/project-template-v2/.claude/agents/refs/atom-skill-library.md +0 -81
  175. package/project-template-v2/.claude/agents/refs/developer-impl-cookbook.md +0 -432
  176. package/project-template-v2/.claude/agents/refs/framework-5-component-filter.md +0 -252
  177. package/project-template-v2/.claude/agents/refs/framework-game-feel-juice.md +0 -266
  178. package/project-template-v2/.claude/agents/refs/framework-mda.md +0 -147
  179. package/project-template-v2/.claude/agents/refs/game-designer-gameplay-sufficiency.md +0 -123
  180. package/project-template-v2/.claude/agents/refs/ta-3d-flip-recipe.md +0 -88
  181. package/project-template-v2/.claude/agents/refs/ta-atlas-deliverable-standard.md +0 -67
  182. package/project-template-v2/.claude/agents/refs/ta-batch-pipeline-recipes.md +0 -120
  183. package/project-template-v2/.claude/agents/refs/ta-image-generation-detail.md +0 -300
  184. package/project-template-v2/.claude/agents/refs/ta-image-ops-reference.md +0 -495
  185. package/project-template-v2/.claude/agents/refs/ta-pipeline-cookbook.md +0 -1141
  186. package/project-template-v2/.claude/agents/refs/ta-tools-reference.md +0 -111
  187. package/project-template-v2/.claude/agents/refs/ta-vfx-preset-catalog.md +0 -365
  188. package/project-template-v2/.claude/agents/refs/threejs-cannon-pitfalls.md +0 -412
  189. package/project-template-v2/.claude/agents/reviewer.md +0 -75
  190. package/project-template-v2/.claude/agents/technical-artist.md +0 -86
  191. package/project-template-v2/.claude/hooks/snapshot-milestone.mjs +0 -243
  192. package/project-template-v2/.claude/hooks/user-prompt.mjs +0 -133
  193. package/project-template-v2/.claude/settings.json +0 -33
  194. package/project-template-v2/.claude/skills/brainstorming/SKILL.md +0 -161
  195. package/project-template-v2/.claude/skills/brainstorming/scripts/frame-template.html +0 -270
  196. package/project-template-v2/.claude/skills/brainstorming/scripts/helper.js +0 -177
  197. package/project-template-v2/.claude/skills/brainstorming/scripts/server.cjs +0 -354
  198. package/project-template-v2/.claude/skills/brainstorming/scripts/start-server.sh +0 -148
  199. package/project-template-v2/.claude/skills/brainstorming/scripts/stop-server.sh +0 -56
  200. package/project-template-v2/.claude/skills/brainstorming/scripts/wait-for-selection.sh +0 -62
  201. package/project-template-v2/.claude/skills/brainstorming/spec-document-reviewer-prompt.md +0 -49
  202. package/project-template-v2/.claude/skills/brainstorming/visual-companion.md +0 -309
  203. package/project-template-v2/.claude/skills/playcraft-ad-psychology/SKILL.md +0 -182
  204. package/project-template-v2/.claude/skills/playcraft-art-style-guide/SKILL.md +0 -123
  205. package/project-template-v2/.claude/skills/playcraft-asset-state-sheet/SKILL.md +0 -205
  206. package/project-template-v2/.claude/skills/playcraft-audio-generation/SKILL.md +0 -280
  207. package/project-template-v2/.claude/skills/playcraft-batch-pipeline/SKILL.md +0 -184
  208. package/project-template-v2/.claude/skills/playcraft-build-optimizer/SKILL.md +0 -306
  209. package/project-template-v2/.claude/skills/playcraft-image-generation/SKILL.md +0 -298
  210. package/project-template-v2/.claude/skills/playcraft-image-generation/reference/build-sprite-sheet.template.mjs +0 -123
  211. package/project-template-v2/.claude/skills/playcraft-image-generation/reference/compare-style.template.mjs +0 -254
  212. package/project-template-v2/.claude/skills/playcraft-image-generation/reference/gen-batch-sprite.template.mjs +0 -324
  213. package/project-template-v2/.claude/skills/playcraft-image-generation/reference/gen-batch.template.mjs +0 -97
  214. package/project-template-v2/.claude/skills/playcraft-image-generation/reference/gen-edit-variants.template.mjs +0 -118
  215. package/project-template-v2/.claude/skills/playcraft-image-generation/reference/process-batch.template.mjs +0 -137
  216. package/project-template-v2/.claude/skills/playcraft-image-generation/reference/prompt-cookbook.md +0 -397
  217. package/project-template-v2/.claude/skills/playcraft-image-generation/reference/validate-sprite-sheet.template.mjs +0 -296
  218. package/project-template-v2/.claude/skills/playcraft-image-ops/SKILL.md +0 -122
  219. package/project-template-v2/.claude/skills/playcraft-image-processing/SKILL.md +0 -219
  220. package/project-template-v2/.claude/skills/playcraft-masking/SKILL.md +0 -373
  221. package/project-template-v2/.claude/skills/playcraft-playable-optimization/SKILL.md +0 -161
  222. package/project-template-v2/.claude/skills/playcraft-research/SKILL.md +0 -215
  223. package/project-template-v2/.claude/skills/playcraft-skill-recommender/SKILL.md +0 -382
  224. package/project-template-v2/.claude/skills/playcraft-sprite-generation/SKILL.md +0 -423
  225. package/project-template-v2/.claude/skills/playcraft-sprite-remix/SKILL.md +0 -158
  226. package/project-template-v2/.claude/skills/playcraft-sprite-sheet/SKILL.md +0 -100
  227. package/project-template-v2/.claude/skills/playcraft-storyboard/SKILL.md +0 -167
  228. package/project-template-v2/.claude/skills/playcraft-style-qa/SKILL.md +0 -270
  229. package/project-template-v2/.claude/skills/playcraft-text-rendering/SKILL.md +0 -236
  230. package/project-template-v2/.claude/skills/playcraft-vfx-animation/SKILL.md +0 -130
  231. package/project-template-v2/.claude/skills/playwright-cli/SKILL.md +0 -390
  232. package/project-template-v2/.claude/skills/playwright-cli/references/element-attributes.md +0 -23
  233. package/project-template-v2/.claude/skills/playwright-cli/references/playwright-tests.md +0 -39
  234. package/project-template-v2/.claude/skills/playwright-cli/references/request-mocking.md +0 -87
  235. package/project-template-v2/.claude/skills/playwright-cli/references/running-code.md +0 -240
  236. package/project-template-v2/.claude/skills/playwright-cli/references/session-management.md +0 -226
  237. package/project-template-v2/.claude/skills/playwright-cli/references/spec-driven-testing.md +0 -308
  238. package/project-template-v2/.claude/skills/playwright-cli/references/storage-state.md +0 -275
  239. package/project-template-v2/.claude/skills/playwright-cli/references/test-generation.md +0 -134
  240. package/project-template-v2/.claude/skills/playwright-cli/references/tracing.md +0 -142
  241. package/project-template-v2/.claude/skills/playwright-cli/references/video-recording.md +0 -153
  242. package/project-template-v2/.claude/skills/session-analyzer/SKILL.md +0 -386
  243. package/project-template-v2/.claude/skills/session-analyzer/scripts/execution-breakdown.mjs +0 -182
  244. package/project-template-v2/.claude/skills/session-analyzer/scripts/find-turns.mjs +0 -72
  245. package/project-template-v2/.claude/skills/session-analyzer/scripts/heavy-output.mjs +0 -121
  246. package/project-template-v2/.claude/skills/session-analyzer/scripts/resolve-session.mjs +0 -102
  247. package/project-template-v2/.claude/skills/session-analyzer/scripts/subagent-stats.mjs +0 -127
  248. package/project-template-v2/.claude/skills/session-analyzer/scripts/subagent-tool-timeline.mjs +0 -106
  249. package/project-template-v2/.claude/skills/session-analyzer/scripts/time-gaps.mjs +0 -128
  250. package/project-template-v2/.claude/skills/session-analyzer/scripts/turn-timeline.mjs +0 -67
  251. package/project-template-v2/.claude/snapshot.mjs +0 -263
  252. package/project-template-v2/.playcraft/skills.lock.json +0 -152
  253. package/project-template-v2/CLAUDE.md +0 -146
  254. package/project-template-v2/assets/audio/bgm/.gitkeep +0 -0
  255. package/project-template-v2/assets/audio/sfx/.gitkeep +0 -0
  256. package/project-template-v2/assets/bundles/.gitkeep +0 -0
  257. package/project-template-v2/assets/images/bg/.gitkeep +0 -0
  258. package/project-template-v2/assets/images/reference/.gitkeep +0 -0
  259. package/project-template-v2/assets/images/storyboard/.gitkeep +0 -0
  260. package/project-template-v2/assets/images/tiles/.gitkeep +0 -0
  261. package/project-template-v2/assets/images/ui/.gitkeep +0 -0
  262. package/project-template-v2/assets/images/vfx/.gitkeep +0 -0
  263. package/project-template-v2/assets/models/.gitkeep +0 -0
  264. package/project-template-v2/docs/harness/iteration-1/context-flow.md +0 -254
  265. package/project-template-v2/docs/harness/iteration-1/generate-flow.md +0 -91
  266. package/project-template-v2/docs/harness/iteration-1/ideate-flow.md +0 -214
  267. package/project-template-v2/docs/harness/iteration-1/optimize-flow.md +0 -75
  268. package/project-template-v2/docs/harness/iteration-1/wrapup-flow.md +0 -63
  269. package/project-template-v2/docs/harness/iteration-2/context-flow.md +0 -223
  270. package/project-template-v2/docs/harness/iteration-2/generate-flow.md +0 -129
  271. package/project-template-v2/docs/harness/iteration-2/ideate-flow.md +0 -267
  272. package/project-template-v2/docs/harness/iteration-2/optimize-flow.md +0 -164
  273. package/project-template-v2/docs/harness/iteration-2/wrapup-flow.md +0 -115
  274. package/project-template-v2/docs/harness/orchestrator-flow.md +0 -364
  275. package/project-template-v2/docs/project-state.json +0 -60
  276. package/project-template-v2/docs/project-state.md +0 -72
  277. package/project-template-v2/docs/standards/README.md +0 -225
  278. package/project-template-v2/docs/standards/agent-behavior-standards.md +0 -174
  279. package/project-template-v2/docs/standards/artifacts/design-brief.md +0 -19
  280. package/project-template-v2/docs/standards/artifacts/design.md +0 -22
  281. package/project-template-v2/docs/standards/artifacts/game-code.md +0 -41
  282. package/project-template-v2/docs/standards/artifacts/todo-list.md +0 -41
  283. package/project-template-v2/docs/standards/iter1-agent-behavior-standards.md +0 -343
  284. package/project-template-v2/game/index.ts +0 -18
  285. package/project-template-v2/globals.d.ts +0 -51
  286. package/project-template-v2/index.css +0 -34
  287. package/project-template-v2/index.html +0 -18
  288. package/project-template-v2/main.ts +0 -9
  289. package/project-template-v2/package.json +0 -46
  290. package/project-template-v2/skills/_shared/scripts/dispatch-clear.mjs +0 -31
  291. package/project-template-v2/skills/_shared/scripts/dispatch-set.mjs +0 -86
  292. package/project-template-v2/skills/_shared/scripts/dod-check.mjs +0 -153
  293. package/project-template-v2/skills/_shared/scripts/handoff-append.mjs +0 -70
  294. package/project-template-v2/skills/_shared/scripts/lib/validator-artifacts.mjs +0 -91
  295. package/project-template-v2/skills/_shared/scripts/pipeline/dod-config.mjs +0 -131
  296. package/project-template-v2/skills/_shared/scripts/pipeline/index.mjs +0 -80
  297. package/project-template-v2/skills/_shared/scripts/pipeline/iteration-1-core.mjs +0 -90
  298. package/project-template-v2/skills/_shared/scripts/pipeline/iteration-2-wrap.mjs +0 -93
  299. package/project-template-v2/skills/_shared/scripts/pipeline/iteration-3-visual.mjs +0 -23
  300. package/project-template-v2/skills/_shared/scripts/render-project-state.mjs +0 -230
  301. package/project-template-v2/skills/_shared/scripts/state-advance-stage.mjs +0 -58
  302. package/project-template-v2/skills/_shared/scripts/state-get.mjs +0 -339
  303. package/project-template-v2/skills/_shared/scripts/state-handoff.mjs +0 -39
  304. package/project-template-v2/skills/_shared/scripts/state-set.mjs +0 -94
  305. package/project-template-v2/skills/_shared/scripts/state-store.mjs +0 -783
  306. package/project-template-v2/skills/_shared/scripts/todo-add.mjs +0 -88
  307. package/project-template-v2/skills/_shared/scripts/todo-get.mjs +0 -130
  308. package/project-template-v2/skills/_shared/scripts/todo-remove.mjs +0 -33
  309. package/project-template-v2/skills/_shared/scripts/todo-set.mjs +0 -47
  310. package/project-template-v2/skills/_shared/scripts/verify-asset-code-sync.mjs +0 -268
  311. package/project-template-v2/skills/_shared/scripts/verify-env.mjs +0 -285
  312. package/project-template-v2/skills/_shared/scripts/verify-placeholders.mjs +0 -161
  313. package/project-template-v2/skills/playable-autoplay/SKILL.md +0 -176
  314. package/project-template-v2/skills/playable-autoplay/agents/openai.yaml +0 -4
  315. package/project-template-v2/skills/playable-debug/SKILL.md +0 -116
  316. package/project-template-v2/skills/playable-debug/agents/openai.yaml +0 -4
  317. package/project-template-v2/skills/playable-debug/references/debug-config.md +0 -40
  318. package/project-template-v2/skills/playable-record/SKILL.md +0 -140
  319. package/project-template-v2/skills/playable-record/scripts/lib/dev-server.mjs +0 -104
  320. package/project-template-v2/skills/playable-record/scripts/lib/record-audio-bridge.js +0 -141
  321. package/project-template-v2/skills/playable-record/scripts/record-playable.mjs +0 -425
  322. package/project-template-v2/skills/playable-record/scripts/verify-contract.mjs +0 -261
  323. package/project-template-v2/skills/playable-record/scripts/verify-firstwin.mjs +0 -398
  324. package/project-template-v2/skills/playable-record/scripts/verify-fusion.mjs +0 -322
  325. package/project-template-v2/skills/playable-record/scripts/verify-lifecycle.mjs +0 -105
  326. package/project-template-v2/skills/playable-record/scripts/verify-vlm-video.mjs +0 -230
  327. package/project-template-v2/skills/playable-validate/SKILL.md +0 -61
  328. package/project-template-v2/skills/playable-validate/validation-rules.md +0 -14
  329. package/project-template-v2/skills/playable-verify-ui/SKILL.md +0 -63
  330. package/project-template-v2/skills/playable-verify-ui/scripts/lib/__init__.py +0 -1
  331. package/project-template-v2/skills/playable-verify-ui/scripts/lib/config_expr.js +0 -218
  332. package/project-template-v2/skills/playable-verify-ui/scripts/lib/node_utils.js +0 -51
  333. package/project-template-v2/skills/playable-verify-ui/scripts/lib/profile_loader.py +0 -59
  334. package/project-template-v2/skills/playable-verify-ui/scripts/lib/report.py +0 -106
  335. package/project-template-v2/skills/playable-verify-ui/scripts/lib/runtime_contract.js +0 -116
  336. package/project-template-v2/skills/playable-verify-ui/scripts/verify_fetch_antipatterns.py +0 -59
  337. package/project-template-v2/skills/playable-verify-ui/scripts/verify_hardcoded_layout.js +0 -64
  338. package/project-template-v2/skills/playable-verify-ui/scripts/verify_runtime_contract.js +0 -58
  339. package/project-template-v2/skills/playable-verify-ui/scripts/verify_text_overlap.py +0 -333
  340. package/project-template-v2/ta-workspace/scripts/.gitkeep +0 -0
  341. package/project-template-v2/tsconfig.json +0 -20
  342. package/project-template-v2/vite.config.ts +0 -27
  343. package/project-templates/batch-locks/phaser.yaml +0 -922
  344. package/project-templates/batch-locks/threejs.yaml +0 -978
  345. package/project-templates/empty/AGENTS.md +0 -39
  346. 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
- }