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,153 +0,0 @@
1
- import fs from "node:fs";
2
- import path from "node:path";
3
- import { artifact, contained, hash, verifyArtifact } from "./policy.mjs";
4
-
5
- const durableRoot = ".nccgs/evidence/runtime";
6
- const legacyRoot = ".nccgs/runtime/";
7
- const isRef = value => value && typeof value === "object" && typeof value.path === "string" && typeof value.sha256 === "string";
8
- const encode = value => Buffer.from(`${JSON.stringify(value, null, 2)}\n`, "utf8");
9
-
10
- function readReference(project, ref, label) {
11
- try {
12
- const file = verifyArtifact(project, ref);
13
- const bytes = fs.readFileSync(file);
14
- if (hash(bytes) !== ref.sha256) throw new Error("Evidence changed while being copied");
15
- return bytes;
16
- } catch (error) {
17
- throw new Error(`${label}: missing, stale, or unsafe evidence '${ref?.path ?? "unknown"}': ${error.message}`);
18
- }
19
- }
20
-
21
- // Content-addressed copies retain the original bytes. Plan every copy before any
22
- // writes so a missing legacy source cannot produce a partly migrated task.
23
- function copyPlan(project) {
24
- const writes = new Map();
25
- const migrations = [];
26
- const seenMigrations = new Set();
27
- const add = (kind, bytes) => {
28
- const sha256 = hash(bytes);
29
- const relative = `${durableRoot}/${kind}/${sha256}.json`;
30
- const file = contained(project, relative);
31
- if (fs.existsSync(file)) {
32
- if (!fs.statSync(file).isFile() || hash(fs.readFileSync(file)) !== sha256) {
33
- throw new Error(`Durable evidence collision or corruption: ${relative}`);
34
- }
35
- } else writes.set(relative, bytes);
36
- return { path: relative, sha256 };
37
- };
38
- const note = (from, to, kind) => {
39
- if (from.path === to.path && from.sha256 === to.sha256) return;
40
- const key = `${kind}:${from.path}:${from.sha256}:${to.path}`;
41
- if (!seenMigrations.has(key)) {
42
- migrations.push({ kind, from: { ...from }, to: { ...to } });
43
- seenMigrations.add(key);
44
- }
45
- };
46
- const source = ref => {
47
- const bytes = readReference(project, ref, "Runtime source");
48
- if (ref.path.startsWith(`${durableRoot}/sources/`)) return { ...ref };
49
- const durable = add("sources", bytes);
50
- note(ref, durable, "source");
51
- return durable;
52
- };
53
- const observation = (value, sourceRef) => {
54
- const durableSource = source(sourceRef);
55
- const normalized = { ...value, observationSource: durableSource };
56
- if (sourceRef.path !== durableSource.path || sourceRef.sha256 !== durableSource.sha256) {
57
- normalized.originalObservationSource = value.originalObservationSource ?? { ...sourceRef };
58
- }
59
- return add("observations", encode(normalized));
60
- };
61
- const commit = () => {
62
- // Recheck destinations before writing; never overwrite an existing artifact.
63
- for (const [relative, bytes] of writes) {
64
- const file = contained(project, relative);
65
- if (fs.existsSync(file) && (!fs.statSync(file).isFile() || hash(fs.readFileSync(file)) !== hash(bytes))) {
66
- throw new Error(`Durable evidence collision or corruption: ${relative}`);
67
- }
68
- }
69
- for (const [relative, bytes] of writes) {
70
- const file = contained(project, relative);
71
- fs.mkdirSync(path.dirname(file), { recursive: true });
72
- try { fs.writeFileSync(file, bytes, { flag: "wx" }); }
73
- catch (error) { if (error.code !== "EEXIST") throw error; }
74
- if (artifact(project, relative).sha256 !== hash(bytes)) {
75
- throw new Error(`Durable evidence copy failed verification: ${relative}`);
76
- }
77
- }
78
- };
79
- return { add, source, observation, note, migrations, commit };
80
- }
81
-
82
- /** Persist an observation and an exact durable copy of its raw source.
83
- * Callers retain responsibility for validating runtime identity and provenance.
84
- */
85
- export function persistRuntimeObservation(project, observation, sourceRef) {
86
- if (!observation || typeof observation !== "object" || Array.isArray(observation)) {
87
- throw new Error("Runtime observation must be an object");
88
- }
89
- const plan = copyPlan(project);
90
- const result = plan.observation(observation, sourceRef);
91
- plan.commit();
92
- return result;
93
- }
94
-
95
- /** Return a migrated clone; the caller owns task locking and atomic task writes.
96
- * No source, stage, history entry, review counter, or original artifact is deleted.
97
- * This does not refresh snapshots, evidence times, approvals, or task validity.
98
- */
99
- export function migrateTaskEvidence(project, task) {
100
- const plan = copyPlan(project);
101
- const cache = new Map();
102
- const migrateReference = ref => {
103
- const key = `${ref.path}:${ref.sha256}`;
104
- if (cache.has(key)) return { ...ref, ...cache.get(key) };
105
- const bytes = readReference(project, ref, "Runtime observation");
106
- let value;
107
- try { value = JSON.parse(bytes.toString("utf8")); }
108
- catch {
109
- if (ref.path.includes("/observations/")) throw new Error(`Invalid runtime observation JSON: ${ref.path}`);
110
- }
111
- let result = ref;
112
- if (value?.origin === "runtime-observation") {
113
- if (!isRef(value.observationSource)) throw new Error(`Runtime observation has no verifiable raw source: ${ref.path}`);
114
- const sourceRef = value.observationSource;
115
- const source = plan.source(sourceRef);
116
- const needsCopy = !ref.path.startsWith(`${durableRoot}/observations/`) || source.path !== sourceRef.path;
117
- if (needsCopy) {
118
- const archive = plan.add("sources", bytes);
119
- plan.note(ref, archive, "observation-archive");
120
- const migrated = { ...value, observationSource: source,
121
- originalObservationSource: value.originalObservationSource ?? { ...sourceRef },
122
- evidenceMigration: { originalObservation: { ...ref }, archivedObservation: archive,
123
- ...(value.evidenceMigration ? { previous: value.evidenceMigration } : {}) } };
124
- result = plan.add("observations", encode(migrated));
125
- plan.note(ref, result, "observation");
126
- }
127
- } else if (ref.path.startsWith(legacyRoot)) {
128
- if (ref.path.includes("/observations/")) throw new Error(`Invalid runtime observation origin: ${ref.path}`);
129
- result = plan.source(ref);
130
- }
131
- cache.set(key, result);
132
- return { ...ref, ...result };
133
- };
134
- const walk = (value, key = "") => {
135
- if (Array.isArray(value)) return value.map(item => walk(item, key));
136
- if (!value || typeof value !== "object") return value;
137
- // Original paths in our audit records describe where bytes came from; they
138
- // are not live dependencies after a clean copy removes the ignored runtime.
139
- if (value.action === "migrate-evidence" ||
140
- (["source", "observation", "observation-archive"].includes(value.kind) && isRef(value.from) && isRef(value.to))) {
141
- return structuredClone(value);
142
- }
143
- if (isRef(value)) {
144
- // Do not revalidate unrelated old plan/report refs when migrating history.
145
- if (key === "runtime" || value.path.startsWith(legacyRoot)) return migrateReference(value);
146
- return { ...value };
147
- }
148
- return Object.fromEntries(Object.entries(value).map(([name, child]) => [name, walk(child, name)]));
149
- };
150
- const migrated = walk(task);
151
- plan.commit();
152
- return { task: migrated, migrations: plan.migrations, changed: plan.migrations.length > 0 };
153
- }
@@ -1,297 +0,0 @@
1
- import fs from "node:fs";
2
- import path from "node:path";
3
- import { performance } from "node:perf_hooks";
4
- import { hash, json, contained, artifact, verifyArtifact, atomicJson, loadPipeline, resolveExecution } from "./policy.mjs";
5
- import { canonicalInputs, pinInputs, inputPolicy, isOutput, isUnityGenerated, unityGeneratedState } from "./inputs.mjs";
6
- import { migrateTaskEvidence } from "./evidence.mjs";
7
- import { acquireLock } from "./process-lock.mjs";
8
- import { initializeStandalone, checkStandalone, recordStandalone, extendStandalone, refreshStandalone,
9
- reclassifyStandalone, exportExternalStandalone, importExternalStandalone } from "./lifecycle.mjs";
10
-
11
- export const stages = ["implementation", "review", "report", "astra", "acceptance"];
12
- function requireValue(condition, message) { if (!condition) throw new Error(message); }
13
- export function taskPath(project, id) {
14
- requireValue(typeof id === "string" && /^[a-zA-Z0-9][a-zA-Z0-9_-]{0,79}$/.test(id), "Invalid task ID");
15
- return contained(project, `.nccgs/tasks/${id}.json`);
16
- }
17
- export function snapshot(project, task = null, { includeFiles = false } = {}) {
18
- const started = performance.now();
19
- const excluded = new Set(loadPipeline(project).snapshotExcludes);
20
- const policy = inputPolicy(project);
21
- const inputs = canonicalInputs(project, policy);
22
- const files = [];
23
- let bytes = 0, readHashMs = 0;
24
- function walk(relative = "") {
25
- for (const entry of fs.readdirSync(path.join(project, relative), { withFileTypes: true })) {
26
- if (!relative && excluded.has(entry.name)) continue;
27
- const name = relative ? `${relative}/${entry.name}` : entry.name;
28
- const file = contained(project, name);
29
- if (isOutput(name, policy) || isUnityGenerated(name, policy)) continue;
30
- if (entry.isDirectory()) walk(name);
31
- else if (entry.isFile()) {
32
- const readStarted = performance.now();
33
- const data = fs.readFileSync(file);
34
- files.push([name, hash(data)]);
35
- bytes += data.length;
36
- readHashMs += performance.now() - readStarted;
37
- }
38
- else throw new Error(`Unsupported snapshot entry: ${name}`);
39
- }
40
- }
41
- walk();
42
- const generatedFiles = unityGeneratedState(project, policy);
43
- files.sort(([a], [b]) => a < b ? -1 : a > b ? 1 : 0);
44
- return { sha256: hash(JSON.stringify({ files, canonicalInputs: inputs.sha256 })), sourceSha256: hash(JSON.stringify(files)), files: files.length,
45
- bytes, canonicalInputSha256: inputs.sha256, canonicalInputFiles: inputs.entries.filter(e => e.kind === "file").length,
46
- canonicalInputBytes: inputs.bytes, readHashMs: readHashMs + inputs.readHashMs, durationMs: performance.now() - started,
47
- ...(includeFiles ? { fileEntries: files } : {}),
48
- ...(generatedFiles.length ? { unityGeneratedFiles: generatedFiles } : {}) };
49
- }
50
- function tierRoute(pipeline, risk) {
51
- const tier = pipeline.contract.taskTiers?.[risk];
52
- requireValue(tier, "Task risk must be FAST, STANDARD or CONTROLLED; existing tasks without a risk tier must be recreated and evidence recorded again");
53
- const route = pipeline.profiles["astra-claude"].models[tier.implementationClass];
54
- requireValue(route && Number.isSafeInteger(tier.maxReviewRounds) && tier.maxReviewRounds > 0, "Invalid task tier policy");
55
- return { tier, route: { class: tier.implementationClass, model: route.model, effort: route.effort } };
56
- }
57
- function taskRouting(pipeline, task) {
58
- const { tier, route } = tierRoute(pipeline, task.risk);
59
- requireValue(task.implementationRoute && ["class", "model", "effort"].every(key => task.implementationRoute[key] === route[key]), "Task implementation route missing or changed; create a new task against the current policy");
60
- const budget = task.reviewBudget;
61
- requireValue(budget && Number.isSafeInteger(budget.used) && budget.used >= 0 && Number.isSafeInteger(budget.limit) && Array.isArray(budget.extensions), "Task review budget missing or invalid; create a new task and record evidence again");
62
- let limit = tier.maxReviewRounds;
63
- for (const extension of budget.extensions) {
64
- requireValue(Number.isSafeInteger(extension.rounds) && extension.rounds > 0 && extension.rounds <= tier.maxReviewRounds && extension.reason?.trim() && Number.isFinite(Date.parse(extension.at)) && extension.previousLimit === limit && extension.newLimit === limit + extension.rounds, "Invalid review budget extension audit");
65
- limit = extension.newLimit;
66
- }
67
- requireValue(budget.limit === limit && budget.used <= limit, "Review budget does not match its extension audit");
68
- return { tier, route, budget: { used: budget.used, limit, remaining: limit - budget.used } };
69
- }
70
- function initializeUnlocked(project, id, plan, requirements = null, risk = "STANDARD") {
71
- const file = taskPath(project, id);
72
- requireValue(!fs.existsSync(file), `Task already exists: ${id}`);
73
- const projectGates = artifact(project, ".nccgs/gates.json");
74
- const projectPolicy = artifact(project, ".nccgs/project.yaml");
75
- requireValue(json(verifyArtifact(project, projectGates)).policySha256 === projectPolicy.sha256, "Astra must map/review project gates against the current project.yaml hash");
76
- const pipeline = loadPipeline(project);
77
- const { tier, route } = tierRoute(pipeline, risk);
78
- const task = { schemaVersion: 1, id, profile: "astra-claude", risk, implementationRoute: route,
79
- reviewBudget: { used: 0, limit: tier.maxReviewRounds, extensions: [] },
80
- createdAt: new Date().toISOString(), pipelineHash: hash(JSON.stringify(pipeline)), plan: artifact(project, plan), projectPolicy, projectGates, requirements: requirements ? artifact(project, requirements) : null, canonicalInputs: pinInputs(project), stages: {}, history: [] };
81
- atomicJson(file, task);
82
- return task;
83
- }
84
- function runtime(project, task, stage, expected, snap) {
85
- const file = verifyArtifact(project, stage.runtime);
86
- const trace = json(file);
87
- requireValue(trace.schemaVersion === 1 && trace.origin === "runtime-observation", "Runtime evidence must be an observation, not configuration");
88
- requireValue(trace.taskId === task.id && trace.snapshot === snap, "Runtime evidence belongs to another task/snapshot");
89
- requireValue(trace.status === "completed" && trace.sessionId && trace.agentId, "Runtime observation is incomplete");
90
- requireValue(Date.parse(trace.capturedAt) >= Date.parse(task.createdAt) && Date.parse(trace.capturedAt) <= Date.now(), "Runtime observation has invalid time");
91
- requireValue(Date.parse(trace.capturedAt) >= Date.parse(task.canonicalInputs.pinnedAt), "Runtime observation predates current input pin; capture a fresh run");
92
- const models = trace.modelsUsed?.length ? trace.modelsUsed : [trace.observedModel];
93
- const matches = (model) => expected.model === "fable" ? /^claude-fable-\d[\w.-]*$/.test(model ?? "")
94
- : expected.model === "sonnet" ? /^claude-sonnet-\d[\w.-]*$/.test(model ?? "") : model === expected.model;
95
- requireValue(matches(trace.observedModel) && models.every(matches), "Observed model/fallback does not satisfy pipeline");
96
- requireValue(trace.observedEffort === expected.effort, "Observed effort missing or mismatched; configuration is not proof");
97
- requireValue(trace.observationSource, "Runtime observation requires a source artifact");
98
- const source = json(verifyArtifact(project, trace.observationSource));
99
- requireValue((source.observedModel ?? source.resolvedModel) === trace.observedModel && source.observedEffort === trace.observedEffort, "Observation differs from its raw model/effort source");
100
- requireValue(source.taskId === task.id && source.snapshot === snap && source.sessionId === trace.sessionId && source.agentId === trace.agentId, "Observation source identity/snapshot mismatch");
101
- requireValue(source.capturedAt === trace.capturedAt && source.status === trace.status, "Observation source time/status mismatch");
102
- const sourceModels = source.modelsUsed?.length ? source.modelsUsed : [source.observedModel ?? source.resolvedModel];
103
- requireValue(JSON.stringify(sourceModels) === JSON.stringify(models), "Observation dropped or changed source fallback history");
104
- requireValue(stage.runtime.path.startsWith(".nccgs/evidence/runtime/observations/") && trace.observationSource.path.startsWith(".nccgs/evidence/runtime/sources/"), "Runtime evidence is not durable; run task migrate-evidence before closure");
105
- return trace;
106
- }
107
- function reviewEvidence(project, task, stage, expected, snap, implementer, allowNegative = false) {
108
- const trace = runtime(project, task, stage, expected, snap);
109
- requireValue(`${trace.sessionId}/${trace.agentId}` !== implementer, "Review must be independent of implementation");
110
- requireValue(Date.parse(trace.capturedAt) >= Date.parse(task.stages.implementation.recordedAt), "Review runtime predates implementation evidence");
111
- requireValue(Array.isArray(stage.findings) && typeof stage.criteriaMet === "boolean", "Review requires findings and an acceptance criteria assessment");
112
- requireValue(stage.verdict === "PASS" || (allowNegative && ["CHANGES_REQUIRED", "BLOCKED"].includes(stage.verdict)), "Fable review has not passed");
113
- if (stage.verdict === "PASS") {
114
- requireValue(!stage.findings.some(f => ["BLOCKER", "HIGH"].includes(f.severity) && f.status !== "RESOLVED"), "Review has open blocking findings");
115
- requireValue(stage.criteriaMet === true, "Required acceptance criteria are not proven");
116
- }
117
- verifyArtifact(project, stage.evidence);
118
- }
119
- export function check(project, task, target = "done") {
120
- if (task.schemaVersion === 2) return checkStandalone(project, task, target);
121
- requireValue(task.schemaVersion === 1 && task.profile === "astra-claude", "Unsupported task record");
122
- taskPath(project, task.id);
123
- const pipeline = loadPipeline(project);
124
- requireValue(task.pipelineHash === hash(JSON.stringify(pipeline)), "Pipeline policy changed; create a new task against the new policy");
125
- const routing = taskRouting(pipeline, task);
126
- requireValue(task.canonicalInputs?.schemaVersion === 1 && Number.isFinite(Date.parse(task.canonicalInputs.pinnedAt)), "Legacy task lacks canonical input pins; run task refresh-inputs --reason TEXT and record fresh evidence");
127
- requireValue(task.canonicalInputs.sha256 === canonicalInputs(project).sha256, "Canonical inputs are stale; review the changes, run task refresh-inputs --reason TEXT, and record fresh evidence");
128
- verifyArtifact(project, task.plan);
129
- verifyArtifact(project, task.projectPolicy);
130
- const obligations = [task.projectGates, task.requirements].filter(Boolean).map(ref => json(verifyArtifact(project, ref)));
131
- requireValue(obligations.length > 0, "Project gate manifest is required");
132
- for (const spec of obligations) requireValue(spec.schemaVersion === 1 && [spec.requiredChecks, spec.requiredArtifacts, spec.manualGates].every(Array.isArray), "Invalid gate manifest schema");
133
- const snap = snapshot(project).sha256;
134
- const end = target === "done" ? 5 : stages.indexOf(target);
135
- requireValue(end >= 0, "Invalid gate target");
136
- let previous = Date.parse(task.createdAt);
137
- let implementer;
138
- for (const name of stages.slice(0, end)) {
139
- const stage = task.stages[name];
140
- requireValue(stage && stage.snapshot === snap, `${name}: missing or stale for current snapshot`);
141
- const at = Date.parse(stage.recordedAt);
142
- requireValue(Number.isFinite(at) && at >= previous && at <= Date.now(), `${name}: invalid sequence timestamp`);
143
- previous = at;
144
- if (name === "implementation" || name === "review") {
145
- if (name === "implementation") {
146
- const trace = runtime(project, task, stage, routing.route, snap);
147
- implementer = `${trace.sessionId}/${trace.agentId}`;
148
- requireValue(Array.isArray(stage.checks) && stage.checks.length > 0, "Implementation requires verification evidence");
149
- for (const test of stage.checks) {
150
- requireValue(test.name && test.status === "PASS", "Verification contains missing/failed/unproven checks");
151
- const evidenceFile = verifyArtifact(project, test.evidence);
152
- if (test.evidence.path.endsWith(".json")) {
153
- const evidence = json(evidenceFile);
154
- if (evidence.origin === "verification-command") {
155
- requireValue(evidence.taskId === task.id && evidence.name === test.name && evidence.snapshot === snap && evidence.status === "PASS" && evidence.exitCode === 0 && evidence.sourceUnchanged === true, "Recorded verification execution failed or is stale");
156
- requireValue(Date.parse(evidence.startedAt) >= Date.parse(task.canonicalInputs.pinnedAt), "Verification execution predates current input pin; rerun the check");
157
- verifyArtifact(project, evidence.log);
158
- }
159
- }
160
- }
161
- for (const spec of obligations) for (const name of spec.requiredChecks) requireValue(stage.checks.some(c => c.name === name && c.status === "PASS"), `Required check missing: ${name}`);
162
- } else {
163
- reviewEvidence(project, task, stage, pipeline.profiles[task.profile].models.review, snap, implementer);
164
- }
165
- } else if (name === "report") {
166
- verifyArtifact(project, stage.evidence);
167
- for (const spec of obligations) for (const relative of spec.requiredArtifacts) {
168
- const ref = stage.artifacts?.find(item => item.path === relative);
169
- requireValue(ref, `Required closure artifact missing: ${relative}`);
170
- verifyArtifact(project, ref);
171
- }
172
- }
173
- else {
174
- const approval = json(verifyArtifact(project, stage.evidence));
175
- const actor = name === "astra" ? "Astra" : "Product Owner";
176
- const decision = name === "astra" ? "PASS" : "ACCEPTED";
177
- requireValue(approval.actor === actor && approval.decision === decision, `${name}: explicit ${actor} decision required`);
178
- requireValue(approval.taskId === task.id && approval.snapshot === snap, `${name}: sign-off covers a different snapshot`);
179
- requireValue(approval.statement?.trim() && approval.reference?.trim(), `${name}: decision statement and source reference required`);
180
- requireValue(Date.parse(approval.decidedAt) >= Date.parse(task.stages[name === "astra" ? "report" : "astra"].recordedAt) && Date.parse(approval.decidedAt) <= at, `${name}: sign-off predates its prerequisite`);
181
- if (name === "acceptance") for (const spec of obligations) for (const id of spec.manualGates) requireValue(approval.gates?.some(g => g.id === id && g.decision === "ACCEPTED" && g.reference?.trim()), `Manual gate missing: ${id}`);
182
- }
183
- }
184
- const exhausted = target === "review" && routing.budget.remaining === 0;
185
- return { allowed: !exhausted, target, snapshot: snap, risk: task.risk, implementationRoute: routing.route, reviewBudget: routing.budget,
186
- ...(exhausted ? { message: `Review budget exhausted (${routing.budget.used}/${routing.budget.limit}); stop and escalate. An external operator may explicitly extend-review with a reason; exhausted budget never means PASS` } : {}),
187
- phase: exhausted ? "REVIEW_BUDGET_EXHAUSTED" : target === "done" ? "DONE" : `READY_FOR_${target.toUpperCase()}` };
188
- }
189
- function recordUnlocked(project, id, name, input) {
190
- const existing = json(taskPath(project, id));
191
- if (existing.schemaVersion === 2) return recordStandalone(project, existing, name, input);
192
- requireValue(stages.includes(name), "Unknown pipeline stage");
193
- if (["astra", "acceptance"].includes(name) && (process.env.CLAUDECODE || process.env.CLAUDE_CODE_ENTRYPOINT)) throw new Error("External sign-offs must be imported outside the Claude session");
194
- const file = taskPath(project, id);
195
- const task = json(file);
196
- const status = check(project, task, name);
197
- requireValue(status.allowed, status.message);
198
- requireValue(input.snapshot === status.snapshot, "Submitted evidence does not cover the current snapshot");
199
- if (name === "review") {
200
- const pipeline = loadPipeline(project);
201
- const implementation = runtime(project, task, task.stages.implementation, status.implementationRoute, status.snapshot);
202
- reviewEvidence(project, task, input, pipeline.profiles[task.profile].models.review, status.snapshot, `${implementation.sessionId}/${implementation.agentId}`, true);
203
- task.reviewBudget.used += 1;
204
- }
205
- task.history.push({ recordedAt: new Date().toISOString(), replacedFrom: name, stages: structuredClone(task.stages) });
206
- for (const downstream of stages.slice(stages.indexOf(name))) delete task.stages[downstream];
207
- task.stages[name] = { ...input, recordedAt: new Date().toISOString() };
208
- // Failed reviews can be retained as evidence but never unlock the next stage.
209
- const externalDecision = ["astra", "acceptance"].includes(name) ? json(verifyArtifact(project, input.evidence)).decision : null;
210
- const negative = (name === "review" && ["CHANGES_REQUIRED", "BLOCKED"].includes(input.verdict)) || ["CHANGES_REQUIRED", "REJECTED"].includes(externalDecision);
211
- if (!negative) {
212
- const next = stages[stages.indexOf(name) + 1] ?? "done";
213
- check(project, task, next);
214
- }
215
- delete task.closed;
216
- atomicJson(file, task);
217
- return task;
218
- }
219
- function extendReviewUnlocked(project, id, reason, rounds) {
220
- const existing = json(taskPath(project, id));
221
- if (existing.schemaVersion === 2) return extendStandalone(project, existing, reason, rounds);
222
- requireValue(!(process.env.CLAUDECODE || process.env.CLAUDE_CODE_ENTRYPOINT), "Review budget extensions must be requested outside the Claude session");
223
- requireValue(typeof reason === "string" && reason.trim(), "Review budget extension requires a reason");
224
- const file = taskPath(project, id);
225
- const task = json(file);
226
- check(project, task, "implementation");
227
- const { tier } = taskRouting(loadPipeline(project), task);
228
- requireValue(Number.isSafeInteger(rounds) && rounds > 0 && rounds <= tier.maxReviewRounds, `Review budget extension requires an integer from 1 to ${tier.maxReviewRounds}`);
229
- requireValue(Number.isSafeInteger(task.reviewBudget.limit + rounds), "Review budget limit is too large");
230
- const extension = { at: new Date().toISOString(), reason: reason.trim(), rounds, previousLimit: task.reviewBudget.limit, newLimit: task.reviewBudget.limit + rounds };
231
- task.reviewBudget.limit = extension.newLimit;
232
- task.reviewBudget.extensions.push(extension);
233
- task.history.push({ recordedAt: extension.at, action: "extend-review", ...extension });
234
- atomicJson(file, task);
235
- return task;
236
- }
237
- function closeUnlocked(project, id) {
238
- const file = taskPath(project, id);
239
- const task = json(file);
240
- const status = check(project, task, "done");
241
- task.closed = { snapshot: status.snapshot, at: new Date().toISOString() };
242
- atomicJson(file, task);
243
- return status;
244
- }
245
-
246
- function refreshInputsUnlocked(project, id, reason) {
247
- const existing = json(taskPath(project, id));
248
- if (existing.schemaVersion === 2) return refreshStandalone(project, existing, reason);
249
- requireValue(typeof reason === "string" && reason.trim(), "Input refresh requires a reason");
250
- const file = taskPath(project, id);
251
- const task = json(file);
252
- requireValue(task.schemaVersion === 1 && task.profile === "astra-claude", "Unsupported task record");
253
- const pipeline = loadPipeline(project);
254
- requireValue(task.pipelineHash === hash(JSON.stringify(pipeline)), "Input refresh cannot migrate a changed pipeline");
255
- taskRouting(pipeline, task);
256
- const projectPolicy = artifact(project, ".nccgs/project.yaml");
257
- const projectGates = artifact(project, ".nccgs/gates.json");
258
- requireValue(json(verifyArtifact(project, projectGates)).policySha256 === projectPolicy.sha256, "Project gates must be remapped to the current project.yaml hash before input refresh");
259
- const plan = artifact(project, task.plan.path);
260
- const requirements = task.requirements ? artifact(project, task.requirements.path) : null;
261
- const pins = pinInputs(project);
262
- task.history.push({ action: "refresh-inputs", recordedAt: pins.pinnedAt, reason: reason.trim(),
263
- canonicalInputs: task.canonicalInputs ?? null, plan: task.plan, projectPolicy: task.projectPolicy,
264
- projectGates: task.projectGates, requirements: task.requirements, stages: structuredClone(task.stages), closed: task.closed ?? null });
265
- Object.assign(task, { canonicalInputs: pins, plan, projectPolicy, projectGates, requirements, stages: {} });
266
- delete task.closed;
267
- // Validate new mappings before committing; a failed refresh leaves the task intact.
268
- check(project, task, "implementation");
269
- atomicJson(file, task);
270
- return task;
271
- }
272
-
273
- function mutate(project, id, action) {
274
- const lock = acquireLock(`${taskPath(project, id)}.lock`, { taskId: id });
275
- try { return action(); } finally { lock.release(); }
276
- }
277
- export const withTask = mutate;
278
- export const initialize = (project, id, plan, requirements = null, risk = null, options = {}) => mutate(project, id, () =>
279
- resolveExecution(project).name === "standalone"
280
- ? initializeStandalone(project, id, { ...options, plan, requirements, ...(risk ? { risk } : {}) })
281
- : initializeUnlocked(project, id, plan, requirements, risk || "STANDARD"));
282
- export const record = (project, id, stage, evidence) => mutate(project, id, () => recordUnlocked(project, id, stage, evidence));
283
- export const extendReview = (project, id, reason, rounds) => mutate(project, id, () => extendReviewUnlocked(project, id, reason, rounds));
284
- export const close = (project, id) => mutate(project, id, () => closeUnlocked(project, id));
285
- export const refreshInputs = (project, id, reason) => mutate(project, id, () => refreshInputsUnlocked(project, id, reason));
286
- export const reclassify = (project, id, changes) => mutate(project, id, () => reclassifyStandalone(project, json(taskPath(project, id)), changes));
287
- export const exportExternal = (project, id, relative) => mutate(project, id, () => exportExternalStandalone(project, json(taskPath(project, id)), relative));
288
- export const importExternal = (project, id, relative) => mutate(project, id, () => importExternalStandalone(project, json(taskPath(project, id)), relative));
289
- export const migrateEvidence = (project, id) => mutate(project, id, () => {
290
- const file = taskPath(project, id);
291
- const result = migrateTaskEvidence(project, json(file));
292
- if (result.changed) {
293
- result.task.history.push({ action: "migrate-evidence", recordedAt: new Date().toISOString(), migrations: result.migrations });
294
- atomicJson(file, result.task);
295
- }
296
- return { id, changed: result.changed, migrations: result.migrations };
297
- });
@@ -1,51 +0,0 @@
1
- import fs from "node:fs";
2
- import { artifact, json, verifyArtifact } from "./policy.mjs";
3
- import { check, record, taskPath } from "./gates.mjs";
4
- import { getDispatch } from "./orchestration.mjs";
5
- import { readReviewHandoff, validateReviewStructure } from "./review-handoff.mjs";
6
-
7
- const need = (ok, message) => { if (!ok) throw new Error(`Handoff: ${message}`); };
8
-
9
- function context(project, id, dispatchId, relative) {
10
- const task = json(taskPath(project, id)), dispatch = getDispatch(project, id, dispatchId);
11
- need(dispatch.contractHash === task.contractHash, "dispatch contract is stale");
12
- need(dispatch.handoffPaths?.includes(relative), "file must be this dispatch's declared handoff");
13
- need(["running", "completed"].includes(dispatch.status), "handoff inspection requires a running or completed dispatch");
14
- const state = check(project, task, task.mode === "implement" ? "implementation" : "analysis");
15
- need(state.allowed, state.message);
16
- const expected = dispatch.status === "completed" ? dispatch.completedSnapshot : dispatch.kind === "implementation" ? state.snapshot : dispatch.snapshot;
17
- need(state.snapshot === expected, "source snapshot is stale");
18
- // A completed handoff is always read through its captured reference. A new hash
19
- // cannot legitimize edits made after completion.
20
- const evidence = dispatch.status === "completed"
21
- ? dispatch.handoff?.artifacts?.find(ref => ref.path === relative) : artifact(project, relative);
22
- need(evidence, "completed dispatch did not pin this handoff");
23
- const content = fs.readFileSync(verifyArtifact(project, evidence), "utf8");
24
- return { task, dispatch, snapshot: state.snapshot, evidence, content };
25
- }
26
-
27
- export function validateHandoff(project, id, dispatchId, relative) {
28
- const ctx = context(project, id, dispatchId, relative);
29
- const markers = [...ctx.content.matchAll(/^NCCGS-HANDOFF: (PARTIAL|COMPLETE)\r?$/gm)];
30
- need(markers.length === 1, "exactly one PARTIAL or COMPLETE marker is required");
31
- const complete = markers[0][1] === "COMPLETE";
32
- if (ctx.dispatch.kind === "review") {
33
- const { value } = readReviewHandoff(ctx.content, ctx.task, ctx.snapshot, false);
34
- validateReviewStructure(value, ctx.task);
35
- }
36
- verifyArtifact(project, ctx.evidence);
37
- return { status: "VALID", taskId: id, dispatchId, evidence: ctx.evidence, complete,
38
- scope: "Structure only; not native completion, semantic review, verification or acceptance. No task, budget or handoff was changed." };
39
- }
40
-
41
- export function recordReviewHandoff(project, id, dispatchId, relative) {
42
- const ctx = context(project, id, dispatchId, relative);
43
- need(ctx.dispatch.kind === "review" && ctx.dispatch.status === "completed", "a completed independent review dispatch is required");
44
- need(ctx.task.execution.reviewContractRequired === true, "automatic import requires the reviewer-owned contract policy; legacy records retain their workflow");
45
- const { value } = readReviewHandoff(ctx.content, ctx.task, ctx.snapshot);
46
- // No caller-supplied verdict, findings, conditions, runtime or snapshot. The
47
- // existing record path checks independence, telemetry, criteria and budgets,
48
- // appends history, and rejects reusing a dispatch. It never closes the task.
49
- return record(project, id, "review", { snapshot: ctx.snapshot, dispatchId, runtime: ctx.dispatch.runtime, evidence: ctx.evidence,
50
- verdict: value.verdict, criteriaMet: value.criteriaMet, findings: value.findings, conditions: value.conditions });
51
- }
@@ -1,34 +0,0 @@
1
- // Exact managed-hook identity across legacy shell and direct-executable forms.
2
- // Never identify a hook by the executable alone: many custom hooks use node.
3
- const scriptPattern = /^(?:\$\{CLAUDE_PROJECT_DIR\}\/)?(\.claude\/nccgs\/hooks\/[\w-]+\.mjs)$/;
4
- const phases = new Set(['pre', 'stop', 'start', 'failure']);
5
-
6
- export function managedHookKey(hook) {
7
- if (!hook || hook.type !== 'command' || typeof hook.command !== 'string') return null;
8
- let script, args;
9
- if (Object.hasOwn(hook, 'args')) {
10
- if (hook.command !== 'node' || !Array.isArray(hook.args) || !hook.args.every(x => typeof x === 'string')) return null;
11
- [script, ...args] = hook.args;
12
- } else {
13
- const match = hook.command.match(/^node (?:"([^"\r\n]+)"|([^\s"'`$;&|<>]+))(?: (pre|stop|start|failure))?$/);
14
- if (!match) return null;
15
- script = match[1] ?? match[2];
16
- args = match[3] ? [match[3]] : [];
17
- }
18
- const relative = typeof script === 'string' ? script.match(scriptPattern)?.[1] : null;
19
- if (!relative || args.length > 1 || args.some(x => !phases.has(x))) return null;
20
- return JSON.stringify([relative, ...args]);
21
- }
22
-
23
- export function requiredHookPresent(actual, expected) {
24
- return actual && actual.type === expected.type && actual.command === expected.command
25
- && JSON.stringify(actual.args) === JSON.stringify(expected.args)
26
- && actual.onFailure === expected.onFailure
27
- && actual.if === undefined && actual.once !== true && actual.async !== true
28
- && (actual.timeout === undefined || actual.timeout >= expected.timeout);
29
- }
30
-
31
- export function referencesNccgsHook(hook) {
32
- return [hook?.command, ...(Array.isArray(hook?.args) ? hook.args : [])]
33
- .some(x => typeof x === 'string' && /(?:^|[\\/])\.claude[\\/]nccgs[\\/]/i.test(x));
34
- }
@@ -1,108 +0,0 @@
1
- import fs from "node:fs";
2
- import { performance } from "node:perf_hooks";
3
- import { contained, json, hash } from "./policy.mjs";
4
-
5
- export const inputManifest = ".nccgs/inputs.json";
6
- export function inputPolicy(project) {
7
- const file = contained(project, inputManifest);
8
- const policy = fs.existsSync(file) ? json(file) : { schemaVersion: 1, canonicalInputs: [], outputDirectories: [], checks: {} };
9
- if (policy.schemaVersion !== 1 || !Array.isArray(policy.canonicalInputs) || !Array.isArray(policy.outputDirectories)
10
- || !policy.checks || typeof policy.checks !== "object" || Array.isArray(policy.checks)) throw new Error("Invalid .nccgs/inputs.json schema");
11
- for (const key of Object.keys(policy)) if (!["schemaVersion", "canonicalInputs", "outputDirectories", "checks", "unityGeneratedFiles"].includes(key)) throw new Error(`Unknown input manifest field: ${key}`);
12
- const generated = policy.unityGeneratedFiles === undefined ? [] : policy.unityGeneratedFiles;
13
- if (!Array.isArray(generated) || generated.length > 256) throw new Error("unityGeneratedFiles must be an array of at most 256 exact file paths");
14
- const seenGenerated = new Set();
15
- for (const relative of generated) {
16
- const file = contained(project, relative);
17
- // Opt-in derived metadata only. Never ignore whole directories, wildcards,
18
- // nested tool projects, source, assets, packages or project settings.
19
- if (!/^[^/]+\.(?:csproj|sln|slnx)$/.test(relative)
20
- && !/^\.vscode\/(?:extensions|launch|settings)\.json$/.test(relative)
21
- && !/^UserSettings\/(?:EditorUserSettings\.asset|Search\.settings)$/.test(relative)) {
22
- throw new Error(`Unsupported Unity generated file: ${relative}`);
23
- }
24
- const key = relative.toLowerCase();
25
- if (seenGenerated.has(key)) throw new Error(`Duplicate Unity generated file: ${relative}`);
26
- seenGenerated.add(key);
27
- if (fs.existsSync(file) && !fs.statSync(file).isFile()) throw new Error(`Unity generated path is not a file: ${relative}`);
28
- for (const input of policy.canonicalInputs) if (overlaps(input, relative)) throw new Error(`Canonical input/generated file overlap: ${input} and ${relative}`);
29
- }
30
- if (generated.length) {
31
- const version = contained(project, "ProjectSettings/ProjectVersion.txt");
32
- if (!fs.existsSync(version) || !/^m_EditorVersion: \d+\.\d+\.\d+[abfp]\d+\s*$/m.test(fs.readFileSync(version, "utf8"))
33
- || !fs.existsSync(contained(project, "Packages/manifest.json")) || !fs.statSync(contained(project, "Assets")).isDirectory()) {
34
- throw new Error("unityGeneratedFiles requires a Unity project (Assets, Packages/manifest.json, ProjectSettings/ProjectVersion.txt)");
35
- }
36
- }
37
- for (const relative of [...policy.canonicalInputs, ...policy.outputDirectories]) contained(project, relative);
38
- for (const relative of policy.outputDirectories) {
39
- // Keep source roots in the snapshot. Unity build destinations must be deliberately
40
- // placed below these dedicated roots; arbitrary ignore globs are not supported.
41
- if (!/^(Build|Builds)\/[A-Za-z0-9_-][A-Za-z0-9_./ -]*$/.test(relative)) throw new Error("Output directories must be explicit subdirectories of Build/ or Builds/");
42
- const file = contained(project, relative);
43
- if (fs.existsSync(file) && !fs.statSync(file).isDirectory()) throw new Error(`Output path is not a directory: ${relative}`);
44
- for (const input of policy.canonicalInputs) if (overlaps(input, relative)) throw new Error(`Canonical input/output overlap: ${input} and ${relative}`);
45
- }
46
- for (const relative of policy.canonicalInputs) {
47
- if (relative.toLowerCase() === ".nccgs" || /^\.nccgs\/(evidence|runtime|tasks|backups|closures)(\/|$)/i.test(relative)) throw new Error(`Generated state cannot be a canonical input: ${relative}`);
48
- }
49
- for (const [name, config] of Object.entries(policy.checks)) {
50
- if (!name.trim() || !config || typeof config !== "object" || Array.isArray(config)
51
- || Object.keys(config).some(key => key !== "timeoutMs") || !Number.isSafeInteger(config.timeoutMs)
52
- || config.timeoutMs < 100 || config.timeoutMs > 7200000) throw new Error(`Check ${name}: timeoutMs must be an integer from 100 to 7200000`);
53
- }
54
- return policy;
55
- }
56
- function overlaps(a, b) {
57
- a = a.toLowerCase(); b = b.toLowerCase();
58
- return a === b || a.startsWith(`${b}/`) || b.startsWith(`${a}/`);
59
- }
60
- export function isOutput(relative, policy) {
61
- const normalize = name => process.platform === "win32" ? name.toLowerCase() : name;
62
- return policy.outputDirectories.some(dir => normalize(relative) === normalize(dir) || normalize(relative).startsWith(`${normalize(dir)}/`));
63
- }
64
- export function isUnityGenerated(relative, policy) {
65
- const normalize = name => process.platform === "win32" ? name.toLowerCase() : name;
66
- return (policy.unityGeneratedFiles ?? []).some(file => normalize(relative) === normalize(file));
67
- }
68
- export function unityGeneratedState(project, policy) {
69
- return (policy.unityGeneratedFiles ?? []).map(relative => {
70
- const file = contained(project, relative);
71
- return { path: relative, sha256: fs.existsSync(file) ? hash(fs.readFileSync(file)) : null };
72
- }).sort((a, b) => a.path < b.path ? -1 : a.path > b.path ? 1 : 0);
73
- }
74
- export function canonicalInputs(project, policy = inputPolicy(project)) {
75
- const entries = new Map();
76
- let bytes = 0, readHashMs = 0;
77
- function capture(relative, optional = false) {
78
- if (entries.has(relative)) return;
79
- const file = contained(project, relative);
80
- if (!fs.existsSync(file)) {
81
- if (!optional) throw new Error(`Canonical input missing: ${relative}`);
82
- entries.set(relative, { path: relative, kind: "missing" });
83
- return;
84
- }
85
- const stat = fs.statSync(file);
86
- if (stat.isDirectory()) {
87
- entries.set(relative, { path: relative, kind: "directory" });
88
- for (const name of fs.readdirSync(file).sort()) capture(`${relative}/${name}`);
89
- } else if (stat.isFile()) {
90
- const start = performance.now();
91
- const data = fs.readFileSync(file);
92
- entries.set(relative, { path: relative, sha256: hash(data), kind: "file" });
93
- readHashMs += performance.now() - start;
94
- bytes += data.length;
95
- } else throw new Error(`Unsupported canonical input: ${relative}`);
96
- }
97
- capture(inputManifest, true);
98
- capture(".nccgs/requirements.yaml", true);
99
- capture(".nccgs/autonomy.json", true);
100
- capture(".nccgs/decisions", true);
101
- for (const relative of policy.canonicalInputs) capture(relative);
102
- const files = [...entries.values()].sort((a, b) => a.path < b.path ? -1 : a.path > b.path ? 1 : 0);
103
- return { schemaVersion: 1, sha256: hash(JSON.stringify(files)), entries: files, bytes, readHashMs };
104
- }
105
- export function pinInputs(project) {
106
- const { schemaVersion, sha256, entries } = canonicalInputs(project);
107
- return { schemaVersion, sha256, entries, pinnedAt: new Date().toISOString() };
108
- }