@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,1325 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { spawnSync } from 'node:child_process';
4
+ import { createHash } from 'node:crypto';
5
+ import { accessSync, constants as fsConstants, promises as fs } from 'node:fs';
6
+ import path from 'node:path';
7
+ import { fileURLToPath, pathToFileURL } from 'node:url';
8
+
9
+ import {
10
+ canonicalJson,
11
+ deriveObjectTypeSlugV1,
12
+ loadIdentifierValidationContract,
13
+ } from './validate-object-type-identifiers.mjs';
14
+
15
+ const SCHEMA_VERSION = 'eai.object-type-routing.workspace-compatibility/v1';
16
+ const CONTRACT_VERSION = 'eai.object-type-routing/v1';
17
+ const SCRIPT_PATH = fileURLToPath(import.meta.url);
18
+ const IS_DIRECT_RUN = process.argv[1] && path.resolve(process.argv[1]) === SCRIPT_PATH;
19
+ const SOURCE_ROUTE_OWNER = 'front/eai-app-template/packages/platform-sdk/src/resource-routing.ts';
20
+ const GOVERNED_FIELDS = Object.freeze([
21
+ 'object_type',
22
+ 'parent_type',
23
+ 'objectTypes',
24
+ 'object_types',
25
+ 'parent_object_type',
26
+ 'target_type',
27
+ ]);
28
+ const RESERVED_SLUGS = Object.freeze(['operations', 'query', 'search', 'storage']);
29
+ const NAME_PATTERN = '^[A-Z][A-Za-z0-9]*$';
30
+ const SLUG_PATTERN = '^[a-z0-9]+(?:-[a-z0-9]+)*$';
31
+ const OPENAPI_FIELD_ALIASES = Object.freeze({
32
+ parent_object_type: Object.freeze(['parent_object_type', 'parentType']),
33
+ });
34
+ const RELATIONSHIP_REFERENCES = Object.freeze({
35
+ sourceField: 'linkTypes[].targetObjectType',
36
+ sourceAcceptedIdentifiers: Object.freeze(['same-manifest-name', 'slug']),
37
+ adapterMustEmit: 'slug',
38
+ persistedIdentifier: 'slug',
39
+ runtimeField: 'target_type',
40
+ runtimeIdentifier: 'slug',
41
+ historicalStoredSlugIsAuthoritative: true,
42
+ });
43
+ const RELATIONSHIP_REFERENCE_VECTORS = Object.freeze([
44
+ Object.freeze({
45
+ declaredName: 'GitHubConnection',
46
+ declaredSlug: 'github-connection',
47
+ sourceReference: 'GitHubConnection',
48
+ emittedReference: 'github-connection',
49
+ }),
50
+ Object.freeze({
51
+ declaredName: 'OPAMeasure',
52
+ declaredSlug: 'opameasure',
53
+ sourceReference: 'OPAMeasure',
54
+ emittedReference: 'opameasure',
55
+ }),
56
+ ]);
57
+
58
+ const ADAPTERS = Object.freeze([
59
+ {
60
+ component: 'Configurator',
61
+ kind: 'typescript',
62
+ path: 'front/Configurator/src/collections/ObjectTypes/identifierContract.ts',
63
+ },
64
+ {
65
+ component: 'eai-app-template',
66
+ kind: 'typescript',
67
+ path: 'front/eai-app-template/packages/platform-sdk/src/resource-routing.ts',
68
+ },
69
+ {
70
+ component: 'eai-cli',
71
+ kind: 'typescript',
72
+ path: 'ops/eai-cli/src/lib/object-type-identifiers.ts',
73
+ },
74
+ {
75
+ component: 'eai-gofer',
76
+ kind: 'gofer',
77
+ path: 'ops/gofer/.specify/scripts/node/validate-object-type-identifiers.mjs',
78
+ },
79
+ {
80
+ component: 'PublicAPI',
81
+ kind: 'python',
82
+ path: 'mid/PublicAPI/src/app/services/object_type_identifiers.py',
83
+ },
84
+ {
85
+ component: 'AdminAPI',
86
+ kind: 'python',
87
+ path: 'mid/AdminAPI/src/services/object_type_identifiers.py',
88
+ },
89
+ {
90
+ component: 'ResourceAPI',
91
+ kind: 'python',
92
+ path: 'mid/ResourceAPI/src/services/object_type_identifiers.py',
93
+ },
94
+ ]);
95
+
96
+ const COVERAGE_OWNERS = Object.freeze([
97
+ ['Configurator', 'front/Configurator/.eai/test-coverage.json'],
98
+ ['eai-app-template', 'front/eai-app-template/.eai/test-coverage.json'],
99
+ ['eai-cli', 'ops/eai-cli/.eai/test-coverage.json'],
100
+ ['eai-gofer', 'ops/gofer/.eai/test-coverage.json'],
101
+ ['PublicAPI', 'mid/PublicAPI/.eai/test-coverage.json'],
102
+ ['AdminAPI', 'mid/AdminAPI/.eai/test-coverage.json'],
103
+ ['ResourceAPI', 'mid/ResourceAPI/.eai/test-coverage.json'],
104
+ ['tech-docs', 'ops/tech-docs/.eai/test-coverage.json'],
105
+ ]);
106
+
107
+ const MIRRORS = Object.freeze([
108
+ {
109
+ component: 'eai-gofer-contract',
110
+ source: 'ops/tech-docs/static/contracts/object-type-routing-v1.json',
111
+ installed: 'ops/gofer/.specify/contracts/object-type-routing-v1.json',
112
+ },
113
+ {
114
+ component: 'eai-gofer-extension',
115
+ source: 'ops/gofer/.specify/config/object-type-routing.json',
116
+ installed: 'ops/gofer/extension/resources/specify-config/object-type-routing.json',
117
+ },
118
+ {
119
+ component: 'eai-gofer-extension',
120
+ source: 'ops/gofer/.specify/contracts/object-type-routing-v1.json',
121
+ installed: 'ops/gofer/extension/resources/contracts/object-type-routing-v1.json',
122
+ },
123
+ {
124
+ component: 'eai-gofer-extension',
125
+ source: 'ops/gofer/.specify/schemas/object-type-identifier-audit-v1.schema.json',
126
+ installed: 'ops/gofer/extension/resources/schemas/object-type-identifier-audit-v1.schema.json',
127
+ },
128
+ {
129
+ component: 'eai-gofer-extension',
130
+ source: 'ops/gofer/.specify/schemas/object-type-routing-phase-bundle-v1.schema.json',
131
+ installed:
132
+ 'ops/gofer/extension/resources/schemas/object-type-routing-phase-bundle-v1.schema.json',
133
+ },
134
+ {
135
+ component: 'eai-cli-installed-gofer',
136
+ source: 'ops/gofer/.specify/config/object-type-routing.json',
137
+ installed: 'ops/eai-cli/resources/gofer/config/object-type-routing.json',
138
+ },
139
+ {
140
+ component: 'eai-cli-installed-gofer',
141
+ source: 'ops/gofer/.specify/contracts/object-type-routing-v1.json',
142
+ installed: 'ops/eai-cli/resources/gofer/contracts/object-type-routing-v1.json',
143
+ },
144
+ {
145
+ component: 'eai-cli-installed-gofer',
146
+ source: 'ops/gofer/.specify/schemas/object-type-identifier-audit-v1.schema.json',
147
+ installed: 'ops/eai-cli/resources/gofer/schemas/object-type-identifier-audit-v1.schema.json',
148
+ },
149
+ {
150
+ component: 'eai-cli-installed-gofer',
151
+ source: 'ops/gofer/.specify/schemas/object-type-routing-phase-bundle-v1.schema.json',
152
+ installed:
153
+ 'ops/eai-cli/resources/gofer/schemas/object-type-routing-phase-bundle-v1.schema.json',
154
+ },
155
+ ]);
156
+
157
+ class WorkspaceInputError extends Error {
158
+ constructor(code, message) {
159
+ super(message);
160
+ this.name = 'WorkspaceInputError';
161
+ this.code = code;
162
+ }
163
+ }
164
+
165
+ function digestBytes(value) {
166
+ return `sha256:${createHash('sha256').update(value).digest('hex')}`;
167
+ }
168
+
169
+ function digestJson(value) {
170
+ return digestBytes(canonicalJson(value));
171
+ }
172
+
173
+ function compareText(left, right) {
174
+ return String(left).localeCompare(String(right), 'en');
175
+ }
176
+
177
+ function sortFindings(findings) {
178
+ return [...findings].sort(
179
+ (left, right) =>
180
+ compareText(left.component, right.component) ||
181
+ compareText(left.path, right.path) ||
182
+ compareText(left.code, right.code) ||
183
+ compareText(left.message, right.message)
184
+ );
185
+ }
186
+
187
+ function finding(component, artifactPath, code, message, evidence = undefined) {
188
+ return {
189
+ classification: 'blocking',
190
+ component,
191
+ path: artifactPath,
192
+ code,
193
+ message,
194
+ ...(evidence === undefined ? {} : { evidence }),
195
+ };
196
+ }
197
+
198
+ async function readRequired(workspace, relativePath, label = relativePath) {
199
+ try {
200
+ return await fs.readFile(path.join(workspace, relativePath));
201
+ } catch (error) {
202
+ throw new WorkspaceInputError(
203
+ 'AUTHORITY_UNREADABLE',
204
+ `${label} is not readable (${error?.code ?? 'unknown error'}).`
205
+ );
206
+ }
207
+ }
208
+
209
+ async function readOptional(workspace, relativePath) {
210
+ try {
211
+ return await fs.readFile(path.join(workspace, relativePath));
212
+ } catch (error) {
213
+ if (error?.code === 'ENOENT') return undefined;
214
+ throw error;
215
+ }
216
+ }
217
+
218
+ function parseJson(bytes, label) {
219
+ try {
220
+ return JSON.parse(bytes.toString('utf8'));
221
+ } catch {
222
+ throw new WorkspaceInputError('JSON_MALFORMED', `${label} is not valid JSON.`);
223
+ }
224
+ }
225
+
226
+ function matchingBrace(source, openIndex) {
227
+ let depth = 0;
228
+ let quote = '';
229
+ let escaped = false;
230
+ let lineComment = false;
231
+ let blockComment = false;
232
+ let regularExpression = false;
233
+
234
+ for (let index = openIndex; index < source.length; index += 1) {
235
+ const character = source[index];
236
+ const next = source[index + 1];
237
+ if (lineComment) {
238
+ if (character === '\n') lineComment = false;
239
+ continue;
240
+ }
241
+ if (blockComment) {
242
+ if (character === '*' && next === '/') {
243
+ blockComment = false;
244
+ index += 1;
245
+ }
246
+ continue;
247
+ }
248
+ if (quote) {
249
+ if (escaped) escaped = false;
250
+ else if (character === '\\') escaped = true;
251
+ else if (character === quote) quote = '';
252
+ continue;
253
+ }
254
+ if (regularExpression) {
255
+ if (escaped) escaped = false;
256
+ else if (character === '\\') escaped = true;
257
+ else if (character === '/') regularExpression = false;
258
+ continue;
259
+ }
260
+ if (character === '/' && next === '/') {
261
+ lineComment = true;
262
+ index += 1;
263
+ continue;
264
+ }
265
+ if (character === '/' && next === '*') {
266
+ blockComment = true;
267
+ index += 1;
268
+ continue;
269
+ }
270
+ if (character === "'" || character === '"' || character === '`') {
271
+ quote = character;
272
+ continue;
273
+ }
274
+ if (character === '/' && /[=(,:!&|?;\[]/.test(source[index - 1] ?? '=')) {
275
+ regularExpression = true;
276
+ continue;
277
+ }
278
+ if (character === '{') depth += 1;
279
+ if (character === '}') {
280
+ depth -= 1;
281
+ if (depth === 0) return index;
282
+ }
283
+ }
284
+ return -1;
285
+ }
286
+
287
+ function typeScriptFunctionBody(source, functionName, component) {
288
+ const declaration = new RegExp(
289
+ `(?:export\\s+)?function\\s+${functionName}\\s*\\(\\s*([A-Za-z_$][\\w$]*)[^)]*\\)\\s*(?::\\s*[A-Za-z_$][\\w$<>[\\]| ]*\\s*)?\\{`,
290
+ 'm'
291
+ ).exec(source);
292
+ if (!declaration) throw new Error(`${component} does not declare ${functionName}().`);
293
+ const openIndex = declaration.index + declaration[0].lastIndexOf('{');
294
+ const closeIndex = matchingBrace(source, openIndex);
295
+ if (closeIndex === -1) throw new Error(`${component} ${functionName}() is incomplete.`);
296
+ return {
297
+ parameter: declaration[1],
298
+ body: source.slice(openIndex + 1, closeIndex),
299
+ };
300
+ }
301
+
302
+ export function executableTypeScriptDeriver(source, component) {
303
+ const { parameter, body } = typeScriptFunctionBody(
304
+ source,
305
+ 'deriveObjectTypeSlugV1',
306
+ component
307
+ );
308
+ if (!/^\s*return\s+/m.test(body)) {
309
+ throw new Error(`${component} derivation function has no executable return expression.`);
310
+ }
311
+
312
+ const mapDeclaration =
313
+ /ESTABLISHED_NAME_SLUGS\s*=\s*new Map(?:<[^>]+>)?\s*\(([\s\S]*?)\)\s*;?/m.exec(source);
314
+ if (!mapDeclaration) {
315
+ throw new Error(`${component} does not declare ESTABLISHED_NAME_SLUGS.`);
316
+ }
317
+ const establishedNameSlugs = new Map(
318
+ Function(`'use strict'; return (${mapDeclaration[1]});`)()
319
+ );
320
+
321
+ let trimAsciiWhitespace;
322
+ if (/\btrimAsciiWhitespace\s*\(/.test(body)) {
323
+ const asciiHelper = typeScriptFunctionBody(source, 'isAsciiWhitespace', component);
324
+ const trimHelper = typeScriptFunctionBody(source, 'trimAsciiWhitespace', component);
325
+ const isAsciiWhitespace = Function(
326
+ asciiHelper.parameter,
327
+ `'use strict';\n${asciiHelper.body}`
328
+ );
329
+ const executeTrim = Function(
330
+ 'isAsciiWhitespace',
331
+ trimHelper.parameter,
332
+ `'use strict';\n${trimHelper.body}`
333
+ );
334
+ trimAsciiWhitespace = (value) => executeTrim(isAsciiWhitespace, value);
335
+ }
336
+
337
+ const executeDerivation = Function(
338
+ 'ESTABLISHED_NAME_SLUGS',
339
+ 'trimAsciiWhitespace',
340
+ parameter,
341
+ `'use strict';\n${body}`
342
+ );
343
+ return (value) => executeDerivation(establishedNameSlugs, trimAsciiWhitespace, value);
344
+ }
345
+
346
+ function sourcePatterns(source, component) {
347
+ const name = /(?:OBJECT_TYPE_)?NAME_PATTERN\s*=\s*\/([^/]+)\/([a-z]*)/.exec(source);
348
+ const slug = /(?:OBJECT_TYPE_)?SLUG_PATTERN\s*=\s*\/([^/]+)\/([a-z]*)/.exec(source);
349
+ if (!name || !slug) throw new Error(`${component} does not declare literal name/slug patterns.`);
350
+ return {
351
+ name: { pattern: name[1], flags: name[2], expression: new RegExp(name[1], name[2]) },
352
+ slug: { pattern: slug[1], flags: slug[2] },
353
+ };
354
+ }
355
+
356
+ function pythonExecutable() {
357
+ return 'python3';
358
+ }
359
+
360
+ function executePythonAdapter(absolutePath, vectors) {
361
+ const program = String.raw`
362
+ import importlib.util, json, sys
363
+ module_path = sys.argv[1]
364
+ vectors = json.loads(sys.argv[2])
365
+ spec = importlib.util.spec_from_file_location("eai_object_type_adapter", module_path)
366
+ if spec is None or spec.loader is None:
367
+ raise RuntimeError("adapter module is not loadable")
368
+ module = importlib.util.module_from_spec(spec)
369
+ spec.loader.exec_module(module)
370
+ print(json.dumps([{
371
+ "output": module.derive_object_type_slug(vector["input"]),
372
+ "manifestNameValid": module.is_valid_object_type_manifest_name(vector["input"]),
373
+ } for vector in vectors], separators=(",", ":"), sort_keys=True))
374
+ `;
375
+ const result = spawnSync(
376
+ pythonExecutable(),
377
+ ['-c', program, absolutePath, JSON.stringify(vectors)],
378
+ { encoding: 'utf8', timeout: 15_000 }
379
+ );
380
+ if (result.error || result.status !== 0) {
381
+ throw new Error(
382
+ `Python adapter execution failed: ${result.error?.message ?? result.stderr.trim() ?? 'unknown error'}`
383
+ );
384
+ }
385
+ return JSON.parse(result.stdout.trim());
386
+ }
387
+
388
+ async function reduceAdapter(workspace, definition, vectors, contract) {
389
+ const bytes = await readOptional(workspace, definition.path);
390
+ if (!bytes) {
391
+ return {
392
+ adapter: {
393
+ component: definition.component,
394
+ path: definition.path,
395
+ digest: null,
396
+ compatible: false,
397
+ vectors: [],
398
+ },
399
+ findings: [
400
+ finding(
401
+ definition.component,
402
+ definition.path,
403
+ 'ADAPTER_MISSING',
404
+ 'The canonical identifier adapter is missing.'
405
+ ),
406
+ ],
407
+ };
408
+ }
409
+
410
+ const source = bytes.toString('utf8');
411
+ const adapterFindings = [];
412
+ let results = [];
413
+ let declaredNamePattern;
414
+ let declaredSlugPattern;
415
+ try {
416
+ if (definition.kind === 'typescript') {
417
+ const derive = executableTypeScriptDeriver(source, definition.component);
418
+ const patterns = sourcePatterns(source, definition.component);
419
+ declaredNamePattern = patterns.name.pattern;
420
+ declaredSlugPattern = patterns.slug.pattern;
421
+ results = vectors.map((vector) => ({
422
+ output: derive(vector.input),
423
+ manifestNameValid: patterns.name.expression.test(vector.input),
424
+ }));
425
+ } else if (definition.kind === 'python') {
426
+ results = executePythonAdapter(path.join(workspace, definition.path), vectors);
427
+ declaredNamePattern = /OBJECT_TYPE_NAME_PATTERN[^=]*=\s*r?["']([^"']+)["']/.exec(source)?.[1];
428
+ declaredSlugPattern = /OBJECT_TYPE_SLUG_PATTERN[^=]*=\s*r?["']([^"']+)["']/.exec(source)?.[1];
429
+ } else {
430
+ results = vectors.map((vector) => ({
431
+ output: deriveObjectTypeSlugV1(vector.input),
432
+ manifestNameValid: contract.namePattern.test(vector.input),
433
+ }));
434
+ declaredNamePattern = NAME_PATTERN;
435
+ declaredSlugPattern = SLUG_PATTERN;
436
+ }
437
+ } catch (error) {
438
+ adapterFindings.push(
439
+ finding(
440
+ definition.component,
441
+ definition.path,
442
+ 'ADAPTER_UNEXECUTABLE',
443
+ error instanceof Error ? error.message : String(error)
444
+ )
445
+ );
446
+ }
447
+
448
+ if (declaredNamePattern !== NAME_PATTERN || declaredSlugPattern !== SLUG_PATTERN) {
449
+ adapterFindings.push(
450
+ finding(
451
+ definition.component,
452
+ definition.path,
453
+ 'ADAPTER_PATTERN_DRIFT',
454
+ 'The adapter name or slug pattern differs from the authoritative contract.'
455
+ )
456
+ );
457
+ }
458
+ for (const reserved of RESERVED_SLUGS) {
459
+ if (
460
+ definition.kind !== 'gofer' &&
461
+ !source.includes(`'${reserved}'`) &&
462
+ !source.includes(`"${reserved}"`)
463
+ ) {
464
+ adapterFindings.push(
465
+ finding(
466
+ definition.component,
467
+ definition.path,
468
+ 'ADAPTER_RESERVED_SET_DRIFT',
469
+ `The adapter does not declare reserved slug ${reserved}.`
470
+ )
471
+ );
472
+ }
473
+ }
474
+ if (!source.includes(CONTRACT_VERSION)) {
475
+ adapterFindings.push(
476
+ finding(
477
+ definition.component,
478
+ definition.path,
479
+ 'ADAPTER_VERSION_DRIFT',
480
+ 'The adapter does not declare the canonical contract version.'
481
+ )
482
+ );
483
+ }
484
+
485
+ const vectorEvidence = vectors.map((vector, ordinal) => {
486
+ const observed = results[ordinal] ?? {};
487
+ const compatible =
488
+ observed.output === vector.output && observed.manifestNameValid === vector.manifestNameValid;
489
+ if (!compatible) {
490
+ adapterFindings.push(
491
+ finding(
492
+ definition.component,
493
+ definition.path,
494
+ 'ADAPTER_VECTOR_DRIFT',
495
+ `The adapter differs from authoritative vector ${ordinal}.`,
496
+ {
497
+ ordinal,
498
+ expectedOutput: vector.output,
499
+ observedOutput: observed.output ?? null,
500
+ expectedManifestNameValid: vector.manifestNameValid,
501
+ observedManifestNameValid: observed.manifestNameValid ?? null,
502
+ }
503
+ )
504
+ );
505
+ }
506
+ return {
507
+ ordinal,
508
+ output: observed.output ?? null,
509
+ manifestNameValid: observed.manifestNameValid ?? null,
510
+ compatible,
511
+ };
512
+ });
513
+
514
+ return {
515
+ adapter: {
516
+ component: definition.component,
517
+ path: definition.path,
518
+ digest: digestBytes(bytes),
519
+ compatible: adapterFindings.length === 0,
520
+ vectors: vectorEvidence,
521
+ },
522
+ findings: adapterFindings,
523
+ };
524
+ }
525
+
526
+ function validateAuthority(contract, manifestSchema, actionSchema, auditConfig) {
527
+ const findings = [];
528
+ if (contract.contractVersion !== CONTRACT_VERSION) {
529
+ findings.push(
530
+ finding(
531
+ 'tech-docs',
532
+ 'ops/tech-docs/static/contracts/object-type-routing-v1.json',
533
+ 'CONTRACT_VERSION_DRIFT',
534
+ 'Contract version is not v1.'
535
+ )
536
+ );
537
+ }
538
+ if (contract.authoritativeTransportIdentifier !== 'slug') {
539
+ findings.push(
540
+ finding(
541
+ 'tech-docs',
542
+ 'ops/tech-docs/static/contracts/object-type-routing-v1.json',
543
+ 'TRANSPORT_IDENTIFIER_DRIFT',
544
+ 'The authoritative transport identifier must be slug.'
545
+ )
546
+ );
547
+ }
548
+ if (
549
+ contract.name?.pattern !== NAME_PATTERN ||
550
+ contract.slug?.pattern !== SLUG_PATTERN ||
551
+ canonicalJson(contract.slug?.reserved) !== canonicalJson(RESERVED_SLUGS) ||
552
+ canonicalJson(contract.governedTransportFields) !== canonicalJson(GOVERNED_FIELDS) ||
553
+ contract.derivation?.algorithm !== CONTRACT_VERSION ||
554
+ contract.derivation?.vectors?.length !== 11
555
+ ) {
556
+ findings.push(
557
+ finding(
558
+ 'tech-docs',
559
+ 'ops/tech-docs/static/contracts/object-type-routing-v1.json',
560
+ 'CONTRACT_SHAPE_DRIFT',
561
+ 'The contract patterns, reserved slugs, governed fields, algorithm, or vector count drifted.'
562
+ )
563
+ );
564
+ }
565
+ if (canonicalJson(contract.relationshipReferences) !== canonicalJson(RELATIONSHIP_REFERENCES)) {
566
+ findings.push(
567
+ finding(
568
+ 'tech-docs',
569
+ 'ops/tech-docs/static/contracts/object-type-routing-v1.json',
570
+ 'RELATIONSHIP_REFERENCE_CONTRACT_DRIFT',
571
+ 'Relationship references must resolve same-manifest names to exact declared slugs before publication and runtime use.'
572
+ )
573
+ );
574
+ }
575
+ const relationshipGuidance = String(auditConfig?.canonicalGuidance ?? '');
576
+ if (
577
+ !relationshipGuidance.includes('linkTypes[].targetObjectType') ||
578
+ !relationshipGuidance.includes('target_type') ||
579
+ !relationshipGuidance.includes('same-manifest name shorthand')
580
+ ) {
581
+ findings.push(
582
+ finding(
583
+ 'eai-gofer',
584
+ 'ops/gofer/.specify/config/object-type-routing.json',
585
+ 'RELATIONSHIP_SOURCE_AUDIT_DRIFT',
586
+ 'The source audit must require linkTypes[].targetObjectType and runtime target_type to use the declared slug after same-manifest name resolution.'
587
+ )
588
+ );
589
+ }
590
+ const expectedArtifacts = {
591
+ openapi: '/openapi.json',
592
+ manifestSchema: '/v4/data/contracts/object-type-manifest.schema.json',
593
+ resourceActionSchema: '/v4/data/contracts/resource-action.schema.json',
594
+ };
595
+ if (canonicalJson(contract.artifacts) !== canonicalJson(expectedArtifacts)) {
596
+ findings.push(
597
+ finding(
598
+ 'tech-docs',
599
+ 'ops/tech-docs/static/contracts/object-type-routing-v1.json',
600
+ 'CONTRACT_ARTIFACT_LINK_DRIFT',
601
+ 'The public artifact links differ from v1.'
602
+ )
603
+ );
604
+ }
605
+
606
+ const manifestSlug = manifestSchema.properties?.slug;
607
+ if (
608
+ manifestSchema.$schema !== 'https://json-schema.org/draft/2020-12/schema' ||
609
+ manifestSchema.$id !== 'urn:eai:schema:object-type-manifest:v1' ||
610
+ manifestSchema['x-eai-object-type-routing-contract'] !== CONTRACT_VERSION ||
611
+ manifestSchema['x-eai-object-type-routing-derivation'] !== CONTRACT_VERSION ||
612
+ canonicalJson(manifestSchema.required) !== canonicalJson(['name', 'slug']) ||
613
+ manifestSchema.properties?.name?.pattern !== NAME_PATTERN ||
614
+ manifestSlug?.pattern !== SLUG_PATTERN ||
615
+ manifestSlug?.format !== 'eai-object-type-slug' ||
616
+ canonicalJson(manifestSlug?.not?.enum) !== canonicalJson(RESERVED_SLUGS)
617
+ ) {
618
+ findings.push(
619
+ finding(
620
+ 'tech-docs',
621
+ 'ops/tech-docs/static/schemas/object-type-manifest-v1.schema.json',
622
+ 'MANIFEST_SCHEMA_DRIFT',
623
+ 'The manifest schema is not the strict Draft 2020-12 v1 schema.'
624
+ )
625
+ );
626
+ }
627
+ if (
628
+ actionSchema.$schema !== 'https://json-schema.org/draft/2020-12/schema' ||
629
+ actionSchema.$id !== 'urn:eai:schema:resource-action:v1' ||
630
+ actionSchema['x-eai-object-type-routing-contract'] !== CONTRACT_VERSION ||
631
+ actionSchema.type !== 'object' ||
632
+ actionSchema.additionalProperties !== false ||
633
+ canonicalJson(Object.keys(actionSchema.properties ?? {}).sort()) !== canonicalJson(['params'])
634
+ ) {
635
+ findings.push(
636
+ finding(
637
+ 'tech-docs',
638
+ 'ops/tech-docs/static/schemas/resource-action-v1.schema.json',
639
+ 'ACTION_SCHEMA_DRIFT',
640
+ 'The resource action schema is not the closed Draft 2020-12 v1 schema.'
641
+ )
642
+ );
643
+ }
644
+ return findings;
645
+ }
646
+
647
+ function validateRelationshipReferenceVectors() {
648
+ const findings = [];
649
+ for (const vector of RELATIONSHIP_REFERENCE_VECTORS) {
650
+ const emitted = String(vector.emittedReference ?? '');
651
+ const declared = String(vector.declaredSlug ?? '');
652
+ if (emitted !== declared || !new RegExp(SLUG_PATTERN).test(emitted)) {
653
+ findings.push(
654
+ finding(
655
+ 'tech-docs',
656
+ 'ops/tech-docs/static/contracts/object-type-routing-v1.json',
657
+ 'RELATIONSHIP_REFERENCE_VECTOR_INVALID',
658
+ `Relationship vector ${String(vector.declaredName ?? '<unknown>')} does not emit its exact declared slug.`
659
+ )
660
+ );
661
+ }
662
+ }
663
+ return findings;
664
+ }
665
+
666
+ function containsReference(value, reference) {
667
+ if (Array.isArray(value)) return value.some((child) => containsReference(child, reference));
668
+ if (!value || typeof value !== 'object') return false;
669
+ if (value.$ref === reference) return true;
670
+ return Object.values(value).some((child) => containsReference(child, reference));
671
+ }
672
+
673
+ function generatedOpenApi(workspace) {
674
+ const publicApiRoot = path.join(workspace, 'mid/PublicAPI');
675
+ const candidates = [
676
+ path.join(publicApiRoot, '.venv/bin/python'),
677
+ path.join(publicApiRoot, 'venv/bin/python'),
678
+ pythonExecutable(),
679
+ ];
680
+ const executable = candidates.find((candidate) => {
681
+ if (!candidate.includes(path.sep)) return true;
682
+ try {
683
+ return fsSyncAccess(candidate);
684
+ } catch {
685
+ return false;
686
+ }
687
+ });
688
+ const marker = '__EAI_OBJECT_TYPE_OPENAPI__=';
689
+ const program = [
690
+ 'import json',
691
+ 'from main import app',
692
+ `print("${marker}" + json.dumps(app.openapi(), separators=(",", ":"), sort_keys=True))`,
693
+ ].join('\n');
694
+ const result = spawnSync(executable ?? 'python3', ['-c', program], {
695
+ cwd: path.join(publicApiRoot, 'src'),
696
+ encoding: 'utf8',
697
+ timeout: 30_000,
698
+ env: { ...process.env, NO_COLOR: '1' },
699
+ });
700
+ if (result.error || result.status !== 0) {
701
+ throw new Error(result.error?.message ?? result.stderr.trim() ?? 'OpenAPI generation failed.');
702
+ }
703
+ const markerIndex = result.stdout.lastIndexOf(marker);
704
+ if (markerIndex === -1) throw new Error('OpenAPI generator did not emit its result marker.');
705
+ return JSON.parse(result.stdout.slice(markerIndex + marker.length).trim());
706
+ }
707
+
708
+ function fsSyncAccess(file) {
709
+ try {
710
+ accessSync(file, fsConstants.X_OK);
711
+ return true;
712
+ } catch {
713
+ return false;
714
+ }
715
+ }
716
+
717
+ function validateOpenApi(document) {
718
+ const findings = [];
719
+ const schemas = document.components?.schemas ?? {};
720
+ const slugReference = '#/components/schemas/ObjectTypeSlug';
721
+ const errorReference = '#/components/schemas/CanonicalObjectTypeSlugErrorResponse';
722
+ const slug = schemas.ObjectTypeSlug;
723
+ if (
724
+ slug?.type !== 'string' ||
725
+ slug?.format !== 'eai-object-type-slug' ||
726
+ slug?.pattern !== SLUG_PATTERN ||
727
+ canonicalJson(slug?.not?.enum) !== canonicalJson(RESERVED_SLUGS) ||
728
+ slug?.['x-eai-object-type-routing-contract'] !== CONTRACT_VERSION
729
+ ) {
730
+ findings.push(
731
+ finding(
732
+ 'PublicAPI',
733
+ '/openapi.json',
734
+ 'OPENAPI_SLUG_SCHEMA_DRIFT',
735
+ 'ObjectTypeSlug is missing or differs from the v1 transport schema.'
736
+ )
737
+ );
738
+ }
739
+
740
+ let governedOperationCount = 0;
741
+ for (const [route, pathItem] of Object.entries(document.paths ?? {})) {
742
+ if (!pathItem || typeof pathItem !== 'object') continue;
743
+ for (const [method, operation] of Object.entries(pathItem)) {
744
+ if (
745
+ !['get', 'post', 'put', 'patch', 'delete'].includes(method) ||
746
+ !operation ||
747
+ typeof operation !== 'object'
748
+ )
749
+ continue;
750
+ const governedParameters = (operation.parameters ?? []).filter(
751
+ (parameter) =>
752
+ parameter?.in === 'path' && ['object_type', 'parent_type'].includes(parameter.name)
753
+ );
754
+ const governedBody = containsReference(operation.requestBody, slugReference);
755
+ if (route.startsWith('/v4/data/resources/') && governedParameters.length > 0) {
756
+ governedOperationCount += 1;
757
+ if (governedParameters.some((parameter) => parameter.schema?.$ref !== slugReference)) {
758
+ findings.push(
759
+ finding(
760
+ 'PublicAPI',
761
+ '/openapi.json',
762
+ 'OPENAPI_PATH_PARAMETER_DRIFT',
763
+ `${method.toUpperCase()} ${route} does not reference ObjectTypeSlug for every governed path parameter.`
764
+ )
765
+ );
766
+ }
767
+ }
768
+ if ((governedParameters.length > 0 || governedBody) && route.startsWith('/v4/')) {
769
+ const errorSchema = operation.responses?.['400']?.content?.['application/json']?.schema;
770
+ if (errorSchema?.$ref !== errorReference) {
771
+ findings.push(
772
+ finding(
773
+ 'PublicAPI',
774
+ '/openapi.json',
775
+ 'OPENAPI_ERROR_RESPONSE_DRIFT',
776
+ `${method.toUpperCase()} ${route} does not publish the canonical 400 response.`
777
+ )
778
+ );
779
+ }
780
+ }
781
+ if (
782
+ !route.startsWith('/v4/') &&
783
+ (governedParameters.some((parameter) => parameter.schema?.$ref === slugReference) ||
784
+ governedBody)
785
+ ) {
786
+ findings.push(
787
+ finding(
788
+ 'PublicAPI',
789
+ '/openapi.json',
790
+ 'OPENAPI_LEGACY_SCOPE_EXPANSION',
791
+ `${method.toUpperCase()} ${route} applies the v4 slug contract to a legacy route.`
792
+ )
793
+ );
794
+ }
795
+ }
796
+ }
797
+ if (governedOperationCount === 0) {
798
+ findings.push(
799
+ finding(
800
+ 'PublicAPI',
801
+ '/openapi.json',
802
+ 'OPENAPI_ROUTE_INVENTORY_EMPTY',
803
+ 'No governed v4 Object Type path operations were discovered.'
804
+ )
805
+ );
806
+ }
807
+ for (const field of GOVERNED_FIELDS.slice(2)) {
808
+ const fieldNames = OPENAPI_FIELD_ALIASES[field] ?? [field];
809
+ const represented = Object.values(schemas).some(
810
+ (schema) =>
811
+ fieldNames.some(
812
+ (fieldName) =>
813
+ schema?.properties?.[fieldName] &&
814
+ containsReference(schema.properties[fieldName], slugReference)
815
+ )
816
+ );
817
+ if (!represented) {
818
+ findings.push(
819
+ finding(
820
+ 'PublicAPI',
821
+ '/openapi.json',
822
+ 'OPENAPI_GOVERNED_FIELD_MISSING',
823
+ `Governed field ${field} does not reference ObjectTypeSlug.`
824
+ )
825
+ );
826
+ }
827
+ }
828
+ const persistedSlug = schemas.ObjectTypeDocument?.properties?.slug;
829
+ if (
830
+ persistedSlug?.type !== 'string' ||
831
+ persistedSlug?.$ref === slugReference ||
832
+ persistedSlug?.pattern ||
833
+ persistedSlug?.format
834
+ ) {
835
+ findings.push(
836
+ finding(
837
+ 'PublicAPI',
838
+ '/openapi.json',
839
+ 'OPENAPI_LEGACY_DOCUMENT_DRIFT',
840
+ 'ObjectTypeDocument.slug must remain a plain required string for legacy reads.'
841
+ )
842
+ );
843
+ }
844
+ return { findings, governedOperationCount };
845
+ }
846
+
847
+ async function reduceRuntimeAssets(workspace) {
848
+ const publications = [
849
+ [
850
+ 'ops/tech-docs/static/contracts/object-type-routing-v1.json',
851
+ 'mid/PublicAPI/src/app/contracts/object-type-routing-v1.json',
852
+ ],
853
+ [
854
+ 'ops/tech-docs/static/schemas/object-type-manifest-v1.schema.json',
855
+ 'mid/PublicAPI/src/app/contracts/object-type-manifest-v1.schema.json',
856
+ ],
857
+ [
858
+ 'ops/tech-docs/static/schemas/resource-action-v1.schema.json',
859
+ 'mid/PublicAPI/src/app/contracts/resource-action-v1.schema.json',
860
+ ],
861
+ ];
862
+ const findings = [];
863
+ const assets = [];
864
+ for (const [authorityPath, runtimePath] of publications) {
865
+ const authority = await readRequired(workspace, authorityPath);
866
+ const runtime = await readOptional(workspace, runtimePath);
867
+ const byteEqual = runtime !== undefined && authority.equals(runtime);
868
+ if (!byteEqual) {
869
+ findings.push(
870
+ finding(
871
+ 'PublicAPI',
872
+ runtimePath,
873
+ 'RUNTIME_ASSET_DRIFT',
874
+ 'The deployable runtime asset is not byte-equal to tech-docs authority.'
875
+ )
876
+ );
877
+ }
878
+ assets.push({
879
+ authorityPath,
880
+ runtimePath,
881
+ authorityDigest: digestBytes(authority),
882
+ runtimeDigest: runtime ? digestBytes(runtime) : null,
883
+ byteEqual,
884
+ });
885
+ }
886
+ return { assets, findings };
887
+ }
888
+
889
+ async function reduceMirrors(workspace) {
890
+ const findings = [];
891
+ const mirrors = [];
892
+ for (const mirror of MIRRORS) {
893
+ const source = await readOptional(workspace, mirror.source);
894
+ const installed = await readOptional(workspace, mirror.installed);
895
+ const byteEqual = source !== undefined && installed !== undefined && source.equals(installed);
896
+ if (!byteEqual) {
897
+ findings.push(
898
+ finding(
899
+ mirror.component,
900
+ mirror.installed,
901
+ 'INSTALLED_MIRROR_DRIFT',
902
+ 'The installed Gofer resource is missing or differs from its source.'
903
+ )
904
+ );
905
+ }
906
+ mirrors.push({
907
+ ...mirror,
908
+ sourceDigest: source ? digestBytes(source) : null,
909
+ installedDigest: installed ? digestBytes(installed) : null,
910
+ byteEqual,
911
+ });
912
+ }
913
+ return { mirrors, findings };
914
+ }
915
+
916
+ async function reduceCoverage(workspace) {
917
+ const findings = [];
918
+ const coverageOwnership = [];
919
+ for (const [component, coveragePath] of COVERAGE_OWNERS) {
920
+ const bytes = await readOptional(workspace, coveragePath);
921
+ if (!bytes) {
922
+ findings.push(
923
+ finding(
924
+ component,
925
+ coveragePath,
926
+ 'COVERAGE_OWNER_MISSING',
927
+ 'The pre-E1 coverage map is missing.'
928
+ )
929
+ );
930
+ coverageOwnership.push({
931
+ component,
932
+ path: coveragePath,
933
+ digest: null,
934
+ featureIds: [],
935
+ owned: false,
936
+ });
937
+ continue;
938
+ }
939
+ let document;
940
+ try {
941
+ document = JSON.parse(bytes.toString('utf8'));
942
+ } catch {
943
+ throw new WorkspaceInputError('JSON_MALFORMED', `${coveragePath} is not valid JSON.`);
944
+ }
945
+ const repositories = Object.values(document.repositories ?? {});
946
+ const features = repositories.flatMap((repository) => repository?.features ?? []);
947
+ const ownedFeatures = features.filter((feature) =>
948
+ /(?:canonical.*object-type|object-type.*(?:routing|identifier)|routing.*object-type)/i.test(
949
+ String(feature?.id ?? '')
950
+ )
951
+ );
952
+ const owned = ownedFeatures.some(
953
+ (feature) =>
954
+ Array.isArray(feature.owned_paths) &&
955
+ feature.owned_paths.length > 0 &&
956
+ Array.isArray(feature.required_repo_tests) &&
957
+ feature.required_repo_tests.length > 0
958
+ );
959
+ if (!owned) {
960
+ findings.push(
961
+ finding(
962
+ component,
963
+ coveragePath,
964
+ 'COVERAGE_OWNER_INCOMPLETE',
965
+ 'No canonical Object Type routing feature owns paths and repository tests.'
966
+ )
967
+ );
968
+ }
969
+ coverageOwnership.push({
970
+ component,
971
+ path: coveragePath,
972
+ digest: digestBytes(bytes),
973
+ featureIds: ownedFeatures.map((feature) => String(feature.id)).sort(compareText),
974
+ owned,
975
+ });
976
+ }
977
+ return { coverageOwnership, findings };
978
+ }
979
+
980
+ async function reduceLegacyEvidence(workspace) {
981
+ const evidencePaths = [
982
+ 'mid/ResourceAPI/src/services/object_type_cache.py',
983
+ 'mid/ResourceAPI/tests/unit/test_resource_service_routing.py',
984
+ 'mid/ResourceAPI/tests/unit/test_object_type_identifiers.py',
985
+ 'front/eai-app-template/src/lib/platform/verify-platform.ts',
986
+ 'front/Configurator/src/collections/ObjectTypes/identifierContract.ts',
987
+ ];
988
+ const sources = new Map();
989
+ for (const evidencePath of evidencePaths) {
990
+ const bytes = await readOptional(workspace, evidencePath);
991
+ sources.set(evidencePath, bytes);
992
+ }
993
+ const cache = sources.get(evidencePaths[0])?.toString('utf8') ?? '';
994
+ const routingTests = sources.get(evidencePaths[1])?.toString('utf8') ?? '';
995
+ const identifierTests = sources.get(evidencePaths[2])?.toString('utf8') ?? '';
996
+ const templateVerification = sources.get(evidencePaths[3])?.toString('utf8') ?? '';
997
+ const configurator = sources.get(evidencePaths[4])?.toString('utf8') ?? '';
998
+ const checks = {
999
+ resourceApiExactStoredSlugLookup:
1000
+ cache.includes('types.get(slug)') && cache.includes('without alias probes'),
1001
+ resourceApiLegacySlugBytePreserved: routingTests.includes(
1002
+ 'test_resolve_adapter_passes_legacy_stored_slug_to_cache_byte_for_byte'
1003
+ ),
1004
+ resourceApiUnknownSlugNoAliasProbe:
1005
+ routingTests.includes(
1006
+ 'test_resolve_adapter_preserves_unknown_canonical_slug_404_without_alias_probe'
1007
+ ) && identifierTests.includes('rejected_without_normalization_or_aliases'),
1008
+ templateUsesStoredLegacySlugExactly:
1009
+ templateVerification.includes('client.resources.list(firstSlug') &&
1010
+ templateVerification.includes('never\n // retry with a name, alias'),
1011
+ configuratorIdentifierChangesRequireMigration:
1012
+ configurator.includes('OBJECT_TYPE_IDENTIFIER_MIGRATION_REQUIRED') &&
1013
+ configurator.includes('status: 400 | 409'),
1014
+ };
1015
+ const findings = [];
1016
+ for (const [check, passed] of Object.entries(checks)) {
1017
+ if (!passed) {
1018
+ findings.push(
1019
+ finding(
1020
+ 'legacy-exact-slug',
1021
+ evidencePaths.join(','),
1022
+ 'LEGACY_EXACT_SLUG_EVIDENCE_MISSING',
1023
+ `Legacy exact-slug/no-alias evidence failed: ${check}.`
1024
+ )
1025
+ );
1026
+ }
1027
+ }
1028
+ return {
1029
+ compatible: Object.values(checks).every(Boolean),
1030
+ checks,
1031
+ evidence: evidencePaths.map((evidencePath) => ({
1032
+ path: evidencePath,
1033
+ digest: sources.get(evidencePath) ? digestBytes(sources.get(evidencePath)) : null,
1034
+ })),
1035
+ findings,
1036
+ };
1037
+ }
1038
+
1039
+ export async function reduceObjectTypeRoutingWorkspace(workspaceInput) {
1040
+ const workspace = path.resolve(workspaceInput);
1041
+ let workspaceStat;
1042
+ try {
1043
+ workspaceStat = await fs.stat(workspace);
1044
+ } catch {
1045
+ throw new WorkspaceInputError('WORKSPACE_UNREADABLE', 'Workspace is not readable.');
1046
+ }
1047
+ if (!workspaceStat.isDirectory()) {
1048
+ throw new WorkspaceInputError('WORKSPACE_UNSUPPORTED', 'Workspace must be a directory.');
1049
+ }
1050
+
1051
+ const authorityPaths = {
1052
+ contract: 'ops/tech-docs/static/contracts/object-type-routing-v1.json',
1053
+ manifestSchema: 'ops/tech-docs/static/schemas/object-type-manifest-v1.schema.json',
1054
+ actionSchema: 'ops/tech-docs/static/schemas/resource-action-v1.schema.json',
1055
+ auditSchema: 'ops/gofer/.specify/schemas/object-type-identifier-audit-v1.schema.json',
1056
+ auditConfig: 'ops/gofer/.specify/config/object-type-routing.json',
1057
+ };
1058
+ // Fail in declared authority order, not filesystem completion order.
1059
+ const authorityEntries = [];
1060
+ for (const [key, relativePath] of Object.entries(authorityPaths)) {
1061
+ const bytes = await readRequired(workspace, relativePath);
1062
+ authorityEntries.push([key, { path: relativePath, bytes, digest: digestBytes(bytes) }]);
1063
+ }
1064
+ const authority = Object.fromEntries(authorityEntries);
1065
+ const contractDocument = parseJson(authority.contract.bytes, authority.contract.path);
1066
+ const manifestSchema = parseJson(authority.manifestSchema.bytes, authority.manifestSchema.path);
1067
+ const actionSchema = parseJson(authority.actionSchema.bytes, authority.actionSchema.path);
1068
+ parseJson(authority.auditSchema.bytes, authority.auditSchema.path);
1069
+ const auditConfig = parseJson(authority.auditConfig.bytes, authority.auditConfig.path);
1070
+
1071
+ const identifierContract = await loadIdentifierValidationContract({
1072
+ contractPath: path.join(workspace, authority.contract.path),
1073
+ schemaPath: path.join(workspace, authority.auditSchema.path),
1074
+ configPath: path.join(workspace, authority.auditConfig.path),
1075
+ });
1076
+ const vectors = contractDocument.derivation?.vectors ?? [];
1077
+ const allFindings = [
1078
+ ...validateAuthority(contractDocument, manifestSchema, actionSchema, auditConfig),
1079
+ ...validateRelationshipReferenceVectors(),
1080
+ ];
1081
+
1082
+ const adapters = [];
1083
+ for (const definition of ADAPTERS) {
1084
+ const reduced = await reduceAdapter(workspace, definition, vectors, identifierContract);
1085
+ adapters.push(reduced.adapter);
1086
+ allFindings.push(...reduced.findings);
1087
+ }
1088
+
1089
+ const runtimeAssets = await reduceRuntimeAssets(workspace);
1090
+ allFindings.push(...runtimeAssets.findings);
1091
+
1092
+ let openapi = { digest: null, governedOperationCount: 0, compatible: false };
1093
+ try {
1094
+ const openapiDocument = generatedOpenApi(workspace);
1095
+ const openapiValidation = validateOpenApi(openapiDocument);
1096
+ allFindings.push(...openapiValidation.findings);
1097
+ openapi = {
1098
+ digest: digestJson(openapiDocument),
1099
+ governedOperationCount: openapiValidation.governedOperationCount,
1100
+ compatible: openapiValidation.findings.length === 0,
1101
+ };
1102
+ } catch (error) {
1103
+ allFindings.push(
1104
+ finding(
1105
+ 'PublicAPI',
1106
+ '/openapi.json',
1107
+ 'OPENAPI_GENERATION_FAILED',
1108
+ error instanceof Error ? error.message : String(error)
1109
+ )
1110
+ );
1111
+ }
1112
+
1113
+ let rawRouteAudit;
1114
+ try {
1115
+ const auditModulePath = path.join(
1116
+ workspace,
1117
+ 'ops/gofer/.specify/scripts/node/validate-v4-resource-contract.mjs'
1118
+ );
1119
+ const auditModule = await import(pathToFileURL(auditModulePath).href);
1120
+ const audit = await auditModule.validateWorkspace(workspace);
1121
+ const ownerBytes = await readOptional(workspace, SOURCE_ROUTE_OWNER);
1122
+ const ownerOccurrenceCount = ownerBytes
1123
+ ? (ownerBytes.toString('utf8').match(/\/v4\/data\/resources\b/g) ?? []).length
1124
+ : 0;
1125
+ if (auditModule.OBJECT_TYPE_ROUTING_AUDIT_CONFIG?.soleOwner !== SOURCE_ROUTE_OWNER) {
1126
+ allFindings.push(
1127
+ finding(
1128
+ 'eai-gofer',
1129
+ authority.auditConfig.path,
1130
+ 'SOLE_ROUTE_OWNER_DRIFT',
1131
+ 'The raw-route audit sole owner differs from the approved SDK module.'
1132
+ )
1133
+ );
1134
+ }
1135
+ if (ownerOccurrenceCount === 0) {
1136
+ allFindings.push(
1137
+ finding(
1138
+ 'eai-app-template',
1139
+ SOURCE_ROUTE_OWNER,
1140
+ 'SOLE_ROUTE_OWNER_EMPTY',
1141
+ 'The sole route owner does not construct the v4 resource route root.'
1142
+ )
1143
+ );
1144
+ }
1145
+ for (const violation of audit.violations) {
1146
+ allFindings.push(
1147
+ finding(
1148
+ 'eai-gofer',
1149
+ violation.location?.file ?? violation.file ?? '<unknown>',
1150
+ violation.rule ?? violation.ruleId ?? 'RAW_ROUTE_AUDIT_FINDING',
1151
+ violation.message ?? violation.remediation ?? 'Raw route audit finding.',
1152
+ {
1153
+ line: violation.location?.line ?? violation.line ?? null,
1154
+ column: violation.location?.column ?? null,
1155
+ }
1156
+ )
1157
+ );
1158
+ }
1159
+ rawRouteAudit = {
1160
+ soleOwner: auditModule.OBJECT_TYPE_ROUTING_AUDIT_CONFIG?.soleOwner ?? null,
1161
+ soleOwnerOccurrenceCount: ownerOccurrenceCount,
1162
+ filesScanned: audit.filesScanned,
1163
+ findingCount: audit.violations.length,
1164
+ digest: digestJson(audit),
1165
+ compatible:
1166
+ audit.valid &&
1167
+ auditModule.OBJECT_TYPE_ROUTING_AUDIT_CONFIG?.soleOwner === SOURCE_ROUTE_OWNER &&
1168
+ ownerOccurrenceCount > 0,
1169
+ };
1170
+ } catch (error) {
1171
+ allFindings.push(
1172
+ finding(
1173
+ 'eai-gofer',
1174
+ 'ops/gofer/.specify/scripts/node/validate-v4-resource-contract.mjs',
1175
+ 'RAW_ROUTE_AUDIT_FAILED',
1176
+ error instanceof Error ? error.message : String(error)
1177
+ )
1178
+ );
1179
+ rawRouteAudit = {
1180
+ soleOwner: null,
1181
+ soleOwnerOccurrenceCount: 0,
1182
+ filesScanned: 0,
1183
+ findingCount: 1,
1184
+ digest: null,
1185
+ compatible: false,
1186
+ };
1187
+ }
1188
+
1189
+ const mirrors = await reduceMirrors(workspace);
1190
+ const coverage = await reduceCoverage(workspace);
1191
+ const legacy = await reduceLegacyEvidence(workspace);
1192
+ allFindings.push(...mirrors.findings, ...coverage.findings, ...legacy.findings);
1193
+
1194
+ const findings = sortFindings(allFindings);
1195
+ const blockingFindingCount = findings.length;
1196
+ const compatible = blockingFindingCount === 0;
1197
+ const componentDigests = Object.fromEntries(
1198
+ adapters.map((adapter) => [adapter.component, adapter.digest])
1199
+ );
1200
+ const artifactDigests = Object.fromEntries(
1201
+ [
1202
+ ...Object.values(authority).map((entry) => [entry.path, entry.digest]),
1203
+ ...runtimeAssets.assets.map((entry) => [entry.runtimePath, entry.runtimeDigest]),
1204
+ ['/openapi.json', openapi.digest],
1205
+ ].sort(([left], [right]) => compareText(left, right))
1206
+ );
1207
+
1208
+ return {
1209
+ schemaVersion: SCHEMA_VERSION,
1210
+ contractVersion: CONTRACT_VERSION,
1211
+ authoritativeTransportIdentifier: contractDocument.authoritativeTransportIdentifier ?? null,
1212
+ compatible,
1213
+ blockingFindingCount,
1214
+ exitCode: compatible ? 0 : 2,
1215
+ findings,
1216
+ contract: {
1217
+ path: authority.contract.path,
1218
+ digest: authority.contract.digest,
1219
+ vectorCount: vectors.length,
1220
+ governedTransportFields: contractDocument.governedTransportFields ?? [],
1221
+ },
1222
+ adapters,
1223
+ runtimeAssets: runtimeAssets.assets,
1224
+ schemas: {
1225
+ manifest: {
1226
+ id: manifestSchema.$id ?? null,
1227
+ dialect: manifestSchema.$schema ?? null,
1228
+ digest: authority.manifestSchema.digest,
1229
+ },
1230
+ resourceAction: {
1231
+ id: actionSchema.$id ?? null,
1232
+ dialect: actionSchema.$schema ?? null,
1233
+ digest: authority.actionSchema.digest,
1234
+ },
1235
+ identifierAudit: {
1236
+ id: identifierContract.auditSchema.$id ?? null,
1237
+ digest: authority.auditSchema.digest,
1238
+ },
1239
+ },
1240
+ openapi,
1241
+ rawRouteAudit,
1242
+ legacyExactSlug: legacy,
1243
+ generatedResources: mirrors.mirrors,
1244
+ coverageOwnership: coverage.coverageOwnership,
1245
+ componentDigests,
1246
+ artifactDigests,
1247
+ };
1248
+ }
1249
+
1250
+ function parseArguments(argv) {
1251
+ const options = { workspace: process.cwd(), json: false };
1252
+ for (let index = 0; index < argv.length; index += 1) {
1253
+ const argument = argv[index];
1254
+ if (argument === '--json') {
1255
+ options.json = true;
1256
+ continue;
1257
+ }
1258
+ if (argument === '--help' || argument === '-h') {
1259
+ options.help = true;
1260
+ continue;
1261
+ }
1262
+ if (argument === '--workspace' || argument === '--output') {
1263
+ const value = argv[index + 1];
1264
+ if (!value || value.startsWith('--')) {
1265
+ throw new WorkspaceInputError('ARGUMENT_MISSING', `${argument} requires a path.`);
1266
+ }
1267
+ options[argument.slice(2)] = value;
1268
+ index += 1;
1269
+ continue;
1270
+ }
1271
+ throw new WorkspaceInputError('ARGUMENT_UNSUPPORTED', `Unsupported argument: ${argument}`);
1272
+ }
1273
+ return options;
1274
+ }
1275
+
1276
+ async function writeAtomic(file, contents) {
1277
+ const target = path.resolve(file);
1278
+ const directory = path.dirname(target);
1279
+ const temporary = path.join(directory, `.${path.basename(target)}.${process.pid}.tmp`);
1280
+ await fs.mkdir(directory, { recursive: true });
1281
+ try {
1282
+ await fs.writeFile(temporary, contents, { encoding: 'utf8', mode: 0o600 });
1283
+ await fs.rename(temporary, target);
1284
+ } catch (error) {
1285
+ await fs.rm(temporary, { force: true });
1286
+ throw error;
1287
+ }
1288
+ }
1289
+
1290
+ async function main(argv) {
1291
+ let options;
1292
+ try {
1293
+ options = parseArguments(argv);
1294
+ if (options.help) {
1295
+ process.stdout.write(
1296
+ 'Usage: validate-object-type-routing-workspace.mjs [--workspace <path>] [--output <path>] [--json]\n'
1297
+ );
1298
+ return 0;
1299
+ }
1300
+ const report = await reduceObjectTypeRoutingWorkspace(options.workspace);
1301
+ const serialized = `${JSON.stringify(report, null, 2)}\n`;
1302
+ if (options.output) await writeAtomic(options.output, serialized);
1303
+ if (options.json) process.stdout.write(serialized);
1304
+ else {
1305
+ process.stdout.write(
1306
+ `${report.compatible ? 'PASS' : 'BLOCKED'} Object Type routing workspace (${report.blockingFindingCount} blocking finding(s))\n`
1307
+ );
1308
+ }
1309
+ return report.exitCode;
1310
+ } catch (error) {
1311
+ const code = error instanceof WorkspaceInputError ? error.code : 'WORKSPACE_REDUCTION_FAILED';
1312
+ process.stderr.write(`${code}: ${error instanceof Error ? error.message : String(error)}\n`);
1313
+ return 4;
1314
+ }
1315
+ }
1316
+
1317
+ export const WORKSPACE_REDUCER_EXIT_CODES = Object.freeze({
1318
+ compatible: 0,
1319
+ blocking: 2,
1320
+ malformed: 4,
1321
+ });
1322
+
1323
+ if (IS_DIRECT_RUN) {
1324
+ process.exitCode = await main(process.argv.slice(2));
1325
+ }