@enterpriseai/cli 3.19.0 → 3.19.1

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 (362) hide show
  1. package/package.json +1 -1
  2. package/resources/gofer/.gofer-version +4 -357
  3. package/resources/gofer/agents-skills/eai/SKILL.md +365 -0
  4. package/resources/gofer/agents-skills/eai-update/SKILL.md +56 -0
  5. package/resources/gofer/agents-skills/gofer-documentation/SKILL.md +93 -0
  6. package/resources/gofer/bash-scripts/create-new-feature.sh +3 -1
  7. package/resources/gofer/bash-scripts/sync-implementation-status.sh +4 -3
  8. package/resources/gofer/bash-scripts/update-agent-context.sh +7 -8
  9. package/resources/gofer/bash-scripts/validate-artifact.sh +10 -6
  10. package/resources/gofer/bash-scripts/verify-object-type-routing-workspace.sh +184 -0
  11. package/resources/gofer/claude-commands/eai-update.md +46 -0
  12. package/resources/gofer/claude-commands/eai.md +355 -0
  13. package/resources/gofer/claude-skills/eai/SKILL.md +365 -0
  14. package/resources/gofer/claude-skills/eai-update/SKILL.md +56 -0
  15. package/resources/gofer/claude-skills/gofer-documentation/SKILL.md +93 -0
  16. package/resources/gofer/commands/0_gofer_start.md +440 -99
  17. package/resources/gofer/commands/0a_problem_validation.md +187 -27
  18. package/resources/gofer/commands/10_gofer_cloud.md +183 -23
  19. package/resources/gofer/commands/1_gofer_research.md +239 -30
  20. package/resources/gofer/commands/2_gofer_specify.md +239 -35
  21. package/resources/gofer/commands/3_gofer_plan.md +259 -43
  22. package/resources/gofer/commands/4_gofer_tasks.md +401 -81
  23. package/resources/gofer/commands/5_gofer_implement.md +375 -84
  24. package/resources/gofer/commands/6_gofer_validate.md +284 -53
  25. package/resources/gofer/commands/7_gofer_save.md +187 -26
  26. package/resources/gofer/commands/7a_stakeholder_comms.md +183 -23
  27. package/resources/gofer/commands/8_gofer_branding.md +183 -23
  28. package/resources/gofer/commands/9_gofer_tests.md +212 -23
  29. package/resources/gofer/commands/gofer_bootstrap_workspace.md +121 -8
  30. package/resources/gofer/commands/gofer_check_workspace.md +123 -8
  31. package/resources/gofer/commands/gofer_constitution.md +183 -23
  32. package/resources/gofer/commands/gofer_diagnose.md +183 -23
  33. package/resources/gofer/commands/gofer_eai_first_run.md +254 -25
  34. package/resources/gofer/commands/gofer_hydrate.md +183 -23
  35. package/resources/gofer/commands/gofer_personality.md +117 -6
  36. package/resources/gofer/commands/gofer_plan.md +117 -6
  37. package/resources/gofer/commands/gofer_side.md +117 -6
  38. package/resources/gofer/commands/gofer_spec_summary.md +183 -23
  39. package/resources/gofer/commands/gofer_tdd.md +183 -23
  40. package/resources/gofer/commands/gofer_vocabulary.md +185 -25
  41. package/resources/gofer/commands/gofer_zoom_out.md +183 -23
  42. package/resources/gofer/config/typesafe-learning-review.json +16 -0
  43. package/resources/gofer/config/typesafe-semantic-review.json +9 -0
  44. package/resources/gofer/copilot-instructions/gofer-cost.instructions.md +15 -6
  45. package/resources/gofer/copilot-instructions/typescript.instructions.md +1 -1
  46. package/resources/gofer/copilot-prompts/eai-update.prompt.md +58 -0
  47. package/resources/gofer/copilot-prompts/eai.prompt.md +367 -0
  48. package/resources/gofer/gemini/commands/gofer/eai-update.md +22 -0
  49. package/resources/gofer/gemini/commands/gofer/eai-update.toml +2 -0
  50. package/resources/gofer/gemini/commands/gofer/eai.md +357 -0
  51. package/resources/gofer/gemini/commands/gofer/eai.toml +2 -0
  52. package/resources/gofer/gemini/commands/gofer/manifest.json +3 -27
  53. package/resources/gofer/gemini/extension.json +4 -4
  54. package/resources/gofer/github-agents/eai.agent.md +83 -0
  55. package/resources/gofer/github-agents/gofer-business.agent.md +73 -4
  56. package/resources/gofer/github-agents/gofer-implement.agent.md +71 -2
  57. package/resources/gofer/github-agents/gofer-plan.agent.md +72 -2
  58. package/resources/gofer/github-agents/gofer-research.agent.md +72 -2
  59. package/resources/gofer/github-agents/gofer-validate.agent.md +72 -2
  60. package/resources/gofer/github-skills/eai/SKILL.md +365 -0
  61. package/resources/gofer/github-skills/eai-update/SKILL.md +56 -0
  62. package/resources/gofer/github-skills/gofer-documentation/SKILL.md +93 -0
  63. package/resources/gofer/grok-skills/eai/SKILL.md +267 -14
  64. package/resources/gofer/grok-skills/eai-update/SKILL.md +56 -0
  65. package/resources/gofer/hook-scripts/user-prompt-submit.mjs +58 -13
  66. package/resources/gofer/instruction-templates/base/agents-base.md +8 -4
  67. package/resources/gofer/instruction-templates/gofer/gofer-claude.md +7 -5
  68. package/resources/gofer/instruction-templates/gofer/gofer-copilot.md +10 -8
  69. package/resources/gofer/memory/constitution.md +9 -7
  70. package/resources/gofer/memory/gofer-model-policy.yaml +23 -1
  71. package/resources/gofer/memory/lessons.md +0 -31
  72. package/resources/gofer/node-scripts/canonical-descriptions.mjs +1 -1
  73. package/resources/gofer/node-scripts/check-version-alignment.mjs +4 -7
  74. package/resources/gofer/node-scripts/delivery-lineage-corpus.mjs +156 -0
  75. package/resources/gofer/node-scripts/generate-commands.mjs +1073 -265
  76. package/resources/gofer/node-scripts/gofer-acceptance-check.mjs +143 -0
  77. package/resources/gofer/node-scripts/gofer-agent-catalog.mjs +271 -0
  78. package/resources/gofer/node-scripts/gofer-benchmark-executor.mjs +123 -0
  79. package/resources/gofer/node-scripts/gofer-benchmark-sign.mjs +62 -0
  80. package/resources/gofer/node-scripts/gofer-benchmark-signer.mjs +89 -0
  81. package/resources/gofer/node-scripts/gofer-benchmark.mjs +76 -0
  82. package/resources/gofer/node-scripts/gofer-blocker-control.mjs +274 -0
  83. package/resources/gofer/node-scripts/gofer-claude-adapter.mjs +154 -0
  84. package/resources/gofer/node-scripts/gofer-closed-loop-audit.mjs +19 -2
  85. package/resources/gofer/node-scripts/gofer-delivery-check.mjs +121 -0
  86. package/resources/gofer/node-scripts/gofer-encrypted-key.mjs +58 -0
  87. package/resources/gofer/node-scripts/gofer-execution-metrics.mjs +477 -0
  88. package/resources/gofer/node-scripts/gofer-execution-recovery.mjs +334 -0
  89. package/resources/gofer/node-scripts/gofer-grok-adapter.mjs +184 -0
  90. package/resources/gofer/node-scripts/gofer-heldout-corpus.mjs +73 -0
  91. package/resources/gofer/node-scripts/gofer-heldout-snapshot.mjs +286 -0
  92. package/resources/gofer/node-scripts/gofer-heldout-verifier.mjs +211 -0
  93. package/resources/gofer/node-scripts/gofer-host-capability.mjs +335 -0
  94. package/resources/gofer/node-scripts/gofer-independent-reviewer.mjs +130 -0
  95. package/resources/gofer/node-scripts/gofer-live-routing.mjs +109 -0
  96. package/resources/gofer/node-scripts/gofer-local-capability-issuer.mjs +71 -0
  97. package/resources/gofer/node-scripts/gofer-local-isolation.mjs +175 -0
  98. package/resources/gofer/node-scripts/gofer-local-settings-cleanup.mjs +388 -0
  99. package/resources/gofer/node-scripts/gofer-loop-audit.mjs +54 -3
  100. package/resources/gofer/node-scripts/gofer-native-adapter.mjs +567 -0
  101. package/resources/gofer/node-scripts/gofer-native-benchmark-dispatch.mjs +145 -0
  102. package/resources/gofer/node-scripts/gofer-native-runtime.mjs +169 -0
  103. package/resources/gofer/node-scripts/gofer-pre-edit-check.mjs +204 -0
  104. package/resources/gofer/node-scripts/gofer-priority-check.mjs +214 -0
  105. package/resources/gofer/node-scripts/gofer-response-check.mjs +56 -0
  106. package/resources/gofer/node-scripts/gofer-reviewed-learning.mjs +1232 -0
  107. package/resources/gofer/node-scripts/gofer-run-verified-task.mjs +330 -0
  108. package/resources/gofer/node-scripts/gofer-runtime-ledger.mjs +289 -0
  109. package/resources/gofer/node-scripts/gofer-semantic-drift.mjs +584 -0
  110. package/resources/gofer/node-scripts/gofer-surface-update.mjs +1178 -0
  111. package/resources/gofer/node-scripts/gofer-trust-bootstrap.mjs +77 -0
  112. package/resources/gofer/node-scripts/gofer-trusted-benchmark.mjs +102 -0
  113. package/resources/gofer/node-scripts/gofer-trusted-evaluator.mjs +274 -0
  114. package/resources/gofer/node-scripts/gofer-tty-prompt.mjs +34 -0
  115. package/resources/gofer/node-scripts/gofer-typesafe-credentials.mjs +435 -0
  116. package/resources/gofer/node-scripts/gofer-ui-preview.mjs +1212 -0
  117. package/resources/gofer/node-scripts/gofer-verified-execution.mjs +484 -0
  118. package/resources/gofer/node-scripts/gofer-verifier-key-ceremony.mjs +101 -0
  119. package/resources/gofer/node-scripts/gofer-worktree-layout.mjs +32 -0
  120. package/resources/gofer/node-scripts/object-type-routing-phase-bundle.mjs +360 -0
  121. package/resources/gofer/node-scripts/package-agent-plugin.mjs +574 -82
  122. package/resources/gofer/node-scripts/parse-stage-command.mjs +1 -1
  123. package/resources/gofer/node-scripts/render-delivery-lineage.mjs +178 -0
  124. package/resources/gofer/node-scripts/sync-extension-resources.mjs +78 -2
  125. package/resources/gofer/node-scripts/validate-object-type-identifiers.mjs +767 -0
  126. package/resources/gofer/node-scripts/validate-object-type-routing-workspace.mjs +1325 -0
  127. package/resources/gofer/node-scripts/validate-v4-resource-contract.d.mts +44 -0
  128. package/resources/gofer/node-scripts/validate-v4-resource-contract.mjs +957 -0
  129. package/resources/gofer/node-scripts/workspace-bootstrap-lib.mjs +685 -116
  130. package/resources/gofer/references/agent-catalog.json +126 -0
  131. package/resources/gofer/references/blocker-mediation.md +156 -0
  132. package/resources/gofer/references/business-updates-and-goal-checks.md +109 -0
  133. package/resources/gofer/references/delivery-lineage.md +48 -0
  134. package/resources/gofer/references/mvp-capability-validation.md +102 -0
  135. package/resources/gofer/references/platform/README.md +1 -1
  136. package/resources/gofer/references/platform/eai-app-template.md +15 -13
  137. package/resources/gofer/references/platform/eai-auth-access.md +104 -0
  138. package/resources/gofer/references/platform/eai-config-driven-ui.md +5 -5
  139. package/resources/gofer/references/platform/eai-error-catalog.yaml +77 -19
  140. package/resources/gofer/references/platform/eai-repo-contract.md +61 -23
  141. package/resources/gofer/references/platform/eai-service-patterns.md +102 -105
  142. package/resources/gofer/references/platform/eai.md +44 -8
  143. package/resources/gofer/references/platform/vertical-template.md +10 -9
  144. package/resources/gofer/references/priority-outcome-protection.md +152 -0
  145. package/resources/gofer/references/verified-agent-execution.md +179 -0
  146. package/resources/gofer/schemas/gofer-learning-trace-v1.json +70 -0
  147. package/resources/gofer/specify-commands/0_gofer_start.md +440 -99
  148. package/resources/gofer/specify-commands/0a_problem_validation.md +187 -27
  149. package/resources/gofer/specify-commands/10_gofer_cloud.md +183 -23
  150. package/resources/gofer/specify-commands/1_gofer_research.md +239 -30
  151. package/resources/gofer/specify-commands/2_gofer_specify.md +239 -35
  152. package/resources/gofer/specify-commands/3_gofer_plan.md +259 -43
  153. package/resources/gofer/specify-commands/4_gofer_tasks.md +401 -81
  154. package/resources/gofer/specify-commands/5_gofer_implement.md +375 -84
  155. package/resources/gofer/specify-commands/6_gofer_validate.md +284 -53
  156. package/resources/gofer/specify-commands/7_gofer_save.md +187 -26
  157. package/resources/gofer/specify-commands/7a_stakeholder_comms.md +183 -23
  158. package/resources/gofer/specify-commands/8_gofer_branding.md +183 -23
  159. package/resources/gofer/specify-commands/9_gofer_tests.md +212 -23
  160. package/resources/gofer/specify-commands/gofer_bootstrap_workspace.md +121 -8
  161. package/resources/gofer/specify-commands/gofer_check_workspace.md +123 -8
  162. package/resources/gofer/specify-commands/gofer_constitution.md +183 -23
  163. package/resources/gofer/specify-commands/gofer_diagnose.md +183 -23
  164. package/resources/gofer/specify-commands/gofer_eai_first_run.md +254 -25
  165. package/resources/gofer/specify-commands/gofer_hydrate.md +183 -23
  166. package/resources/gofer/specify-commands/gofer_personality.md +117 -6
  167. package/resources/gofer/specify-commands/gofer_plan.md +117 -6
  168. package/resources/gofer/specify-commands/gofer_side.md +117 -6
  169. package/resources/gofer/specify-commands/gofer_spec_summary.md +183 -23
  170. package/resources/gofer/specify-commands/gofer_tdd.md +183 -23
  171. package/resources/gofer/specify-commands/gofer_vocabulary.md +185 -25
  172. package/resources/gofer/specify-commands/gofer_zoom_out.md +183 -23
  173. package/resources/gofer/specify-config/object-type-routing.json +24 -0
  174. package/resources/gofer/specify-config/typesafe-learning-review.json +16 -0
  175. package/resources/gofer/specify-config/typesafe-semantic-review.json +9 -0
  176. package/resources/gofer/system-skills/eai/SKILL.md +365 -0
  177. package/resources/gofer/system-skills/eai-update/SKILL.md +56 -0
  178. package/resources/gofer/system-skills/gofer-documentation/SKILL.md +93 -0
  179. package/resources/gofer/templates/build-map-template.md +64 -0
  180. package/resources/gofer/templates/business-scenarios-template.json +14 -0
  181. package/resources/gofer/templates/ciso-security-summary-template.md +3 -3
  182. package/resources/gofer/templates/context-bundle-template.md +4 -3
  183. package/resources/gofer/templates/contract-pack-template.md +8 -8
  184. package/resources/gofer/templates/cto-architecture-summary-template.md +3 -3
  185. package/resources/gofer/templates/delivery-lineage-template.json +8 -0
  186. package/resources/gofer/templates/eai-preflight-template.md +109 -68
  187. package/resources/gofer/templates/goal-ledger-template.json +1 -1
  188. package/resources/gofer/templates/gofer-model-policy.yaml +28 -6
  189. package/resources/gofer/templates/loop-contract-template.json +3 -1
  190. package/resources/gofer/templates/plan-template.md +8 -7
  191. package/resources/gofer/templates/priority-plan-template.json +29 -0
  192. package/resources/gofer/templates/proposal-review-template.md +6 -3
  193. package/resources/gofer/templates/release-capability-ledger-template.md +24 -0
  194. package/resources/gofer/templates/research-template.md +7 -6
  195. package/resources/gofer/templates/spec-summary-template.md +1 -1
  196. package/resources/gofer/templates/spec-template.md +45 -6
  197. package/resources/gofer/templates/tasks-template.md +12 -3
  198. package/resources/gofer/templates/ui-preview-brief-template.md +55 -5
  199. package/resources/gofer/templates/ui-review-log-template.md +21 -3
  200. package/resources/gofer/templates/ui-show-and-tell-template.md +46 -0
  201. package/resources/gofer/templates/visuals/capability-heatmap-template.md +2 -2
  202. package/resources/gofer/templates/working-backwards-prfaq-template.md +9 -8
  203. package/resources/linked-sources.json +2 -2
  204. package/resources/gofer/agents-skills/0_gofer_start/SKILL.md +0 -1287
  205. package/resources/gofer/agents-skills/0a_problem_validation/SKILL.md +0 -429
  206. package/resources/gofer/agents-skills/10_gofer_cloud/SKILL.md +0 -635
  207. package/resources/gofer/agents-skills/1_gofer_research/SKILL.md +0 -1159
  208. package/resources/gofer/agents-skills/2_gofer_specify/SKILL.md +0 -860
  209. package/resources/gofer/agents-skills/3_gofer_plan/SKILL.md +0 -899
  210. package/resources/gofer/agents-skills/4_gofer_tasks/SKILL.md +0 -760
  211. package/resources/gofer/agents-skills/5_gofer_implement/SKILL.md +0 -944
  212. package/resources/gofer/agents-skills/6_gofer_validate/SKILL.md +0 -2302
  213. package/resources/gofer/agents-skills/7_gofer_save/SKILL.md +0 -423
  214. package/resources/gofer/agents-skills/7a_stakeholder_comms/SKILL.md +0 -508
  215. package/resources/gofer/agents-skills/8_gofer_branding/SKILL.md +0 -315
  216. package/resources/gofer/agents-skills/9_gofer_tests/SKILL.md +0 -558
  217. package/resources/gofer/agents-skills/gofer_bootstrap_workspace/SKILL.md +0 -148
  218. package/resources/gofer/agents-skills/gofer_check_workspace/SKILL.md +0 -119
  219. package/resources/gofer/agents-skills/gofer_constitution/SKILL.md +0 -612
  220. package/resources/gofer/agents-skills/gofer_diagnose/SKILL.md +0 -114
  221. package/resources/gofer/agents-skills/gofer_eai_first_run/SKILL.md +0 -397
  222. package/resources/gofer/agents-skills/gofer_hydrate/SKILL.md +0 -561
  223. package/resources/gofer/agents-skills/gofer_personality/SKILL.md +0 -44
  224. package/resources/gofer/agents-skills/gofer_plan/SKILL.md +0 -40
  225. package/resources/gofer/agents-skills/gofer_side/SKILL.md +0 -45
  226. package/resources/gofer/agents-skills/gofer_spec_summary/SKILL.md +0 -112
  227. package/resources/gofer/agents-skills/gofer_tdd/SKILL.md +0 -112
  228. package/resources/gofer/agents-skills/gofer_vocabulary/SKILL.md +0 -112
  229. package/resources/gofer/agents-skills/gofer_zoom_out/SKILL.md +0 -112
  230. package/resources/gofer/claude-commands/0_gofer_start.md +0 -1282
  231. package/resources/gofer/claude-commands/0a_problem_validation.md +0 -424
  232. package/resources/gofer/claude-commands/10_gofer_cloud.md +0 -630
  233. package/resources/gofer/claude-commands/1_gofer_research.md +0 -1154
  234. package/resources/gofer/claude-commands/2_gofer_specify.md +0 -855
  235. package/resources/gofer/claude-commands/3_gofer_plan.md +0 -894
  236. package/resources/gofer/claude-commands/4_gofer_tasks.md +0 -755
  237. package/resources/gofer/claude-commands/5_gofer_implement.md +0 -939
  238. package/resources/gofer/claude-commands/6_gofer_validate.md +0 -2297
  239. package/resources/gofer/claude-commands/7_gofer_save.md +0 -418
  240. package/resources/gofer/claude-commands/7a_stakeholder_comms.md +0 -503
  241. package/resources/gofer/claude-commands/8_gofer_branding.md +0 -310
  242. package/resources/gofer/claude-commands/9_gofer_tests.md +0 -553
  243. package/resources/gofer/claude-commands/gofer_bootstrap_workspace.md +0 -143
  244. package/resources/gofer/claude-commands/gofer_check_workspace.md +0 -114
  245. package/resources/gofer/claude-commands/gofer_constitution.md +0 -607
  246. package/resources/gofer/claude-commands/gofer_diagnose.md +0 -109
  247. package/resources/gofer/claude-commands/gofer_eai_first_run.md +0 -392
  248. package/resources/gofer/claude-commands/gofer_hydrate.md +0 -556
  249. package/resources/gofer/claude-commands/gofer_personality.md +0 -39
  250. package/resources/gofer/claude-commands/gofer_plan.md +0 -35
  251. package/resources/gofer/claude-commands/gofer_side.md +0 -40
  252. package/resources/gofer/claude-commands/gofer_spec_summary.md +0 -107
  253. package/resources/gofer/claude-commands/gofer_tdd.md +0 -107
  254. package/resources/gofer/claude-commands/gofer_vocabulary.md +0 -107
  255. package/resources/gofer/claude-commands/gofer_zoom_out.md +0 -107
  256. package/resources/gofer/claude-skills/eai-gofer/SKILL.md +0 -56
  257. package/resources/gofer/copilot-prompts/0_gofer_start.prompt.md +0 -1308
  258. package/resources/gofer/copilot-prompts/0a_problem_validation.prompt.md +0 -429
  259. package/resources/gofer/copilot-prompts/10_gofer_cloud.prompt.md +0 -644
  260. package/resources/gofer/copilot-prompts/1_gofer_research.prompt.md +0 -1177
  261. package/resources/gofer/copilot-prompts/2_gofer_specify.prompt.md +0 -878
  262. package/resources/gofer/copilot-prompts/3_gofer_plan.prompt.md +0 -917
  263. package/resources/gofer/copilot-prompts/4_gofer_tasks.prompt.md +0 -778
  264. package/resources/gofer/copilot-prompts/5_gofer_implement.prompt.md +0 -962
  265. package/resources/gofer/copilot-prompts/6_gofer_validate.prompt.md +0 -2310
  266. package/resources/gofer/copilot-prompts/7_gofer_save.prompt.md +0 -433
  267. package/resources/gofer/copilot-prompts/7a_stakeholder_comms.prompt.md +0 -516
  268. package/resources/gofer/copilot-prompts/8_gofer_branding.prompt.md +0 -323
  269. package/resources/gofer/copilot-prompts/9_gofer_tests.prompt.md +0 -566
  270. package/resources/gofer/copilot-prompts/gofer_bootstrap_workspace.prompt.md +0 -161
  271. package/resources/gofer/copilot-prompts/gofer_check_workspace.prompt.md +0 -132
  272. package/resources/gofer/copilot-prompts/gofer_constitution.prompt.md +0 -621
  273. package/resources/gofer/copilot-prompts/gofer_diagnose.prompt.md +0 -127
  274. package/resources/gofer/copilot-prompts/gofer_eai_first_run.prompt.md +0 -410
  275. package/resources/gofer/copilot-prompts/gofer_hydrate.prompt.md +0 -571
  276. package/resources/gofer/copilot-prompts/gofer_personality.prompt.md +0 -57
  277. package/resources/gofer/copilot-prompts/gofer_plan.prompt.md +0 -53
  278. package/resources/gofer/copilot-prompts/gofer_side.prompt.md +0 -58
  279. package/resources/gofer/copilot-prompts/gofer_spec_summary.prompt.md +0 -125
  280. package/resources/gofer/copilot-prompts/gofer_tdd.prompt.md +0 -125
  281. package/resources/gofer/copilot-prompts/gofer_vocabulary.prompt.md +0 -125
  282. package/resources/gofer/copilot-prompts/gofer_zoom_out.prompt.md +0 -125
  283. package/resources/gofer/gemini/commands/gofer/0_gofer_start.md +0 -1282
  284. package/resources/gofer/gemini/commands/gofer/0_gofer_start.toml +0 -2
  285. package/resources/gofer/gemini/commands/gofer/0a_problem_validation.md +0 -424
  286. package/resources/gofer/gemini/commands/gofer/0a_problem_validation.toml +0 -2
  287. package/resources/gofer/gemini/commands/gofer/10_gofer_cloud.md +0 -630
  288. package/resources/gofer/gemini/commands/gofer/10_gofer_cloud.toml +0 -2
  289. package/resources/gofer/gemini/commands/gofer/1_gofer_research.md +0 -1154
  290. package/resources/gofer/gemini/commands/gofer/1_gofer_research.toml +0 -2
  291. package/resources/gofer/gemini/commands/gofer/2_gofer_specify.md +0 -855
  292. package/resources/gofer/gemini/commands/gofer/2_gofer_specify.toml +0 -2
  293. package/resources/gofer/gemini/commands/gofer/3_gofer_plan.md +0 -894
  294. package/resources/gofer/gemini/commands/gofer/3_gofer_plan.toml +0 -2
  295. package/resources/gofer/gemini/commands/gofer/4_gofer_tasks.md +0 -755
  296. package/resources/gofer/gemini/commands/gofer/4_gofer_tasks.toml +0 -2
  297. package/resources/gofer/gemini/commands/gofer/5_gofer_implement.md +0 -939
  298. package/resources/gofer/gemini/commands/gofer/5_gofer_implement.toml +0 -2
  299. package/resources/gofer/gemini/commands/gofer/6_gofer_validate.md +0 -2297
  300. package/resources/gofer/gemini/commands/gofer/6_gofer_validate.toml +0 -2
  301. package/resources/gofer/gemini/commands/gofer/7_gofer_save.md +0 -418
  302. package/resources/gofer/gemini/commands/gofer/7_gofer_save.toml +0 -2
  303. package/resources/gofer/gemini/commands/gofer/7a_stakeholder_comms.md +0 -503
  304. package/resources/gofer/gemini/commands/gofer/7a_stakeholder_comms.toml +0 -2
  305. package/resources/gofer/gemini/commands/gofer/8_gofer_branding.md +0 -310
  306. package/resources/gofer/gemini/commands/gofer/8_gofer_branding.toml +0 -2
  307. package/resources/gofer/gemini/commands/gofer/9_gofer_tests.md +0 -553
  308. package/resources/gofer/gemini/commands/gofer/9_gofer_tests.toml +0 -2
  309. package/resources/gofer/gemini/commands/gofer/gofer_bootstrap_workspace.md +0 -143
  310. package/resources/gofer/gemini/commands/gofer/gofer_bootstrap_workspace.toml +0 -2
  311. package/resources/gofer/gemini/commands/gofer/gofer_check_workspace.md +0 -114
  312. package/resources/gofer/gemini/commands/gofer/gofer_check_workspace.toml +0 -2
  313. package/resources/gofer/gemini/commands/gofer/gofer_constitution.md +0 -607
  314. package/resources/gofer/gemini/commands/gofer/gofer_constitution.toml +0 -2
  315. package/resources/gofer/gemini/commands/gofer/gofer_diagnose.md +0 -109
  316. package/resources/gofer/gemini/commands/gofer/gofer_diagnose.toml +0 -2
  317. package/resources/gofer/gemini/commands/gofer/gofer_eai_first_run.md +0 -392
  318. package/resources/gofer/gemini/commands/gofer/gofer_eai_first_run.toml +0 -2
  319. package/resources/gofer/gemini/commands/gofer/gofer_hydrate.md +0 -556
  320. package/resources/gofer/gemini/commands/gofer/gofer_hydrate.toml +0 -2
  321. package/resources/gofer/gemini/commands/gofer/gofer_personality.md +0 -39
  322. package/resources/gofer/gemini/commands/gofer/gofer_personality.toml +0 -2
  323. package/resources/gofer/gemini/commands/gofer/gofer_plan.md +0 -35
  324. package/resources/gofer/gemini/commands/gofer/gofer_plan.toml +0 -2
  325. package/resources/gofer/gemini/commands/gofer/gofer_side.md +0 -40
  326. package/resources/gofer/gemini/commands/gofer/gofer_side.toml +0 -2
  327. package/resources/gofer/gemini/commands/gofer/gofer_spec_summary.md +0 -107
  328. package/resources/gofer/gemini/commands/gofer/gofer_spec_summary.toml +0 -2
  329. package/resources/gofer/gemini/commands/gofer/gofer_tdd.md +0 -107
  330. package/resources/gofer/gemini/commands/gofer/gofer_tdd.toml +0 -2
  331. package/resources/gofer/gemini/commands/gofer/gofer_vocabulary.md +0 -107
  332. package/resources/gofer/gemini/commands/gofer/gofer_vocabulary.toml +0 -2
  333. package/resources/gofer/gemini/commands/gofer/gofer_zoom_out.md +0 -107
  334. package/resources/gofer/gemini/commands/gofer/gofer_zoom_out.toml +0 -2
  335. package/resources/gofer/github-skills/eai-gofer/SKILL.md +0 -56
  336. package/resources/gofer/system-skills/0_gofer_start/SKILL.md +0 -1287
  337. package/resources/gofer/system-skills/0a_problem_validation/SKILL.md +0 -429
  338. package/resources/gofer/system-skills/10_gofer_cloud/SKILL.md +0 -635
  339. package/resources/gofer/system-skills/1_gofer_research/SKILL.md +0 -1159
  340. package/resources/gofer/system-skills/2_gofer_specify/SKILL.md +0 -860
  341. package/resources/gofer/system-skills/3_gofer_plan/SKILL.md +0 -899
  342. package/resources/gofer/system-skills/4_gofer_tasks/SKILL.md +0 -760
  343. package/resources/gofer/system-skills/5_gofer_implement/SKILL.md +0 -944
  344. package/resources/gofer/system-skills/6_gofer_validate/SKILL.md +0 -2302
  345. package/resources/gofer/system-skills/7_gofer_save/SKILL.md +0 -423
  346. package/resources/gofer/system-skills/7a_stakeholder_comms/SKILL.md +0 -508
  347. package/resources/gofer/system-skills/8_gofer_branding/SKILL.md +0 -315
  348. package/resources/gofer/system-skills/9_gofer_tests/SKILL.md +0 -558
  349. package/resources/gofer/system-skills/gofer_bootstrap_workspace/SKILL.md +0 -148
  350. package/resources/gofer/system-skills/gofer_check_workspace/SKILL.md +0 -119
  351. package/resources/gofer/system-skills/gofer_constitution/SKILL.md +0 -612
  352. package/resources/gofer/system-skills/gofer_diagnose/SKILL.md +0 -114
  353. package/resources/gofer/system-skills/gofer_eai_first_run/SKILL.md +0 -397
  354. package/resources/gofer/system-skills/gofer_hydrate/SKILL.md +0 -561
  355. package/resources/gofer/system-skills/gofer_personality/SKILL.md +0 -44
  356. package/resources/gofer/system-skills/gofer_plan/SKILL.md +0 -40
  357. package/resources/gofer/system-skills/gofer_side/SKILL.md +0 -45
  358. package/resources/gofer/system-skills/gofer_spec_summary/SKILL.md +0 -112
  359. package/resources/gofer/system-skills/gofer_tdd/SKILL.md +0 -112
  360. package/resources/gofer/system-skills/gofer_vocabulary/SKILL.md +0 -112
  361. package/resources/gofer/system-skills/gofer_zoom_out/SKILL.md +0 -112
  362. 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 };