nccgs 2.1.1 → 3.0.0-rc.2

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 (705) hide show
  1. package/CHANGELOG.md +76 -235
  2. package/LICENSE +1 -1
  3. package/README.md +87 -206
  4. package/THIRD_PARTY_NOTICES.md +6 -34
  5. package/bin/nccgs.mjs +96 -0
  6. package/cli/doctor.mjs +82 -0
  7. package/cli/feedback.mjs +13 -0
  8. package/cli/install.mjs +111 -0
  9. package/cli/release.mjs +59 -0
  10. package/cli/run.mjs +35 -0
  11. package/cli/spawn.mjs +20 -0
  12. package/cli/uninstall.mjs +43 -0
  13. package/cli/update-check.mjs +66 -0
  14. package/docs/EVIDENCE-VERIFICATION.md +22 -0
  15. package/package.json +23 -30
  16. package/runtime/core/diag.mjs +43 -0
  17. package/runtime/core/feedback-policy.mjs +54 -0
  18. package/runtime/core/fs.mjs +80 -0
  19. package/runtime/core/job-object.mjs +73 -0
  20. package/runtime/core/modes.mjs +87 -0
  21. package/runtime/core/process-tree.mjs +109 -0
  22. package/runtime/core/project.mjs +113 -0
  23. package/runtime/core/snapshot.mjs +114 -0
  24. package/runtime/hooks/common.mjs +22 -0
  25. package/runtime/hooks/done-guard.mjs +15 -0
  26. package/runtime/hooks/guard-mcp.mjs +8 -0
  27. package/runtime/hooks/guard-shell.mjs +16 -0
  28. package/runtime/hooks/guard-write.mjs +25 -0
  29. package/runtime/hooks/session-log.mjs +7 -0
  30. package/runtime/hooks/session-start.mjs +40 -0
  31. package/runtime/hooks/unity-transport.mjs +12 -0
  32. package/runtime/modes.json +39 -0
  33. package/runtime/task/cost.mjs +103 -0
  34. package/runtime/task/criteria.mjs +128 -0
  35. package/runtime/task/feedback.mjs +136 -0
  36. package/runtime/task/ledger.mjs +109 -0
  37. package/runtime/task/plan.mjs +69 -0
  38. package/runtime/task/project.mjs +79 -0
  39. package/runtime/task/report.mjs +252 -0
  40. package/runtime/task/task.mjs +238 -0
  41. package/runtime/unity/assets.mjs +51 -0
  42. package/runtime/unity/playtest.mjs +145 -0
  43. package/runtime/unity/unity.mjs +350 -0
  44. package/scripts/check-job-object.mjs +18 -0
  45. package/scripts/sync-unity-skills.mjs +35 -119
  46. package/template/CLAUDE.md +39 -0
  47. package/template/agents/fast-fix.md +9 -0
  48. package/template/agents/implementer.md +19 -0
  49. package/template/agents/playtester.md +15 -0
  50. package/template/agents/reviewer.md +19 -0
  51. package/template/agents/scout.md +9 -0
  52. package/template/ponytail/README.md +8 -0
  53. package/{.claude/nccgs/packages → template}/ponytail/engineering.md +10 -0
  54. package/template/protocols/evidence.md +52 -0
  55. package/template/protocols/playtest.md +45 -0
  56. package/template/protocols/review.md +34 -0
  57. package/template/protocols/unity-cli-notes.md +56 -0
  58. package/template/settings.fragment.json +33 -0
  59. package/template/skills/art-bible/SKILL.md +19 -0
  60. package/template/skills/asset-spec/SKILL.md +19 -0
  61. package/template/skills/brainstorm/SKILL.md +17 -0
  62. package/template/skills/feedback/SKILL.md +16 -0
  63. package/template/skills/map-systems/SKILL.md +25 -0
  64. package/template/skills/playtest/SKILL.md +17 -0
  65. package/template/skills/status/SKILL.md +18 -0
  66. package/template/skills/test/SKILL.md +34 -0
  67. package/template/skills/unity-foundation/SKILL.md +17 -0
  68. package/template/skills/vertical-slice/SKILL.md +17 -0
  69. package/template/skills/work/SKILL.md +65 -0
  70. package/tools/feedback-worker/README.md +12 -0
  71. package/tools/feedback-worker/worker.js +39 -0
  72. package/tools/feedback-worker/wrangler.toml +12 -0
  73. package/unity-skills/2d-pixel-perfect/SKILL.md +208 -0
  74. package/unity-skills/2d-pixel-perfect/references/api-reference.md +81 -0
  75. package/unity-skills/2d-pixel-perfect/references/camera-setup-builtin.cs +40 -0
  76. package/unity-skills/2d-pixel-perfect/references/camera-setup-urp.cs +49 -0
  77. package/unity-skills/2d-pixel-perfect/references/pipeline-detection.cs +50 -0
  78. package/unity-skills/2d-pixel-perfect/references/sprite-settings.cs +37 -0
  79. package/unity-skills/asset-transformer-toolkit/SECURITY.md +15 -0
  80. package/unity-skills/asset-transformer-toolkit/SKILL.md +39 -0
  81. package/unity-skills/asset-transformer-toolkit/references/create-importer.md +121 -0
  82. package/unity-skills/asset-transformer-toolkit/references/lods.md +61 -0
  83. package/unity-skills/asset-transformer-toolkit/references/rule-api.md +154 -0
  84. package/unity-skills/asset-transformer-toolkit/references/ruleblock-api.md +37 -0
  85. package/unity-skills/asset-transformer-toolkit/references/ruleset-api.md +138 -0
  86. package/unity-skills/asset-transformer-toolkit/references/rulesets-and-actions.md +227 -0
  87. package/unity-skills/audio-setup-mixers/SECURITY.md +16 -0
  88. package/unity-skills/audio-setup-mixers/SKILL.md +127 -0
  89. package/unity-skills/audio-setup-mixers/references/api.md +162 -0
  90. package/unity-skills/build-gtk/SKILL.md +242 -0
  91. package/unity-skills/build-gtk/references/graph-api.md +324 -0
  92. package/unity-skills/build-gtk/references/pitfalls.md +86 -0
  93. package/unity-skills/build-gtk/references/runtime-and-visualization.md +196 -0
  94. package/unity-skills/build-gtk/references/state-machine-api.md +286 -0
  95. package/unity-skills/build-live-game/SKILL.md +255 -0
  96. package/{.claude/skills → unity-skills}/build-live-game/references/achievements.md +132 -154
  97. package/{.claude/skills → unity-skills}/build-live-game/references/apis.md +10 -19
  98. package/{.claude/skills → unity-skills}/build-live-game/references/authentication.md +14 -20
  99. package/{.claude/skills → unity-skills}/build-live-game/references/battlepass.md +269 -225
  100. package/unity-skills/build-live-game/references/blueprints-and-samples.md +75 -0
  101. package/unity-skills/build-live-game/references/cloud-code-cloudbehaviours.md +1111 -0
  102. package/unity-skills/build-live-game/references/cloud-code-modules.md +1276 -0
  103. package/unity-skills/build-live-game/references/cloud-code.md +58 -0
  104. package/{.claude/skills → unity-skills}/build-live-game/references/cloud-save.md +15 -25
  105. package/{.claude/skills → unity-skills}/build-live-game/references/deployment.md +33 -18
  106. package/{.claude/skills → unity-skills}/build-live-game/references/player-account.md +31 -23
  107. package/{.claude/skills → unity-skills}/build-live-game/references/tooling.md +0 -56
  108. package/unity-skills/build-live-game/references/ugs-cli.md +86 -0
  109. package/unity-skills/craft-game-floors/SECURITY.md +23 -0
  110. package/unity-skills/craft-game-floors/SKILL.md +134 -0
  111. package/unity-skills/craft-game-floors/references/art-direction.md +85 -0
  112. package/unity-skills/craft-game-floors/references/camera-rigs.md +51 -0
  113. package/unity-skills/craft-game-floors/references/character-motion.md +35 -0
  114. package/unity-skills/craft-game-floors/references/game-audio.md +47 -0
  115. package/unity-skills/craft-game-floors/references/game-feel.md +68 -0
  116. package/unity-skills/craft-game-floors/references/game-shell.md +45 -0
  117. package/unity-skills/craft-game-floors/references/live-floor.md +35 -0
  118. package/unity-skills/craft-game-floors/references/placeholder-assets.md +35 -0
  119. package/unity-skills/craft-game-floors/references/scene-lighting.md +52 -0
  120. package/unity-skills/craft-game-floors/references/toon-shading.md +34 -0
  121. package/unity-skills/craft-game-floors/references/vfx.md +40 -0
  122. package/unity-skills/craft-game-floors/references/visual-scorecard.md +43 -0
  123. package/unity-skills/create-2d-physics/SECURITY.md +16 -0
  124. package/unity-skills/create-2d-physics/SKILL.md +128 -0
  125. package/unity-skills/create-2d-physics/references/2d-physics-core.md +155 -0
  126. package/unity-skills/create-2d-physics/references/legacy-2d-physics.md +45 -0
  127. package/unity-skills/create-tile-palette-or-rule-tiles/SKILL.md +12 -0
  128. package/unity-skills/create-tile-palette-or-rule-tiles/references/hexagonalruletile.md +71 -0
  129. package/unity-skills/create-tile-palette-or-rule-tiles/references/palette-create.md +38 -0
  130. package/unity-skills/create-tile-palette-or-rule-tiles/references/ruletile-createempty.md +35 -0
  131. package/unity-skills/create-tile-palette-or-rule-tiles/references/ruletile-createfromsegment.md +212 -0
  132. package/unity-skills/create-tile-palette-or-rule-tiles/references/ruletile.md +90 -0
  133. package/unity-skills/create-tile-palette-or-rule-tiles/scripts/CreatePaletteTemplate.cs +148 -0
  134. package/unity-skills/create-tile-palette-or-rule-tiles/scripts/ManualWorkflowExample.cs +63 -0
  135. package/unity-skills/create-tile-palette-or-rule-tiles/scripts/RuleTileGenerator.cs +61 -0
  136. package/unity-skills/create-tile-palette-or-rule-tiles/scripts/TilemapRuleTileCreateFromSegment.cs +225 -0
  137. package/unity-skills/generate-editor-search-query/SECURITY.md +17 -0
  138. package/unity-skills/generate-editor-search-query/SKILL.md +117 -0
  139. package/unity-skills/generate-editor-search-query/references/open-search-window.md +70 -0
  140. package/unity-skills/generate-editor-search-query/references/query-patterns.md +124 -0
  141. package/{.claude/skills → unity-skills}/implement-in-app-purchases/SKILL.md +1 -2
  142. package/{.claude/skills → unity-skills}/implement-in-app-purchases/references/api-notes.md +25 -28
  143. package/{.claude/skills → unity-skills}/implement-in-app-purchases/references/path-convert-native-google-billing.md +1 -1
  144. package/{.claude/skills → unity-skills}/implement-in-app-purchases/references/path-implement-iap-d2c.md +40 -5
  145. package/{.claude/skills → unity-skills}/initialize-ai-navigation/SKILL.md +4 -4
  146. package/{.claude/skills → unity-skills}/initialize-ai-navigation/references/navigation-system.md +3 -3
  147. package/{.claude/skills → unity-skills}/levelplay-unity-integration/CHANGELOG.md +12 -0
  148. package/{.claude/skills → unity-skills}/levelplay-unity-integration/README.md +9 -5
  149. package/unity-skills/levelplay-unity-integration/SKILL.md +442 -0
  150. package/{.claude/skills → unity-skills}/levelplay-unity-integration/references/banner-api.md +15 -8
  151. package/{.claude/skills → unity-skills}/levelplay-unity-integration/references/best-practices.md +604 -536
  152. package/unity-skills/levelplay-unity-integration/references/dependency-resolution.md +94 -0
  153. package/{.claude/skills → unity-skills}/levelplay-unity-integration/references/ilrd-api.md +2 -2
  154. package/{.claude/skills → unity-skills}/levelplay-unity-integration/references/initialization-api.md +221 -0
  155. package/{.claude/skills → unity-skills}/levelplay-unity-integration/references/interstitial-api.md +11 -3
  156. package/{.claude/skills → unity-skills}/levelplay-unity-integration/references/ios-setup.md +6 -34
  157. package/{.claude/skills → unity-skills}/levelplay-unity-integration/references/migration-sdk-9.md +1 -1
  158. package/{.claude/skills → unity-skills}/levelplay-unity-integration/references/privacy-settings.md +14 -29
  159. package/{.claude/skills → unity-skills}/levelplay-unity-integration/references/rewarded-api.md +20 -4
  160. package/unity-skills/levelplay-unity-integration/references/testing-and-validation.md +222 -0
  161. package/unity-skills/levelplay-unity-integration/references/troubleshooting.md +99 -0
  162. package/unity-skills/localization/SKILL.md +347 -0
  163. package/{.claude/skills → unity-skills}/localization/references/api-notes.md +4 -0
  164. package/unity-skills/localization/resources/L10nBatchProcessor.cs +191 -0
  165. package/unity-skills/manage-sprite-atlas/SKILL.md +351 -0
  166. package/unity-skills/manage-sprite-atlas/references/addressables-delivery.md +58 -0
  167. package/unity-skills/manage-sprite-atlas/references/api.md +382 -0
  168. package/unity-skills/manage-sprite-atlas/references/best-practices.md +183 -0
  169. package/unity-skills/manage-sprite-atlas/references/common-errors.md +123 -0
  170. package/unity-skills/manage-sprite-atlas/references/custom-packing.md +147 -0
  171. package/unity-skills/manage-sprite-atlas/references/manual-authoring.md +39 -0
  172. package/unity-skills/manage-sprite-atlas/resources/authoringvsruntime.cs +176 -0
  173. package/unity-skills/manage-sprite-atlas/resources/buildaddressablespostprocess.cs +59 -0
  174. package/unity-skills/manage-sprite-atlas/resources/cacheloadedatlases.cs +145 -0
  175. package/unity-skills/manage-sprite-atlas/resources/cleanupbatchoperations.cs +119 -0
  176. package/unity-skills/manage-sprite-atlas/resources/createandconfiguremasteratlas.cs +57 -0
  177. package/unity-skills/manage-sprite-atlas/resources/custompackersetup.cs +88 -0
  178. package/unity-skills/manage-sprite-atlas/resources/deprecatedmethods.cs +142 -0
  179. package/unity-skills/manage-sprite-atlas/resources/dontmodifywithoutsaving.cs +120 -0
  180. package/unity-skills/manage-sprite-atlas/resources/dontpackinruntimebuilds.cs +190 -0
  181. package/unity-skills/manage-sprite-atlas/resources/dontscriptspriteatlasineditor.cs +114 -0
  182. package/unity-skills/manage-sprite-atlas/resources/editorconfiguration.cs +95 -0
  183. package/unity-skills/manage-sprite-atlas/resources/enablespritepacking.cs +172 -0
  184. package/unity-skills/manage-sprite-atlas/resources/gridspritepacker.cs +50 -0
  185. package/unity-skills/manage-sprite-atlas/resources/handlelatebinding.cs +147 -0
  186. package/unity-skills/manage-sprite-atlas/resources/handlenullcases.cs +141 -0
  187. package/unity-skills/manage-sprite-atlas/resources/migratev1tov2.cs +335 -0
  188. package/unity-skills/manage-sprite-atlas/resources/multipagepacker.cs +80 -0
  189. package/unity-skills/manage-sprite-atlas/resources/optimizetexturesettings.cs +191 -0
  190. package/unity-skills/manage-sprite-atlas/resources/packerdebugging.cs +158 -0
  191. package/unity-skills/manage-sprite-atlas/resources/packtransform.cs +51 -0
  192. package/unity-skills/manage-sprite-atlas/resources/platformnames.cs +127 -0
  193. package/unity-skills/manage-sprite-atlas/resources/queryspritesefficiently.cs +222 -0
  194. package/unity-skills/manage-sprite-atlas/resources/registercallbacks.cs +152 -0
  195. package/unity-skills/manage-sprite-atlas/resources/runtimeatlasloader.cs +15 -0
  196. package/unity-skills/manage-sprite-atlas/resources/runtimespriteaccess.cs +19 -0
  197. package/unity-skills/manage-sprite-atlas/resources/savespriteatlasasset.cs +107 -0
  198. package/unity-skills/manage-sprite-atlas/resources/scriptablepacker.cs +81 -0
  199. package/unity-skills/manage-sprite-atlas/resources/setincludeinbuild.cs +164 -0
  200. package/unity-skills/manage-sprite-atlas/resources/sizeoptimizedpacker.cs +88 -0
  201. package/unity-skills/manage-sprite-atlas/resources/spriteatlaslatebinding.cs +123 -0
  202. package/unity-skills/manage-sprite-atlas/resources/spriteatlasprebuildgenerator.cs +219 -0
  203. package/unity-skills/manage-sprite-atlas/resources/spritedata.cs +35 -0
  204. package/unity-skills/manage-sprite-atlas/resources/spritepack.cs +39 -0
  205. package/unity-skills/manage-sprite-atlas/resources/texturedata.cs +15 -0
  206. package/unity-skills/manage-sprite-atlas/resources/updatebuildscripts.cs +357 -0
  207. package/unity-skills/manage-sprite-atlas/resources/updatesettingsconfiguration.cs +135 -0
  208. package/unity-skills/manage-sprite-atlas/resources/usevariantswisely.cs +179 -0
  209. package/unity-skills/manage-sprite-atlas/resources/variantatlas.cs +39 -0
  210. package/unity-skills/manifest.json +1155 -0
  211. package/unity-skills/migrate-birp-to-urp/SECURITY.md +16 -0
  212. package/unity-skills/migrate-birp-to-urp/SKILL.md +543 -0
  213. package/unity-skills/migrate-birp-to-urp/references/capturing-the-editor.md +66 -0
  214. package/unity-skills/migrate-birp-to-urp/references/complex-shader-situations.md +272 -0
  215. package/unity-skills/migrate-birp-to-urp/references/custom-shader-triage.md +123 -0
  216. package/unity-skills/migrate-birp-to-urp/references/implementation-patterns.md +529 -0
  217. package/unity-skills/migrate-birp-to-urp/references/migration-workflow.md +265 -0
  218. package/unity-skills/migrate-birp-to-urp/references/quality-settings-map.md +69 -0
  219. package/unity-skills/new-unity-project/SECURITY.md +26 -0
  220. package/unity-skills/new-unity-project/SKILL.md +386 -0
  221. package/unity-skills/new-unity-project/references/skill-setup.md +66 -0
  222. package/unity-skills/optimize-audio/SECURITY.md +16 -0
  223. package/{.claude/skills → unity-skills}/optimize-audio/SKILL.md +17 -17
  224. package/{.claude/skills → unity-skills}/optimize-audio/resources/audio-import-api.md +8 -5
  225. package/{.claude/skills → unity-skills}/optimize-text-mesh-pro/SKILL.md +1 -11
  226. package/unity-skills/optimize-web/SECURITY.md +16 -0
  227. package/{.claude/skills → unity-skills}/optimize-web/SKILL.md +164 -27
  228. package/unity-skills/optimize-web/scripts/WebOptimizer.cs +46 -0
  229. package/unity-skills/optimize-web/scripts/toktx-examples.sh +11 -0
  230. package/{.claude/skills → unity-skills}/physics-3d-collision/SKILL.md +2 -2
  231. package/unity-skills/physics-3d-collision/references/troubleshooting.md +8 -0
  232. package/unity-skills/project-auditor-fixes/SKILL.md +64 -0
  233. package/{.claude/skills → unity-skills}/setup-multiplayer-services/SKILL.md +1 -4
  234. package/{.claude/skills → unity-skills}/setup-vivox-voice-chat/SKILL.md +1 -1
  235. package/{.claude/skills → unity-skills}/shader-graph-create-custom-node/SKILL.md +1 -1
  236. package/unity-skills/sprite-editor/SECURITY.md +16 -0
  237. package/{.claude/skills → unity-skills}/sprite-editor/SKILL.md +9 -9
  238. package/{.claude/skills → unity-skills}/sprite-editor/references/templates.md +1 -1
  239. package/unity-skills/sprite-segment-3x3grid/SKILL.md +136 -0
  240. package/unity-skills/sprite-segment-3x3grid/scripts/SpriteGridAnalysis.cs +119 -0
  241. package/{.claude/skills → unity-skills}/ui/SKILL.md +1 -1
  242. package/{.claude/skills → unity-skills}/ui-imgui/SKILL.md +1 -7
  243. package/{.claude/skills → unity-skills}/ui-ugui/SKILL.md +3 -9
  244. package/{.claude/skills → unity-skills}/ui-uitk/SKILL.md +8 -14
  245. package/{.claude/skills → unity-skills}/ui-uitk/references/custom-elements.md +1 -1
  246. package/unity-skills/unity-cli/CHANGELOG.md +515 -0
  247. package/unity-skills/unity-cli/SECURITY.md +68 -0
  248. package/unity-skills/unity-cli/SKILL.md +723 -0
  249. package/unity-skills/unity-cli/references/auth-license-cloud.md +318 -0
  250. package/unity-skills/unity-cli/references/build-run-test.md +555 -0
  251. package/unity-skills/unity-cli/references/cloud-automation.md +736 -0
  252. package/{.claude/skills → unity-skills}/unity-cli/references/collaboration.md +166 -105
  253. package/unity-skills/unity-cli/references/config-hub.md +239 -0
  254. package/unity-skills/unity-cli/references/diagnostics-maintenance.md +720 -0
  255. package/unity-skills/unity-cli/references/docs-workflow.md +179 -0
  256. package/unity-skills/unity-cli/references/editors-install.md +476 -0
  257. package/unity-skills/unity-cli/references/integration-advanced.md +1130 -0
  258. package/unity-skills/unity-cli/references/playmode-verification-loop.md +279 -0
  259. package/unity-skills/unity-cli/references/projects-templates.md +996 -0
  260. package/unity-skills/unity-cli/references/version-control.md +612 -0
  261. package/{.claude/skills → unity-skills}/unity-package-management/SKILL.md +60 -12
  262. package/{.claude/skills → unity-skills}/unity-package-management/references/select-packages.md +39 -21
  263. package/unity-skills/unity-pipeline/SECURITY.md +17 -0
  264. package/unity-skills/unity-pipeline/SKILL.md +335 -0
  265. package/unity-skills/urp-postprocessing/SECURITY.md +16 -0
  266. package/{.claude/skills → unity-skills}/urp-postprocessing/SKILL.md +12 -12
  267. package/{.claude/skills → unity-skills}/urp-postprocessing/references/code-templates.md +39 -8
  268. package/{.claude/skills → unity-skills}/validate-urp-render-graph-renderer-feature/SKILL.md +1 -1
  269. package/.claude/agents/nccgs-adversarial-reviewer.md +0 -43
  270. package/.claude/agents/nccgs-engine-programmer.md +0 -27
  271. package/.claude/agents/nccgs-fast-implementer.md +0 -30
  272. package/.claude/agents/nccgs-game-designer.md +0 -26
  273. package/.claude/agents/nccgs-gameplay-programmer.md +0 -26
  274. package/.claude/agents/nccgs-qa-engineer.md +0 -27
  275. package/.claude/agents/nccgs-task-scout.md +0 -24
  276. package/.claude/agents/nccgs-ui-programmer.md +0 -27
  277. package/.claude/agents/nccgs-unity-build-specialist.md +0 -27
  278. package/.claude/agents/nccgs-unity-implementer.md +0 -28
  279. package/.claude/agents/nccgs-unity-systems-specialist.md +0 -27
  280. package/.claude/agents/nccgs-unity-ui-specialist.md +0 -27
  281. package/.claude/agents/nccgs-verification-engineer.md +0 -27
  282. package/.claude/nccgs/MEMORY.md +0 -66
  283. package/.claude/nccgs/THIRD_PARTY_NOTICES.md +0 -29
  284. package/.claude/nccgs/VERSION +0 -1
  285. package/.claude/nccgs/agent-library/nccgs-accessibility-specialist.md +0 -25
  286. package/.claude/nccgs/agent-library/nccgs-adversarial-reviewer.md +0 -41
  287. package/.claude/nccgs/agent-library/nccgs-ai-programmer.md +0 -25
  288. package/.claude/nccgs/agent-library/nccgs-analytics-engineer.md +0 -25
  289. package/.claude/nccgs/agent-library/nccgs-art-direction-lead.md +0 -25
  290. package/.claude/nccgs/agent-library/nccgs-audio-direction-lead.md +0 -25
  291. package/.claude/nccgs/agent-library/nccgs-creative-director.md +0 -25
  292. package/.claude/nccgs/agent-library/nccgs-documentation-manager.md +0 -25
  293. package/.claude/nccgs/agent-library/nccgs-economy-designer.md +0 -25
  294. package/.claude/nccgs/agent-library/nccgs-engine-programmer.md +0 -25
  295. package/.claude/nccgs/agent-library/nccgs-fast-implementer.md +0 -28
  296. package/.claude/nccgs/agent-library/nccgs-game-design-lead.md +0 -25
  297. package/.claude/nccgs/agent-library/nccgs-game-designer.md +0 -24
  298. package/.claude/nccgs/agent-library/nccgs-gameplay-programmer.md +0 -24
  299. package/.claude/nccgs/agent-library/nccgs-level-designer.md +0 -25
  300. package/.claude/nccgs/agent-library/nccgs-live-ops-designer.md +0 -25
  301. package/.claude/nccgs/agent-library/nccgs-localization-lead.md +0 -25
  302. package/.claude/nccgs/agent-library/nccgs-narrative-lead.md +0 -25
  303. package/.claude/nccgs/agent-library/nccgs-network-programmer.md +0 -25
  304. package/.claude/nccgs/agent-library/nccgs-performance-analyst.md +0 -25
  305. package/.claude/nccgs/agent-library/nccgs-producer.md +0 -25
  306. package/.claude/nccgs/agent-library/nccgs-production-coordinator.md +0 -22
  307. package/.claude/nccgs/agent-library/nccgs-programming-lead.md +0 -25
  308. package/.claude/nccgs/agent-library/nccgs-prototyper.md +0 -25
  309. package/.claude/nccgs/agent-library/nccgs-qa-engineer.md +0 -25
  310. package/.claude/nccgs/agent-library/nccgs-qa-lead.md +0 -25
  311. package/.claude/nccgs/agent-library/nccgs-release-engineer.md +0 -25
  312. package/.claude/nccgs/agent-library/nccgs-release-lead.md +0 -25
  313. package/.claude/nccgs/agent-library/nccgs-security-engineer.md +0 -25
  314. package/.claude/nccgs/agent-library/nccgs-sound-designer.md +0 -25
  315. package/.claude/nccgs/agent-library/nccgs-systems-designer.md +0 -25
  316. package/.claude/nccgs/agent-library/nccgs-task-scout.md +0 -22
  317. package/.claude/nccgs/agent-library/nccgs-technical-architect.md +0 -25
  318. package/.claude/nccgs/agent-library/nccgs-technical-artist.md +0 -25
  319. package/.claude/nccgs/agent-library/nccgs-technical-director.md +0 -25
  320. package/.claude/nccgs/agent-library/nccgs-tools-programmer.md +0 -25
  321. package/.claude/nccgs/agent-library/nccgs-ui-programmer.md +0 -25
  322. package/.claude/nccgs/agent-library/nccgs-unity-build-specialist.md +0 -25
  323. package/.claude/nccgs/agent-library/nccgs-unity-content-specialist.md +0 -25
  324. package/.claude/nccgs/agent-library/nccgs-unity-implementer.md +0 -26
  325. package/.claude/nccgs/agent-library/nccgs-unity-rendering-specialist.md +0 -25
  326. package/.claude/nccgs/agent-library/nccgs-unity-systems-specialist.md +0 -25
  327. package/.claude/nccgs/agent-library/nccgs-unity-ui-specialist.md +0 -25
  328. package/.claude/nccgs/agent-library/nccgs-ux-designer.md +0 -25
  329. package/.claude/nccgs/agent-library/nccgs-verification-engineer.md +0 -25
  330. package/.claude/nccgs/agent-library/nccgs-world-builder.md +0 -25
  331. package/.claude/nccgs/agent-library/nccgs-writer.md +0 -25
  332. package/.claude/nccgs/constitution.md +0 -187
  333. package/.claude/nccgs/hooks/agent-audit.mjs +0 -16
  334. package/.claude/nccgs/hooks/closure-guard.mjs +0 -59
  335. package/.claude/nccgs/hooks/common.mjs +0 -42
  336. package/.claude/nccgs/hooks/post-compact.mjs +0 -1
  337. package/.claude/nccgs/hooks/pre-compact.mjs +0 -8
  338. package/.claude/nccgs/hooks/protect-git.mjs +0 -22
  339. package/.claude/nccgs/hooks/protect-write.mjs +0 -17
  340. package/.claude/nccgs/hooks/runtime-observation.mjs +0 -11
  341. package/.claude/nccgs/hooks/session-start.mjs +0 -29
  342. package/.claude/nccgs/hooks/session-stop.mjs +0 -7
  343. package/.claude/nccgs/hooks/unity-transport-guard.mjs +0 -11
  344. package/.claude/nccgs/packages/ponytail/README.md +0 -46
  345. package/.claude/nccgs/packages/ponytail/manifest.json +0 -24
  346. package/.claude/nccgs/pipeline.json +0 -260
  347. package/.claude/nccgs/protocols/agent-contract.md +0 -101
  348. package/.claude/nccgs/protocols/astra-claude.md +0 -111
  349. package/.claude/nccgs/protocols/bounded-repair.md +0 -246
  350. package/.claude/nccgs/protocols/context-packets.md +0 -23
  351. package/.claude/nccgs/protocols/delivery-acceptance.md +0 -105
  352. package/.claude/nccgs/protocols/design-lifecycle.md +0 -139
  353. package/.claude/nccgs/protocols/editor-session-evidence.md +0 -52
  354. package/.claude/nccgs/protocols/evidence.md +0 -31
  355. package/.claude/nccgs/protocols/model-routing.md +0 -46
  356. package/.claude/nccgs/protocols/orchestration.md +0 -74
  357. package/.claude/nccgs/protocols/review-handoff.md +0 -101
  358. package/.claude/nccgs/protocols/shared-workflow-context.md +0 -33
  359. package/.claude/nccgs/protocols/standalone-gates.md +0 -329
  360. package/.claude/nccgs/protocols/standalone-pilot.md +0 -144
  361. package/.claude/nccgs/protocols/standalone.md +0 -207
  362. package/.claude/nccgs/protocols/task-autonomy.md +0 -55
  363. package/.claude/nccgs/protocols/task-gates.md +0 -144
  364. package/.claude/nccgs/protocols/task-slices.md +0 -106
  365. package/.claude/nccgs/protocols/unity-boundary.md +0 -31
  366. package/.claude/nccgs/routing.generated.md +0 -49
  367. package/.claude/nccgs/settings.fragment.json +0 -213
  368. package/.claude/nccgs/studio.json +0 -472
  369. package/.claude/nccgs/tools/approve-overrides.mjs +0 -81
  370. package/.claude/nccgs/tools/autonomy.mjs +0 -40
  371. package/.claude/nccgs/tools/command-process.mjs +0 -50
  372. package/.claude/nccgs/tools/command-tokens.mjs +0 -22
  373. package/.claude/nccgs/tools/compile-policy.mjs +0 -121
  374. package/.claude/nccgs/tools/configure-models.mjs +0 -96
  375. package/.claude/nccgs/tools/criteria.mjs +0 -121
  376. package/.claude/nccgs/tools/delivery-budget.mjs +0 -52
  377. package/.claude/nccgs/tools/design-readiness.mjs +0 -158
  378. package/.claude/nccgs/tools/editor-session-evidence.mjs +0 -66
  379. package/.claude/nccgs/tools/evidence.mjs +0 -153
  380. package/.claude/nccgs/tools/gates.mjs +0 -297
  381. package/.claude/nccgs/tools/handoff.mjs +0 -51
  382. package/.claude/nccgs/tools/hook-transport.mjs +0 -34
  383. package/.claude/nccgs/tools/inputs.mjs +0 -108
  384. package/.claude/nccgs/tools/installation-guard.mjs +0 -55
  385. package/.claude/nccgs/tools/integrity.mjs +0 -69
  386. package/.claude/nccgs/tools/lifecycle.mjs +0 -542
  387. package/.claude/nccgs/tools/native-completion.mjs +0 -30
  388. package/.claude/nccgs/tools/orchestration.mjs +0 -680
  389. package/.claude/nccgs/tools/paths.mjs +0 -60
  390. package/.claude/nccgs/tools/policy.mjs +0 -107
  391. package/.claude/nccgs/tools/process-lock.mjs +0 -74
  392. package/.claude/nccgs/tools/repair-packet.mjs +0 -106
  393. package/.claude/nccgs/tools/returned-handoff.mjs +0 -47
  394. package/.claude/nccgs/tools/review-budget.mjs +0 -171
  395. package/.claude/nccgs/tools/review-handoff.mjs +0 -66
  396. package/.claude/nccgs/tools/runtime.mjs +0 -71
  397. package/.claude/nccgs/tools/session-budget.mjs +0 -67
  398. package/.claude/nccgs/tools/shared-context-guard.mjs +0 -60
  399. package/.claude/nccgs/tools/shared-context.mjs +0 -25
  400. package/.claude/nccgs/tools/task-slices.mjs +0 -147
  401. package/.claude/nccgs/tools/task.mjs +0 -145
  402. package/.claude/nccgs/tools/tool-guard.mjs +0 -120
  403. package/.claude/nccgs/tools/unity-repair.mjs +0 -128
  404. package/.claude/nccgs/tools/unity-transport.mjs +0 -170
  405. package/.claude/nccgs/tools/verification-jobs.mjs +0 -171
  406. package/.claude/nccgs/tools/verification-worker.mjs +0 -71
  407. package/.claude/nccgs/tools/windows-compiler-server.cs +0 -163
  408. package/.claude/nccgs/tools/windows-job.cs +0 -103
  409. package/.claude/nccgs/unity-skills-manifest.json +0 -727
  410. package/.claude/nccgs/workflow-catalog.json +0 -654
  411. package/.claude/rules/nccgs-canonical-docs.md +0 -19
  412. package/.claude/rules/nccgs-editor-tools.md +0 -12
  413. package/.claude/rules/nccgs-localization.md +0 -12
  414. package/.claude/rules/nccgs-networking.md +0 -13
  415. package/.claude/rules/nccgs-performance.md +0 -14
  416. package/.claude/rules/nccgs-rendering.md +0 -16
  417. package/.claude/rules/nccgs-security.md +0 -13
  418. package/.claude/rules/nccgs-tests.md +0 -18
  419. package/.claude/rules/nccgs-ui.md +0 -14
  420. package/.claude/rules/nccgs-unity-assets.md +0 -21
  421. package/.claude/rules/nccgs-unity-code.md +0 -22
  422. package/.claude/skills/accessibility-review/SKILL.md +0 -22
  423. package/.claude/skills/accessibility-review/references/astra.md +0 -17
  424. package/.claude/skills/accessibility-review/references/legacy.md +0 -7
  425. package/.claude/skills/architecture-decision/SKILL.md +0 -22
  426. package/.claude/skills/architecture-decision/references/astra.md +0 -12
  427. package/.claude/skills/architecture-decision/references/legacy.md +0 -7
  428. package/.claude/skills/asset-audit/SKILL.md +0 -22
  429. package/.claude/skills/asset-audit/references/astra.md +0 -17
  430. package/.claude/skills/asset-audit/references/legacy.md +0 -7
  431. package/.claude/skills/audit/SKILL.md +0 -22
  432. package/.claude/skills/audit/references/astra.md +0 -17
  433. package/.claude/skills/audit/references/dimensions.md +0 -46
  434. package/.claude/skills/audit/references/legacy.md +0 -9
  435. package/.claude/skills/balance-review/SKILL.md +0 -22
  436. package/.claude/skills/balance-review/references/astra.md +0 -17
  437. package/.claude/skills/balance-review/references/legacy.md +0 -7
  438. package/.claude/skills/bug-triage/SKILL.md +0 -22
  439. package/.claude/skills/bug-triage/references/astra.md +0 -27
  440. package/.claude/skills/bug-triage/references/legacy.md +0 -7
  441. package/.claude/skills/build-live-game/SKILL.md +0 -317
  442. package/.claude/skills/build-live-game/references/cloud-code.md +0 -563
  443. package/.claude/skills/closure/SKILL.md +0 -22
  444. package/.claude/skills/closure/references/astra.md +0 -15
  445. package/.claude/skills/closure/references/legacy.md +0 -7
  446. package/.claude/skills/compatibility-review/SKILL.md +0 -22
  447. package/.claude/skills/compatibility-review/references/astra.md +0 -17
  448. package/.claude/skills/compatibility-review/references/legacy.md +0 -7
  449. package/.claude/skills/context-pack/SKILL.md +0 -22
  450. package/.claude/skills/context-pack/references/astra.md +0 -12
  451. package/.claude/skills/context-pack/references/legacy.md +0 -7
  452. package/.claude/skills/dependency-review/SKILL.md +0 -22
  453. package/.claude/skills/dependency-review/references/astra.md +0 -17
  454. package/.claude/skills/dependency-review/references/legacy.md +0 -7
  455. package/.claude/skills/design/SKILL.md +0 -24
  456. package/.claude/skills/design/references/astra.md +0 -12
  457. package/.claude/skills/design/references/legacy.md +0 -13
  458. package/.claude/skills/design-review/SKILL.md +0 -24
  459. package/.claude/skills/design-review/references/astra.md +0 -17
  460. package/.claude/skills/design-review/references/legacy.md +0 -7
  461. package/.claude/skills/evidence-review/SKILL.md +0 -22
  462. package/.claude/skills/evidence-review/references/astra.md +0 -17
  463. package/.claude/skills/evidence-review/references/legacy.md +0 -7
  464. package/.claude/skills/hotfix/SKILL.md +0 -22
  465. package/.claude/skills/hotfix/references/astra.md +0 -30
  466. package/.claude/skills/hotfix/references/legacy.md +0 -7
  467. package/.claude/skills/incident-recovery/SKILL.md +0 -22
  468. package/.claude/skills/incident-recovery/references/astra.md +0 -27
  469. package/.claude/skills/incident-recovery/references/legacy.md +0 -7
  470. package/.claude/skills/levelplay-unity-integration/SKILL.md +0 -1126
  471. package/.claude/skills/localization/SKILL.md +0 -135
  472. package/.claude/skills/localization/resources/L10nBatchProcessor.cs +0 -69
  473. package/.claude/skills/localize-game/SKILL.md +0 -22
  474. package/.claude/skills/localize-game/references/astra.md +0 -27
  475. package/.claude/skills/localize-game/references/legacy.md +0 -7
  476. package/.claude/skills/migrate-project/SKILL.md +0 -22
  477. package/.claude/skills/migrate-project/references/astra.md +0 -30
  478. package/.claude/skills/migrate-project/references/legacy.md +0 -19
  479. package/.claude/skills/migrate-project/references/procedure.md +0 -96
  480. package/.claude/skills/milestone-review/SKILL.md +0 -22
  481. package/.claude/skills/milestone-review/references/astra.md +0 -12
  482. package/.claude/skills/milestone-review/references/legacy.md +0 -7
  483. package/.claude/skills/nccgs-code-review/SKILL.md +0 -22
  484. package/.claude/skills/nccgs-code-review/references/astra.md +0 -21
  485. package/.claude/skills/nccgs-code-review/references/legacy.md +0 -7
  486. package/.claude/skills/new-unity-project/SKILL.md +0 -179
  487. package/.claude/skills/performance-audit/SKILL.md +0 -22
  488. package/.claude/skills/performance-audit/references/astra.md +0 -17
  489. package/.claude/skills/performance-audit/references/legacy.md +0 -7
  490. package/.claude/skills/physics-3d-collision/references/troubleshooting.md +0 -41
  491. package/.claude/skills/plan-feature/SKILL.md +0 -22
  492. package/.claude/skills/plan-feature/references/astra.md +0 -12
  493. package/.claude/skills/plan-feature/references/legacy.md +0 -7
  494. package/.claude/skills/playtest/SKILL.md +0 -22
  495. package/.claude/skills/playtest/references/astra.md +0 -31
  496. package/.claude/skills/playtest/references/legacy.md +0 -7
  497. package/.claude/skills/project-stage/SKILL.md +0 -22
  498. package/.claude/skills/project-stage/references/astra.md +0 -12
  499. package/.claude/skills/project-stage/references/legacy.md +0 -7
  500. package/.claude/skills/prototype-feature/SKILL.md +0 -22
  501. package/.claude/skills/prototype-feature/references/astra.md +0 -31
  502. package/.claude/skills/prototype-feature/references/legacy.md +0 -7
  503. package/.claude/skills/qa-plan/SKILL.md +0 -22
  504. package/.claude/skills/qa-plan/references/astra.md +0 -12
  505. package/.claude/skills/qa-plan/references/legacy.md +0 -7
  506. package/.claude/skills/release/SKILL.md +0 -22
  507. package/.claude/skills/release/references/astra.md +0 -30
  508. package/.claude/skills/release/references/legacy.md +0 -11
  509. package/.claude/skills/release-readiness/SKILL.md +0 -22
  510. package/.claude/skills/release-readiness/references/astra.md +0 -17
  511. package/.claude/skills/release-readiness/references/legacy.md +0 -7
  512. package/.claude/skills/retrospective/SKILL.md +0 -22
  513. package/.claude/skills/retrospective/references/astra.md +0 -12
  514. package/.claude/skills/retrospective/references/legacy.md +0 -7
  515. package/.claude/skills/review/SKILL.md +0 -22
  516. package/.claude/skills/review/references/astra.md +0 -21
  517. package/.claude/skills/review/references/legacy.md +0 -9
  518. package/.claude/skills/security-audit/SKILL.md +0 -22
  519. package/.claude/skills/security-audit/references/astra.md +0 -17
  520. package/.claude/skills/security-audit/references/legacy.md +0 -7
  521. package/.claude/skills/sprint-plan/SKILL.md +0 -22
  522. package/.claude/skills/sprint-plan/references/astra.md +0 -12
  523. package/.claude/skills/sprint-plan/references/legacy.md +0 -7
  524. package/.claude/skills/status/SKILL.md +0 -22
  525. package/.claude/skills/status/references/astra.md +0 -19
  526. package/.claude/skills/status/references/legacy.md +0 -9
  527. package/.claude/skills/story-readiness/SKILL.md +0 -24
  528. package/.claude/skills/story-readiness/references/astra.md +0 -17
  529. package/.claude/skills/story-readiness/references/legacy.md +0 -7
  530. package/.claude/skills/test/SKILL.md +0 -22
  531. package/.claude/skills/test/references/astra.md +0 -27
  532. package/.claude/skills/test/references/legacy.md +0 -9
  533. package/.claude/skills/ui-review/SKILL.md +0 -22
  534. package/.claude/skills/ui-review/references/astra.md +0 -17
  535. package/.claude/skills/ui-review/references/legacy.md +0 -7
  536. package/.claude/skills/unity-cli/CHANGELOG.md +0 -233
  537. package/.claude/skills/unity-cli/SECURITY.md +0 -22
  538. package/.claude/skills/unity-cli/SKILL.md +0 -414
  539. package/.claude/skills/unity-cli/references/auth-license-cloud.md +0 -146
  540. package/.claude/skills/unity-cli/references/build-run-test.md +0 -349
  541. package/.claude/skills/unity-cli/references/config-hub.md +0 -103
  542. package/.claude/skills/unity-cli/references/diagnostics-maintenance.md +0 -326
  543. package/.claude/skills/unity-cli/references/editors-install.md +0 -327
  544. package/.claude/skills/unity-cli/references/integration-advanced.md +0 -472
  545. package/.claude/skills/unity-cli/references/projects-templates.md +0 -574
  546. package/.claude/skills/work/SKILL.md +0 -22
  547. package/.claude/skills/work/references/astra.md +0 -32
  548. package/.claude/skills/work/references/classification.md +0 -41
  549. package/.claude/skills/work/references/closure.md +0 -60
  550. package/.claude/skills/work/references/feature-contracts.md +0 -36
  551. package/.claude/skills/work/references/legacy.md +0 -29
  552. package/.claude/skills/work/references/verification.md +0 -26
  553. package/CLAUDE.md +0 -10
  554. package/MEMORY.md +0 -109
  555. package/UPGRADING.md +0 -130
  556. package/VERSION +0 -1
  557. package/docs/ARCHITECTURE.md +0 -131
  558. package/docs/ASSET-PRODUCTION-GRAPHIFY-PLAN.md +0 -230
  559. package/docs/BOUNDED-REPAIR.md +0 -80
  560. package/docs/EDITOR-SESSION-EVIDENCE.md +0 -52
  561. package/docs/HANDOFF-AUTOMATION.md +0 -144
  562. package/docs/HUONG-DAN-MIGRATE-VA-SU-DUNG.md +0 -117
  563. package/docs/MIGRATION-MATRIX.md +0 -23
  564. package/docs/NCCGS-1.3.md +0 -13
  565. package/docs/NCCGS-1.4.1.md +0 -149
  566. package/docs/NCCGS-1.4.md +0 -184
  567. package/docs/NCCGS-1.5-IMPLEMENTATION-PLAN.md +0 -378
  568. package/docs/NCCGS-1.5-PILOT.md +0 -130
  569. package/docs/NCCGS-1.5.md +0 -237
  570. package/docs/PHASE-1-OPERATIONS.md +0 -278
  571. package/docs/PHASE-2-OPERATIONS.md +0 -183
  572. package/docs/PROJECT-POLICY.md +0 -94
  573. package/docs/RELEASE-STATUS.md +0 -150
  574. package/docs/TASK-SLICING.md +0 -57
  575. package/docs/UNINSTALL.md +0 -134
  576. package/docs/UPGRADE-QUALIFICATION.md +0 -45
  577. package/docs/WFK17-HOOK-REPAIR.md +0 -71
  578. package/docs/WORKFLOWS.md +0 -85
  579. package/package-assets/nccgs-project.gitignore +0 -2
  580. package/package-assets/setup-vivox-voice-chat-evals.gitignore +0 -7
  581. package/scaffold/.nccgs/autonomy.json +0 -4
  582. package/scaffold/.nccgs/bugs/.gitkeep +0 -1
  583. package/scaffold/.nccgs/closures/.gitkeep +0 -1
  584. package/scaffold/.nccgs/context/.gitkeep +0 -1
  585. package/scaffold/.nccgs/decisions/.gitkeep +0 -1
  586. package/scaffold/.nccgs/evidence/.gitkeep +0 -1
  587. package/scaffold/.nccgs/execution.json +0 -10
  588. package/scaffold/.nccgs/features/.gitkeep +0 -1
  589. package/scaffold/.nccgs/gates.json +0 -7
  590. package/scaffold/.nccgs/inputs.json +0 -6
  591. package/scaffold/.nccgs/migrations/.gitkeep +0 -1
  592. package/scaffold/.nccgs/playtests/.gitkeep +0 -1
  593. package/scaffold/.nccgs/project.yaml +0 -109
  594. package/scaffold/.nccgs/requirements.yaml +0 -10
  595. package/scaffold/.nccgs/reviews/.gitkeep +0 -1
  596. package/scaffold/.nccgs/state.md +0 -40
  597. package/scaffold/.nccgs/templates/agent-handoff.md +0 -37
  598. package/scaffold/.nccgs/templates/architecture-decision.md +0 -27
  599. package/scaffold/.nccgs/templates/closure-record.md +0 -62
  600. package/scaffold/.nccgs/templates/context-packet.yaml +0 -17
  601. package/scaffold/.nccgs/templates/design-contract.json +0 -34
  602. package/scaffold/.nccgs/templates/evidence-record.md +0 -23
  603. package/scaffold/.nccgs/templates/feature-contract.md +0 -60
  604. package/scaffold/.nccgs/templates/implementation-report.md +0 -52
  605. package/scaffold/.nccgs/templates/migration-plan.md +0 -40
  606. package/scaffold/.nccgs/templates/repair-packet.json +0 -14
  607. package/scaffold/.nccgs/templates/repair-unity-code.json +0 -18
  608. package/scaffold/.nccgs/templates/repair-unity-editor.json +0 -21
  609. package/scaffold/.nccgs/templates/task-slices.json +0 -28
  610. package/scaffold/.nccgs/templates/waiver.md +0 -11
  611. package/scripts/benchmark-snapshot.mjs +0 -205
  612. package/scripts/benchmark-v15.mjs +0 -173
  613. package/scripts/cli.mjs +0 -205
  614. package/scripts/doctor.mjs +0 -261
  615. package/scripts/install.mjs +0 -530
  616. package/scripts/recover-session.mjs +0 -89
  617. package/scripts/run.mjs +0 -86
  618. package/scripts/supervise.mjs +0 -152
  619. package/scripts/uninstall.mjs +0 -292
  620. package/scripts/validate.mjs +0 -285
  621. package/scripts/work-handoff.mjs +0 -38
  622. package/tests/autonomy.test.mjs +0 -126
  623. package/tests/benchmark-v15.test.mjs +0 -65
  624. package/tests/design-readiness.test.mjs +0 -200
  625. package/tests/editor-session-evidence.test.mjs +0 -45
  626. package/tests/evidence.test.mjs +0 -186
  627. package/tests/fixtures/compiler-shutdown.cs +0 -67
  628. package/tests/fixtures/native-provider.mjs +0 -61
  629. package/tests/framework.test.mjs +0 -740
  630. package/tests/gates.test.mjs +0 -479
  631. package/tests/hook-repair.test.mjs +0 -106
  632. package/tests/lifecycle-v15.test.mjs +0 -346
  633. package/tests/native-completion-notices.test.mjs +0 -181
  634. package/tests/orchestration-v15.test.mjs +0 -596
  635. package/tests/phase1.test.mjs +0 -427
  636. package/tests/phase2.test.mjs +0 -250
  637. package/tests/policy-v15.test.mjs +0 -234
  638. package/tests/ponytail-package.test.mjs +0 -75
  639. package/tests/returned-handoff-notices.test.mjs +0 -170
  640. package/tests/review-budget.test.mjs +0 -177
  641. package/tests/runtime-v15.test.mjs +0 -1198
  642. package/tests/session-budget.test.mjs +0 -34
  643. package/tests/task-slices.test.mjs +0 -285
  644. package/tests/uninstall.test.mjs +0 -477
  645. package/tests/unity-generated.test.mjs +0 -140
  646. package/tests/unity-transport.test.mjs +0 -348
  647. /package/{.claude/nccgs/packages → template}/ponytail/LICENSE +0 -0
  648. /package/{.claude/nccgs/packages → template}/ponytail/NOTICE.md +0 -0
  649. /package/{.claude/nccgs/packages → template}/ponytail/complexity-review.md +0 -0
  650. /package/{.claude/skills → unity-skills}/build-live-game/references/remote-config.md +0 -0
  651. /package/{.claude/skills → unity-skills}/implement-in-app-purchases/README.md +0 -0
  652. /package/{.claude/skills → unity-skills}/implement-in-app-purchases/references/codeless-catalog.md +0 -0
  653. /package/{.claude/skills → unity-skills}/implement-in-app-purchases/references/convert-adapty.md +0 -0
  654. /package/{.claude/skills → unity-skills}/implement-in-app-purchases/references/convert-essentialkit.md +0 -0
  655. /package/{.claude/skills → unity-skills}/implement-in-app-purchases/references/convert-revenuecat.md +0 -0
  656. /package/{.claude/skills → unity-skills}/implement-in-app-purchases/references/convert-unipay.md +0 -0
  657. /package/{.claude/skills → unity-skills}/implement-in-app-purchases/references/migration-v4-to-v5.md +0 -0
  658. /package/{.claude/skills → unity-skills}/implement-in-app-purchases/references/path-add-iap-to-new-project.md +0 -0
  659. /package/{.claude/skills → unity-skills}/implement-in-app-purchases/references/path-convert-native-storekit.md +0 -0
  660. /package/{.claude/skills → unity-skills}/implement-in-app-purchases/references/platform-notes.md +0 -0
  661. /package/{.claude/skills → unity-skills}/implement-in-app-purchases/references/pre-check.md +0 -0
  662. /package/{.claude/skills → unity-skills}/localization/resources/LocalizedFontAsset.cs +0 -0
  663. /package/{.claude/skills → unity-skills}/optimize-audio/resources/platform-settings.md +0 -0
  664. /package/{.claude/skills → unity-skills}/optimize-web/resources/WebOptimizer.cs +0 -0
  665. /package/{.claude/skills → unity-skills}/optimize-web/resources/toktx-examples.sh +0 -0
  666. /package/{.claude/skills → unity-skills}/physics-3d-collision/resources/CollisionDebugger.cs +0 -0
  667. /package/{.claude/skills → unity-skills}/setup-multiplayer-services/references/dgs-entrypoint.md +0 -0
  668. /package/{.claude/skills → unity-skills}/setup-multiplayer-services/references/entrypoints.md +0 -0
  669. /package/{.claude/skills → unity-skills}/setup-multiplayer-services/references/examples.md +0 -0
  670. /package/{.claude/skills → unity-skills}/setup-multiplayer-services/references/implementation-fit.md +0 -0
  671. /package/{.claude/skills → unity-skills}/setup-multiplayer-services/references/underlying-services.md +0 -0
  672. /package/{.claude/skills → unity-skills}/setup-multiplayer-services/references/workflows-prerequisites.md +0 -0
  673. /package/{.claude/skills → unity-skills}/setup-vivox-voice-chat/evals/.env.example +0 -0
  674. /package/{.claude/skills → unity-skills}/setup-vivox-voice-chat/evals/README.md +0 -0
  675. /package/{.claude/skills → unity-skills}/setup-vivox-voice-chat/evals/promptfooconfig.yaml +0 -0
  676. /package/{.claude/skills → unity-skills}/setup-vivox-voice-chat/evals/tests/init-and-login.yaml +0 -0
  677. /package/{.claude/skills → unity-skills}/setup-vivox-voice-chat/evals/tests/text-chat.yaml +0 -0
  678. /package/{.claude/skills → unity-skills}/setup-vivox-voice-chat/evals/tests/voice-channels.yaml +0 -0
  679. /package/{.claude/skills → unity-skills}/setup-vivox-voice-chat/references/events-and-participants.md +0 -0
  680. /package/{.claude/skills → unity-skills}/setup-vivox-voice-chat/references/init-and-login.md +0 -0
  681. /package/{.claude/skills → unity-skills}/setup-vivox-voice-chat/references/text-chat.md +0 -0
  682. /package/{.claude/skills → unity-skills}/setup-vivox-voice-chat/references/troubleshooting.md +0 -0
  683. /package/{.claude/skills → unity-skills}/setup-vivox-voice-chat/references/voice-channels.md +0 -0
  684. /package/{.claude/skills → unity-skills}/shader-graph-create-custom-node/resources/all_hints.hlsl +0 -0
  685. /package/{.claude/skills → unity-skills}/sprite-editor/references/api_reference.md +0 -0
  686. /package/{.claude/skills → unity-skills}/sprite-editor/references/background.md +0 -0
  687. /package/{.claude/skills → unity-skills}/sprite-editor/scripts/AutomaticSliceTexture.cs +0 -0
  688. /package/{.claude/skills → unity-skills}/sprite-editor/scripts/GenerateNewSpriteRects.cs +0 -0
  689. /package/{.claude/skills → unity-skills}/sprite-editor/scripts/GetTextureSourceImageSize.cs +0 -0
  690. /package/{.claude/skills → unity-skills}/sprite-editor/scripts/GetTextureToSlice.cs +0 -0
  691. /package/{.claude/skills → unity-skills}/sprite-editor/scripts/GridSliceTexture.cs +0 -0
  692. /package/{.claude/skills → unity-skills}/sprite-editor/scripts/IsometricSliceTexture.cs +0 -0
  693. /package/{.claude/skills → unity-skills}/sprite-editor/scripts/README.md +0 -0
  694. /package/{.claude/skills → unity-skills}/sprite-editor/scripts/SetPivotExample.cs +0 -0
  695. /package/{.claude/skills → unity-skills}/sprite-editor/scripts/SpriteToPng.cs +0 -0
  696. /package/{.claude/skills → unity-skills}/ui-imgui/references/gui-elements.md +0 -0
  697. /package/{.claude/skills → unity-skills}/ui-imgui/references/templates.md +0 -0
  698. /package/{.claude/skills → unity-skills}/ui-ugui/references/scrollview-setup.md +0 -0
  699. /package/{.claude/skills → unity-skills}/ui-uitk/references/common-issues.md +0 -0
  700. /package/{.claude/skills → unity-skills}/ui-uitk/references/painter2d.md +0 -0
  701. /package/{.claude/skills → unity-skills}/ui-uitk/references/pointermanipulator-guide.md +0 -0
  702. /package/{.claude/skills → unity-skills}/ui-uitk/references/svg-icons.md +0 -0
  703. /package/{.claude/skills → unity-skills}/ui-uitk/references/ui-runtime-binding.md +0 -0
  704. /package/{.claude/skills → unity-skills}/ui-uitk/references/uss-guide.md +0 -0
  705. /package/{.claude/skills → unity-skills}/urp-postprocessing/references/effect-reference.md +0 -0
@@ -1,120 +0,0 @@
1
- import { commandTokens } from "./command-tokens.mjs";
2
- import { safeSharedContextCommand } from "./shared-context-guard.mjs";
3
- import { assertUnityCliOnlyInput } from "./unity-transport.mjs";
4
- import path from "node:path";
5
- import { contained, json, resolveExecution } from "./policy.mjs";
6
- import { taskPath, check } from "./gates.mjs";
7
- import { boundTask } from "./runtime.mjs";
8
- import { claim, findDispatch, rejectUnclaimed, admitRepairTool, dispatchPrompt, pinnedRepairEvidence } from "./orchestration.mjs";
9
- import { requireDesignReady } from "./design-readiness.mjs";
10
- import { inFinalReviewPhase } from "./review-budget.mjs";
11
-
12
- const need = (condition, message) => { if (!condition) throw new Error(message); };
13
- const reads = new Set(["Read", "Glob", "Grep", "WebSearch", "WebFetch", "AskUserQuestion"]);
14
- const governance = new Set(["init", "bind", "inspect", "check", "snapshot", "ref", "record", "report", "reclassify", "refresh-inputs", "reserve", "dispatch-status", "dispatch-prompt", "checkpoint", "resume", "telemetry", "export-external", "close", "job-status", "job-wait", "acceptance-status", "design-validate", "design-compare", "handoff-validate", "record-review", "slice-preview", "slice-plan", "slice-status", "budget-status"]);
15
- export function parseTaskCommand(command, project = process.cwd()) {
16
- const tokens = commandTokens(command);
17
- if (!tokens) return null;
18
- const script = tokens[1]?.replaceAll("\\", "/");
19
- if (tokens[0] !== "node" || !script || path.resolve(project, script) !== path.resolve(project, ".claude/nccgs/tools/task.mjs")) return null;
20
- const separator = tokens.indexOf("--");
21
- const options = separator < 0 ? tokens : tokens.slice(0, separator);
22
- const projectOptions = options.flatMap((t, i) => t === "--project" ? [i] : []);
23
- if (projectOptions.length > 1 || options.some(t => t.startsWith("--project="))) return null;
24
- if (projectOptions.length && (!options[projectOptions[0] + 1] || path.resolve(project, options[projectOptions[0] + 1]) !== path.resolve(project))) return null;
25
- return { command: tokens[2], options, forwarded: separator < 0 ? null : tokens.slice(separator + 1) };
26
- }
27
- export function safeTaskCommand(command, project = process.cwd()) {
28
- const parsed = parseTaskCommand(command, project);
29
- return parsed && governance.has(parsed.command) && !parsed.forwarded ? parsed.command : null;
30
- }
31
- export function safeVerifyCommand(command, project = process.cwd()) {
32
- const parsed = parseTaskCommand(command, project);
33
- return Boolean(parsed?.command === "verify" && parsed.forwarded?.length && parsed.options.includes("--id") && parsed.options.includes("--name"));
34
- }
35
- export function recoveryTool(input, project = process.cwd()) {
36
- return !input.agent_id && ["Bash", "PowerShell"].includes(input.tool_name) && ["report", "inspect"].includes(safeTaskCommand(input.tool_input?.command ?? "", project));
37
- }
38
- function ownHandoffValidation(command, project, task, dispatch) {
39
- const parsed = parseTaskCommand(command, project);
40
- if (!parsed || parsed.command !== "handoff-validate" || parsed.forwarded || dispatch?.status !== "running") return false;
41
- const values = new Map(), args = parsed.options.slice(3);
42
- for (let i = 0; i < args.length; i += 2) {
43
- if (!["--id", "--dispatch", "--file", "--project"].includes(args[i]) || values.has(args[i]) || !args[i + 1] || args[i + 1].startsWith("--")) return false;
44
- values.set(args[i], args[i + 1]);
45
- }
46
- return values.get("--id") === task?.id && values.get("--dispatch") === dispatch.id && dispatch.handoffPaths?.includes(values.get("--file"));
47
- }
48
- export function guardTool(project, input) {
49
- assertUnityCliOnlyInput(input);
50
- if (recoveryTool(input, project)) return;
51
- if (resolveExecution(project).name !== "standalone") return;
52
- const tool = input.tool_input ?? {}, name = input.tool_name;
53
- let dispatch = findDispatch(project, input);
54
- const id = dispatch?.taskId ?? boundTask(project, input.session_id);
55
- const task = id ? json(taskPath(project, id)) : null;
56
- if (task && task.schemaVersion !== 2) throw new Error("Legacy tasks keep compatibility gates; create a fresh standalone task after migration");
57
- if (input.agent_id) need(dispatch, "Worker tool has no correlated dispatch; cannot bypass its scope or budget");
58
- if (input.agent_id && dispatch?.workPacket) { requireDesignReady(project, task); return admitRepairTool(project, dispatch.id, input); }
59
- if (reads.has(name)) return;
60
- if (["Agent", "Task"].includes(name)) {
61
- need(!input.agent_id, "NCCGS workers cannot recursively delegate");
62
- need(dispatch && /^\[NCCGS-DISPATCH:[\w-]+\]/.test(tool.prompt ?? ""), "Reserve this Agent call first and prefix its prompt with [NCCGS-DISPATCH:ID]");
63
- need(task && dispatch.taskId === task.id, "Dispatch task missing");
64
- try {
65
- need(tool.run_in_background !== true, "Managed workers must use foreground Agent calls; use task verify --background for durable engine jobs");
66
- if (dispatch.kind === "review") {
67
- const readiness = check(project, task, "review");
68
- need(readiness.allowed, readiness.message);
69
- }
70
- const prompt = dispatch.workPacket || dispatch.slice ? dispatchPrompt(project, task.id, dispatch.id).prompt : null;
71
- claim(project, dispatch.id, { sessionId: input.session_id, toolUseId: input.tool_use_id, agent: tool.subagent_type });
72
- if (prompt) return { updatedInput: { ...tool, prompt } };
73
- } catch (error) {
74
- if (input.hook_event_name === "PreToolUse" && dispatch.status === "reserved" && tool.subagent_type === dispatch.agent) {
75
- try { rejectUnclaimed(project, dispatch.id, { sessionId: input.session_id, toolUseId: input.tool_use_id, agent: tool.subagent_type, reason: error.message }); }
76
- catch { /* A concurrent claim or uncertain state must stay fail-closed. */ }
77
- }
78
- throw error;
79
- }
80
- return;
81
- }
82
- const readOnly = task?.mode !== "implement" || (dispatch && dispatch.kind !== "implementation");
83
- if (["Write", "Edit", "MultiEdit", "NotebookEdit"].includes(name)) {
84
- const absolute = path.resolve(project, tool.file_path || tool.path || tool.notebook_path || ".");
85
- const relative = path.relative(project, absolute).split(path.sep).join("/");
86
- contained(project, relative);
87
- need(!/^\.(?:claude|nccgs)(?:\/|$)/i.test(relative) || relative.startsWith(".nccgs/evidence/"), "Framework/governance records must be changed through the task CLI or external configuration");
88
- if (relative.startsWith(".nccgs/evidence/")) {
89
- need(!(dispatch?.handoffTransport === "native-result" && dispatch.handoffPaths?.includes(relative)), "Native-result handoff is captured only from the correlated final response; return text without writing this path");
90
- need(!pinnedRepairEvidence(project, relative), "Reserved repair packet/context evidence is immutable; preserve it and create a fresh packet for a new eligible attempt");
91
- need(!/^\.nccgs\/evidence\/(?:(?:runtime|criteria|design-checks|checkpoints|repair-operations|slices|external\/requests)\/|check-)/i.test(relative), "Captured runtime/checkpoint/verification/external request evidence is immutable and never authored by Claude");
92
- if (input.agent_id && readOnly) need(task?.contract.analysisArtifacts?.includes(relative), "Read-only worker may write only declared analysis artifacts");
93
- return;
94
- }
95
- need(task && !readOnly, "Audit/plan tasks cannot edit source; declare analysis artifacts under .nccgs/evidence/analysis/");
96
- requireDesignReady(project, task);
97
- need(dispatch && dispatch.status === "running" && dispatch.agentId === input.agent_id, "Source writes require a running, correlated implementation dispatch");
98
- const lower = relative.toLowerCase();
99
- if (dispatch.slice) need(dispatch.writePaths.some(p => lower === p.toLowerCase()), "Slice writes require an exact planned file; directory ownership is not granted");
100
- need(dispatch.writePaths.some(p => lower === p.toLowerCase() || lower.startsWith(p.toLowerCase() + "/")), "Write is outside this dispatch's owned paths");
101
- return;
102
- }
103
- if (["Bash", "PowerShell"].includes(name)) {
104
- const command = tool.command ?? "";
105
- if (input.agent_id && ownHandoffValidation(command, project, task, dispatch)) return;
106
- need(!/\b(?:dispatch-reconcile|extend-dispatch|extend-review|import-external|migrate-execution|migrate-framework|budget-plan)\b|--stage\s+["']?(?:acceptance|astra)\b/i.test(command), "External decisions cannot be made by the Claude executor");
107
- if (safeTaskCommand(command, project)) { need(!input.agent_id, "Coordinator owns lifecycle commands"); return; }
108
- if (!input.agent_id && safeSharedContextCommand(command, project)) return;
109
- need(task && !readOnly, "Audit/plan/review shell execution is blocked; use read tools or externally supplied verification evidence");
110
- requireDesignReady(project, task);
111
- // Coordinator may run declared checks after workers finish. This command
112
- // can execute a verifier, so it is allowed only for implementation tasks.
113
- if (!input.agent_id && safeVerifyCommand(command, project)) { need(!inFinalReviewPhase(project, input.session_id), "Final-review reserve cannot run new verification jobs; use existing receipts"); return; }
114
- need(dispatch?.kind === "implementation" && dispatch.status === "running" && input.agent_id === dispatch.agentId, "Shell mutation requires a correlated implementation worker");
115
- return;
116
- }
117
- if (task) requireDesignReady(project, task);
118
- need(task && !readOnly && dispatch?.kind === "implementation" && dispatch.status === "running" && input.agent_id === dispatch.agentId,
119
- "Tool is not in the read-only allowlist; a correlated implementation dispatch is required");
120
- }
@@ -1,128 +0,0 @@
1
- import fs from "node:fs";
2
- import path from "node:path";
3
- import crypto from "node:crypto";
4
- import { artifact, atomicJson, contained, json, verifyArtifact } from "./policy.mjs";
5
- import { snapshot } from "./gates.mjs";
6
-
7
- const need = (ok, message) => { if (!ok) throw new Error(`Unity repair: ${message}`); };
8
- const keys = (value, allowed) => value && typeof value === "object" && !Array.isArray(value) && Object.keys(value).every(k => allowed.includes(k));
9
- const code = /\.(?:cs|asmdef|asmref|shader|hlsl|cginc|compute|uxml|uss)$/i;
10
- const asset = /\.(?:unity|prefab|asset|mat|controller|overrideController|anim)$/i;
11
- export const unityCodePath = relative => relative.startsWith("Assets/") && code.test(relative);
12
- export const unitySceneSafety = "loaded-scenes-clean-v1";
13
- export const unityRepairProfiles = Object.freeze({
14
- "unity-code": Object.freeze({ files: 8, workCalls: 24, readCalls: 12, handoffCalls: 3, durationMs: 900000 }),
15
- "unity-editor": Object.freeze({ files: 8, workCalls: 20, readCalls: 8, handoffCalls: 3, durationMs: 900000 })
16
- });
17
-
18
- function guid(project, relative) {
19
- const value = fs.readFileSync(contained(project, relative), "utf8").match(/^guid: ([a-f0-9]{32})\r?$/m)?.[1];
20
- need(value, `missing or invalid Unity GUID in ${relative}`);
21
- return value;
22
- }
23
-
24
- // The packet pins a chosen operation, not a general shell/MCP capability. The
25
- // installed Unity CLI binds every call to this project's absolute path.
26
- export function validateUnityRepair(project, packet) {
27
- const profile = unityRepairProfiles[packet.repairType];
28
- need(profile, "repairType must be unity-code or unity-editor");
29
- need(fs.existsSync(contained(project, "ProjectSettings/ProjectVersion.txt")), "requires an existing Unity project");
30
- need(packet.changes.length <= profile.files, `at most ${profile.files} exact files per packet`);
31
- for (const change of packet.changes) {
32
- need(keys(change, ["path", "operation", "instruction"]) && ["edit", "create"].includes(change.operation), "each change needs edit or create operation");
33
- need(unityCodePath(change.path) || (packet.repairType === "unity-editor" && change.path.startsWith("Assets/") && asset.test(change.path)), "file type must match the repair profile under Assets/; no raw metadata, packages or project settings");
34
- const file = contained(project, change.path);
35
- need(fs.statSync(path.dirname(file)).isDirectory(), "create files only in existing folders; folder creation needs a separate scoped change");
36
- if (change.operation === "edit") {
37
- need(fs.existsSync(file) && fs.statSync(file).isFile(), "edit requires an existing file");
38
- guid(project, `${change.path}.meta`);
39
- } else need(!fs.existsSync(file) && !fs.existsSync(contained(project, `${change.path}.meta`)), "create target or companion metadata already exists");
40
- }
41
- need(keys(packet.unity, ["capabilities", "steps"]) && Array.isArray(packet.unity.steps) && packet.unity.steps.length <= 4, "unity requires capabilities and at most four fixed steps");
42
- if (packet.unity.steps.length || packet.unity.capabilities !== undefined) {
43
- need(packet.unity.capabilities?.path?.startsWith(".nccgs/evidence/") && !packet.unity.capabilities.path.startsWith(".nccgs/evidence/work-packets/"), "pin Unity command discovery evidence");
44
- verifyArtifact(project, packet.unity.capabilities);
45
- }
46
- need((packet.repairType === "unity-code" && packet.changes.every(c => c.operation === "edit")) || packet.unity.steps.length > 0, "asset repairs and new code require an Editor/import step before completion");
47
- const ids = new Set();
48
- for (const step of packet.unity.steps) {
49
- need(keys(step, ["id", "command", "arguments", "timeoutMs"]) && /^[a-zA-Z][\w-]{0,39}$/.test(step.id ?? "") && !ids.has(step.id), "steps need unique bounded IDs");
50
- ids.add(step.id);
51
- need(/^[a-zA-Z][\w-]{0,79}$/.test(step.command ?? "") && Array.isArray(step.arguments) && step.arguments.length <= 8 &&
52
- step.arguments.every(a => typeof a === "string" && a.length <= 8000 && !a.startsWith("-") && !a.includes("\0")), "use a discovered command and positional arguments only; routing/global flags are generated");
53
- need(Number.isSafeInteger(step.timeoutMs) && step.timeoutMs >= 1000 && step.timeoutMs <= 60000, "step timeoutMs must be 1000-60000; long verification belongs to managed jobs");
54
- need(step.command === "eval" && step.arguments.length === 1, "new Editor steps require eval with one C# statement body so the dirty-scene check runs atomically before the operation");
55
- need(!/^\s*(?:global\s+)?using\s+(?:static\s+)?[\w.]+\s*(?:=|;)/m.test(step.arguments[0]), "eval bodies must use fully qualified types; top-level using directives cannot follow the scene guard");
56
- }
57
- const { files, ...limits } = profile;
58
- return limits;
59
- }
60
-
61
- export function captureUnityRepairScope(project, dispatch, source) {
62
- if (dispatch.workPacket?.schemaVersion !== 2) return;
63
- const metaGuids = Object.fromEntries(dispatch.workPacket.changes.map(c => [c.path, c.operation === "edit" ? guid(project, `${c.path}.meta`) : null]));
64
- const relative = `.nccgs/evidence/work-packets/${dispatch.id}-scope.json`;
65
- atomicJson(contained(project, relative), { schemaVersion: 1, taskId: dispatch.taskId, dispatchId: dispatch.id,
66
- sourceSnapshot: source.sha256, fileEntries: source.fileEntries, metaGuids });
67
- dispatch.workPacket.scope = artifact(project, relative);
68
- }
69
-
70
- export function verifyUnityRepairScope(project, dispatch, complete = false) {
71
- if (dispatch.workPacket?.schemaVersion !== 2) return;
72
- const p = dispatch.workPacket, baseline = json(verifyArtifact(project, p.scope));
73
- need(baseline.dispatchId === dispatch.id && baseline.taskId === dispatch.taskId && baseline.sourceSnapshot === dispatch.snapshot, "scope baseline identity changed");
74
- const before = new Map(baseline.fileEntries), after = new Map(snapshot(project, null, { includeFiles: true }).fileEntries);
75
- const owned = new Set(p.changes.flatMap(c => [c.path, `${c.path}.meta`]));
76
- for (const [file, hash] of before) {
77
- need(after.has(file), `source file removed: ${file}; deletions/renames are outside this packet`);
78
- need(after.get(file) === hash || owned.has(file), `source changed outside exact ownership: ${file}`);
79
- }
80
- for (const file of after.keys()) need(before.has(file) || owned.has(file), `source created outside exact ownership: ${file}`);
81
- for (const c of p.changes) {
82
- const meta = `${c.path}.meta`, present = after.has(meta);
83
- if (present) {
84
- const current = guid(project, meta);
85
- need(!baseline.metaGuids[c.path] || current === baseline.metaGuids[c.path], `existing GUID changed: ${meta}`);
86
- }
87
- if (complete) need(after.has(c.path) && present, `output or imported metadata missing: ${c.path}; finish import before native completion`);
88
- }
89
- }
90
-
91
- export function repairEditorCommand(dispatch, step) {
92
- return `node .claude/nccgs/tools/task.mjs repair-editor --id ${dispatch.taskId} --dispatch ${dispatch.id} --step ${step.id}`;
93
- }
94
-
95
- export function unityEditorToolScope(dispatch, input) {
96
- if (dispatch.workPacket?.schemaVersion !== 2 || input.tool_name !== "Bash") return null;
97
- const tool = input.tool_input ?? {}, step = dispatch.workPacket.unity.steps.find(s => repairEditorCommand(dispatch, s) === tool.command);
98
- need(step && keys(tool, ["command", "timeout", "description", "run_in_background"]) && tool.run_in_background !== true &&
99
- Number.isSafeInteger(tool.timeout) && tool.timeout >= step.timeoutMs + 5000 && tool.timeout <= 120000,
100
- "only the fixed repair-editor command is permitted, foreground, with timeout at least step timeoutMs + 5000");
101
- return { bucket: "work", read: false, editorStep: step.id };
102
- }
103
-
104
- export function unityEditorInvocation(project, step, safety = null) {
105
- need(safety === null || safety === unitySceneSafety, "unknown pinned scene safety policy");
106
- let sceneGuard = null, args = step.arguments;
107
- if (safety) {
108
- need(step.command === "eval" && args.length === 1, "guarded Editor step requires one eval body");
109
- sceneGuard = { policy: safety, token: crypto.randomUUID() };
110
- // Same Editor eval, before any packet statement: includes untitled/additive
111
- // loaded scenes. Never auto-save, discard or switch a dirty scene.
112
- const prefix = `{ for (int nccgsSceneIndex = 0; nccgsSceneIndex < UnityEngine.SceneManagement.SceneManager.sceneCount; nccgsSceneIndex++) { var nccgsScene = UnityEngine.SceneManagement.SceneManager.GetSceneAt(nccgsSceneIndex); if (nccgsScene.isDirty) return new { nccgsSceneGuard = "${safety}", token = "${sceneGuard.token}", blockedScene = string.IsNullOrEmpty(nccgsScene.path) ? "<untitled>" : nccgsScene.path }; } }\n`;
113
- args = [prefix + args[0]];
114
- }
115
- return { ...(sceneGuard ? { sceneGuard } : {}), executable: process.platform === "win32" ? "unity.exe" : "unity", arguments: ["command", step.command, ...args,
116
- "--caller", "plugin", "--skill", "unity-cli",
117
- "--project-path", fs.realpathSync(project), "--timeout", String(Math.ceil(step.timeoutMs / 1000)), "--format", "json", "--no-pager", "--non-interactive"] };
118
- }
119
-
120
- export function blockedUnityScene(invocation, result) {
121
- if (!invocation.sceneGuard || result.status !== 0 || result.error || result.signal) return null;
122
- try {
123
- const response = JSON.parse(result.stdout), envelope = response.data?.result, value = envelope?.result;
124
- if (response.success === true && envelope.success === true && value?.nccgsSceneGuard === invocation.sceneGuard.policy &&
125
- value.token === invocation.sceneGuard.token && typeof value.blockedScene === "string") return value.blockedScene;
126
- } catch { /* Unknown output retains existing conservative execution handling. */ }
127
- return null;
128
- }
@@ -1,170 +0,0 @@
1
- import fs from "node:fs";
2
- import path from "node:path";
3
- import { conflictingLaunchOption } from "./autonomy.mjs";
4
-
5
- const object = value => value !== null && typeof value === "object" && !Array.isArray(value);
6
- const unityIdentity = /(?:^|[^a-z0-9])(?:unity(?:mcp)?|mcpforunity(?:server)?|coplay(?:dev)?|anklebreaker)(?=$|[^a-z0-9])/i;
7
- const unityName = value => unityIdentity.test(value)
8
- || unityIdentity.test(String(value).replace(/([a-z0-9])([A-Z])/g, "$1 $2"));
9
- const unityProvider = value => /mcpforunity|mcp-for-unity|unity[-_]mcp|coplay(?:dev|\.dev)|com\.anklebreaker/i.test(value);
10
- const fail = message => { throw new Error(`Unity CLI-only: ${message}`); };
11
- // The only argv allowed before strict isolation: the framework-owned permission
12
- // pair produced by autonomy.mjs permissionModeArgs. No other prefix is accepted.
13
- const ownedPrefix = prefix => Array.isArray(prefix) && prefix.length === 2 && prefix[0] === "--permission-mode"
14
- && ["default", "bypassPermissions"].includes(prefix[1]);
15
-
16
- // Default sessions do not discover MCP servers from user settings or plugins.
17
- // An external caller may explicitly supply a non-Unity MCP configuration. Keep
18
- // file arguments as paths: never copy their possible credentials into run state.
19
- // `prefix` is the fixed framework-owned launch prefix (permission mode). Strict
20
- // isolation follows it directly, before every caller-controlled argument, so a
21
- // forwarded option missing its value can never consume the isolation flag.
22
- export function unityCliMcpArgs(args, project, prefix) {
23
- if (!ownedPrefix(prefix)) fail("launch requires the fixed NCCGS --permission-mode default|bypassPermissions prefix");
24
- let config = null, strict = false;
25
- const remaining = [];
26
- for (let i = 0; i < args.length; i++) {
27
- const arg = args[i];
28
- if (arg === "--") { remaining.push(...args.slice(i)); break; }
29
- if (arg === "--strict-mcp-config") {
30
- if (strict) fail("duplicate --strict-mcp-config");
31
- strict = true; continue;
32
- }
33
- if (arg.startsWith("--strict-mcp-config=")) fail("strict MCP isolation cannot be disabled");
34
- if (arg === "--mcp-config" || arg.startsWith("--mcp-config=")) {
35
- if (config !== null) fail("use one explicit MCP configuration");
36
- config = arg === "--mcp-config" ? args[++i] : arg.slice("--mcp-config=".length);
37
- if (typeof config !== "string" || !config.trim() || config.startsWith("--")) fail("--mcp-config requires JSON or a JSON file");
38
- continue;
39
- }
40
- remaining.push(arg);
41
- }
42
- config ??= '{"mcpServers":{}}';
43
- let value;
44
- try {
45
- const text = config.trim().startsWith("{") ? config : fs.readFileSync(path.resolve(project, config), "utf8");
46
- value = JSON.parse(text.replace(/^\uFEFF/, ""));
47
- } catch { fail("MCP configuration must be readable valid JSON; no fallback to global servers"); }
48
- if (!object(value) || Object.keys(value).some(k => k !== "mcpServers") || !object(value.mcpServers))
49
- fail("MCP configuration must contain only a mcpServers object");
50
- for (const [name, server] of Object.entries(value.mcpServers)) {
51
- if (!object(server)) fail("invalid MCP server definition");
52
- const command = typeof server.command === "string" && server.command.trim();
53
- const url = typeof server.url === "string" && server.url.trim();
54
- if ((!command && !url) || (command && url)
55
- || (server.args !== undefined && (!Array.isArray(server.args) || !server.args.every(x => typeof x === "string"))))
56
- fail("invalid MCP command/endpoint definition");
57
- const route = [server.command, server.url, ...(Array.isArray(server.args) ? server.args : [])].filter(x => typeof x === "string").join(" ");
58
- if (unityName(name) || unityProvider(route) || /\bunity(?:\.exe)?\s+mcp\b/i.test(route))
59
- fail("Unity MCP servers are forbidden; use direct Unity CLI/Pipeline commands");
60
- }
61
- // Claude's config option is variadic. End it at argv end or the explicit
62
- // option terminator, so no prompt or unchecked second config can be consumed.
63
- // A trailing caller option missing its value may consume "--mcp-config"; the
64
- // strict flag stays effective, so that fails closed with no MCP servers.
65
- const boundary = remaining.indexOf("--");
66
- const caller = boundary < 0 ? remaining : remaining.slice(0, boundary);
67
- const terminated = boundary < 0 ? [] : remaining.slice(boundary);
68
- return [...prefix, "--strict-mcp-config", ...caller, "--mcp-config", config, ...terminated];
69
- }
70
-
71
- // Recovery retains its original arguments and budgets. An old unsafe record is
72
- // refused, not silently rewritten or relaunched with different server settings.
73
- // Canonical layout: [...prefix, --strict-mcp-config, ...caller, --mcp-config,
74
- // <one validated config>, (-- ...terminated)].
75
- // `prefix` must be the owned pair for the run's recorded permission mode.
76
- export function assertStrictUnityCliArgs(args, project, prefix) {
77
- if (!ownedPrefix(prefix)) fail("retained run has no valid NCCGS permission prefix; use an authorized fresh continuation without resetting spent budgets");
78
- if (!Array.isArray(args) || !args.every(x => typeof x === "string") || !args.includes("--strict-mcp-config")
79
- || !args.some(x => x === "--mcp-config" || x.startsWith("--mcp-config=")))
80
- fail("retained run lacks strict MCP isolation; use an authorized fresh continuation without resetting spent budgets");
81
- if (args[0] !== prefix[0] || args[1] !== prefix[1] || args[2] !== "--strict-mcp-config")
82
- fail("retained arguments do not place strict MCP isolation directly after the fixed permission prefix, before caller arguments; use an authorized fresh continuation without resetting spent budgets");
83
- // R09: the same ownership policy as a fresh launch. Only the verified fixed
84
- // permission prefix is skipped; an R08-canonical record may still carry e.g.
85
- // --restricted, which would ignore project settings and hooks.
86
- const owned = args.slice(prefix.length).find(arg => conflictingLaunchOption.test(arg));
87
- if (owned !== undefined)
88
- fail(`retained arguments contain NCCGS-owned launch option ${owned}; use an authorized fresh continuation without resetting spent budgets`);
89
- const canonical = unityCliMcpArgs(args.slice(prefix.length), project, prefix);
90
- if (JSON.stringify(canonical) !== JSON.stringify(args))
91
- fail("retained arguments lack the canonical single-configuration boundary; use an authorized fresh continuation without resetting spent budgets");
92
- }
93
-
94
- // This recognizes ordinary shell invocations; it does not execute or attempt to
95
- // sandbox arbitrary scripts, encoded payloads, or a deliberately hostile client.
96
- function tokens(command) {
97
- const result = []; let word = "", quote = null;
98
- const flush = () => { if (word) result.push(word); word = ""; };
99
- for (let i = 0; i < command.length; i++) {
100
- const c = command[i];
101
- if (c === "`" && command[i + 1]) { word += command[++i]; continue; }
102
- if (quote) {
103
- if (c === quote) {
104
- if (quote === "'" && command[i + 1] === "'") { word += "'"; i++; }
105
- else quote = null;
106
- } else word += c;
107
- continue;
108
- }
109
- if (c === "'" || c === '"') { quote = c; continue; }
110
- if (c === "{" && word === "$") {
111
- const end = command.indexOf("}", i + 1);
112
- if (end >= 0) { word += command.slice(i, end + 1); i = end; continue; }
113
- }
114
- if (c === "\n" || c === "\r") { flush(); result.push(";"); continue; }
115
- if (/\s/.test(c)) { flush(); continue; }
116
- if (/[;&|(){}]/.test(c)) { flush(); result.push(c); continue; }
117
- word += c;
118
- }
119
- flush(); return result;
120
- }
121
- function inspectShell(command, depth = 0) {
122
- if (depth > 3) fail("nested command wrappers exceed the inspected transport boundary");
123
- const parts = tokens(command);
124
- for (let i = 0; i < parts.length; i++) {
125
- const previous = parts[i - 1];
126
- const invocation = i === 0 || ["&", ";", "|", "(", "{", ".", "sudo", "env", "exec", "call", "command"].includes(previous)
127
- || /^[A-Za-z_]\w*=/.test(previous ?? "");
128
- if (!invocation) continue;
129
- const program = parts[i].replaceAll("\\", "/").split("/").at(-1).toLowerCase().replace(/\.exe$/, "");
130
- if ((program === "unity" || /^\$(?:env:)?[\w:{}]+$/i.test(parts[i])) && parts[i + 1]?.toLowerCase() === "mcp")
131
- fail("unity mcp/configure is disabled; call Unity CLI/Pipeline directly");
132
- if (/^(?:mcp-for-unity|mcpforunityserver)$/.test(program)) fail("Coplay Unity MCP launch is disabled");
133
- const end = parts.findIndex((x, n) => n > i && [";", "|", "&", ")"].includes(x));
134
- const arguments_ = parts.slice(i + 1, end < 0 ? undefined : end);
135
- if (["uvx", "uv", "pip", "pip3", "pipx", "npx", "npm", "pnpm", "bunx"].includes(program)) {
136
- const following = arguments_.join(" ");
137
- if (unityProvider(following)) fail("Unity MCP installation or launch is disabled");
138
- }
139
- if (["claude", "codex"].includes(program) && arguments_[0]?.toLowerCase() === "mcp"
140
- && ["add", "add-json", "add-from-claude-desktop"].includes(arguments_[1]?.toLowerCase())) {
141
- const registration = arguments_.slice(2).join(" ");
142
- if (unityName(registration) || unityProvider(registration))
143
- fail("Unity MCP registration through Claude/Codex is disabled");
144
- }
145
- if (["python", "python3", "node"].includes(program)
146
- && unityProvider(arguments_[0] === "-m" ? arguments_[1] ?? "" : arguments_[0] ?? ""))
147
- fail("Unity MCP launch is disabled");
148
- if (program === "git" && parts[i + 1] === "clone" && unityProvider(parts.slice(i + 2).join(" ")))
149
- fail("Unity MCP installation is disabled");
150
- if (["start-process", "start"].includes(program)) {
151
- const target = arguments_.join(" ");
152
- if (unityProvider(target) || (/\bunity(?:\.exe)?\b/i.test(target) && /\bmcp\b/i.test(target)))
153
- fail("Unity MCP launch is disabled");
154
- }
155
- if (["invoke-expression", "iex"].includes(program) && arguments_.length)
156
- inspectShell(arguments_.join(" "), depth + 1);
157
- if (["cmd", "powershell", "pwsh", "bash", "sh"].includes(program)) {
158
- const option = parts.findIndex((x, n) => n > i && ["/c", "-c", "-lc", "-ic", "-command"].includes(x.toLowerCase()));
159
- if (option >= 0 && parts[option + 1]) inspectShell(parts.slice(option + 1).join(" "), depth + 1);
160
- }
161
- }
162
- }
163
- export function assertUnityCliOnlyInput(input) {
164
- const tool = input.tool_name ?? "";
165
- const server = /^mcp__/i.test(tool) ? tool.slice(5).split("__")[0]
166
- : /^mcp:/i.test(tool) ? tool.slice(4).split(":")[0] : null;
167
- if (server !== null && unityName(server))
168
- fail("Unity MCP tools are disabled, including discovery and read-only tools");
169
- if (["Bash", "PowerShell"].includes(input.tool_name)) inspectShell(input.tool_input?.command ?? "");
170
- }
@@ -1,171 +0,0 @@
1
- import fs from "node:fs";
2
- import path from "node:path";
3
- import crypto from "node:crypto";
4
- import { fileURLToPath } from "node:url";
5
- import { spawnSync } from "node:child_process";
6
- import { artifact, atomicJson, contained, hash, json, verifyArtifact } from "./policy.mjs";
7
- import { snapshot, taskPath } from "./gates.mjs";
8
- import { inputPolicy } from "./inputs.mjs";
9
- import { acquireLock, ownerState, pidState } from "./process-lock.mjs";
10
- import { captureCriteria, measurementBaseline } from "./criteria.mjs";
11
- import { inFinalReviewPhase } from "./review-budget.mjs";
12
-
13
- const worker = fileURLToPath(new URL("./verification-worker.mjs", import.meta.url));
14
- const need = (condition, message) => { if (!condition) throw new Error(message); };
15
- export function jobDirectory(project, jobId) {
16
- need(typeof jobId === "string" && /^[a-f0-9-]{36}$/.test(jobId), "Invalid verification job ID");
17
- return contained(project, `.nccgs/jobs/${jobId}`);
18
- }
19
- export function readJob(project, jobId) {
20
- const job = json(path.join(jobDirectory(project, jobId), "request.json"));
21
- need(job.schemaVersion === 1 && job.id === jobId && job.project === fs.realpathSync(project), "Verification job identity mismatch");
22
- return job;
23
- }
24
- export function finishJob(project, job, result) {
25
- const directory = jobDirectory(project, job.id);
26
- const receipt = `.nccgs/evidence/check-${job.id}.json`;
27
- if (fs.existsSync(contained(project, receipt))) return jobStatus(project, job.id, job.taskId);
28
- let after = null, afterGenerated = [], snapshotError = null;
29
- try {
30
- const captured = snapshot(project, json(taskPath(project, job.taskId)));
31
- after = captured.sha256; afterGenerated = captured.unityGeneratedFiles ?? [];
32
- } catch (error) { snapshotError = error.message; }
33
- const beforeGenerated = new Map((job.unityGeneratedBaseline ?? []).map(file => [file.path, file.sha256]));
34
- const generatedFileChanges = afterGenerated.filter(file => beforeGenerated.get(file.path) !== file.sha256)
35
- .map(file => ({ path: file.path, beforeSha256: beforeGenerated.get(file.path) ?? null, afterSha256: file.sha256 }));
36
- const logPath = `.nccgs/evidence/check-${job.id}.log`;
37
- fs.mkdirSync(path.dirname(contained(project, logPath)), { recursive: true });
38
- if (!fs.existsSync(contained(project, logPath))) fs.writeFileSync(contained(project, logPath), result.error || "No command output captured\n");
39
- else if (fs.statSync(contained(project, logPath)).size === 0) fs.appendFileSync(contained(project, logPath), "[NCCGS command produced no output]\n");
40
- if (result.error || snapshotError) fs.appendFileSync(contained(project, logPath), `\n${result.error ?? ""}\n${snapshotError ?? ""}\n`);
41
- const status = result.exitCode === 0 && !result.error && !result.timedOut && job.snapshot === after ? "PASS" : "FAIL";
42
- atomicJson(contained(project, receipt), { schemaVersion: 1, origin: "verification-command", taskId: job.taskId, name: job.name,
43
- jobId: job.id, requestKey: job.requestKey, snapshot: job.snapshot, contractHash: job.contractHash,
44
- queuedAt: job.queuedAt, startedAt: result.startedAt ?? job.queuedAt, finishedAt: new Date().toISOString(),
45
- timeoutMs: job.timeoutMs, supervisorDeadline: job.supervisorDeadline ?? null,
46
- timedOut: result.timedOut === true, signal: result.signal ?? null,
47
- snapshotError, executable: job.executable, arguments: job.arguments, exitCode: result.exitCode ?? null,
48
- ...(job.unityGeneratedBaseline ? { unityGeneratedFiles: { before: job.unityGeneratedBaseline, after: afterGenerated, changes: generatedFileChanges } } : {}),
49
- error: result.error ?? null, sourceUnchanged: job.snapshot === after, status, log: artifact(project, logPath),
50
- acceptance: captureCriteria(project, job, status) });
51
- atomicJson(path.join(directory, "result.json"), { status, evidence: artifact(project, receipt) });
52
- return jobStatus(project, job.id, job.taskId);
53
- }
54
- export function jobStatus(project, jobId, taskId) {
55
- const job = readJob(project, jobId), directory = jobDirectory(project, jobId);
56
- need(!taskId || taskId === job.taskId, "Verification job belongs to another task");
57
- const receipt = `.nccgs/evidence/check-${job.id}.json`;
58
- if (fs.existsSync(contained(project, receipt))) {
59
- const resultPath = path.join(directory, "result.json");
60
- const evidence = fs.existsSync(resultPath) ? json(resultPath).evidence : artifact(project, receipt);
61
- const result = json(verifyArtifact(project, evidence));
62
- need(result.jobId === job.id && result.taskId === job.taskId && result.snapshot === job.snapshot && result.name === job.name, "Verification receipt identity mismatch");
63
- verifyArtifact(project, result.log);
64
- return { jobId, taskId: job.taskId, name: job.name, status: result.status, evidence, acceptance: result.acceptance ?? null };
65
- }
66
- const lockPath = path.join(directory, "owner.lock");
67
- if (fs.existsSync(lockPath)) {
68
- let owner; try { owner = json(lockPath); } catch { /* incomplete owner */ }
69
- const state = ownerState(owner);
70
- if (state === "dead") {
71
- const lock = acquireLock(lockPath, { jobId });
72
- try { return finishJob(project, job, { error: "Verification owner exited without a terminal receipt; attempt retained, no automatic rerun" }); }
73
- finally { lock.release(); }
74
- }
75
- return { jobId, taskId: job.taskId, name: job.name, status: state === "unknown" ? "UNCERTAIN" : "RUNNING", owner: owner ?? null };
76
- }
77
- const launchPath = path.join(directory, "launch.json");
78
- const launch = fs.existsSync(launchPath) ? json(launchPath) : null;
79
- const launchError = fs.existsSync(path.join(directory, "launch-error.json"));
80
- return { jobId, taskId: job.taskId, name: job.name, status: launchError || (launch && pidState(launch.pid) === "dead") ? "UNCERTAIN" : "STARTING",
81
- ...(fs.existsSync(path.join(directory, "worker.log")) ? { diagnostics: fs.readFileSync(path.join(directory, "worker.log"), "utf8").slice(-4000) } : {}) };
82
- }
83
- export function listJobs(project, taskId) {
84
- const directory = contained(project, ".nccgs/jobs");
85
- if (!fs.existsSync(directory)) return [];
86
- return fs.readdirSync(directory, { withFileTypes: true }).filter(e => e.isDirectory()).flatMap(e => {
87
- const job = readJob(project, e.name);
88
- return !taskId || job.taskId === taskId ? [jobStatus(project, job.id, job.taskId)] : [];
89
- });
90
- }
91
- export function pendingJobs(project, taskId) { return listJobs(project, taskId).filter(job => !["PASS", "FAIL"].includes(job.status)); }
92
- export function startVerification(project, taskId, options) {
93
- project = fs.realpathSync(project);
94
- need(!inFinalReviewPhase(project, process.env.NCCGS_SUPERVISED_SESSION), "Final-review reserve cannot run new verification jobs; use existing receipts");
95
- const task = json(taskPath(project, taskId));
96
- need(task.schemaVersion !== 2 || task.mode === "implement" || !(process.env.CLAUDECODE || process.env.CLAUDE_CODE_ENTRYPOINT), "Audit/plan tasks cannot run arbitrary verification commands inside Claude");
97
- need(typeof options.name === "string" && options.name.trim() && options.executable, "verify requires --name CHECK -- EXECUTABLE [ARGS]");
98
- const configuredTimeout = inputPolicy(project).checks[options.name]?.timeoutMs;
99
- const timeoutMs = options.timeoutMs === undefined ? (configuredTimeout ?? 300000) : options.timeoutMs;
100
- need(Number.isSafeInteger(timeoutMs) && timeoutMs >= 100 && timeoutMs <= 7200000, "Verification timeoutMs must be an integer from 100 to 7200000");
101
- need(configuredTimeout === undefined || timeoutMs <= configuredTimeout, "Verification timeout cannot exceed the configured check timeout");
102
- let supervisorDeadline;
103
- if (process.env.NCCGS_SUPERVISED_SESSION) {
104
- const owner = json(contained(project, `.nccgs/runs/task-${taskId}.lock`));
105
- need(/^[a-f0-9-]{36}$/.test(owner.runId ?? ""), "Missing supervised verification run identity");
106
- const run = json(contained(project, `.nccgs/runs/${owner.runId}/run.json`));
107
- need(run.project === project && run.taskId === taskId && run.sessionId === process.env.NCCGS_SUPERVISED_SESSION &&
108
- Number.isSafeInteger(run.deadline), "Supervised verification run binding mismatch");
109
- supervisorDeadline = run.deadline;
110
- }
111
- const requestKey = options.requestKey ?? crypto.randomUUID();
112
- need(/^[\w-]{1,100}$/.test(requestKey), "Verification request key must use 1-100 letters, digits, underscores or hyphens");
113
- const key = hash(`${taskId}\n${requestKey}`);
114
- // Keep the request-key index outside the job directories.
115
- const index = contained(project, `.nccgs/job-requests/${key}.json`);
116
- const lock = acquireLock(`${index}.lock`, { taskId, requestKey });
117
- let measurementLock;
118
- try {
119
- const captured = snapshot(project, task), current = captured.sha256;
120
- const spec = { taskId, name: options.name, executable: options.executable, arguments: options.arguments ?? [],
121
- timeoutMs, snapshot: current, contractHash: task.contractHash ?? null,
122
- ...(supervisorDeadline === undefined ? {} : { supervisorDeadline }),
123
- criteria: (task.contract?.acceptance ?? []).filter(c => !c.manual && c.check === options.name) };
124
- const requestHash = hash(JSON.stringify(spec));
125
- if (fs.existsSync(index)) {
126
- const previous = json(index);
127
- need(previous.requestHash === requestHash, "Verification request key reused with changed source/command/contract; use a new key for a new attempt");
128
- return jobStatus(project, previous.jobId, taskId);
129
- }
130
- need(supervisorDeadline === undefined || Date.now() < supervisorDeadline, "Supervised run deadline reached; no new verification");
131
- const outputPaths = spec.criteria.flatMap(c => (c.assertions ?? []).map(r => r.artifact.toLowerCase()));
132
- if (outputPaths.length) {
133
- measurementLock = acquireLock(contained(project, ".nccgs/measurement-start.lock"), { taskId, requestKey });
134
- for (const pending of pendingJobs(project)) {
135
- const other = readJob(project, pending.jobId);
136
- need(!(other.criteria ?? []).some(c => (c.assertions ?? []).some(r => outputPaths.includes(r.artifact.toLowerCase()))),
137
- "Another verification owns these measurement outputs; wait for its terminal receipt before starting a new attempt");
138
- }
139
- }
140
- const baseline = measurementBaseline(project, spec.criteria);
141
- const jobId = crypto.randomUUID(), directory = jobDirectory(project, jobId);
142
- fs.mkdirSync(directory, { recursive: true });
143
- fs.mkdirSync(contained(project, ".nccgs/evidence"), { recursive: true });
144
- const job = { schemaVersion: 1, id: jobId, project, ...spec, requestKey, requestHash, measurementBaseline: baseline, queuedAt: new Date().toISOString(),
145
- ...(captured.unityGeneratedFiles ? { unityGeneratedBaseline: captured.unityGeneratedFiles } : {}),
146
- sessionId: process.env.NCCGS_SUPERVISED_SESSION || null };
147
- atomicJson(path.join(directory, "request.json"), job);
148
- atomicJson(index, { jobId, requestHash }); // pinned before launch: an ambiguous crash cannot mint a duplicate
149
- const launched = spawnSync(process.execPath, [worker, "launch", project, jobId], { cwd: project, encoding: "utf8", windowsHide: true, timeout: 15000 });
150
- if (launched.status !== 0 || launched.error) {
151
- // A launcher timeout/error may occur after its detached child was created.
152
- // Preserve uncertainty and let the actual owner publish its own receipt.
153
- atomicJson(path.join(directory, "launch-error.json"), { at: new Date().toISOString(), error: launched.error?.message || launched.stderr, exitCode: launched.status });
154
- }
155
- return jobStatus(project, jobId, taskId);
156
- } finally { measurementLock?.release(); lock.release(); }
157
- }
158
- export function waitVerification(project, jobId, taskId, timeoutMs = 30000) {
159
- need(Number.isSafeInteger(timeoutMs) && timeoutMs >= 0 && timeoutMs <= 7200000 + 30000, "Invalid job wait timeout");
160
- const deadline = Date.now() + timeoutMs;
161
- for (;;) {
162
- const result = jobStatus(project, jobId, taskId);
163
- if (["PASS", "FAIL"].includes(result.status)) {
164
- const launchPath = path.join(jobDirectory(project, jobId), "launch.json");
165
- // A receipt is durable before the worker exits. Synchronous callers also
166
- // wait for that owner to release its cwd/handles before disposing a project.
167
- if (!fs.existsSync(launchPath) || pidState(json(launchPath).pid) === "dead" || Date.now() >= deadline) return result;
168
- } else if (result.status === "UNCERTAIN" || Date.now() >= deadline) return result;
169
- Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, Math.min(100, deadline - Date.now()));
170
- }
171
- }