@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,77 @@
1
+ #!/usr/bin/env node
2
+ /** Prepare the local capability identity without granting it runtime authority. */
3
+ import { execFileSync } from 'node:child_process';
4
+ import { generateKeyPairSync, randomUUID } from 'node:crypto';
5
+ import { constants } from 'node:fs';
6
+ import { lstat, mkdir, open, realpath } from 'node:fs/promises';
7
+ import path from 'node:path';
8
+ import { fileURLToPath } from 'node:url';
9
+
10
+ const denied = () => new Error('LOCAL_TRUST_SETUP_REQUIRES_REVIEW');
11
+
12
+ function accountHome() {
13
+ if (typeof process.getuid !== 'function') throw denied();
14
+ if (process.platform === 'darwin') {
15
+ const name = execFileSync('/usr/bin/id', ['-un'], { encoding: 'utf8', timeout: 3000 }).trim();
16
+ if (!/^[a-zA-Z0-9._-]+$/.test(name)) throw denied();
17
+ const record = execFileSync('/usr/bin/dscl', ['.', '-read', path.join(path.sep, 'Users', name), 'NFSHomeDirectory'],
18
+ { encoding: 'utf8', timeout: 3000 }).trim();
19
+ return /^NFSHomeDirectory: (\/[^\n]+)$/.exec(record)?.[1] ?? null;
20
+ }
21
+ if (process.platform === 'linux') {
22
+ const record = execFileSync('/usr/bin/getent', ['passwd', String(process.getuid())],
23
+ { encoding: 'utf8', timeout: 3000 }).trim().split(':');
24
+ return record.length === 7 && record[2] === String(process.getuid()) ? record[5] : null;
25
+ }
26
+ throw denied();
27
+ }
28
+
29
+ async function writeExclusive(filename, value) {
30
+ const file = await open(filename, constants.O_WRONLY | constants.O_CREAT | constants.O_EXCL | constants.O_NOFOLLOW, 0o600);
31
+ try { await file.writeFile(value, 'utf8'); }
32
+ finally { await file.close(); }
33
+ }
34
+
35
+ /** Used by trusted setup only. Existing material is never replaced or activated. */
36
+ export async function initializeStagedTrust(root) {
37
+ if (!path.isAbsolute(root)) throw denied();
38
+ const parent = await realpath(path.dirname(root));
39
+ const parentInfo = await lstat(parent);
40
+ if (!parentInfo.isDirectory() || ![0, process.getuid()].includes(parentInfo.uid) ||
41
+ (parentInfo.mode & 0o022) !== 0 || parent !== path.dirname(root)) throw denied();
42
+ await mkdir(root, { mode: 0o700 });
43
+ const rootInfo = await lstat(root);
44
+ if (!rootInfo.isDirectory() || rootInfo.uid !== process.getuid() ||
45
+ (rootInfo.mode & 0o077) !== 0) throw denied();
46
+ const staged = path.join(root, 'staged-keys');
47
+ await mkdir(staged, { mode: 0o700 });
48
+ // The benchmark verifier key is not staged here. A worker sandbox can read
49
+ // the account home, so a plaintext verifier key would be forgeable. It is
50
+ // created, encrypted, by the human-run gofer-verifier-key-ceremony.mjs.
51
+ const identities = [
52
+ { name: 'capability-evaluator', host: 'codex', evaluator: 'gofer-native-host-evaluator' },
53
+ ];
54
+ const records = [];
55
+ for (const identity of identities) {
56
+ const pair = generateKeyPairSync('ed25519');
57
+ const keyId = `${identity.name}-${randomUUID()}`;
58
+ await writeExclusive(path.join(staged, `${identity.name}.private.pem`),
59
+ pair.privateKey.export({ type: 'pkcs8', format: 'pem' }));
60
+ await writeExclusive(path.join(staged, `${identity.name}.public.pem`),
61
+ pair.publicKey.export({ type: 'spki', format: 'pem' }));
62
+ records.push({ ...identity, keyId });
63
+ }
64
+ await writeExclusive(path.join(root, 'trusted-evaluators.json'),
65
+ `${JSON.stringify({ schemaVersion: 1, evaluators: [] }, null, 2)}\n`);
66
+ await writeExclusive(path.join(staged, 'identities.json'), `${JSON.stringify(records, null, 2)}\n`);
67
+ return { root, identities: records.map(({ name, keyId }) => ({ name, keyId })), active: false };
68
+ }
69
+
70
+ if (process.argv[1] && fileURLToPath(import.meta.url) === path.resolve(process.argv[1])) {
71
+ if (process.argv.length !== 2) throw denied();
72
+ const home = accountHome();
73
+ if (!home || !path.isAbsolute(home)) throw denied();
74
+ initializeStagedTrust(path.join(home, '.eai-gofer-trust'))
75
+ .then(result => process.stdout.write(`${JSON.stringify(result)}\n`))
76
+ .catch(error => { process.stderr.write(`${error.message}\n`); process.exitCode = 1; });
77
+ }
@@ -0,0 +1,102 @@
1
+ /** Authenticate a held-out benchmark report before it can govern routing. */
2
+ import { createHash, createPublicKey, verify } from 'node:crypto';
3
+ import { resolveTrustedEvaluatorPublicKey } from './gofer-trusted-evaluator.mjs';
4
+
5
+ const text = value => typeof value === 'string' && value.trim().length > 0;
6
+ const sha256 = value => createHash('sha256').update(value).digest('hex');
7
+ const denied = () => new Error('TRUSTED_BENCHMARK_REQUIRED');
8
+ const VERIFIER = 'gofer-heldout-benchmark-verifier';
9
+ const digest = value => /^[a-f0-9]{64}$/.test(value ?? '');
10
+ const nonnegative = value => Number.isFinite(value) && value >= 0;
11
+ const wilson95 = (passes, total) => {
12
+ const z = 1.96;
13
+ const p = passes / total;
14
+ const denominator = 1 + z ** 2 / total;
15
+ const centre = (p + z ** 2 / (2 * total)) / denominator;
16
+ const spread = z * Math.sqrt((p * (1 - p) + z ** 2 / (4 * total)) / total) / denominator;
17
+ return { lower: Math.max(0, centre - spread), upper: Math.min(1, centre + spread) };
18
+ };
19
+
20
+ function validReport(report, receiptHash) {
21
+ if (report?.schemaVersion !== 2 || report.repetitions !== 3 ||
22
+ !Number.isInteger(report.caseCount) || report.caseCount < 4 ||
23
+ !Array.isArray(report.runs) || report.runs.length !== report.caseCount * 3 ||
24
+ !text(report.provenance?.harnessId) || !text(report.provenance?.modelId) ||
25
+ !digest(report.provenance?.corpusHash) ||
26
+ report.provenance?.capabilityReceiptHash !== receiptHash) return false;
27
+ const seen = new Set();
28
+ const executions = new Set();
29
+ const verifications = new Set();
30
+ let passes = 0;
31
+ let cost = 0;
32
+ let duration = 0;
33
+ for (const run of report.runs) {
34
+ const pair = `${run?.caseId}:${run?.run}`;
35
+ if (!text(run?.caseId) || !Number.isInteger(run.run) || run.run < 1 || run.run > 3 ||
36
+ seen.has(pair) || run.modelId !== report.provenance.modelId ||
37
+ !nonnegative(run.costUsd) || !nonnegative(run.durationMs) ||
38
+ !digest(run.receipt) || !digest(run.inputHash) || !digest(run.verifierReceipt) ||
39
+ !digest(run.reviewReceipt) || !text(run.verifierId) ||
40
+ !text(run.failureClassification) || typeof run.functionalVerified !== 'boolean' ||
41
+ executions.has(run.receipt) || verifications.has(run.verifierReceipt)) return false;
42
+ seen.add(pair);
43
+ executions.add(run.receipt);
44
+ verifications.add(run.verifierReceipt);
45
+ passes += Number(run.functionalVerified);
46
+ cost += run.costUsd;
47
+ duration += run.durationMs;
48
+ }
49
+ const cases = new Set(report.runs.map(run => run.caseId));
50
+ if (cases.size !== report.caseCount ||
51
+ [...cases].some(id => [1, 2, 3].some(run => !seen.has(`${id}:${run}`)))) return false;
52
+ const reliability = passes / report.runs.length;
53
+ const interval = report.confidenceInterval;
54
+ const expectedInterval = wilson95(passes, report.runs.length);
55
+ return report.functionalPasses === passes && report.functionalRuns === report.runs.length &&
56
+ Math.abs(report.reliability - reliability) < 1e-12 &&
57
+ Math.abs(report.costUsd - cost) < 1e-9 && report.durationMs === duration &&
58
+ report.status === (passes === report.runs.length ? 'pass' : 'fail') &&
59
+ interval?.level === 0.95 &&
60
+ Math.abs(interval.lower - expectedInterval.lower) < 1e-12 &&
61
+ Math.abs(interval.upper - expectedInterval.upper) < 1e-12;
62
+ }
63
+
64
+ /**
65
+ * A signed attestation binds all report fields, including every run verdict,
66
+ * cost, review receipt, and provenance field. Only a separately registered
67
+ * verifier key may authorize this evidence for the native runtime.
68
+ */
69
+ export async function verifyTrustedBenchmarkEvidence({ host, receiptHash, evidence,
70
+ attestation, capabilityKeyId, capabilityPublicKey, workspaceRoot, now = Date.now() } = {}) {
71
+ if (!text(host) || !/^[a-f0-9]{64}$/.test(receiptHash ?? '') || !text(capabilityKeyId) ||
72
+ !capabilityPublicKey || !text(workspaceRoot) || !Number.isFinite(now) || !attestation ||
73
+ attestation.schemaVersion !== 1 || attestation.host !== host ||
74
+ attestation.capabilityReceiptHash !== receiptHash ||
75
+ attestation.verification !== 'functional-tests+independent-review' ||
76
+ !text(attestation.verifierVersion) || attestation.provenance?.evaluator !== VERIFIER ||
77
+ !text(attestation.provenance?.keyId) || attestation.provenance.keyId === capabilityKeyId ||
78
+ !text(attestation.provenance?.source) || attestation.signature?.algorithm !== 'ed25519' ||
79
+ attestation.signature.keyId !== attestation.provenance.keyId ||
80
+ !/^[A-Za-z0-9_-]+$/.test(attestation.signature.value ?? '')) throw denied();
81
+ const verifiedAt = Date.parse(attestation.verifiedAt);
82
+ const expiresAt = Date.parse(attestation.expiresAt);
83
+ if (!Number.isFinite(verifiedAt) || !Number.isFinite(expiresAt) ||
84
+ verifiedAt > now || expiresAt <= now || expiresAt <= verifiedAt) throw denied();
85
+ let bytes;
86
+ try { bytes = JSON.stringify(evidence); } catch { throw denied(); }
87
+ const reports = Array.isArray(evidence) ? evidence : [evidence];
88
+ if (!reports.length || !reports.every(report => validReport(report, receiptHash)) ||
89
+ attestation.evidenceHash !== sha256(bytes)) throw denied();
90
+ const { signature, ...payload } = attestation;
91
+ const publicKey = await resolveTrustedEvaluatorPublicKey(attestation,
92
+ { workspaceRoot }).catch(() => { throw denied(); });
93
+ try {
94
+ const capabilityKey = capabilityPublicKey?.type === 'public'
95
+ ? capabilityPublicKey : createPublicKey(capabilityPublicKey);
96
+ if (publicKey.export({ type: 'spki', format: 'der' }).equals(
97
+ capabilityKey.export({ type: 'spki', format: 'der' }))) throw denied();
98
+ } catch { throw denied(); }
99
+ if (!verify(null, Buffer.from(JSON.stringify(payload)), publicKey,
100
+ Buffer.from(signature.value, 'base64url'))) throw denied();
101
+ return Object.freeze({ valid: true, receiptHash, receipt: `benchmark:${sha256(JSON.stringify(attestation))}` });
102
+ }
@@ -0,0 +1,274 @@
1
+ /** Read a locally provisioned evaluator key. The worker never chooses it. */
2
+ import { createHash, createPrivateKey, createPublicKey } from 'node:crypto';
3
+ import { execFileSync } from 'node:child_process';
4
+ import { constants } from 'node:fs';
5
+ import { lstat, open, realpath } from 'node:fs/promises';
6
+ import path from 'node:path';
7
+ import { loadHeldOutCorpus } from './gofer-heldout-corpus.mjs';
8
+ import { decryptSigningKey } from './gofer-encrypted-key.mjs';
9
+
10
+ const text = value => typeof value === 'string' && value.trim().length > 0;
11
+ const inside = (parent, child) => {
12
+ const relative = path.relative(parent, child);
13
+ return relative === '' || (relative !== '..' && !relative.startsWith(`..${path.sep}`) && !path.isAbsolute(relative));
14
+ };
15
+ const denied = () => new Error('TRUSTED_EVALUATOR_REQUIRED');
16
+
17
+ export function accountTrustRoot() {
18
+ // HOME is caller-controlled. Resolve the account record by effective UID.
19
+ if (process.platform === 'linux') {
20
+ const uid = process.getuid();
21
+ const record = execFileSync('/usr/bin/getent', ['passwd', String(uid)],
22
+ { encoding: 'utf8', timeout: 3000 }).trim();
23
+ const fields = record.split(':');
24
+ const home = fields.length === 7 && fields[2] === String(uid) ? fields[5] : null;
25
+ if (!home || !path.isAbsolute(home) || home.includes('\n')) throw denied();
26
+ return path.join(home, '.eai-gofer-trust');
27
+ }
28
+ if (process.platform !== 'darwin') throw denied();
29
+ const name = execFileSync('/usr/bin/id', ['-un'], { encoding: 'utf8', timeout: 3000 }).trim();
30
+ if (!/^[a-zA-Z0-9._-]+$/.test(name)) throw denied();
31
+ const record = execFileSync('/usr/bin/dscl', ['.', '-read', path.join(path.sep, 'Users', name), 'NFSHomeDirectory'],
32
+ { encoding: 'utf8', timeout: 3000 }).trim();
33
+ const home = /^NFSHomeDirectory: (\/[^\n]+)$/.exec(record)?.[1];
34
+ if (!home) throw denied();
35
+ return path.join(home, '.eai-gofer-trust');
36
+ }
37
+
38
+ // A directory handle stays bound to the inode it opened even if something
39
+ // later renames or replaces the path. Re-checking a path-based file open
40
+ // against the handle's device/inode closes the gap between validating a
41
+ // directory and reading a file inside it: a same-uid path substitution is
42
+ // detected instead of silently trusted.
43
+ async function assertSameDirectory(candidatePath, boundInfo) {
44
+ const current = await lstat(candidatePath).catch(() => null);
45
+ if (!current || current.dev !== boundInfo.dev || current.ino !== boundInfo.ino) throw denied();
46
+ }
47
+
48
+ async function inspectAccountTrustRoot(root, workspaceRoot) {
49
+ if (!path.isAbsolute(root)) throw denied();
50
+ const [workspace, parent] = await Promise.all([realpath(workspaceRoot), realpath(path.dirname(root))]);
51
+ const parentInfo = await lstat(parent);
52
+ const canonicalRoot = path.join(parent, path.basename(root));
53
+ if (!parentInfo.isDirectory() || ![0, process.getuid()].includes(parentInfo.uid) ||
54
+ (parentInfo.mode & 0o022) !== 0 || inside(workspace, canonicalRoot) ||
55
+ inside(canonicalRoot, workspace)) throw denied();
56
+ const handle = await open(canonicalRoot, constants.O_RDONLY | constants.O_DIRECTORY | constants.O_NOFOLLOW);
57
+ try {
58
+ const rootInfo = await handle.stat();
59
+ if (!rootInfo.isDirectory() || rootInfo.uid !== process.getuid() ||
60
+ (rootInfo.mode & 0o077) !== 0) throw denied();
61
+ return { canonicalRoot, handle, info: rootInfo };
62
+ } catch (err) { await handle.close(); throw err; }
63
+ }
64
+
65
+ // Open a file below a directory already validated by `inspectAccountTrustRoot`,
66
+ // re-confirming immediately beforehand that the directory path has not been
67
+ // substituted since that validation.
68
+ async function openVerifiedFile(directory, filename) {
69
+ const filePath = path.join(directory.canonicalRoot, filename);
70
+ const file = await open(filePath, constants.O_RDONLY | constants.O_NOFOLLOW);
71
+ try {
72
+ await assertSameDirectory(directory.canonicalRoot, directory.info);
73
+ return file;
74
+ } catch (err) { await file.close(); throw err; }
75
+ }
76
+
77
+ export const VERIFIER_EVALUATOR = 'gofer-heldout-benchmark-verifier';
78
+
79
+ /** Verifier keys are trusted only from a root-owned registry. Anything the
80
+ * account can write, an unsandboxed process in that account can also write. */
81
+ export function protectedVerifierRegistryPath() {
82
+ if (process.platform === 'darwin') return '/Library/Application Support/EAI Gofer/verifier-registry.json';
83
+ if (process.platform === 'linux') return '/etc/eai-gofer/verifier-registry.json';
84
+ throw denied();
85
+ }
86
+
87
+ async function loadProtectedVerifierKey(receipt, { path: registryPath = protectedVerifierRegistryPath(),
88
+ ownerUid = 0 } = {}) {
89
+ try {
90
+ if (!path.isAbsolute(registryPath) || !Number.isInteger(ownerUid)) throw denied();
91
+ const parent = await realpath(path.dirname(registryPath));
92
+ for (let current = parent; ;) {
93
+ const info = await lstat(current);
94
+ if (!info.isDirectory() || ![0, ownerUid].includes(info.uid) || (info.mode & 0o022) !== 0) throw denied();
95
+ const above = path.dirname(current);
96
+ if (above === current) break;
97
+ current = above;
98
+ }
99
+ let registry;
100
+ const file = await open(path.join(parent, path.basename(registryPath)),
101
+ constants.O_RDONLY | constants.O_NOFOLLOW);
102
+ try {
103
+ const info = await file.stat();
104
+ if (!info.isFile() || info.uid !== ownerUid || info.nlink !== 1 ||
105
+ (info.mode & 0o022) !== 0 || info.size < 2 || info.size > 65536) throw denied();
106
+ registry = JSON.parse(await file.readFile('utf8'));
107
+ } finally { await file.close(); }
108
+ if (registry?.schemaVersion !== 1 || !Array.isArray(registry.evaluators) ||
109
+ registry.evaluators.length < 1 || registry.evaluators.length > 32 ||
110
+ registry.evaluators.some(item => !text(item?.keyId) || !text(item?.host) ||
111
+ item.evaluator !== VERIFIER_EVALUATOR || !text(item?.publicKeyPem)) ||
112
+ new Set(registry.evaluators.map(item => item.keyId)).size !== registry.evaluators.length) throw denied();
113
+ const entry = registry.evaluators.find(item => item.keyId === receipt.provenance.keyId &&
114
+ item.host === receipt.host);
115
+ if (!entry) throw denied();
116
+ const key = createPublicKey(entry.publicKeyPem);
117
+ if (key.asymmetricKeyType !== 'ed25519') throw denied();
118
+ return key;
119
+ } catch { throw denied(); }
120
+ }
121
+
122
+ /**
123
+ * The default trust root is fixed outside the checkout. `trustRoot` exists for
124
+ * isolated tests; the production composition root never accepts an override.
125
+ */
126
+ export async function resolveTrustedEvaluatorPublicKey(receipt, { workspaceRoot, trustRoot, protectedRegistry } = {}) {
127
+ if (process.platform === 'win32' || typeof process.getuid !== 'function' ||
128
+ !text(workspaceRoot) || !text(receipt?.host) || !text(receipt?.provenance?.keyId) ||
129
+ !text(receipt?.provenance?.evaluator)) throw denied();
130
+ if (receipt.provenance.evaluator === VERIFIER_EVALUATOR) return loadProtectedVerifierKey(receipt, protectedRegistry);
131
+ const root = trustRoot ?? accountTrustRoot();
132
+ try {
133
+ const directory = await inspectAccountTrustRoot(root, workspaceRoot);
134
+ let registry;
135
+ try {
136
+ const file = await openVerifiedFile(directory, 'trusted-evaluators.json');
137
+ try {
138
+ const actual = await file.stat();
139
+ if (!actual.isFile() || actual.uid !== process.getuid() ||
140
+ (actual.mode & 0o077) !== 0 || actual.size < 2 || actual.size > 65536) throw denied();
141
+ registry = JSON.parse(await file.readFile('utf8'));
142
+ } finally { await file.close(); }
143
+ } finally { await directory.handle.close(); }
144
+ if (registry?.schemaVersion !== 1 || !Array.isArray(registry.evaluators) ||
145
+ registry.evaluators.length < 1 || registry.evaluators.length > 32 ||
146
+ registry.evaluators.some(item => !text(item?.keyId) || !text(item?.host) ||
147
+ !text(item?.evaluator) || !text(item?.publicKeyPem)) ||
148
+ new Set(registry.evaluators.map(item => item.keyId)).size !== registry.evaluators.length) throw denied();
149
+ const entry = registry.evaluators.find(item => item.keyId === receipt.provenance.keyId &&
150
+ item.host === receipt.host && item.evaluator === receipt.provenance.evaluator);
151
+ if (!entry) throw denied();
152
+ const key = createPublicKey(entry.publicKeyPem);
153
+ if (key.asymmetricKeyType !== 'ed25519') throw denied();
154
+ return key;
155
+ } catch { throw denied(); }
156
+ }
157
+
158
+ /** Only activated identities can sign. Production issuers never expose a
159
+ * caller-selected trust root; the override is for isolated tests. */
160
+ async function loadActiveEvaluatorKey({ workspaceRoot, trustRoot, identityName, evaluator,
161
+ getPassphrase, protectedRegistry } = {}) {
162
+ if (!text(workspaceRoot) || process.platform === 'win32' || typeof process.getuid !== 'function') throw denied();
163
+ const root = trustRoot ?? accountTrustRoot();
164
+ try {
165
+ const active = path.join(root, 'active-keys');
166
+ const handle = await open(active, constants.O_RDONLY | constants.O_DIRECTORY | constants.O_NOFOLLOW);
167
+ let identity, privateKey;
168
+ try {
169
+ const activeInfo = await handle.stat();
170
+ if (!activeInfo.isDirectory() || activeInfo.uid !== process.getuid() ||
171
+ (activeInfo.mode & 0o077) !== 0) throw denied();
172
+ const directory = { canonicalRoot: active, handle, info: activeInfo };
173
+ const identityFile = await openVerifiedFile(directory, `${identityName}.json`);
174
+ try {
175
+ const info = await identityFile.stat();
176
+ if (!info.isFile() || info.uid !== process.getuid() ||
177
+ (info.mode & 0o077) !== 0 || info.size < 2 || info.size > 4096) throw denied();
178
+ identity = JSON.parse(await identityFile.readFile('utf8'));
179
+ } finally { await identityFile.close(); }
180
+ if (identity?.schemaVersion !== 1 || identity.host !== 'codex' ||
181
+ identity.evaluator !== evaluator || !text(identity.keyId)) throw denied();
182
+ const publicKey = await resolveTrustedEvaluatorPublicKey({ host: identity.host,
183
+ provenance: { evaluator: identity.evaluator, keyId: identity.keyId } }, { workspaceRoot, trustRoot, protectedRegistry });
184
+ if (evaluator === VERIFIER_EVALUATOR) {
185
+ // A plaintext verifier key is readable by any worker. Only an
186
+ // encrypted envelope, opened with a passphrase a person types, loads.
187
+ if (typeof getPassphrase !== 'function') throw denied();
188
+ const envelopeFile = await openVerifiedFile(directory, `${identityName}.private.enc.json`);
189
+ let envelope;
190
+ try {
191
+ const info = await envelopeFile.stat();
192
+ if (!info.isFile() || info.uid !== process.getuid() || info.nlink !== 1 ||
193
+ (info.mode & 0o077) !== 0 || info.size < 100 || info.size > 8192) throw denied();
194
+ envelope = JSON.parse(await envelopeFile.readFile('utf8'));
195
+ } finally { await envelopeFile.close(); }
196
+ privateKey = await decryptSigningKey(envelope, await getPassphrase());
197
+ } else {
198
+ const privateFile = await openVerifiedFile(directory, `${identityName}.private.pem`);
199
+ try {
200
+ const info = await privateFile.stat();
201
+ if (!info.isFile() || info.uid !== process.getuid() ||
202
+ (info.mode & 0o077) !== 0 || info.size < 32 || info.size > 8192) throw denied();
203
+ privateKey = createPrivateKey(await privateFile.readFile('utf8'));
204
+ } finally { await privateFile.close(); }
205
+ }
206
+ if (privateKey.asymmetricKeyType !== 'ed25519' ||
207
+ !createPublicKey(privateKey).export({ type: 'spki', format: 'der' })
208
+ .equals(publicKey.export({ type: 'spki', format: 'der' }))) throw denied();
209
+ } finally { await handle.close(); }
210
+ return Object.freeze({ privateKey, keyId: identity.keyId });
211
+ } catch { throw denied(); }
212
+ }
213
+
214
+ export async function loadActiveCodexEvaluatorKey({ workspaceRoot, trustRoot } = {}) {
215
+ return loadActiveEvaluatorKey({ workspaceRoot, trustRoot,
216
+ identityName: 'codex-evaluator', evaluator: 'gofer-native-host-evaluator' });
217
+ }
218
+
219
+ export async function loadActiveBenchmarkVerifierKey({ workspaceRoot, trustRoot, getPassphrase,
220
+ protectedRegistry } = {}) {
221
+ return loadActiveEvaluatorKey({ workspaceRoot, trustRoot, getPassphrase, protectedRegistry,
222
+ identityName: 'heldout-verifier', evaluator: VERIFIER_EVALUATOR });
223
+ }
224
+
225
+ /** The controller pins one corpus inside its account-owned trust root.
226
+ * A worker cannot select a path or replace a pinned input through this API. */
227
+ export async function loadTrustedHeldOutCorpus({ workspaceRoot, trustRoot } = {}) {
228
+ if (!text(workspaceRoot) || process.platform === 'win32' ||
229
+ typeof process.getuid !== 'function') throw denied();
230
+ const root = trustRoot ?? accountTrustRoot();
231
+ try {
232
+ const trustDirectory = await inspectAccountTrustRoot(root, workspaceRoot);
233
+ let config;
234
+ try {
235
+ const configFile = await openVerifiedFile(trustDirectory, 'heldout-corpus.json');
236
+ try {
237
+ const info = await configFile.stat();
238
+ if (!info.isFile() || info.uid !== process.getuid() || info.nlink !== 1 ||
239
+ (info.mode & 0o077) !== 0 || info.size < 2 || info.size > 4096) throw denied();
240
+ config = JSON.parse(await configFile.readFile('utf8'));
241
+ } finally { await configFile.close(); }
242
+ } finally { await trustDirectory.handle.close(); }
243
+ if (config?.schemaVersion !== 1 || !/^[a-zA-Z0-9][a-zA-Z0-9._-]{0,63}$/.test(config.corpusId ?? '') ||
244
+ !/^[a-f0-9]{64}$/.test(config.corpusHash ?? '')) throw denied();
245
+ const corpora = path.join(trustDirectory.canonicalRoot, 'corpora');
246
+ const corpusRoot = path.join(corpora, config.corpusId);
247
+ for (const directory of [corpora, corpusRoot]) {
248
+ const info = await lstat(directory);
249
+ if (!info.isDirectory() || info.uid !== process.getuid() ||
250
+ (info.mode & 0o077) !== 0) throw denied();
251
+ }
252
+ const manifestFile = await open(path.join(corpusRoot, 'manifest.json'),
253
+ constants.O_RDONLY | constants.O_NOFOLLOW);
254
+ let manifest;
255
+ try {
256
+ const info = await manifestFile.stat();
257
+ if (!info.isFile() || info.uid !== process.getuid() || info.nlink !== 1 ||
258
+ (info.mode & 0o077) !== 0 || info.size < 2 || info.size > 65536) throw denied();
259
+ manifest = JSON.parse(await manifestFile.readFile('utf8'));
260
+ } finally { await manifestFile.close(); }
261
+ if (!Array.isArray(manifest?.cases) ||
262
+ createHash('sha256').update(JSON.stringify(manifest)).digest('hex') !== config.corpusHash) throw denied();
263
+ for (const name of manifest.cases.map(item => item?.inputFile)) {
264
+ if (!text(name) || name === '.' || name === '..' || name.includes('/') ||
265
+ name.includes('\\')) throw denied();
266
+ const info = await lstat(path.join(corpusRoot, name));
267
+ if (!info.isFile() || info.uid !== process.getuid() || info.nlink !== 1 ||
268
+ (info.mode & 0o077) !== 0) throw denied();
269
+ }
270
+ const corpus = await loadHeldOutCorpus({ corpusRoot, workspaceRoot });
271
+ if (corpus.corpusHash !== config.corpusHash) throw denied();
272
+ return Object.freeze({ ...corpus, corpusRoot });
273
+ } catch { throw denied(); }
274
+ }
@@ -0,0 +1,34 @@
1
+ /** Read a secret from a real terminal only. Never from a pipe, an argument,
2
+ * the environment, or a file: a person must be present to type it. */
3
+ import process from 'node:process';
4
+
5
+ const denied = () => new Error('INTERACTIVE_TERMINAL_REQUIRED');
6
+ const CANCEL = new Set([String.fromCharCode(3), String.fromCharCode(4)]);
7
+ const BACKSPACE = new Set([String.fromCharCode(127), String.fromCharCode(8)]);
8
+
9
+ export function promptHidden(label, { stdin = process.stdin, stdout = process.stdout } = {}) {
10
+ if (!stdin.isTTY || !stdout.isTTY || typeof stdin.setRawMode !== 'function') throw denied();
11
+ return new Promise((resolve, reject) => {
12
+ let value = '';
13
+ const finish = (error, result) => {
14
+ stdin.removeListener('data', onData);
15
+ stdin.setRawMode(false);
16
+ stdin.pause();
17
+ stdout.write('\n');
18
+ if (error) reject(error);
19
+ else resolve(result);
20
+ };
21
+ const onData = chunk => {
22
+ for (const character of chunk.toString('utf8')) {
23
+ if (character === '\r' || character === '\n') return finish(null, value);
24
+ if (CANCEL.has(character)) return finish(new Error('PASSPHRASE_ENTRY_CANCELLED'));
25
+ if (BACKSPACE.has(character)) value = value.slice(0, -1);
26
+ else if (character >= ' ') value += character;
27
+ }
28
+ };
29
+ stdout.write(label);
30
+ stdin.setRawMode(true);
31
+ stdin.resume();
32
+ stdin.on('data', onData);
33
+ });
34
+ }