@enterpriseai/cli 3.19.0 → 3.19.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 (364) hide show
  1. package/package.json +3 -3
  2. package/resources/deploy/eai-app-template/producer-pin.json +5 -5
  3. package/resources/deploy/eai-app-template/tests/source-unknown-deployment-evidence.test.mjs +2141 -1
  4. package/resources/gofer/.gofer-version +4 -357
  5. package/resources/gofer/agents-skills/eai/SKILL.md +365 -0
  6. package/resources/gofer/agents-skills/eai-update/SKILL.md +56 -0
  7. package/resources/gofer/agents-skills/gofer-documentation/SKILL.md +93 -0
  8. package/resources/gofer/bash-scripts/create-new-feature.sh +3 -1
  9. package/resources/gofer/bash-scripts/sync-implementation-status.sh +4 -3
  10. package/resources/gofer/bash-scripts/update-agent-context.sh +7 -8
  11. package/resources/gofer/bash-scripts/validate-artifact.sh +10 -6
  12. package/resources/gofer/bash-scripts/verify-object-type-routing-workspace.sh +184 -0
  13. package/resources/gofer/claude-commands/eai-update.md +46 -0
  14. package/resources/gofer/claude-commands/eai.md +355 -0
  15. package/resources/gofer/claude-skills/eai/SKILL.md +365 -0
  16. package/resources/gofer/claude-skills/eai-update/SKILL.md +56 -0
  17. package/resources/gofer/claude-skills/gofer-documentation/SKILL.md +93 -0
  18. package/resources/gofer/commands/0_gofer_start.md +440 -99
  19. package/resources/gofer/commands/0a_problem_validation.md +187 -27
  20. package/resources/gofer/commands/10_gofer_cloud.md +183 -23
  21. package/resources/gofer/commands/1_gofer_research.md +239 -30
  22. package/resources/gofer/commands/2_gofer_specify.md +239 -35
  23. package/resources/gofer/commands/3_gofer_plan.md +259 -43
  24. package/resources/gofer/commands/4_gofer_tasks.md +401 -81
  25. package/resources/gofer/commands/5_gofer_implement.md +375 -84
  26. package/resources/gofer/commands/6_gofer_validate.md +284 -53
  27. package/resources/gofer/commands/7_gofer_save.md +187 -26
  28. package/resources/gofer/commands/7a_stakeholder_comms.md +183 -23
  29. package/resources/gofer/commands/8_gofer_branding.md +183 -23
  30. package/resources/gofer/commands/9_gofer_tests.md +212 -23
  31. package/resources/gofer/commands/gofer_bootstrap_workspace.md +121 -8
  32. package/resources/gofer/commands/gofer_check_workspace.md +123 -8
  33. package/resources/gofer/commands/gofer_constitution.md +183 -23
  34. package/resources/gofer/commands/gofer_diagnose.md +183 -23
  35. package/resources/gofer/commands/gofer_eai_first_run.md +254 -25
  36. package/resources/gofer/commands/gofer_hydrate.md +183 -23
  37. package/resources/gofer/commands/gofer_personality.md +117 -6
  38. package/resources/gofer/commands/gofer_plan.md +117 -6
  39. package/resources/gofer/commands/gofer_side.md +117 -6
  40. package/resources/gofer/commands/gofer_spec_summary.md +183 -23
  41. package/resources/gofer/commands/gofer_tdd.md +183 -23
  42. package/resources/gofer/commands/gofer_vocabulary.md +185 -25
  43. package/resources/gofer/commands/gofer_zoom_out.md +183 -23
  44. package/resources/gofer/config/typesafe-learning-review.json +16 -0
  45. package/resources/gofer/config/typesafe-semantic-review.json +9 -0
  46. package/resources/gofer/copilot-instructions/gofer-cost.instructions.md +15 -6
  47. package/resources/gofer/copilot-instructions/typescript.instructions.md +1 -1
  48. package/resources/gofer/copilot-prompts/eai-update.prompt.md +58 -0
  49. package/resources/gofer/copilot-prompts/eai.prompt.md +367 -0
  50. package/resources/gofer/gemini/commands/gofer/eai-update.md +22 -0
  51. package/resources/gofer/gemini/commands/gofer/eai-update.toml +2 -0
  52. package/resources/gofer/gemini/commands/gofer/eai.md +357 -0
  53. package/resources/gofer/gemini/commands/gofer/eai.toml +2 -0
  54. package/resources/gofer/gemini/commands/gofer/manifest.json +3 -27
  55. package/resources/gofer/gemini/extension.json +4 -4
  56. package/resources/gofer/github-agents/eai.agent.md +83 -0
  57. package/resources/gofer/github-agents/gofer-business.agent.md +73 -4
  58. package/resources/gofer/github-agents/gofer-implement.agent.md +71 -2
  59. package/resources/gofer/github-agents/gofer-plan.agent.md +72 -2
  60. package/resources/gofer/github-agents/gofer-research.agent.md +72 -2
  61. package/resources/gofer/github-agents/gofer-validate.agent.md +72 -2
  62. package/resources/gofer/github-skills/eai/SKILL.md +365 -0
  63. package/resources/gofer/github-skills/eai-update/SKILL.md +56 -0
  64. package/resources/gofer/github-skills/gofer-documentation/SKILL.md +93 -0
  65. package/resources/gofer/grok-skills/eai/SKILL.md +267 -14
  66. package/resources/gofer/grok-skills/eai-update/SKILL.md +56 -0
  67. package/resources/gofer/hook-scripts/user-prompt-submit.mjs +58 -13
  68. package/resources/gofer/instruction-templates/base/agents-base.md +8 -4
  69. package/resources/gofer/instruction-templates/gofer/gofer-claude.md +7 -5
  70. package/resources/gofer/instruction-templates/gofer/gofer-copilot.md +10 -8
  71. package/resources/gofer/memory/constitution.md +9 -7
  72. package/resources/gofer/memory/gofer-model-policy.yaml +23 -1
  73. package/resources/gofer/memory/lessons.md +0 -31
  74. package/resources/gofer/node-scripts/canonical-descriptions.mjs +1 -1
  75. package/resources/gofer/node-scripts/check-version-alignment.mjs +4 -7
  76. package/resources/gofer/node-scripts/delivery-lineage-corpus.mjs +156 -0
  77. package/resources/gofer/node-scripts/generate-commands.mjs +1073 -265
  78. package/resources/gofer/node-scripts/gofer-acceptance-check.mjs +143 -0
  79. package/resources/gofer/node-scripts/gofer-agent-catalog.mjs +271 -0
  80. package/resources/gofer/node-scripts/gofer-benchmark-executor.mjs +123 -0
  81. package/resources/gofer/node-scripts/gofer-benchmark-sign.mjs +62 -0
  82. package/resources/gofer/node-scripts/gofer-benchmark-signer.mjs +89 -0
  83. package/resources/gofer/node-scripts/gofer-benchmark.mjs +76 -0
  84. package/resources/gofer/node-scripts/gofer-blocker-control.mjs +274 -0
  85. package/resources/gofer/node-scripts/gofer-claude-adapter.mjs +154 -0
  86. package/resources/gofer/node-scripts/gofer-closed-loop-audit.mjs +19 -2
  87. package/resources/gofer/node-scripts/gofer-delivery-check.mjs +121 -0
  88. package/resources/gofer/node-scripts/gofer-encrypted-key.mjs +58 -0
  89. package/resources/gofer/node-scripts/gofer-execution-metrics.mjs +477 -0
  90. package/resources/gofer/node-scripts/gofer-execution-recovery.mjs +334 -0
  91. package/resources/gofer/node-scripts/gofer-grok-adapter.mjs +184 -0
  92. package/resources/gofer/node-scripts/gofer-heldout-corpus.mjs +73 -0
  93. package/resources/gofer/node-scripts/gofer-heldout-snapshot.mjs +286 -0
  94. package/resources/gofer/node-scripts/gofer-heldout-verifier.mjs +211 -0
  95. package/resources/gofer/node-scripts/gofer-host-capability.mjs +335 -0
  96. package/resources/gofer/node-scripts/gofer-independent-reviewer.mjs +130 -0
  97. package/resources/gofer/node-scripts/gofer-live-routing.mjs +109 -0
  98. package/resources/gofer/node-scripts/gofer-local-capability-issuer.mjs +71 -0
  99. package/resources/gofer/node-scripts/gofer-local-isolation.mjs +175 -0
  100. package/resources/gofer/node-scripts/gofer-local-settings-cleanup.mjs +388 -0
  101. package/resources/gofer/node-scripts/gofer-loop-audit.mjs +54 -3
  102. package/resources/gofer/node-scripts/gofer-native-adapter.mjs +567 -0
  103. package/resources/gofer/node-scripts/gofer-native-benchmark-dispatch.mjs +145 -0
  104. package/resources/gofer/node-scripts/gofer-native-runtime.mjs +169 -0
  105. package/resources/gofer/node-scripts/gofer-pre-edit-check.mjs +204 -0
  106. package/resources/gofer/node-scripts/gofer-priority-check.mjs +214 -0
  107. package/resources/gofer/node-scripts/gofer-response-check.mjs +56 -0
  108. package/resources/gofer/node-scripts/gofer-reviewed-learning.mjs +1232 -0
  109. package/resources/gofer/node-scripts/gofer-run-verified-task.mjs +330 -0
  110. package/resources/gofer/node-scripts/gofer-runtime-ledger.mjs +289 -0
  111. package/resources/gofer/node-scripts/gofer-semantic-drift.mjs +584 -0
  112. package/resources/gofer/node-scripts/gofer-surface-update.mjs +1178 -0
  113. package/resources/gofer/node-scripts/gofer-trust-bootstrap.mjs +77 -0
  114. package/resources/gofer/node-scripts/gofer-trusted-benchmark.mjs +102 -0
  115. package/resources/gofer/node-scripts/gofer-trusted-evaluator.mjs +274 -0
  116. package/resources/gofer/node-scripts/gofer-tty-prompt.mjs +34 -0
  117. package/resources/gofer/node-scripts/gofer-typesafe-credentials.mjs +435 -0
  118. package/resources/gofer/node-scripts/gofer-ui-preview.mjs +1212 -0
  119. package/resources/gofer/node-scripts/gofer-verified-execution.mjs +484 -0
  120. package/resources/gofer/node-scripts/gofer-verifier-key-ceremony.mjs +101 -0
  121. package/resources/gofer/node-scripts/gofer-worktree-layout.mjs +32 -0
  122. package/resources/gofer/node-scripts/object-type-routing-phase-bundle.mjs +360 -0
  123. package/resources/gofer/node-scripts/package-agent-plugin.mjs +574 -82
  124. package/resources/gofer/node-scripts/parse-stage-command.mjs +1 -1
  125. package/resources/gofer/node-scripts/render-delivery-lineage.mjs +178 -0
  126. package/resources/gofer/node-scripts/sync-extension-resources.mjs +78 -2
  127. package/resources/gofer/node-scripts/validate-object-type-identifiers.mjs +767 -0
  128. package/resources/gofer/node-scripts/validate-object-type-routing-workspace.mjs +1325 -0
  129. package/resources/gofer/node-scripts/validate-v4-resource-contract.d.mts +44 -0
  130. package/resources/gofer/node-scripts/validate-v4-resource-contract.mjs +957 -0
  131. package/resources/gofer/node-scripts/workspace-bootstrap-lib.mjs +685 -116
  132. package/resources/gofer/references/agent-catalog.json +126 -0
  133. package/resources/gofer/references/blocker-mediation.md +156 -0
  134. package/resources/gofer/references/business-updates-and-goal-checks.md +109 -0
  135. package/resources/gofer/references/delivery-lineage.md +48 -0
  136. package/resources/gofer/references/mvp-capability-validation.md +102 -0
  137. package/resources/gofer/references/platform/README.md +1 -1
  138. package/resources/gofer/references/platform/eai-app-template.md +15 -13
  139. package/resources/gofer/references/platform/eai-auth-access.md +104 -0
  140. package/resources/gofer/references/platform/eai-config-driven-ui.md +5 -5
  141. package/resources/gofer/references/platform/eai-error-catalog.yaml +77 -19
  142. package/resources/gofer/references/platform/eai-repo-contract.md +61 -23
  143. package/resources/gofer/references/platform/eai-service-patterns.md +102 -105
  144. package/resources/gofer/references/platform/eai.md +44 -8
  145. package/resources/gofer/references/platform/vertical-template.md +10 -9
  146. package/resources/gofer/references/priority-outcome-protection.md +152 -0
  147. package/resources/gofer/references/verified-agent-execution.md +179 -0
  148. package/resources/gofer/schemas/gofer-learning-trace-v1.json +70 -0
  149. package/resources/gofer/specify-commands/0_gofer_start.md +440 -99
  150. package/resources/gofer/specify-commands/0a_problem_validation.md +187 -27
  151. package/resources/gofer/specify-commands/10_gofer_cloud.md +183 -23
  152. package/resources/gofer/specify-commands/1_gofer_research.md +239 -30
  153. package/resources/gofer/specify-commands/2_gofer_specify.md +239 -35
  154. package/resources/gofer/specify-commands/3_gofer_plan.md +259 -43
  155. package/resources/gofer/specify-commands/4_gofer_tasks.md +401 -81
  156. package/resources/gofer/specify-commands/5_gofer_implement.md +375 -84
  157. package/resources/gofer/specify-commands/6_gofer_validate.md +284 -53
  158. package/resources/gofer/specify-commands/7_gofer_save.md +187 -26
  159. package/resources/gofer/specify-commands/7a_stakeholder_comms.md +183 -23
  160. package/resources/gofer/specify-commands/8_gofer_branding.md +183 -23
  161. package/resources/gofer/specify-commands/9_gofer_tests.md +212 -23
  162. package/resources/gofer/specify-commands/gofer_bootstrap_workspace.md +121 -8
  163. package/resources/gofer/specify-commands/gofer_check_workspace.md +123 -8
  164. package/resources/gofer/specify-commands/gofer_constitution.md +183 -23
  165. package/resources/gofer/specify-commands/gofer_diagnose.md +183 -23
  166. package/resources/gofer/specify-commands/gofer_eai_first_run.md +254 -25
  167. package/resources/gofer/specify-commands/gofer_hydrate.md +183 -23
  168. package/resources/gofer/specify-commands/gofer_personality.md +117 -6
  169. package/resources/gofer/specify-commands/gofer_plan.md +117 -6
  170. package/resources/gofer/specify-commands/gofer_side.md +117 -6
  171. package/resources/gofer/specify-commands/gofer_spec_summary.md +183 -23
  172. package/resources/gofer/specify-commands/gofer_tdd.md +183 -23
  173. package/resources/gofer/specify-commands/gofer_vocabulary.md +185 -25
  174. package/resources/gofer/specify-commands/gofer_zoom_out.md +183 -23
  175. package/resources/gofer/specify-config/object-type-routing.json +24 -0
  176. package/resources/gofer/specify-config/typesafe-learning-review.json +16 -0
  177. package/resources/gofer/specify-config/typesafe-semantic-review.json +9 -0
  178. package/resources/gofer/system-skills/eai/SKILL.md +365 -0
  179. package/resources/gofer/system-skills/eai-update/SKILL.md +56 -0
  180. package/resources/gofer/system-skills/gofer-documentation/SKILL.md +93 -0
  181. package/resources/gofer/templates/build-map-template.md +64 -0
  182. package/resources/gofer/templates/business-scenarios-template.json +14 -0
  183. package/resources/gofer/templates/ciso-security-summary-template.md +3 -3
  184. package/resources/gofer/templates/context-bundle-template.md +4 -3
  185. package/resources/gofer/templates/contract-pack-template.md +8 -8
  186. package/resources/gofer/templates/cto-architecture-summary-template.md +3 -3
  187. package/resources/gofer/templates/delivery-lineage-template.json +8 -0
  188. package/resources/gofer/templates/eai-preflight-template.md +109 -68
  189. package/resources/gofer/templates/goal-ledger-template.json +1 -1
  190. package/resources/gofer/templates/gofer-model-policy.yaml +28 -6
  191. package/resources/gofer/templates/loop-contract-template.json +3 -1
  192. package/resources/gofer/templates/plan-template.md +8 -7
  193. package/resources/gofer/templates/priority-plan-template.json +29 -0
  194. package/resources/gofer/templates/proposal-review-template.md +6 -3
  195. package/resources/gofer/templates/release-capability-ledger-template.md +24 -0
  196. package/resources/gofer/templates/research-template.md +7 -6
  197. package/resources/gofer/templates/spec-summary-template.md +1 -1
  198. package/resources/gofer/templates/spec-template.md +45 -6
  199. package/resources/gofer/templates/tasks-template.md +12 -3
  200. package/resources/gofer/templates/ui-preview-brief-template.md +55 -5
  201. package/resources/gofer/templates/ui-review-log-template.md +21 -3
  202. package/resources/gofer/templates/ui-show-and-tell-template.md +46 -0
  203. package/resources/gofer/templates/visuals/capability-heatmap-template.md +2 -2
  204. package/resources/gofer/templates/working-backwards-prfaq-template.md +9 -8
  205. package/resources/linked-sources.json +4 -4
  206. package/resources/gofer/agents-skills/0_gofer_start/SKILL.md +0 -1287
  207. package/resources/gofer/agents-skills/0a_problem_validation/SKILL.md +0 -429
  208. package/resources/gofer/agents-skills/10_gofer_cloud/SKILL.md +0 -635
  209. package/resources/gofer/agents-skills/1_gofer_research/SKILL.md +0 -1159
  210. package/resources/gofer/agents-skills/2_gofer_specify/SKILL.md +0 -860
  211. package/resources/gofer/agents-skills/3_gofer_plan/SKILL.md +0 -899
  212. package/resources/gofer/agents-skills/4_gofer_tasks/SKILL.md +0 -760
  213. package/resources/gofer/agents-skills/5_gofer_implement/SKILL.md +0 -944
  214. package/resources/gofer/agents-skills/6_gofer_validate/SKILL.md +0 -2302
  215. package/resources/gofer/agents-skills/7_gofer_save/SKILL.md +0 -423
  216. package/resources/gofer/agents-skills/7a_stakeholder_comms/SKILL.md +0 -508
  217. package/resources/gofer/agents-skills/8_gofer_branding/SKILL.md +0 -315
  218. package/resources/gofer/agents-skills/9_gofer_tests/SKILL.md +0 -558
  219. package/resources/gofer/agents-skills/gofer_bootstrap_workspace/SKILL.md +0 -148
  220. package/resources/gofer/agents-skills/gofer_check_workspace/SKILL.md +0 -119
  221. package/resources/gofer/agents-skills/gofer_constitution/SKILL.md +0 -612
  222. package/resources/gofer/agents-skills/gofer_diagnose/SKILL.md +0 -114
  223. package/resources/gofer/agents-skills/gofer_eai_first_run/SKILL.md +0 -397
  224. package/resources/gofer/agents-skills/gofer_hydrate/SKILL.md +0 -561
  225. package/resources/gofer/agents-skills/gofer_personality/SKILL.md +0 -44
  226. package/resources/gofer/agents-skills/gofer_plan/SKILL.md +0 -40
  227. package/resources/gofer/agents-skills/gofer_side/SKILL.md +0 -45
  228. package/resources/gofer/agents-skills/gofer_spec_summary/SKILL.md +0 -112
  229. package/resources/gofer/agents-skills/gofer_tdd/SKILL.md +0 -112
  230. package/resources/gofer/agents-skills/gofer_vocabulary/SKILL.md +0 -112
  231. package/resources/gofer/agents-skills/gofer_zoom_out/SKILL.md +0 -112
  232. package/resources/gofer/claude-commands/0_gofer_start.md +0 -1282
  233. package/resources/gofer/claude-commands/0a_problem_validation.md +0 -424
  234. package/resources/gofer/claude-commands/10_gofer_cloud.md +0 -630
  235. package/resources/gofer/claude-commands/1_gofer_research.md +0 -1154
  236. package/resources/gofer/claude-commands/2_gofer_specify.md +0 -855
  237. package/resources/gofer/claude-commands/3_gofer_plan.md +0 -894
  238. package/resources/gofer/claude-commands/4_gofer_tasks.md +0 -755
  239. package/resources/gofer/claude-commands/5_gofer_implement.md +0 -939
  240. package/resources/gofer/claude-commands/6_gofer_validate.md +0 -2297
  241. package/resources/gofer/claude-commands/7_gofer_save.md +0 -418
  242. package/resources/gofer/claude-commands/7a_stakeholder_comms.md +0 -503
  243. package/resources/gofer/claude-commands/8_gofer_branding.md +0 -310
  244. package/resources/gofer/claude-commands/9_gofer_tests.md +0 -553
  245. package/resources/gofer/claude-commands/gofer_bootstrap_workspace.md +0 -143
  246. package/resources/gofer/claude-commands/gofer_check_workspace.md +0 -114
  247. package/resources/gofer/claude-commands/gofer_constitution.md +0 -607
  248. package/resources/gofer/claude-commands/gofer_diagnose.md +0 -109
  249. package/resources/gofer/claude-commands/gofer_eai_first_run.md +0 -392
  250. package/resources/gofer/claude-commands/gofer_hydrate.md +0 -556
  251. package/resources/gofer/claude-commands/gofer_personality.md +0 -39
  252. package/resources/gofer/claude-commands/gofer_plan.md +0 -35
  253. package/resources/gofer/claude-commands/gofer_side.md +0 -40
  254. package/resources/gofer/claude-commands/gofer_spec_summary.md +0 -107
  255. package/resources/gofer/claude-commands/gofer_tdd.md +0 -107
  256. package/resources/gofer/claude-commands/gofer_vocabulary.md +0 -107
  257. package/resources/gofer/claude-commands/gofer_zoom_out.md +0 -107
  258. package/resources/gofer/claude-skills/eai-gofer/SKILL.md +0 -56
  259. package/resources/gofer/copilot-prompts/0_gofer_start.prompt.md +0 -1308
  260. package/resources/gofer/copilot-prompts/0a_problem_validation.prompt.md +0 -429
  261. package/resources/gofer/copilot-prompts/10_gofer_cloud.prompt.md +0 -644
  262. package/resources/gofer/copilot-prompts/1_gofer_research.prompt.md +0 -1177
  263. package/resources/gofer/copilot-prompts/2_gofer_specify.prompt.md +0 -878
  264. package/resources/gofer/copilot-prompts/3_gofer_plan.prompt.md +0 -917
  265. package/resources/gofer/copilot-prompts/4_gofer_tasks.prompt.md +0 -778
  266. package/resources/gofer/copilot-prompts/5_gofer_implement.prompt.md +0 -962
  267. package/resources/gofer/copilot-prompts/6_gofer_validate.prompt.md +0 -2310
  268. package/resources/gofer/copilot-prompts/7_gofer_save.prompt.md +0 -433
  269. package/resources/gofer/copilot-prompts/7a_stakeholder_comms.prompt.md +0 -516
  270. package/resources/gofer/copilot-prompts/8_gofer_branding.prompt.md +0 -323
  271. package/resources/gofer/copilot-prompts/9_gofer_tests.prompt.md +0 -566
  272. package/resources/gofer/copilot-prompts/gofer_bootstrap_workspace.prompt.md +0 -161
  273. package/resources/gofer/copilot-prompts/gofer_check_workspace.prompt.md +0 -132
  274. package/resources/gofer/copilot-prompts/gofer_constitution.prompt.md +0 -621
  275. package/resources/gofer/copilot-prompts/gofer_diagnose.prompt.md +0 -127
  276. package/resources/gofer/copilot-prompts/gofer_eai_first_run.prompt.md +0 -410
  277. package/resources/gofer/copilot-prompts/gofer_hydrate.prompt.md +0 -571
  278. package/resources/gofer/copilot-prompts/gofer_personality.prompt.md +0 -57
  279. package/resources/gofer/copilot-prompts/gofer_plan.prompt.md +0 -53
  280. package/resources/gofer/copilot-prompts/gofer_side.prompt.md +0 -58
  281. package/resources/gofer/copilot-prompts/gofer_spec_summary.prompt.md +0 -125
  282. package/resources/gofer/copilot-prompts/gofer_tdd.prompt.md +0 -125
  283. package/resources/gofer/copilot-prompts/gofer_vocabulary.prompt.md +0 -125
  284. package/resources/gofer/copilot-prompts/gofer_zoom_out.prompt.md +0 -125
  285. package/resources/gofer/gemini/commands/gofer/0_gofer_start.md +0 -1282
  286. package/resources/gofer/gemini/commands/gofer/0_gofer_start.toml +0 -2
  287. package/resources/gofer/gemini/commands/gofer/0a_problem_validation.md +0 -424
  288. package/resources/gofer/gemini/commands/gofer/0a_problem_validation.toml +0 -2
  289. package/resources/gofer/gemini/commands/gofer/10_gofer_cloud.md +0 -630
  290. package/resources/gofer/gemini/commands/gofer/10_gofer_cloud.toml +0 -2
  291. package/resources/gofer/gemini/commands/gofer/1_gofer_research.md +0 -1154
  292. package/resources/gofer/gemini/commands/gofer/1_gofer_research.toml +0 -2
  293. package/resources/gofer/gemini/commands/gofer/2_gofer_specify.md +0 -855
  294. package/resources/gofer/gemini/commands/gofer/2_gofer_specify.toml +0 -2
  295. package/resources/gofer/gemini/commands/gofer/3_gofer_plan.md +0 -894
  296. package/resources/gofer/gemini/commands/gofer/3_gofer_plan.toml +0 -2
  297. package/resources/gofer/gemini/commands/gofer/4_gofer_tasks.md +0 -755
  298. package/resources/gofer/gemini/commands/gofer/4_gofer_tasks.toml +0 -2
  299. package/resources/gofer/gemini/commands/gofer/5_gofer_implement.md +0 -939
  300. package/resources/gofer/gemini/commands/gofer/5_gofer_implement.toml +0 -2
  301. package/resources/gofer/gemini/commands/gofer/6_gofer_validate.md +0 -2297
  302. package/resources/gofer/gemini/commands/gofer/6_gofer_validate.toml +0 -2
  303. package/resources/gofer/gemini/commands/gofer/7_gofer_save.md +0 -418
  304. package/resources/gofer/gemini/commands/gofer/7_gofer_save.toml +0 -2
  305. package/resources/gofer/gemini/commands/gofer/7a_stakeholder_comms.md +0 -503
  306. package/resources/gofer/gemini/commands/gofer/7a_stakeholder_comms.toml +0 -2
  307. package/resources/gofer/gemini/commands/gofer/8_gofer_branding.md +0 -310
  308. package/resources/gofer/gemini/commands/gofer/8_gofer_branding.toml +0 -2
  309. package/resources/gofer/gemini/commands/gofer/9_gofer_tests.md +0 -553
  310. package/resources/gofer/gemini/commands/gofer/9_gofer_tests.toml +0 -2
  311. package/resources/gofer/gemini/commands/gofer/gofer_bootstrap_workspace.md +0 -143
  312. package/resources/gofer/gemini/commands/gofer/gofer_bootstrap_workspace.toml +0 -2
  313. package/resources/gofer/gemini/commands/gofer/gofer_check_workspace.md +0 -114
  314. package/resources/gofer/gemini/commands/gofer/gofer_check_workspace.toml +0 -2
  315. package/resources/gofer/gemini/commands/gofer/gofer_constitution.md +0 -607
  316. package/resources/gofer/gemini/commands/gofer/gofer_constitution.toml +0 -2
  317. package/resources/gofer/gemini/commands/gofer/gofer_diagnose.md +0 -109
  318. package/resources/gofer/gemini/commands/gofer/gofer_diagnose.toml +0 -2
  319. package/resources/gofer/gemini/commands/gofer/gofer_eai_first_run.md +0 -392
  320. package/resources/gofer/gemini/commands/gofer/gofer_eai_first_run.toml +0 -2
  321. package/resources/gofer/gemini/commands/gofer/gofer_hydrate.md +0 -556
  322. package/resources/gofer/gemini/commands/gofer/gofer_hydrate.toml +0 -2
  323. package/resources/gofer/gemini/commands/gofer/gofer_personality.md +0 -39
  324. package/resources/gofer/gemini/commands/gofer/gofer_personality.toml +0 -2
  325. package/resources/gofer/gemini/commands/gofer/gofer_plan.md +0 -35
  326. package/resources/gofer/gemini/commands/gofer/gofer_plan.toml +0 -2
  327. package/resources/gofer/gemini/commands/gofer/gofer_side.md +0 -40
  328. package/resources/gofer/gemini/commands/gofer/gofer_side.toml +0 -2
  329. package/resources/gofer/gemini/commands/gofer/gofer_spec_summary.md +0 -107
  330. package/resources/gofer/gemini/commands/gofer/gofer_spec_summary.toml +0 -2
  331. package/resources/gofer/gemini/commands/gofer/gofer_tdd.md +0 -107
  332. package/resources/gofer/gemini/commands/gofer/gofer_tdd.toml +0 -2
  333. package/resources/gofer/gemini/commands/gofer/gofer_vocabulary.md +0 -107
  334. package/resources/gofer/gemini/commands/gofer/gofer_vocabulary.toml +0 -2
  335. package/resources/gofer/gemini/commands/gofer/gofer_zoom_out.md +0 -107
  336. package/resources/gofer/gemini/commands/gofer/gofer_zoom_out.toml +0 -2
  337. package/resources/gofer/github-skills/eai-gofer/SKILL.md +0 -56
  338. package/resources/gofer/system-skills/0_gofer_start/SKILL.md +0 -1287
  339. package/resources/gofer/system-skills/0a_problem_validation/SKILL.md +0 -429
  340. package/resources/gofer/system-skills/10_gofer_cloud/SKILL.md +0 -635
  341. package/resources/gofer/system-skills/1_gofer_research/SKILL.md +0 -1159
  342. package/resources/gofer/system-skills/2_gofer_specify/SKILL.md +0 -860
  343. package/resources/gofer/system-skills/3_gofer_plan/SKILL.md +0 -899
  344. package/resources/gofer/system-skills/4_gofer_tasks/SKILL.md +0 -760
  345. package/resources/gofer/system-skills/5_gofer_implement/SKILL.md +0 -944
  346. package/resources/gofer/system-skills/6_gofer_validate/SKILL.md +0 -2302
  347. package/resources/gofer/system-skills/7_gofer_save/SKILL.md +0 -423
  348. package/resources/gofer/system-skills/7a_stakeholder_comms/SKILL.md +0 -508
  349. package/resources/gofer/system-skills/8_gofer_branding/SKILL.md +0 -315
  350. package/resources/gofer/system-skills/9_gofer_tests/SKILL.md +0 -558
  351. package/resources/gofer/system-skills/gofer_bootstrap_workspace/SKILL.md +0 -148
  352. package/resources/gofer/system-skills/gofer_check_workspace/SKILL.md +0 -119
  353. package/resources/gofer/system-skills/gofer_constitution/SKILL.md +0 -612
  354. package/resources/gofer/system-skills/gofer_diagnose/SKILL.md +0 -114
  355. package/resources/gofer/system-skills/gofer_eai_first_run/SKILL.md +0 -397
  356. package/resources/gofer/system-skills/gofer_hydrate/SKILL.md +0 -561
  357. package/resources/gofer/system-skills/gofer_personality/SKILL.md +0 -44
  358. package/resources/gofer/system-skills/gofer_plan/SKILL.md +0 -40
  359. package/resources/gofer/system-skills/gofer_side/SKILL.md +0 -45
  360. package/resources/gofer/system-skills/gofer_spec_summary/SKILL.md +0 -112
  361. package/resources/gofer/system-skills/gofer_tdd/SKILL.md +0 -112
  362. package/resources/gofer/system-skills/gofer_vocabulary/SKILL.md +0 -112
  363. package/resources/gofer/system-skills/gofer_zoom_out/SKILL.md +0 -112
  364. package/resources/gofer/templates/ui-approval-template.md +0 -32
@@ -0,0 +1,767 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { readFile } from 'node:fs/promises';
4
+ import path from 'node:path';
5
+ import { fileURLToPath } from 'node:url';
6
+
7
+ const VALIDATION_SCHEMA_VERSION = 'eai.object-type-routing.validation/v1';
8
+ const CONTRACT_VERSION = 'eai.object-type-routing/v1';
9
+ const INVENTORY_SCHEMA_VERSION = 'eai.object-type-routing.inventory/v1';
10
+ const NAME_RULE = '^[A-Z][A-Za-z0-9]*$';
11
+ const SLUG_RULE = '^[a-z0-9]+(?:-[a-z0-9]+)*$';
12
+ const SCRIPT_DIRECTORY = path.dirname(fileURLToPath(import.meta.url));
13
+ const DEFAULT_CONFIG_PATH = path.resolve(
14
+ SCRIPT_DIRECTORY,
15
+ '..',
16
+ '..',
17
+ 'config',
18
+ 'object-type-routing.json'
19
+ );
20
+ const DEFAULT_SCHEMA_PATH = path.resolve(
21
+ SCRIPT_DIRECTORY,
22
+ '..',
23
+ '..',
24
+ 'schemas',
25
+ 'object-type-identifier-audit-v1.schema.json'
26
+ );
27
+ const DEFAULT_CONTRACT_CANDIDATES = [
28
+ path.resolve(SCRIPT_DIRECTORY, '..', '..', 'contracts', 'object-type-routing-v1.json'),
29
+ path.resolve(SCRIPT_DIRECTORY, '..', 'contracts', 'object-type-routing-v1.json'),
30
+ path.resolve(
31
+ SCRIPT_DIRECTORY,
32
+ '..',
33
+ '..',
34
+ '..',
35
+ '..',
36
+ 'tech-docs',
37
+ 'static',
38
+ 'contracts',
39
+ 'object-type-routing-v1.json'
40
+ ),
41
+ path.resolve('ops/tech-docs/static/contracts/object-type-routing-v1.json'),
42
+ path.resolve('../tech-docs/static/contracts/object-type-routing-v1.json'),
43
+ ];
44
+ const SOURCE_CLASSIFICATION = 'blocking_source_drift';
45
+ const PERSISTED_CLASSIFICATION = 'report_only_persisted_legacy_drift';
46
+ const ACTIVATION_CLASSIFICATION = 'activation_blocker';
47
+ const ESTABLISHED_NAME_SLUGS = new Map([['GitHubConnection', 'github-connection']]);
48
+
49
+ const IS_DIRECT_RUN =
50
+ process.argv[1] && path.resolve(process.argv[1]) === fileURLToPath(import.meta.url);
51
+
52
+ class ValidationInputError extends Error {
53
+ constructor(code, message) {
54
+ super(message);
55
+ this.name = 'ValidationInputError';
56
+ this.code = code;
57
+ }
58
+ }
59
+
60
+ function isRecord(value) {
61
+ return value !== null && typeof value === 'object' && !Array.isArray(value);
62
+ }
63
+
64
+ function jsonTypeMatches(value, expected) {
65
+ if (expected === 'null') return value === null;
66
+ if (expected === 'array') return Array.isArray(value);
67
+ if (expected === 'object') return isRecord(value);
68
+ if (expected === 'integer') return Number.isInteger(value);
69
+ if (expected === 'number') return typeof value === 'number' && Number.isFinite(value);
70
+ return typeof value === expected;
71
+ }
72
+
73
+ /** Canonical JSON is sufficient here because finding sort keys contain only JSON scalars. */
74
+ export function canonicalJson(value) {
75
+ if (value === null || typeof value !== 'object') return JSON.stringify(value);
76
+ if (Array.isArray(value)) return `[${value.map(canonicalJson).join(',')}]`;
77
+ return `{${Object.keys(value)
78
+ .sort()
79
+ .map((key) => `${JSON.stringify(key)}:${canonicalJson(value[key])}`)
80
+ .join(',')}}`;
81
+ }
82
+
83
+ function compareText(left, right) {
84
+ return left < right ? -1 : left > right ? 1 : 0;
85
+ }
86
+
87
+ /** Return a sorted copy; never mutate source or supplied inventory data. */
88
+ export function sortIdentifierFindings(findings) {
89
+ return [...findings].sort((left, right) => {
90
+ for (const [leftValue, rightValue] of [
91
+ [left.classification, right.classification],
92
+ [canonicalJson(left.location), canonicalJson(right.location)],
93
+ [left.rule, right.rule],
94
+ [left.field ?? '', right.field ?? ''],
95
+ ]) {
96
+ const comparison = compareText(String(leftValue), String(rightValue));
97
+ if (comparison !== 0) return comparison;
98
+ }
99
+ return 0;
100
+ });
101
+ }
102
+
103
+ /** The sole Gofer JavaScript adapter for the ordered v1 algorithm. */
104
+ export function deriveObjectTypeSlugV1(value) {
105
+ const normalizedName = String(value).replace(
106
+ /^[\t\n\v\f\r ]+|[\t\n\v\f\r ]+$/g,
107
+ ''
108
+ );
109
+ const derivationSource = ESTABLISHED_NAME_SLUGS.get(normalizedName) ?? normalizedName;
110
+
111
+ return derivationSource
112
+ .replace(/([A-Z]+)([A-Z][a-z])/g, '$1-$2')
113
+ .replace(/([a-z0-9])([A-Z])/g, '$1-$2')
114
+ .replace(/[\t\n\v\f\r _]+/g, '-')
115
+ .replace(/-+/g, '-')
116
+ .replace(/^-+|-+$/g, '')
117
+ .replace(/[A-Z]/g, (character) =>
118
+ String.fromCharCode(character.charCodeAt(0) + ('a'.charCodeAt(0) - 'A'.charCodeAt(0)))
119
+ );
120
+ }
121
+
122
+ async function readJson(file, label) {
123
+ let text;
124
+ try {
125
+ text = await readFile(file, 'utf8');
126
+ } catch {
127
+ throw new ValidationInputError(`${label.toUpperCase()}_UNREADABLE`, `${label} is not readable.`);
128
+ }
129
+ try {
130
+ return { value: JSON.parse(text), text };
131
+ } catch {
132
+ throw new ValidationInputError(`${label.toUpperCase()}_MALFORMED`, `${label} is not valid JSON.`);
133
+ }
134
+ }
135
+
136
+ async function firstReadableContract(candidates) {
137
+ for (const candidate of candidates) {
138
+ try {
139
+ await readFile(candidate, 'utf8');
140
+ return candidate;
141
+ } catch {
142
+ // Search only fixed local candidates; the validator never performs network discovery.
143
+ }
144
+ }
145
+ throw new ValidationInputError(
146
+ 'CONTRACT_UNREADABLE',
147
+ 'canonical routing contract is not readable; supply --contract.'
148
+ );
149
+ }
150
+
151
+ function assertContractAssets(config, schema, routing) {
152
+ if (
153
+ !isRecord(config) ||
154
+ config.schemaVersion !== 'eai.object-type-routing.source-audit-config/v1' ||
155
+ config.contractVersion !== CONTRACT_VERSION
156
+ ) {
157
+ throw new ValidationInputError('CONFIG_UNSUPPORTED', 'routing config is unsupported.');
158
+ }
159
+ if (
160
+ !isRecord(schema) ||
161
+ schema.$id !== 'urn:eai:schema:object-type-identifier-audit:v1' ||
162
+ !isRecord(schema.$defs) ||
163
+ !isRecord(schema.$defs.IdentifierFinding) ||
164
+ !isRecord(schema.$defs.InventoryRun)
165
+ ) {
166
+ throw new ValidationInputError('SCHEMA_UNSUPPORTED', 'identifier audit schema is unsupported.');
167
+ }
168
+ if (
169
+ !isRecord(routing) ||
170
+ routing.contractVersion !== CONTRACT_VERSION ||
171
+ routing.authoritativeTransportIdentifier !== 'slug' ||
172
+ routing.name?.pattern !== NAME_RULE ||
173
+ routing.slug?.pattern !== SLUG_RULE ||
174
+ routing.derivation?.algorithm !== CONTRACT_VERSION ||
175
+ routing.derivation?.establishedNameSlugs?.GitHubConnection !== 'github-connection' ||
176
+ !Array.isArray(routing.derivation?.vectors) ||
177
+ !Array.isArray(routing.slug?.reserved)
178
+ ) {
179
+ throw new ValidationInputError('CONTRACT_UNSUPPORTED', 'canonical routing contract is unsupported.');
180
+ }
181
+ for (const vector of routing.derivation.vectors) {
182
+ if (
183
+ !isRecord(vector) ||
184
+ typeof vector.input !== 'string' ||
185
+ typeof vector.output !== 'string' ||
186
+ typeof vector.manifestNameValid !== 'boolean' ||
187
+ deriveObjectTypeSlugV1(vector.input) !== vector.output
188
+ ) {
189
+ throw new ValidationInputError(
190
+ 'CONTRACT_VECTOR_UNSUPPORTED',
191
+ 'canonical routing corpus does not match the Gofer v1 adapter.'
192
+ );
193
+ }
194
+ }
195
+ }
196
+
197
+ export async function loadIdentifierValidationContract(options = {}) {
198
+ const configPath = options.configPath ?? DEFAULT_CONFIG_PATH;
199
+ const schemaPath = options.schemaPath ?? DEFAULT_SCHEMA_PATH;
200
+ const contractPath =
201
+ options.contractPath ?? (await firstReadableContract(DEFAULT_CONTRACT_CANDIDATES));
202
+ // Preserve error precedence when more than one required asset is invalid.
203
+ const { value: config } = await readJson(configPath, 'config');
204
+ const { value: schema } = await readJson(schemaPath, 'schema');
205
+ const { value: routing } = await readJson(contractPath, 'contract');
206
+ assertContractAssets(config, schema, routing);
207
+
208
+ return Object.freeze({
209
+ contractVersion: CONTRACT_VERSION,
210
+ config,
211
+ auditSchema: schema,
212
+ namePattern: new RegExp(routing.name.pattern),
213
+ slugPattern: new RegExp(routing.slug.pattern),
214
+ reserved: Object.freeze([...routing.slug.reserved]),
215
+ vectors: Object.freeze(routing.derivation.vectors.map((vector) => Object.freeze({ ...vector }))),
216
+ });
217
+ }
218
+
219
+ function sourceLocation(location, field) {
220
+ return {
221
+ kind: 'source',
222
+ file: location?.file ?? 'object-type-manifest.json',
223
+ line: location?.line ?? 1,
224
+ ...(location?.column ? { column: location.column } : {}),
225
+ field,
226
+ };
227
+ }
228
+
229
+ function sourceFinding(contract, location, rule, field, offendingValue, expectedValue, remediation) {
230
+ const normalized = sourceLocation(location, field);
231
+ return {
232
+ contractVersion: contract.contractVersion,
233
+ rule,
234
+ classification: SOURCE_CLASSIFICATION,
235
+ severity: 'error',
236
+ location: {
237
+ kind: normalized.kind,
238
+ file: normalized.file,
239
+ line: normalized.line,
240
+ ...(normalized.column ? { column: normalized.column } : {}),
241
+ },
242
+ field,
243
+ offendingValue,
244
+ ...(expectedValue === undefined ? {} : { expectedValue }),
245
+ remediation,
246
+ };
247
+ }
248
+
249
+ /** Strictly validate one new source definition in fail-fast contract order. */
250
+ export function validateSourceManifest(manifest, contract, location) {
251
+ if (!isRecord(manifest)) {
252
+ return [
253
+ sourceFinding(
254
+ contract,
255
+ location,
256
+ 'OBJECT_TYPE_NAME_NON_CANONICAL',
257
+ 'name',
258
+ null,
259
+ NAME_RULE,
260
+ `Set name to a PascalCase identifier matching ${NAME_RULE}.`
261
+ ),
262
+ ];
263
+ }
264
+ if (typeof manifest.name !== 'string' || !contract.namePattern.test(manifest.name)) {
265
+ return [
266
+ sourceFinding(
267
+ contract,
268
+ location,
269
+ 'OBJECT_TYPE_NAME_NON_CANONICAL',
270
+ 'name',
271
+ typeof manifest.name === 'string' ? manifest.name : null,
272
+ NAME_RULE,
273
+ `Set name to a PascalCase identifier matching ${NAME_RULE}.`
274
+ ),
275
+ ];
276
+ }
277
+
278
+ const expectedSlug = deriveObjectTypeSlugV1(manifest.name);
279
+ if (!Object.hasOwn(manifest, 'slug') || manifest.slug === null || manifest.slug === '') {
280
+ return [
281
+ sourceFinding(
282
+ contract,
283
+ location,
284
+ 'OBJECT_TYPE_SLUG_MISSING',
285
+ 'slug',
286
+ null,
287
+ expectedSlug,
288
+ 'Add slug using the v1 derivation of name.'
289
+ ),
290
+ ];
291
+ }
292
+ if (
293
+ typeof manifest.slug !== 'string' ||
294
+ !contract.slugPattern.test(manifest.slug) ||
295
+ contract.reserved.includes(manifest.slug)
296
+ ) {
297
+ return [
298
+ sourceFinding(
299
+ contract,
300
+ location,
301
+ 'OBJECT_TYPE_SLUG_NON_CANONICAL',
302
+ 'slug',
303
+ typeof manifest.slug === 'string' ? manifest.slug : null,
304
+ { pattern: SLUG_RULE, reserved: [...contract.reserved] },
305
+ `Set slug to a non-reserved kebab-case identifier matching ${SLUG_RULE}.`
306
+ ),
307
+ ];
308
+ }
309
+ if (manifest.slug !== expectedSlug) {
310
+ return [
311
+ sourceFinding(
312
+ contract,
313
+ location,
314
+ 'OBJECT_TYPE_SLUG_DERIVATION_MISMATCH',
315
+ 'slug',
316
+ manifest.slug,
317
+ expectedSlug,
318
+ 'Set slug to the v1 derivation of name.'
319
+ ),
320
+ ];
321
+ }
322
+ return [];
323
+ }
324
+
325
+ function resolveLocalReference(rootSchema, reference) {
326
+ if (!reference.startsWith('#/')) return undefined;
327
+ return reference
328
+ .slice(2)
329
+ .split('/')
330
+ .map((part) => part.replace(/~1/g, '/').replace(/~0/g, '~'))
331
+ .reduce((value, part) => value?.[part], rootSchema);
332
+ }
333
+
334
+ function schemaErrors(value, schema, rootSchema, instancePath = '$') {
335
+ if (!isRecord(schema)) return [{ path: instancePath, reason: 'unsupported schema node' }];
336
+ if (typeof schema.$ref === 'string') {
337
+ const resolved = resolveLocalReference(rootSchema, schema.$ref);
338
+ return resolved
339
+ ? schemaErrors(value, resolved, rootSchema, instancePath)
340
+ : [{ path: instancePath, reason: 'unsupported schema reference' }];
341
+ }
342
+ if (Array.isArray(schema.oneOf)) {
343
+ const matches = schema.oneOf.filter(
344
+ (candidate) => schemaErrors(value, candidate, rootSchema, instancePath).length === 0
345
+ );
346
+ if (matches.length !== 1) return [{ path: instancePath, reason: 'must match exactly one schema' }];
347
+ }
348
+ const expectedTypes = Array.isArray(schema.type)
349
+ ? schema.type
350
+ : typeof schema.type === 'string'
351
+ ? [schema.type]
352
+ : [];
353
+ if (expectedTypes.length > 0 && !expectedTypes.some((type) => jsonTypeMatches(value, type))) {
354
+ return [{ path: instancePath, reason: `must have type ${expectedTypes.join('|')}` }];
355
+ }
356
+
357
+ const errors = [];
358
+ if (Object.hasOwn(schema, 'const') && canonicalJson(value) !== canonicalJson(schema.const)) {
359
+ errors.push({ path: instancePath, reason: 'must equal the required constant' });
360
+ }
361
+ if (
362
+ Array.isArray(schema.enum) &&
363
+ !schema.enum.some((candidate) => canonicalJson(candidate) === canonicalJson(value))
364
+ ) {
365
+ errors.push({ path: instancePath, reason: 'must be an allowed value' });
366
+ }
367
+ if (typeof value === 'string') {
368
+ if (Number.isInteger(schema.minLength) && value.length < schema.minLength) {
369
+ errors.push({ path: instancePath, reason: `must have length >= ${schema.minLength}` });
370
+ }
371
+ if (typeof schema.pattern === 'string' && !new RegExp(schema.pattern).test(value)) {
372
+ errors.push({ path: instancePath, reason: 'must match the required pattern' });
373
+ }
374
+ if (
375
+ schema.format === 'date-time' &&
376
+ (!/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d+)?Z$/.test(value) ||
377
+ Number.isNaN(Date.parse(value)))
378
+ ) {
379
+ errors.push({ path: instancePath, reason: 'must be a valid UTC date-time' });
380
+ }
381
+ }
382
+ if (typeof value === 'number' && Number.isFinite(schema.minimum) && value < schema.minimum) {
383
+ errors.push({ path: instancePath, reason: `must be >= ${schema.minimum}` });
384
+ }
385
+ if (Array.isArray(value) && isRecord(schema.items)) {
386
+ value.forEach((item, index) => {
387
+ errors.push(...schemaErrors(item, schema.items, rootSchema, `${instancePath}[${index}]`));
388
+ });
389
+ }
390
+ if (isRecord(value)) {
391
+ const properties = isRecord(schema.properties) ? schema.properties : {};
392
+ if (Array.isArray(schema.required)) {
393
+ for (const property of schema.required) {
394
+ if (!Object.hasOwn(value, property)) {
395
+ errors.push({ path: `${instancePath}.${property}`, reason: 'is required' });
396
+ }
397
+ }
398
+ }
399
+ if (schema.additionalProperties === false) {
400
+ for (const property of Object.keys(value)) {
401
+ if (!Object.hasOwn(properties, property)) {
402
+ errors.push({ path: `${instancePath}.${property}`, reason: 'is not allowed' });
403
+ }
404
+ }
405
+ }
406
+ for (const [property, propertySchema] of Object.entries(properties)) {
407
+ if (Object.hasOwn(value, property)) {
408
+ errors.push(
409
+ ...schemaErrors(value[property], propertySchema, rootSchema, `${instancePath}.${property}`)
410
+ );
411
+ }
412
+ }
413
+ }
414
+ if (Array.isArray(schema.allOf)) {
415
+ for (const child of schema.allOf) {
416
+ if (!isRecord(child)) continue;
417
+ const conditionMatches =
418
+ !isRecord(child.if) || schemaErrors(value, child.if, rootSchema, instancePath).length === 0;
419
+ if (conditionMatches && isRecord(child.then)) {
420
+ errors.push(...schemaErrors(value, child.then, rootSchema, instancePath));
421
+ }
422
+ if (!conditionMatches && isRecord(child.else)) {
423
+ errors.push(...schemaErrors(value, child.else, rootSchema, instancePath));
424
+ }
425
+ }
426
+ }
427
+ return errors;
428
+ }
429
+
430
+ function findingSemanticError(finding, report) {
431
+ const locationKind = finding.location.kind;
432
+ const expected = (() => {
433
+ if (locationKind === 'source') return [SOURCE_CLASSIFICATION, 'error'];
434
+ if (
435
+ locationKind === 'persisted' &&
436
+ finding.rule === 'OBJECT_TYPE_SLUG_DERIVATION_MISMATCH'
437
+ ) {
438
+ return [PERSISTED_CLASSIFICATION, 'warning'];
439
+ }
440
+ if (locationKind === 'persisted' && finding.rule === 'OBJECT_TYPE_SLUG_NON_CANONICAL') {
441
+ return [ACTIVATION_CLASSIFICATION, 'error'];
442
+ }
443
+ if (locationKind === 'inventory' && finding.rule === 'OBJECT_TYPE_INVENTORY_INCOMPLETE') {
444
+ return [ACTIVATION_CLASSIFICATION, 'error'];
445
+ }
446
+ return undefined;
447
+ })();
448
+ if (!expected || finding.classification !== expected[0] || finding.severity !== expected[1]) {
449
+ return 'finding rule, location, classification, and severity are inconsistent';
450
+ }
451
+ if (locationKind === 'source') {
452
+ return 'inventory reports cannot contain source-code findings';
453
+ }
454
+ if (locationKind === 'persisted') {
455
+ if (
456
+ !isHmacReference(finding.location.tenantRef) ||
457
+ !isHmacReference(finding.location.recordRef)
458
+ ) {
459
+ return 'persisted locations must use HMAC-redacted references';
460
+ }
461
+ if (!/separately approved[\s\S]*migration/i.test(finding.remediation)) {
462
+ return 'persisted remediation must require a separately approved migration';
463
+ }
464
+ }
465
+ if (
466
+ locationKind === 'inventory' &&
467
+ (finding.location.environment !== report.environment || finding.location.region !== report.region)
468
+ ) {
469
+ return 'inventory finding location must match the report target';
470
+ }
471
+ return undefined;
472
+ }
473
+
474
+ function findingsSummary(findings) {
475
+ return findings.reduce(
476
+ (summary, finding) => {
477
+ summary[finding.classification] += 1;
478
+ return summary;
479
+ },
480
+ {
481
+ blocking_source_drift: 0,
482
+ report_only_persisted_legacy_drift: 0,
483
+ activation_blocker: 0,
484
+ }
485
+ );
486
+ }
487
+
488
+ function isHmacReference(value) {
489
+ return /^(?:[a-z-]+:)?hmac-sha256:[A-Za-z0-9._:-]+$/.test(String(value));
490
+ }
491
+
492
+ function inventoryCompletenessFailures(report) {
493
+ const failures = [];
494
+ if (report.status !== 'complete') failures.push('status');
495
+ if (report.writeAttemptCount !== 0) failures.push('writeAttemptCount');
496
+ if (report.identityKind !== 'USER') failures.push('identityKind');
497
+ if (report.roleVisibilityComplete !== true) failures.push('roleVisibilityComplete');
498
+ if (report.expectedActiveTenantCount !== report.scannedTenantCount) failures.push('tenantCount');
499
+ if (report.expectedTenantSetDigest !== report.scannedTenantSetDigest) failures.push('tenantSetDigest');
500
+ if (report.prePostUniverseStable !== true) failures.push('prePostUniverseStable');
501
+ if (report.tenantPagination.terminal !== true) failures.push('tenantPagination');
502
+ if (report.tenantPagination.recordCount !== report.expectedActiveTenantCount) {
503
+ failures.push('tenantPaginationRecordCount');
504
+ }
505
+ if (
506
+ report.objectTypePagination.length !== report.expectedActiveTenantCount ||
507
+ report.objectTypePagination.some((evidence) => evidence.terminal !== true)
508
+ ) {
509
+ failures.push('objectTypePagination');
510
+ }
511
+ if (
512
+ report.objectTypePagination.reduce((total, evidence) => total + evidence.pageCount, 0) !==
513
+ report.objectTypePageCount
514
+ ) {
515
+ failures.push('objectTypePageCount');
516
+ }
517
+ if (
518
+ report.objectTypePagination.reduce((total, evidence) => total + evidence.recordCount, 0) !==
519
+ report.objectTypeRecordCount
520
+ ) {
521
+ failures.push('objectTypeRecordCount');
522
+ }
523
+ if (report.sourceErrorCount !== 0) failures.push('sourceErrorCount');
524
+ if (Date.parse(report.snapshotStartedAt) > Date.parse(report.snapshotCompletedAt)) {
525
+ failures.push('snapshotOrder');
526
+ }
527
+ if (report.snapshotBasis === 'stable_pre_post_enumeration') {
528
+ if (
529
+ report.preTenantSetDigest !== report.postTenantSetDigest ||
530
+ report.preTenantSetDigest !== report.expectedTenantSetDigest ||
531
+ report.postTenantSetDigest !== report.scannedTenantSetDigest
532
+ ) {
533
+ failures.push('prePostTenantSetDigest');
534
+ }
535
+ }
536
+ return [...new Set(failures)].sort();
537
+ }
538
+
539
+ /** Validate one already-collected report without login, network calls, or writes. */
540
+ export function validateInventoryReport(report, contract) {
541
+ const inventorySchema = contract.auditSchema.$defs.InventoryRun;
542
+ const errors = schemaErrors(report, inventorySchema, contract.auditSchema).sort((left, right) =>
543
+ compareText(`${left.path}:${left.reason}`, `${right.path}:${right.reason}`)
544
+ );
545
+ if (errors.length > 0) {
546
+ return {
547
+ complete: false,
548
+ exitCode: 4,
549
+ findings: [],
550
+ errors,
551
+ completenessFailures: [],
552
+ };
553
+ }
554
+
555
+ if (!isHmacReference(report.releaseOwnerUserRef)) {
556
+ errors.push({
557
+ path: '$.releaseOwnerUserRef',
558
+ reason: 'must be a privacy-safe HMAC reference',
559
+ });
560
+ }
561
+ report.findings.forEach((finding, index) => {
562
+ const reason = findingSemanticError(finding, report);
563
+ if (reason) errors.push({ path: `$.findings[${index}]`, reason });
564
+ });
565
+ const sortedFindings = sortIdentifierFindings(report.findings);
566
+ if (canonicalJson(sortedFindings) !== canonicalJson(report.findings)) {
567
+ errors.push({ path: '$.findings', reason: 'must use canonical finding order' });
568
+ }
569
+ const sortedPagination = [...report.objectTypePagination].sort((left, right) =>
570
+ compareText(left.tenantRef, right.tenantRef)
571
+ );
572
+ if (canonicalJson(sortedPagination) !== canonicalJson(report.objectTypePagination)) {
573
+ errors.push({ path: '$.objectTypePagination', reason: 'must be sorted by tenantRef' });
574
+ }
575
+ if (new Set(report.objectTypePagination.map(({ tenantRef }) => tenantRef)).size !== report.objectTypePagination.length) {
576
+ errors.push({ path: '$.objectTypePagination', reason: 'must contain unique tenantRef values' });
577
+ }
578
+ for (const [index, evidence] of report.objectTypePagination.entries()) {
579
+ if (!isHmacReference(evidence.tenantRef)) {
580
+ errors.push({
581
+ path: `$.objectTypePagination[${index}].tenantRef`,
582
+ reason: 'must be a privacy-safe HMAC reference',
583
+ });
584
+ }
585
+ }
586
+ if (canonicalJson(findingsSummary(report.findings)) !== canonicalJson(report.findingsSummary)) {
587
+ errors.push({ path: '$.findingsSummary', reason: 'must equal the findings classification counts' });
588
+ }
589
+ errors.sort((left, right) =>
590
+ compareText(`${left.path}:${left.reason}`, `${right.path}:${right.reason}`)
591
+ );
592
+ if (errors.length > 0) {
593
+ return {
594
+ complete: false,
595
+ exitCode: 4,
596
+ findings: [],
597
+ errors,
598
+ completenessFailures: [],
599
+ };
600
+ }
601
+
602
+ const completenessFailures = inventoryCompletenessFailures(report);
603
+ const complete = completenessFailures.length === 0;
604
+ const hasBlockingFinding = report.findings.some(
605
+ ({ classification }) =>
606
+ classification === SOURCE_CLASSIFICATION || classification === ACTIVATION_CLASSIFICATION
607
+ );
608
+ return {
609
+ complete,
610
+ exitCode: complete ? (hasBlockingFinding ? 2 : 0) : 3,
611
+ findings: sortedFindings,
612
+ errors: [],
613
+ completenessFailures,
614
+ };
615
+ }
616
+
617
+ function manifestEntries(value) {
618
+ if (Array.isArray(value)) {
619
+ return value.map((manifest, index) => ({ manifest, index }));
620
+ }
621
+ if (!isRecord(value)) return [];
622
+ if (Object.hasOwn(value, 'name') || Object.hasOwn(value, 'slug')) {
623
+ return [{ manifest: value, index: 0 }];
624
+ }
625
+ const entries = [];
626
+ for (const key of Object.keys(value).sort()) {
627
+ if (!Array.isArray(value[key])) continue;
628
+ for (const manifest of value[key]) entries.push({ manifest, index: entries.length });
629
+ }
630
+ return entries;
631
+ }
632
+
633
+ function parseArguments(argv) {
634
+ const options = { json: false };
635
+ for (let index = 0; index < argv.length; index += 1) {
636
+ const argument = argv[index];
637
+ if (argument === '--json') {
638
+ options.json = true;
639
+ continue;
640
+ }
641
+ if (['--manifest', '--inventory', '--contract', '--schema', '--config'].includes(argument)) {
642
+ const value = argv[index + 1];
643
+ if (!value || value.startsWith('--')) {
644
+ throw new ValidationInputError('ARGUMENT_MISSING', `${argument} requires a path.`);
645
+ }
646
+ options[argument.slice(2)] = value;
647
+ index += 1;
648
+ continue;
649
+ }
650
+ throw new ValidationInputError('ARGUMENT_UNSUPPORTED', `Unsupported argument: ${argument}`);
651
+ }
652
+ if (Boolean(options.manifest) === Boolean(options.inventory)) {
653
+ throw new ValidationInputError(
654
+ 'INPUT_KIND_UNSUPPORTED',
655
+ 'Supply exactly one of --manifest or --inventory.'
656
+ );
657
+ }
658
+ return options;
659
+ }
660
+
661
+ function outputResult(result, json) {
662
+ if (json) {
663
+ process.stdout.write(`${JSON.stringify(result, null, 2)}\n`);
664
+ return;
665
+ }
666
+ process.stdout.write(
667
+ `${result.status}: ${result.findings?.length ?? 0} finding(s), exit ${result.exitCode}\n`
668
+ );
669
+ }
670
+
671
+ async function runCli(argv) {
672
+ let options;
673
+ try {
674
+ options = parseArguments(argv);
675
+ const contract = await loadIdentifierValidationContract({
676
+ contractPath: options.contract,
677
+ schemaPath: options.schema,
678
+ configPath: options.config,
679
+ });
680
+ if (options.manifest) {
681
+ const { value } = await readJson(options.manifest, 'manifest');
682
+ const entries = manifestEntries(value);
683
+ if (entries.length === 0) {
684
+ throw new ValidationInputError(
685
+ 'MANIFEST_SHAPE_UNSUPPORTED',
686
+ 'manifest must be one definition, an array, or a keyed array map.'
687
+ );
688
+ }
689
+ const findings = sortIdentifierFindings(
690
+ entries.flatMap(({ manifest, index }) =>
691
+ validateSourceManifest(manifest, contract, {
692
+ file: options.manifest.replace(/\\/g, '/'),
693
+ line: index + 1,
694
+ })
695
+ )
696
+ );
697
+ const exitCode = findings.length > 0 ? 2 : 0;
698
+ const result = {
699
+ schemaVersion: VALIDATION_SCHEMA_VERSION,
700
+ contractVersion: contract.contractVersion,
701
+ inputKind: 'source_manifest',
702
+ status: exitCode === 0 ? 'valid' : 'blocked',
703
+ exitCode,
704
+ findings,
705
+ errors: [],
706
+ };
707
+ outputResult(result, options.json);
708
+ return exitCode;
709
+ }
710
+
711
+ const { value: report } = await readJson(options.inventory, 'inventory');
712
+ const validation = validateInventoryReport(report, contract);
713
+ const status =
714
+ validation.exitCode === 4
715
+ ? 'malformed'
716
+ : validation.exitCode === 3
717
+ ? 'incomplete'
718
+ : validation.exitCode === 2
719
+ ? 'blocked'
720
+ : 'valid';
721
+ const result = {
722
+ schemaVersion: VALIDATION_SCHEMA_VERSION,
723
+ contractVersion: contract.contractVersion,
724
+ inputKind: 'inventory',
725
+ status,
726
+ exitCode: validation.exitCode,
727
+ findings: validation.findings,
728
+ errors: validation.errors,
729
+ completenessFailures: validation.completenessFailures,
730
+ };
731
+ outputResult(result, options.json);
732
+ return validation.exitCode;
733
+ } catch (error) {
734
+ const result = {
735
+ schemaVersion: VALIDATION_SCHEMA_VERSION,
736
+ contractVersion: CONTRACT_VERSION,
737
+ inputKind: options?.inventory ? 'inventory' : options?.manifest ? 'source_manifest' : 'unsupported',
738
+ status: 'malformed',
739
+ exitCode: 4,
740
+ findings: [],
741
+ errors: [
742
+ {
743
+ code: error instanceof ValidationInputError ? error.code : 'VALIDATION_FAILED',
744
+ message:
745
+ error instanceof ValidationInputError
746
+ ? error.message
747
+ : 'Identifier validation could not be completed.',
748
+ },
749
+ ],
750
+ };
751
+ outputResult(result, options?.json ?? argv.includes('--json'));
752
+ return 4;
753
+ }
754
+ }
755
+
756
+ if (IS_DIRECT_RUN) {
757
+ process.exitCode = await runCli(process.argv.slice(2));
758
+ }
759
+
760
+ export const IDENTIFIER_VALIDATION_EXIT_CODES = Object.freeze({
761
+ valid: 0,
762
+ blocked: 2,
763
+ incomplete: 3,
764
+ malformed: 4,
765
+ });
766
+
767
+ export { INVENTORY_SCHEMA_VERSION };