@enterpriseai/cli 3.19.0 → 3.19.2

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