eai-cli 0.0.0-bootstrap.0

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 (690) hide show
  1. package/LICENSE +183 -0
  2. package/NOTICE +4 -0
  3. package/README.md +14 -0
  4. package/dist/commands/agent.d.ts +3 -0
  5. package/dist/commands/agent.d.ts.map +1 -0
  6. package/dist/commands/agent.js +69 -0
  7. package/dist/commands/agent.js.map +1 -0
  8. package/dist/commands/blocks.d.ts +3 -0
  9. package/dist/commands/blocks.d.ts.map +1 -0
  10. package/dist/commands/blocks.js +249 -0
  11. package/dist/commands/blocks.js.map +1 -0
  12. package/dist/commands/chat.d.ts +6 -0
  13. package/dist/commands/chat.d.ts.map +1 -0
  14. package/dist/commands/chat.js +105 -0
  15. package/dist/commands/chat.js.map +1 -0
  16. package/dist/commands/deploy.d.ts +36 -0
  17. package/dist/commands/deploy.d.ts.map +1 -0
  18. package/dist/commands/deploy.js +712 -0
  19. package/dist/commands/deploy.js.map +1 -0
  20. package/dist/commands/dev.d.ts +15 -0
  21. package/dist/commands/dev.d.ts.map +1 -0
  22. package/dist/commands/dev.js +133 -0
  23. package/dist/commands/dev.js.map +1 -0
  24. package/dist/commands/docs.d.ts +6 -0
  25. package/dist/commands/docs.d.ts.map +1 -0
  26. package/dist/commands/docs.js +118 -0
  27. package/dist/commands/docs.js.map +1 -0
  28. package/dist/commands/env.d.ts +10 -0
  29. package/dist/commands/env.d.ts.map +1 -0
  30. package/dist/commands/env.js +200 -0
  31. package/dist/commands/env.js.map +1 -0
  32. package/dist/commands/errors.d.ts +3 -0
  33. package/dist/commands/errors.d.ts.map +1 -0
  34. package/dist/commands/errors.js +72 -0
  35. package/dist/commands/errors.js.map +1 -0
  36. package/dist/commands/gofer.d.ts +3 -0
  37. package/dist/commands/gofer.d.ts.map +1 -0
  38. package/dist/commands/gofer.js +134 -0
  39. package/dist/commands/gofer.js.map +1 -0
  40. package/dist/commands/init.d.ts +14 -0
  41. package/dist/commands/init.d.ts.map +1 -0
  42. package/dist/commands/init.js +1437 -0
  43. package/dist/commands/init.js.map +1 -0
  44. package/dist/commands/login.d.ts +7 -0
  45. package/dist/commands/login.d.ts.map +1 -0
  46. package/dist/commands/login.js +117 -0
  47. package/dist/commands/login.js.map +1 -0
  48. package/dist/commands/provision.d.ts +6 -0
  49. package/dist/commands/provision.d.ts.map +1 -0
  50. package/dist/commands/provision.js +855 -0
  51. package/dist/commands/provision.js.map +1 -0
  52. package/dist/commands/publicapi.d.ts +6 -0
  53. package/dist/commands/publicapi.d.ts.map +1 -0
  54. package/dist/commands/publicapi.js +184 -0
  55. package/dist/commands/publicapi.js.map +1 -0
  56. package/dist/commands/resources.d.ts +38 -0
  57. package/dist/commands/resources.d.ts.map +1 -0
  58. package/dist/commands/resources.js +1010 -0
  59. package/dist/commands/resources.js.map +1 -0
  60. package/dist/commands/runtime.d.ts +3 -0
  61. package/dist/commands/runtime.d.ts.map +1 -0
  62. package/dist/commands/runtime.js +78 -0
  63. package/dist/commands/runtime.js.map +1 -0
  64. package/dist/commands/template.d.ts +3 -0
  65. package/dist/commands/template.d.ts.map +1 -0
  66. package/dist/commands/template.js +365 -0
  67. package/dist/commands/template.js.map +1 -0
  68. package/dist/commands/tenant.d.ts +45 -0
  69. package/dist/commands/tenant.d.ts.map +1 -0
  70. package/dist/commands/tenant.js +1036 -0
  71. package/dist/commands/tenant.js.map +1 -0
  72. package/dist/commands/types.d.ts +130 -0
  73. package/dist/commands/types.d.ts.map +1 -0
  74. package/dist/commands/types.js +1636 -0
  75. package/dist/commands/types.js.map +1 -0
  76. package/dist/commands/update.d.ts +13 -0
  77. package/dist/commands/update.d.ts.map +1 -0
  78. package/dist/commands/update.js +163 -0
  79. package/dist/commands/update.js.map +1 -0
  80. package/dist/commands/user.d.ts +6 -0
  81. package/dist/commands/user.d.ts.map +1 -0
  82. package/dist/commands/user.js +359 -0
  83. package/dist/commands/user.js.map +1 -0
  84. package/dist/commands/verify.d.ts +40 -0
  85. package/dist/commands/verify.d.ts.map +1 -0
  86. package/dist/commands/verify.js +1442 -0
  87. package/dist/commands/verify.js.map +1 -0
  88. package/dist/commands/vertical.d.ts +24 -0
  89. package/dist/commands/vertical.d.ts.map +1 -0
  90. package/dist/commands/vertical.js +301 -0
  91. package/dist/commands/vertical.js.map +1 -0
  92. package/dist/commands/whoami.d.ts +6 -0
  93. package/dist/commands/whoami.d.ts.map +1 -0
  94. package/dist/commands/whoami.js +73 -0
  95. package/dist/commands/whoami.js.map +1 -0
  96. package/dist/commands/workflow.d.ts +6 -0
  97. package/dist/commands/workflow.d.ts.map +1 -0
  98. package/dist/commands/workflow.js +400 -0
  99. package/dist/commands/workflow.js.map +1 -0
  100. package/dist/index.d.ts +10 -0
  101. package/dist/index.d.ts.map +1 -0
  102. package/dist/index.js +272 -0
  103. package/dist/index.js.map +1 -0
  104. package/dist/lib/agent-guide.d.ts +24 -0
  105. package/dist/lib/agent-guide.d.ts.map +1 -0
  106. package/dist/lib/agent-guide.js +155 -0
  107. package/dist/lib/agent-guide.js.map +1 -0
  108. package/dist/lib/api.d.ts +338 -0
  109. package/dist/lib/api.d.ts.map +1 -0
  110. package/dist/lib/api.js +991 -0
  111. package/dist/lib/api.js.map +1 -0
  112. package/dist/lib/auth.d.ts +65 -0
  113. package/dist/lib/auth.d.ts.map +1 -0
  114. package/dist/lib/auth.js +592 -0
  115. package/dist/lib/auth.js.map +1 -0
  116. package/dist/lib/azure-cli.d.ts +6 -0
  117. package/dist/lib/azure-cli.d.ts.map +1 -0
  118. package/dist/lib/azure-cli.js +13 -0
  119. package/dist/lib/azure-cli.js.map +1 -0
  120. package/dist/lib/block-catalog-normalize.d.ts +47 -0
  121. package/dist/lib/block-catalog-normalize.d.ts.map +1 -0
  122. package/dist/lib/block-catalog-normalize.js +355 -0
  123. package/dist/lib/block-catalog-normalize.js.map +1 -0
  124. package/dist/lib/block-catalog-types.d.ts +111 -0
  125. package/dist/lib/block-catalog-types.d.ts.map +1 -0
  126. package/dist/lib/block-catalog-types.js +41 -0
  127. package/dist/lib/block-catalog-types.js.map +1 -0
  128. package/dist/lib/block-catalog-utils.d.ts +7 -0
  129. package/dist/lib/block-catalog-utils.d.ts.map +1 -0
  130. package/dist/lib/block-catalog-utils.js +47 -0
  131. package/dist/lib/block-catalog-utils.js.map +1 -0
  132. package/dist/lib/block-catalog-validation.d.ts +5 -0
  133. package/dist/lib/block-catalog-validation.d.ts.map +1 -0
  134. package/dist/lib/block-catalog-validation.js +112 -0
  135. package/dist/lib/block-catalog-validation.js.map +1 -0
  136. package/dist/lib/block-catalog.d.ts +3 -0
  137. package/dist/lib/block-catalog.d.ts.map +1 -0
  138. package/dist/lib/block-catalog.js +284 -0
  139. package/dist/lib/block-catalog.js.map +1 -0
  140. package/dist/lib/cloud-env.d.ts +25 -0
  141. package/dist/lib/cloud-env.d.ts.map +1 -0
  142. package/dist/lib/cloud-env.js +79 -0
  143. package/dist/lib/cloud-env.js.map +1 -0
  144. package/dist/lib/config.d.ts +116 -0
  145. package/dist/lib/config.d.ts.map +1 -0
  146. package/dist/lib/config.js +195 -0
  147. package/dist/lib/config.js.map +1 -0
  148. package/dist/lib/context.d.ts +43 -0
  149. package/dist/lib/context.d.ts.map +1 -0
  150. package/dist/lib/context.js +68 -0
  151. package/dist/lib/context.js.map +1 -0
  152. package/dist/lib/error-codes.d.ts +56 -0
  153. package/dist/lib/error-codes.d.ts.map +1 -0
  154. package/dist/lib/error-codes.js +211 -0
  155. package/dist/lib/error-codes.js.map +1 -0
  156. package/dist/lib/error-guidance/catalog.d.ts +648 -0
  157. package/dist/lib/error-guidance/catalog.d.ts.map +1 -0
  158. package/dist/lib/error-guidance/catalog.js +940 -0
  159. package/dist/lib/error-guidance/catalog.js.map +1 -0
  160. package/dist/lib/error-guidance/match.d.ts +3 -0
  161. package/dist/lib/error-guidance/match.d.ts.map +1 -0
  162. package/dist/lib/error-guidance/match.js +46 -0
  163. package/dist/lib/error-guidance/match.js.map +1 -0
  164. package/dist/lib/error-guidance/render.d.ts +5 -0
  165. package/dist/lib/error-guidance/render.d.ts.map +1 -0
  166. package/dist/lib/error-guidance/render.js +92 -0
  167. package/dist/lib/error-guidance/render.js.map +1 -0
  168. package/dist/lib/error-guidance/types.d.ts +76 -0
  169. package/dist/lib/error-guidance/types.d.ts.map +1 -0
  170. package/dist/lib/error-guidance/types.js +2 -0
  171. package/dist/lib/error-guidance/types.js.map +1 -0
  172. package/dist/lib/error-guidance/validate.d.ts +3 -0
  173. package/dist/lib/error-guidance/validate.d.ts.map +1 -0
  174. package/dist/lib/error-guidance/validate.js +59 -0
  175. package/dist/lib/error-guidance/validate.js.map +1 -0
  176. package/dist/lib/gofer-installer.d.ts +32 -0
  177. package/dist/lib/gofer-installer.d.ts.map +1 -0
  178. package/dist/lib/gofer-installer.js +589 -0
  179. package/dist/lib/gofer-installer.js.map +1 -0
  180. package/dist/lib/gofer-refresh.d.ts +46 -0
  181. package/dist/lib/gofer-refresh.d.ts.map +1 -0
  182. package/dist/lib/gofer-refresh.js +536 -0
  183. package/dist/lib/gofer-refresh.js.map +1 -0
  184. package/dist/lib/next-route-exports.d.ts +6 -0
  185. package/dist/lib/next-route-exports.d.ts.map +1 -0
  186. package/dist/lib/next-route-exports.js +127 -0
  187. package/dist/lib/next-route-exports.js.map +1 -0
  188. package/dist/lib/npm.d.ts +2 -0
  189. package/dist/lib/npm.d.ts.map +1 -0
  190. package/dist/lib/npm.js +4 -0
  191. package/dist/lib/npm.js.map +1 -0
  192. package/dist/lib/object-type-defaults.d.ts +4 -0
  193. package/dist/lib/object-type-defaults.d.ts.map +1 -0
  194. package/dist/lib/object-type-defaults.js +72 -0
  195. package/dist/lib/object-type-defaults.js.map +1 -0
  196. package/dist/lib/output.d.ts +35 -0
  197. package/dist/lib/output.d.ts.map +1 -0
  198. package/dist/lib/output.js +166 -0
  199. package/dist/lib/output.js.map +1 -0
  200. package/dist/lib/profile.d.ts +52 -0
  201. package/dist/lib/profile.d.ts.map +1 -0
  202. package/dist/lib/profile.js +116 -0
  203. package/dist/lib/profile.js.map +1 -0
  204. package/dist/lib/project-manifest.d.ts +42 -0
  205. package/dist/lib/project-manifest.d.ts.map +1 -0
  206. package/dist/lib/project-manifest.js +191 -0
  207. package/dist/lib/project-manifest.js.map +1 -0
  208. package/dist/lib/resourceapi-bundle.d.ts +33 -0
  209. package/dist/lib/resourceapi-bundle.d.ts.map +1 -0
  210. package/dist/lib/resourceapi-bundle.js +79 -0
  211. package/dist/lib/resourceapi-bundle.js.map +1 -0
  212. package/dist/lib/runtime-contract.d.ts +84 -0
  213. package/dist/lib/runtime-contract.d.ts.map +1 -0
  214. package/dist/lib/runtime-contract.js +318 -0
  215. package/dist/lib/runtime-contract.js.map +1 -0
  216. package/dist/lib/schema-builder.d.ts +28 -0
  217. package/dist/lib/schema-builder.d.ts.map +1 -0
  218. package/dist/lib/schema-builder.js +69 -0
  219. package/dist/lib/schema-builder.js.map +1 -0
  220. package/dist/lib/tenant-context.d.ts +127 -0
  221. package/dist/lib/tenant-context.d.ts.map +1 -0
  222. package/dist/lib/tenant-context.js +573 -0
  223. package/dist/lib/tenant-context.js.map +1 -0
  224. package/dist/lib/update-check.d.ts +52 -0
  225. package/dist/lib/update-check.d.ts.map +1 -0
  226. package/dist/lib/update-check.js +271 -0
  227. package/dist/lib/update-check.js.map +1 -0
  228. package/dist/lib/update-maintenance.d.ts +15 -0
  229. package/dist/lib/update-maintenance.d.ts.map +1 -0
  230. package/dist/lib/update-maintenance.js +187 -0
  231. package/dist/lib/update-maintenance.js.map +1 -0
  232. package/dist/lib/utils.d.ts +23 -0
  233. package/dist/lib/utils.d.ts.map +1 -0
  234. package/dist/lib/utils.js +48 -0
  235. package/dist/lib/utils.js.map +1 -0
  236. package/dist/lib/workflow-provisioning.d.ts +54 -0
  237. package/dist/lib/workflow-provisioning.d.ts.map +1 -0
  238. package/dist/lib/workflow-provisioning.js +281 -0
  239. package/dist/lib/workflow-provisioning.js.map +1 -0
  240. package/package.json +51 -0
  241. package/resources/gofer/.gofer-version +7 -0
  242. package/resources/gofer/agents-skills/0_gofer_start/SKILL.md +1287 -0
  243. package/resources/gofer/agents-skills/0a_problem_validation/SKILL.md +429 -0
  244. package/resources/gofer/agents-skills/10_gofer_cloud/SKILL.md +635 -0
  245. package/resources/gofer/agents-skills/1_gofer_research/SKILL.md +1159 -0
  246. package/resources/gofer/agents-skills/2_gofer_specify/SKILL.md +860 -0
  247. package/resources/gofer/agents-skills/3_gofer_plan/SKILL.md +886 -0
  248. package/resources/gofer/agents-skills/4_gofer_tasks/SKILL.md +748 -0
  249. package/resources/gofer/agents-skills/5_gofer_implement/SKILL.md +924 -0
  250. package/resources/gofer/agents-skills/6_gofer_validate/SKILL.md +2269 -0
  251. package/resources/gofer/agents-skills/7_gofer_save/SKILL.md +423 -0
  252. package/resources/gofer/agents-skills/7a_stakeholder_comms/SKILL.md +508 -0
  253. package/resources/gofer/agents-skills/8_gofer_branding/SKILL.md +315 -0
  254. package/resources/gofer/agents-skills/9_gofer_tests/SKILL.md +558 -0
  255. package/resources/gofer/agents-skills/gofer_bootstrap_workspace/SKILL.md +148 -0
  256. package/resources/gofer/agents-skills/gofer_check_workspace/SKILL.md +119 -0
  257. package/resources/gofer/agents-skills/gofer_constitution/SKILL.md +612 -0
  258. package/resources/gofer/agents-skills/gofer_diagnose/SKILL.md +114 -0
  259. package/resources/gofer/agents-skills/gofer_eai_first_run/SKILL.md +397 -0
  260. package/resources/gofer/agents-skills/gofer_hydrate/SKILL.md +561 -0
  261. package/resources/gofer/agents-skills/gofer_personality/SKILL.md +44 -0
  262. package/resources/gofer/agents-skills/gofer_plan/SKILL.md +40 -0
  263. package/resources/gofer/agents-skills/gofer_side/SKILL.md +45 -0
  264. package/resources/gofer/agents-skills/gofer_spec_summary/SKILL.md +112 -0
  265. package/resources/gofer/agents-skills/gofer_tdd/SKILL.md +112 -0
  266. package/resources/gofer/agents-skills/gofer_vocabulary/SKILL.md +112 -0
  267. package/resources/gofer/agents-skills/gofer_zoom_out/SKILL.md +112 -0
  268. package/resources/gofer/bash-scripts/check-context-health.sh +365 -0
  269. package/resources/gofer/bash-scripts/check-persona-pack.sh +81 -0
  270. package/resources/gofer/bash-scripts/check-prerequisites.sh +168 -0
  271. package/resources/gofer/bash-scripts/common.sh +192 -0
  272. package/resources/gofer/bash-scripts/create-new-feature.sh +260 -0
  273. package/resources/gofer/bash-scripts/install-optional-tools.sh +270 -0
  274. package/resources/gofer/bash-scripts/log-stage.sh +224 -0
  275. package/resources/gofer/bash-scripts/mark-task-complete.sh +74 -0
  276. package/resources/gofer/bash-scripts/pipeline-state.sh +306 -0
  277. package/resources/gofer/bash-scripts/read-failed-approaches.sh +114 -0
  278. package/resources/gofer/bash-scripts/read-session-memories.sh +96 -0
  279. package/resources/gofer/bash-scripts/save-checkpoint.sh +407 -0
  280. package/resources/gofer/bash-scripts/setup-plan.sh +62 -0
  281. package/resources/gofer/bash-scripts/sync-implementation-status.sh +47 -0
  282. package/resources/gofer/bash-scripts/update-agent-context.sh +772 -0
  283. package/resources/gofer/bash-scripts/validate-artifact.sh +335 -0
  284. package/resources/gofer/bash-scripts/verify-task.sh +384 -0
  285. package/resources/gofer/bash-scripts/write-failed-approach.sh +110 -0
  286. package/resources/gofer/bash-scripts/write-periodic-checkpoint.sh +128 -0
  287. package/resources/gofer/bash-scripts/write-session-memory.sh +118 -0
  288. package/resources/gofer/claude-agents/assumption-tracker.md +168 -0
  289. package/resources/gofer/claude-agents/business-metrics-analyzer.md +169 -0
  290. package/resources/gofer/claude-agents/business-problem-validator.md +168 -0
  291. package/resources/gofer/claude-agents/codebase-analyzer.md +124 -0
  292. package/resources/gofer/claude-agents/codebase-locator.md +95 -0
  293. package/resources/gofer/claude-agents/codebase-pattern-finder.md +180 -0
  294. package/resources/gofer/claude-agents/comms-writer.md +158 -0
  295. package/resources/gofer/claude-agents/engineer-review.md +169 -0
  296. package/resources/gofer/claude-agents/implement-bug-triangulator.md +94 -0
  297. package/resources/gofer/claude-agents/implement-code-review-council.md +89 -0
  298. package/resources/gofer/claude-agents/implement-doc-writer.md +89 -0
  299. package/resources/gofer/claude-agents/implement-error-hardener.md +84 -0
  300. package/resources/gofer/claude-agents/implement-performance-explorer.md +95 -0
  301. package/resources/gofer/claude-agents/implement-test-diversifier.md +82 -0
  302. package/resources/gofer/claude-agents/implement-variant-generator.md +80 -0
  303. package/resources/gofer/claude-agents/multi-perspective-judge.md +114 -0
  304. package/resources/gofer/claude-agents/plan-api-comparator.md +90 -0
  305. package/resources/gofer/claude-agents/plan-architecture-diverger.md +100 -0
  306. package/resources/gofer/claude-agents/plan-data-model-stress-tester.md +95 -0
  307. package/resources/gofer/claude-agents/plan-migration-path-finder.md +95 -0
  308. package/resources/gofer/claude-agents/plan-refactor-rewrite-advisor.md +97 -0
  309. package/resources/gofer/claude-agents/research-dependency-evaluator.md +106 -0
  310. package/resources/gofer/claude-agents/research-horizon-scanner.md +100 -0
  311. package/resources/gofer/claude-agents/research-market-scanner.md +137 -0
  312. package/resources/gofer/claude-agents/research-perspective-multiplier.md +102 -0
  313. package/resources/gofer/claude-agents/scope-creep-detector.md +152 -0
  314. package/resources/gofer/claude-agents/specify-ambiguity-detector.md +95 -0
  315. package/resources/gofer/claude-agents/specify-journey-stress-tester.md +92 -0
  316. package/resources/gofer/claude-agents/tasks-cross-cutting-scanner.md +91 -0
  317. package/resources/gofer/claude-agents/tasks-rollback-planner.md +89 -0
  318. package/resources/gofer/claude-agents/validate-security-red-team.md +102 -0
  319. package/resources/gofer/claude-agents/validation-correctness.md +103 -0
  320. package/resources/gofer/claude-agents/validation-integration.md +129 -0
  321. package/resources/gofer/claude-agents/validation-performance.md +120 -0
  322. package/resources/gofer/claude-agents/validation-security.md +115 -0
  323. package/resources/gofer/claude-agents/validation-standards.md +151 -0
  324. package/resources/gofer/claude-agents/validation-test-quality.md +146 -0
  325. package/resources/gofer/claude-agents/visual-bounded-context-writer.md +40 -0
  326. package/resources/gofer/claude-agents/visual-c4-writer.md +45 -0
  327. package/resources/gofer/claude-agents/visual-erd-writer.md +34 -0
  328. package/resources/gofer/claude-agents/visual-heatmap-writer.md +63 -0
  329. package/resources/gofer/claude-agents/visual-risk-writer.md +64 -0
  330. package/resources/gofer/claude-commands/0_gofer_start.md +1282 -0
  331. package/resources/gofer/claude-commands/0a_problem_validation.md +424 -0
  332. package/resources/gofer/claude-commands/10_gofer_cloud.md +630 -0
  333. package/resources/gofer/claude-commands/1_gofer_research.md +1154 -0
  334. package/resources/gofer/claude-commands/2_gofer_specify.md +855 -0
  335. package/resources/gofer/claude-commands/3_gofer_plan.md +881 -0
  336. package/resources/gofer/claude-commands/4_gofer_tasks.md +743 -0
  337. package/resources/gofer/claude-commands/5_gofer_implement.md +919 -0
  338. package/resources/gofer/claude-commands/6_gofer_validate.md +2264 -0
  339. package/resources/gofer/claude-commands/7_gofer_save.md +418 -0
  340. package/resources/gofer/claude-commands/7a_stakeholder_comms.md +503 -0
  341. package/resources/gofer/claude-commands/8_gofer_branding.md +310 -0
  342. package/resources/gofer/claude-commands/9_gofer_tests.md +553 -0
  343. package/resources/gofer/claude-commands/gofer_bootstrap_workspace.md +143 -0
  344. package/resources/gofer/claude-commands/gofer_check_workspace.md +114 -0
  345. package/resources/gofer/claude-commands/gofer_constitution.md +607 -0
  346. package/resources/gofer/claude-commands/gofer_diagnose.md +109 -0
  347. package/resources/gofer/claude-commands/gofer_eai_first_run.md +392 -0
  348. package/resources/gofer/claude-commands/gofer_hydrate.md +556 -0
  349. package/resources/gofer/claude-commands/gofer_personality.md +39 -0
  350. package/resources/gofer/claude-commands/gofer_plan.md +35 -0
  351. package/resources/gofer/claude-commands/gofer_side.md +40 -0
  352. package/resources/gofer/claude-commands/gofer_spec_summary.md +107 -0
  353. package/resources/gofer/claude-commands/gofer_tdd.md +107 -0
  354. package/resources/gofer/claude-commands/gofer_vocabulary.md +107 -0
  355. package/resources/gofer/claude-commands/gofer_zoom_out.md +107 -0
  356. package/resources/gofer/claude-skills/eai-gofer/SKILL.md +56 -0
  357. package/resources/gofer/commands/.gitkeep +0 -0
  358. package/resources/gofer/commands/0_gofer_start.md +1299 -0
  359. package/resources/gofer/commands/0a_problem_validation.md +405 -0
  360. package/resources/gofer/commands/10_gofer_cloud.md +611 -0
  361. package/resources/gofer/commands/1_gofer_research.md +1135 -0
  362. package/resources/gofer/commands/2_gofer_specify.md +836 -0
  363. package/resources/gofer/commands/3_gofer_plan.md +862 -0
  364. package/resources/gofer/commands/4_gofer_tasks.md +724 -0
  365. package/resources/gofer/commands/5_gofer_implement.md +900 -0
  366. package/resources/gofer/commands/6_gofer_validate.md +2245 -0
  367. package/resources/gofer/commands/7_gofer_save.md +399 -0
  368. package/resources/gofer/commands/7a_stakeholder_comms.md +484 -0
  369. package/resources/gofer/commands/8_gofer_branding.md +291 -0
  370. package/resources/gofer/commands/9_gofer_tests.md +534 -0
  371. package/resources/gofer/commands/gofer_bootstrap_workspace.md +159 -0
  372. package/resources/gofer/commands/gofer_check_workspace.md +130 -0
  373. package/resources/gofer/commands/gofer_constitution.md +588 -0
  374. package/resources/gofer/commands/gofer_diagnose.md +89 -0
  375. package/resources/gofer/commands/gofer_eai_first_run.md +392 -0
  376. package/resources/gofer/commands/gofer_hydrate.md +537 -0
  377. package/resources/gofer/commands/gofer_personality.md +61 -0
  378. package/resources/gofer/commands/gofer_plan.md +51 -0
  379. package/resources/gofer/commands/gofer_side.md +56 -0
  380. package/resources/gofer/commands/gofer_spec_summary.md +87 -0
  381. package/resources/gofer/commands/gofer_tdd.md +87 -0
  382. package/resources/gofer/commands/gofer_vocabulary.md +87 -0
  383. package/resources/gofer/commands/gofer_zoom_out.md +87 -0
  384. package/resources/gofer/copilot-instructions/gofer-cost.instructions.md +13 -0
  385. package/resources/gofer/copilot-instructions/language-server.instructions.md +49 -0
  386. package/resources/gofer/copilot-instructions/typescript.instructions.md +47 -0
  387. package/resources/gofer/copilot-instructions/vscode-extension.instructions.md +46 -0
  388. package/resources/gofer/copilot-prompts/0_gofer_start.prompt.md +1308 -0
  389. package/resources/gofer/copilot-prompts/0a_problem_validation.prompt.md +429 -0
  390. package/resources/gofer/copilot-prompts/10_gofer_cloud.prompt.md +644 -0
  391. package/resources/gofer/copilot-prompts/1_gofer_research.prompt.md +1177 -0
  392. package/resources/gofer/copilot-prompts/2_gofer_specify.prompt.md +878 -0
  393. package/resources/gofer/copilot-prompts/3_gofer_plan.prompt.md +904 -0
  394. package/resources/gofer/copilot-prompts/4_gofer_tasks.prompt.md +766 -0
  395. package/resources/gofer/copilot-prompts/5_gofer_implement.prompt.md +942 -0
  396. package/resources/gofer/copilot-prompts/6_gofer_validate.prompt.md +2277 -0
  397. package/resources/gofer/copilot-prompts/7_gofer_save.prompt.md +433 -0
  398. package/resources/gofer/copilot-prompts/7a_stakeholder_comms.prompt.md +516 -0
  399. package/resources/gofer/copilot-prompts/8_gofer_branding.prompt.md +323 -0
  400. package/resources/gofer/copilot-prompts/9_gofer_tests.prompt.md +566 -0
  401. package/resources/gofer/copilot-prompts/gofer_bootstrap_workspace.prompt.md +161 -0
  402. package/resources/gofer/copilot-prompts/gofer_check_workspace.prompt.md +132 -0
  403. package/resources/gofer/copilot-prompts/gofer_constitution.prompt.md +621 -0
  404. package/resources/gofer/copilot-prompts/gofer_diagnose.prompt.md +127 -0
  405. package/resources/gofer/copilot-prompts/gofer_eai_first_run.prompt.md +410 -0
  406. package/resources/gofer/copilot-prompts/gofer_hydrate.prompt.md +571 -0
  407. package/resources/gofer/copilot-prompts/gofer_personality.prompt.md +57 -0
  408. package/resources/gofer/copilot-prompts/gofer_plan.prompt.md +53 -0
  409. package/resources/gofer/copilot-prompts/gofer_side.prompt.md +58 -0
  410. package/resources/gofer/copilot-prompts/gofer_spec_summary.prompt.md +125 -0
  411. package/resources/gofer/copilot-prompts/gofer_tdd.prompt.md +125 -0
  412. package/resources/gofer/copilot-prompts/gofer_vocabulary.prompt.md +125 -0
  413. package/resources/gofer/copilot-prompts/gofer_zoom_out.prompt.md +125 -0
  414. package/resources/gofer/gemini/agents/assumption-tracker.md +171 -0
  415. package/resources/gofer/gemini/agents/business-metrics-analyzer.md +172 -0
  416. package/resources/gofer/gemini/agents/business-problem-validator.md +171 -0
  417. package/resources/gofer/gemini/agents/codebase-analyzer.md +127 -0
  418. package/resources/gofer/gemini/agents/codebase-locator.md +98 -0
  419. package/resources/gofer/gemini/agents/codebase-pattern-finder.md +183 -0
  420. package/resources/gofer/gemini/agents/comms-writer.md +161 -0
  421. package/resources/gofer/gemini/agents/engineer-review.md +172 -0
  422. package/resources/gofer/gemini/agents/implement-bug-triangulator.md +97 -0
  423. package/resources/gofer/gemini/agents/implement-code-review-council.md +92 -0
  424. package/resources/gofer/gemini/agents/implement-doc-writer.md +92 -0
  425. package/resources/gofer/gemini/agents/implement-error-hardener.md +87 -0
  426. package/resources/gofer/gemini/agents/implement-performance-explorer.md +98 -0
  427. package/resources/gofer/gemini/agents/implement-test-diversifier.md +85 -0
  428. package/resources/gofer/gemini/agents/implement-variant-generator.md +83 -0
  429. package/resources/gofer/gemini/agents/multi-perspective-judge.md +117 -0
  430. package/resources/gofer/gemini/agents/plan-api-comparator.md +93 -0
  431. package/resources/gofer/gemini/agents/plan-architecture-diverger.md +103 -0
  432. package/resources/gofer/gemini/agents/plan-data-model-stress-tester.md +98 -0
  433. package/resources/gofer/gemini/agents/plan-migration-path-finder.md +98 -0
  434. package/resources/gofer/gemini/agents/plan-refactor-rewrite-advisor.md +100 -0
  435. package/resources/gofer/gemini/agents/research-dependency-evaluator.md +109 -0
  436. package/resources/gofer/gemini/agents/research-horizon-scanner.md +103 -0
  437. package/resources/gofer/gemini/agents/research-market-scanner.md +140 -0
  438. package/resources/gofer/gemini/agents/research-perspective-multiplier.md +105 -0
  439. package/resources/gofer/gemini/agents/scope-creep-detector.md +155 -0
  440. package/resources/gofer/gemini/agents/specify-ambiguity-detector.md +98 -0
  441. package/resources/gofer/gemini/agents/specify-journey-stress-tester.md +95 -0
  442. package/resources/gofer/gemini/agents/tasks-cross-cutting-scanner.md +94 -0
  443. package/resources/gofer/gemini/agents/tasks-rollback-planner.md +92 -0
  444. package/resources/gofer/gemini/agents/validate-security-red-team.md +105 -0
  445. package/resources/gofer/gemini/agents/validation-correctness.md +106 -0
  446. package/resources/gofer/gemini/agents/validation-integration.md +132 -0
  447. package/resources/gofer/gemini/agents/validation-performance.md +123 -0
  448. package/resources/gofer/gemini/agents/validation-security.md +118 -0
  449. package/resources/gofer/gemini/agents/validation-standards.md +154 -0
  450. package/resources/gofer/gemini/agents/validation-test-quality.md +149 -0
  451. package/resources/gofer/gemini/agents/visual-bounded-context-writer.md +40 -0
  452. package/resources/gofer/gemini/agents/visual-c4-writer.md +44 -0
  453. package/resources/gofer/gemini/agents/visual-erd-writer.md +36 -0
  454. package/resources/gofer/gemini/agents/visual-heatmap-writer.md +63 -0
  455. package/resources/gofer/gemini/agents/visual-risk-writer.md +64 -0
  456. package/resources/gofer/gemini/commands/gofer/.gitkeep +0 -0
  457. package/resources/gofer/gemini/commands/gofer/0_gofer_start.md +1282 -0
  458. package/resources/gofer/gemini/commands/gofer/0_gofer_start.toml +2 -0
  459. package/resources/gofer/gemini/commands/gofer/0a_problem_validation.md +424 -0
  460. package/resources/gofer/gemini/commands/gofer/0a_problem_validation.toml +2 -0
  461. package/resources/gofer/gemini/commands/gofer/10_gofer_cloud.md +630 -0
  462. package/resources/gofer/gemini/commands/gofer/10_gofer_cloud.toml +2 -0
  463. package/resources/gofer/gemini/commands/gofer/1_gofer_research.md +1154 -0
  464. package/resources/gofer/gemini/commands/gofer/1_gofer_research.toml +2 -0
  465. package/resources/gofer/gemini/commands/gofer/2_gofer_specify.md +855 -0
  466. package/resources/gofer/gemini/commands/gofer/2_gofer_specify.toml +2 -0
  467. package/resources/gofer/gemini/commands/gofer/3_gofer_plan.md +881 -0
  468. package/resources/gofer/gemini/commands/gofer/3_gofer_plan.toml +2 -0
  469. package/resources/gofer/gemini/commands/gofer/4_gofer_tasks.md +743 -0
  470. package/resources/gofer/gemini/commands/gofer/4_gofer_tasks.toml +2 -0
  471. package/resources/gofer/gemini/commands/gofer/5_gofer_implement.md +919 -0
  472. package/resources/gofer/gemini/commands/gofer/5_gofer_implement.toml +2 -0
  473. package/resources/gofer/gemini/commands/gofer/6_gofer_validate.md +2264 -0
  474. package/resources/gofer/gemini/commands/gofer/6_gofer_validate.toml +2 -0
  475. package/resources/gofer/gemini/commands/gofer/7_gofer_save.md +418 -0
  476. package/resources/gofer/gemini/commands/gofer/7_gofer_save.toml +2 -0
  477. package/resources/gofer/gemini/commands/gofer/7a_stakeholder_comms.md +503 -0
  478. package/resources/gofer/gemini/commands/gofer/7a_stakeholder_comms.toml +2 -0
  479. package/resources/gofer/gemini/commands/gofer/8_gofer_branding.md +310 -0
  480. package/resources/gofer/gemini/commands/gofer/8_gofer_branding.toml +2 -0
  481. package/resources/gofer/gemini/commands/gofer/9_gofer_tests.md +553 -0
  482. package/resources/gofer/gemini/commands/gofer/9_gofer_tests.toml +2 -0
  483. package/resources/gofer/gemini/commands/gofer/gofer_bootstrap_workspace.md +143 -0
  484. package/resources/gofer/gemini/commands/gofer/gofer_bootstrap_workspace.toml +2 -0
  485. package/resources/gofer/gemini/commands/gofer/gofer_check_workspace.md +114 -0
  486. package/resources/gofer/gemini/commands/gofer/gofer_check_workspace.toml +2 -0
  487. package/resources/gofer/gemini/commands/gofer/gofer_constitution.md +607 -0
  488. package/resources/gofer/gemini/commands/gofer/gofer_constitution.toml +2 -0
  489. package/resources/gofer/gemini/commands/gofer/gofer_diagnose.md +109 -0
  490. package/resources/gofer/gemini/commands/gofer/gofer_diagnose.toml +2 -0
  491. package/resources/gofer/gemini/commands/gofer/gofer_eai_first_run.md +392 -0
  492. package/resources/gofer/gemini/commands/gofer/gofer_eai_first_run.toml +2 -0
  493. package/resources/gofer/gemini/commands/gofer/gofer_hydrate.md +556 -0
  494. package/resources/gofer/gemini/commands/gofer/gofer_hydrate.toml +2 -0
  495. package/resources/gofer/gemini/commands/gofer/gofer_personality.md +39 -0
  496. package/resources/gofer/gemini/commands/gofer/gofer_personality.toml +2 -0
  497. package/resources/gofer/gemini/commands/gofer/gofer_plan.md +35 -0
  498. package/resources/gofer/gemini/commands/gofer/gofer_plan.toml +2 -0
  499. package/resources/gofer/gemini/commands/gofer/gofer_side.md +40 -0
  500. package/resources/gofer/gemini/commands/gofer/gofer_side.toml +2 -0
  501. package/resources/gofer/gemini/commands/gofer/gofer_spec_summary.md +107 -0
  502. package/resources/gofer/gemini/commands/gofer/gofer_spec_summary.toml +2 -0
  503. package/resources/gofer/gemini/commands/gofer/gofer_tdd.md +107 -0
  504. package/resources/gofer/gemini/commands/gofer/gofer_tdd.toml +2 -0
  505. package/resources/gofer/gemini/commands/gofer/gofer_vocabulary.md +107 -0
  506. package/resources/gofer/gemini/commands/gofer/gofer_vocabulary.toml +2 -0
  507. package/resources/gofer/gemini/commands/gofer/gofer_zoom_out.md +107 -0
  508. package/resources/gofer/gemini/commands/gofer/gofer_zoom_out.toml +2 -0
  509. package/resources/gofer/gemini/commands/gofer/manifest.json +32 -0
  510. package/resources/gofer/gemini/extension.json +16 -0
  511. package/resources/gofer/github-agents/gofer-business.agent.md +20 -0
  512. package/resources/gofer/github-agents/gofer-implement.agent.md +15 -0
  513. package/resources/gofer/github-agents/gofer-plan.agent.md +15 -0
  514. package/resources/gofer/github-agents/gofer-research.agent.md +15 -0
  515. package/resources/gofer/github-agents/gofer-validate.agent.md +10 -0
  516. package/resources/gofer/github-skills/eai-gofer/SKILL.md +56 -0
  517. package/resources/gofer/hook-scripts/agent-stop.mjs +655 -0
  518. package/resources/gofer/hook-scripts/log-stage-launch-time.mjs +77 -0
  519. package/resources/gofer/hook-scripts/post-tool-use.mjs +333 -0
  520. package/resources/gofer/hook-scripts/queued-input.mjs +188 -0
  521. package/resources/gofer/hook-scripts/session-lifecycle.mjs +93 -0
  522. package/resources/gofer/hook-scripts/user-prompt-submit.mjs +228 -0
  523. package/resources/gofer/instruction-templates/base/agents-base.md +37 -0
  524. package/resources/gofer/instruction-templates/base/claude-base.md +7 -0
  525. package/resources/gofer/instruction-templates/base/copilot-base.md +26 -0
  526. package/resources/gofer/instruction-templates/gofer/gofer-claude.md +5 -0
  527. package/resources/gofer/instruction-templates/gofer/gofer-copilot.md +9 -0
  528. package/resources/gofer/instruction-templates/languages/generic.md +7 -0
  529. package/resources/gofer/instruction-templates/languages/go.md +8 -0
  530. package/resources/gofer/instruction-templates/languages/java.md +8 -0
  531. package/resources/gofer/instruction-templates/languages/python.md +9 -0
  532. package/resources/gofer/instruction-templates/languages/rust.md +9 -0
  533. package/resources/gofer/instruction-templates/languages/typescript.md +19 -0
  534. package/resources/gofer/instruction-templates/workflow/principles.md +52 -0
  535. package/resources/gofer/memory/constitution.md +391 -0
  536. package/resources/gofer/memory/context-profiles.yaml +74 -0
  537. package/resources/gofer/memory/decisions/000-use-adr-for-decisions.md +67 -0
  538. package/resources/gofer/memory/decisions/001-di-framework.md +190 -0
  539. package/resources/gofer/memory/decisions/002-module-extraction.md +305 -0
  540. package/resources/gofer/memory/decisions/003-error-handling.md +368 -0
  541. package/resources/gofer/memory/decisions/004-cache-eviction.md +436 -0
  542. package/resources/gofer/memory/decisions/005-constants-management.md +520 -0
  543. package/resources/gofer/memory/decisions/README.md +129 -0
  544. package/resources/gofer/memory/diagrams/di-container.mmd +321 -0
  545. package/resources/gofer/memory/diagrams/extension-activation.mmd +184 -0
  546. package/resources/gofer/memory/diagrams/module-dependencies.mmd +264 -0
  547. package/resources/gofer/memory/gofer-model-policy.yaml +97 -0
  548. package/resources/gofer/memory/lessons.md +46 -0
  549. package/resources/gofer/node-scripts/canonical-descriptions.mjs +86 -0
  550. package/resources/gofer/node-scripts/check-version-alignment.mjs +131 -0
  551. package/resources/gofer/node-scripts/codex-doctor.mjs +425 -0
  552. package/resources/gofer/node-scripts/generate-commands.mjs +1366 -0
  553. package/resources/gofer/node-scripts/generate-issues.js +563 -0
  554. package/resources/gofer/node-scripts/gofer-closed-loop-audit.mjs +893 -0
  555. package/resources/gofer/node-scripts/gofer-loop-audit.mjs +541 -0
  556. package/resources/gofer/node-scripts/gofer-performance-report.mjs +306 -0
  557. package/resources/gofer/node-scripts/gofer-workspace-bootstrap.mjs +56 -0
  558. package/resources/gofer/node-scripts/gofer-workspace-check.mjs +56 -0
  559. package/resources/gofer/node-scripts/lib/ai-leverage-tagger.mjs +103 -0
  560. package/resources/gofer/node-scripts/lib/assemble-stakeholder-pack.mjs +114 -0
  561. package/resources/gofer/node-scripts/lib/marp-deck.mjs +87 -0
  562. package/resources/gofer/node-scripts/lib/mermaid-tabular-fallback.mjs +264 -0
  563. package/resources/gofer/node-scripts/lib/render-visual.mjs +54 -0
  564. package/resources/gofer/node-scripts/lib/validate-aliases.mjs +85 -0
  565. package/resources/gofer/node-scripts/lib/visual-counts.mjs +44 -0
  566. package/resources/gofer/node-scripts/lib/visual-pass-pipeline.mjs +134 -0
  567. package/resources/gofer/node-scripts/mermaid-export.mjs +72 -0
  568. package/resources/gofer/node-scripts/package-agent-plugin.mjs +940 -0
  569. package/resources/gofer/node-scripts/parse-stage-command.mjs +211 -0
  570. package/resources/gofer/node-scripts/schemas/.gitkeep +0 -0
  571. package/resources/gofer/node-scripts/schemas/stage-command.schema.json +72 -0
  572. package/resources/gofer/node-scripts/sync-extension-resources.mjs +110 -0
  573. package/resources/gofer/node-scripts/workspace-bootstrap-lib.mjs +1166 -0
  574. package/resources/gofer/powershell-scripts/install-optional-tools.ps1 +214 -0
  575. package/resources/gofer/references/platform/README.md +17 -0
  576. package/resources/gofer/references/platform/deployment-repo.md +9 -0
  577. package/resources/gofer/references/platform/eai-app-template.md +45 -0
  578. package/resources/gofer/references/platform/eai-config-driven-ui.md +156 -0
  579. package/resources/gofer/references/platform/eai-error-catalog.yaml +197 -0
  580. package/resources/gofer/references/platform/eai-repo-contract.md +134 -0
  581. package/resources/gofer/references/platform/eai-service-patterns.md +56 -0
  582. package/resources/gofer/references/platform/eai.md +85 -0
  583. package/resources/gofer/references/platform/vertical-template.md +49 -0
  584. package/resources/gofer/specify-commands/.gitkeep +0 -0
  585. package/resources/gofer/specify-commands/0_gofer_start.md +1299 -0
  586. package/resources/gofer/specify-commands/0a_problem_validation.md +405 -0
  587. package/resources/gofer/specify-commands/10_gofer_cloud.md +611 -0
  588. package/resources/gofer/specify-commands/1_gofer_research.md +1135 -0
  589. package/resources/gofer/specify-commands/2_gofer_specify.md +836 -0
  590. package/resources/gofer/specify-commands/3_gofer_plan.md +862 -0
  591. package/resources/gofer/specify-commands/4_gofer_tasks.md +724 -0
  592. package/resources/gofer/specify-commands/5_gofer_implement.md +900 -0
  593. package/resources/gofer/specify-commands/6_gofer_validate.md +2245 -0
  594. package/resources/gofer/specify-commands/7_gofer_save.md +399 -0
  595. package/resources/gofer/specify-commands/7a_stakeholder_comms.md +484 -0
  596. package/resources/gofer/specify-commands/8_gofer_branding.md +291 -0
  597. package/resources/gofer/specify-commands/9_gofer_tests.md +534 -0
  598. package/resources/gofer/specify-commands/gofer_bootstrap_workspace.md +159 -0
  599. package/resources/gofer/specify-commands/gofer_check_workspace.md +130 -0
  600. package/resources/gofer/specify-commands/gofer_constitution.md +588 -0
  601. package/resources/gofer/specify-commands/gofer_diagnose.md +89 -0
  602. package/resources/gofer/specify-commands/gofer_eai_first_run.md +392 -0
  603. package/resources/gofer/specify-commands/gofer_hydrate.md +537 -0
  604. package/resources/gofer/specify-commands/gofer_personality.md +61 -0
  605. package/resources/gofer/specify-commands/gofer_plan.md +51 -0
  606. package/resources/gofer/specify-commands/gofer_side.md +56 -0
  607. package/resources/gofer/specify-commands/gofer_spec_summary.md +87 -0
  608. package/resources/gofer/specify-commands/gofer_tdd.md +87 -0
  609. package/resources/gofer/specify-commands/gofer_vocabulary.md +87 -0
  610. package/resources/gofer/specify-commands/gofer_zoom_out.md +87 -0
  611. package/resources/gofer/system-skills/0_gofer_start/SKILL.md +1287 -0
  612. package/resources/gofer/system-skills/0a_problem_validation/SKILL.md +429 -0
  613. package/resources/gofer/system-skills/10_gofer_cloud/SKILL.md +635 -0
  614. package/resources/gofer/system-skills/1_gofer_research/SKILL.md +1159 -0
  615. package/resources/gofer/system-skills/2_gofer_specify/SKILL.md +860 -0
  616. package/resources/gofer/system-skills/3_gofer_plan/SKILL.md +886 -0
  617. package/resources/gofer/system-skills/4_gofer_tasks/SKILL.md +748 -0
  618. package/resources/gofer/system-skills/5_gofer_implement/SKILL.md +924 -0
  619. package/resources/gofer/system-skills/6_gofer_validate/SKILL.md +2269 -0
  620. package/resources/gofer/system-skills/7_gofer_save/SKILL.md +423 -0
  621. package/resources/gofer/system-skills/7a_stakeholder_comms/SKILL.md +508 -0
  622. package/resources/gofer/system-skills/8_gofer_branding/SKILL.md +315 -0
  623. package/resources/gofer/system-skills/9_gofer_tests/SKILL.md +558 -0
  624. package/resources/gofer/system-skills/gofer_bootstrap_workspace/SKILL.md +148 -0
  625. package/resources/gofer/system-skills/gofer_check_workspace/SKILL.md +119 -0
  626. package/resources/gofer/system-skills/gofer_constitution/SKILL.md +612 -0
  627. package/resources/gofer/system-skills/gofer_diagnose/SKILL.md +114 -0
  628. package/resources/gofer/system-skills/gofer_eai_first_run/SKILL.md +397 -0
  629. package/resources/gofer/system-skills/gofer_hydrate/SKILL.md +561 -0
  630. package/resources/gofer/system-skills/gofer_personality/SKILL.md +44 -0
  631. package/resources/gofer/system-skills/gofer_plan/SKILL.md +40 -0
  632. package/resources/gofer/system-skills/gofer_side/SKILL.md +45 -0
  633. package/resources/gofer/system-skills/gofer_spec_summary/SKILL.md +112 -0
  634. package/resources/gofer/system-skills/gofer_tdd/SKILL.md +112 -0
  635. package/resources/gofer/system-skills/gofer_vocabulary/SKILL.md +112 -0
  636. package/resources/gofer/system-skills/gofer_zoom_out/SKILL.md +112 -0
  637. package/resources/gofer/templates/agent-file-template.md +28 -0
  638. package/resources/gofer/templates/assumptions-template.md +94 -0
  639. package/resources/gofer/templates/audit-history-template.md +35 -0
  640. package/resources/gofer/templates/brand/brand-profile-template.json +45 -0
  641. package/resources/gofer/templates/brand/document-style-template.md +50 -0
  642. package/resources/gofer/templates/brand/marp-theme-template.css +58 -0
  643. package/resources/gofer/templates/brownfield-analysis.md +44 -0
  644. package/resources/gofer/templates/business-metrics-template.md +120 -0
  645. package/resources/gofer/templates/business-owner-summary-template.md +83 -0
  646. package/resources/gofer/templates/checklist-template.md +40 -0
  647. package/resources/gofer/templates/ciso-security-summary-template.md +70 -0
  648. package/resources/gofer/templates/context-bundle-template.md +76 -0
  649. package/resources/gofer/templates/contract-pack-template.md +109 -0
  650. package/resources/gofer/templates/cto-architecture-summary-template.md +83 -0
  651. package/resources/gofer/templates/discovery-template.md +92 -0
  652. package/resources/gofer/templates/eai-preflight-template.md +144 -0
  653. package/resources/gofer/templates/goal-ledger-template.json +69 -0
  654. package/resources/gofer/templates/gofer-model-policy.yaml +97 -0
  655. package/resources/gofer/templates/issues-template.md +106 -0
  656. package/resources/gofer/templates/journey/base-journey.md +95 -0
  657. package/resources/gofer/templates/journey/industry-variants.yaml +277 -0
  658. package/resources/gofer/templates/loop-contract-template.json +68 -0
  659. package/resources/gofer/templates/plan-template.md +215 -0
  660. package/resources/gofer/templates/problem-brief-template.md +85 -0
  661. package/resources/gofer/templates/proposal-review-template.md +79 -0
  662. package/resources/gofer/templates/research-template.md +222 -0
  663. package/resources/gofer/templates/reuse-scan-template.md +43 -0
  664. package/resources/gofer/templates/sequence-diagrams/option-spectrum.yaml +178 -0
  665. package/resources/gofer/templates/service-fit-matrix-template.md +29 -0
  666. package/resources/gofer/templates/session-handoff-template.md +172 -0
  667. package/resources/gofer/templates/spec-summary-template.md +118 -0
  668. package/resources/gofer/templates/spec-template.md +196 -0
  669. package/resources/gofer/templates/stakeholder-comms-template.md +330 -0
  670. package/resources/gofer/templates/stakeholder-review-index-template.md +54 -0
  671. package/resources/gofer/templates/tasks-template.md +323 -0
  672. package/resources/gofer/templates/ui-approval-template.md +32 -0
  673. package/resources/gofer/templates/ui-preview-brief-template.md +65 -0
  674. package/resources/gofer/templates/ui-review-log-template.md +11 -0
  675. package/resources/gofer/templates/visuals/.gitkeep +0 -0
  676. package/resources/gofer/templates/visuals/bounded-context-map.md +19 -0
  677. package/resources/gofer/templates/visuals/bounded-context-template.md +47 -0
  678. package/resources/gofer/templates/visuals/c4-container-template.md +38 -0
  679. package/resources/gofer/templates/visuals/c4-container.md +20 -0
  680. package/resources/gofer/templates/visuals/c4-context-template.md +46 -0
  681. package/resources/gofer/templates/visuals/capability-heatmap-template.md +54 -0
  682. package/resources/gofer/templates/visuals/data-model-erd-template.md +41 -0
  683. package/resources/gofer/templates/visuals/erd.md +19 -0
  684. package/resources/gofer/templates/visuals/impact-canvas.md +40 -0
  685. package/resources/gofer/templates/visuals/risk-heatmap-template.md +51 -0
  686. package/resources/gofer/templates/visuals/roi-projection.md +17 -0
  687. package/resources/gofer/templates/visuals/value-stream-asis.md +16 -0
  688. package/resources/gofer/templates/visuals/value-stream-tobe.md +18 -0
  689. package/resources/gofer/templates/working-backwards-prfaq-template.md +165 -0
  690. package/resources/linked-sources.json +25 -0
@@ -0,0 +1,1437 @@
1
+ /**
2
+ * eai init — scaffold a new application from the template.
3
+ */
4
+ import { Command } from "commander";
5
+ import { execFile } from "node:child_process";
6
+ import { createRequire } from "node:module";
7
+ import { tmpdir } from "node:os";
8
+ import { promisify } from "node:util";
9
+ import { readFile, writeFile, access, mkdir, rm, cp, mkdtemp, chmod, } from "node:fs/promises";
10
+ import { basename, join, resolve } from "node:path";
11
+ import { randomBytes } from "node:crypto";
12
+ import ora from "ora";
13
+ import chalk from "chalk";
14
+ import inquirer from "inquirer";
15
+ import * as out from "../lib/output.js";
16
+ import { installGoferResources } from "../lib/gofer-installer.js";
17
+ import { applyGoferRefresh, planGoferRefresh } from "../lib/gofer-refresh.js";
18
+ import { isAuthenticated, loadTokens } from "../lib/auth.js";
19
+ import { publicApiUrlForHomeRegion, resolveActiveTenantContext, resolveMainCompanyTenantId, resolvePublicApiUrl, } from "../lib/tenant-context.js";
20
+ import { parseApiError, PlatformAPIClient, } from "../lib/api.js";
21
+ import { patchEnvFile } from "../lib/config.js";
22
+ import { pullCloudEnvValues } from "../lib/cloud-env.js";
23
+ import { getActiveProfile, loadProfileConfig } from "../lib/profile.js";
24
+ import { errMsg, normalizeChildTenantDisplayNameOption } from "../lib/utils.js";
25
+ import { saveProjectManifest } from "../lib/project-manifest.js";
26
+ const exec = promisify(execFile);
27
+ const require = createRequire(import.meta.url);
28
+ const pkg = require("../../package.json");
29
+ const TEMPLATE_REPO = "https://github.com/eai-tools/eai-app-template.git";
30
+ const GITHUB_ORG = "eai-tools";
31
+ const TEMPLATE_REPO_LABEL = `${GITHUB_ORG}/eai-app-template`;
32
+ function buildInitialProjectManifest(templatePlan, packageProfile) {
33
+ return {
34
+ schemaVersion: 1,
35
+ cli: {
36
+ version: pkg.version,
37
+ },
38
+ packages: {
39
+ profile: packageProfile,
40
+ source: packageProfile === "internal"
41
+ ? "enterpriseai-packages"
42
+ : "eai-packages",
43
+ recordedAt: new Date().toISOString(),
44
+ },
45
+ template: {
46
+ repo: templatePlan.cloneSource,
47
+ commit: templatePlan.pinnedCommit,
48
+ displaySource: templatePlan.displaySource,
49
+ initializedAt: new Date().toISOString(),
50
+ },
51
+ };
52
+ }
53
+ export function describeCloneFailure(templateSource, error) {
54
+ const message = error instanceof Error ? error.message : String(error);
55
+ const normalized = message.toLowerCase();
56
+ if (/spawn git enoent/i.test(message) ||
57
+ normalized.includes("git is not recognized") ||
58
+ (normalized.includes("no such file or directory") &&
59
+ normalized.includes("git"))) {
60
+ return [
61
+ "`git` is required to scaffold from a repository source, but it is not installed or not on your PATH.",
62
+ "Install Git, reopen your terminal, and run the command again.",
63
+ "",
64
+ "Windows: winget install --id Git.Git -e",
65
+ "Download: https://git-scm.com/download/win",
66
+ "",
67
+ `Default public template: ${TEMPLATE_REPO}`,
68
+ `Custom source: eai init <name> --from <repo-or-path>`,
69
+ ].join("\n");
70
+ }
71
+ if (isDefaultTemplateSource(templateSource) &&
72
+ /repository .* not found|repository not found|fatal: .* not found/i.test(message)) {
73
+ return (`${message}\n\nThe default template source (${TEMPLATE_REPO}) could not be reached.\n` +
74
+ `Use ${"`"}eai init <name> --from <repo-or-path>${"`"} with another accessible template source if GitHub is blocked from this machine.`);
75
+ }
76
+ return message;
77
+ }
78
+ function loadLinkedSourcesManifest() {
79
+ try {
80
+ return require("../../resources/linked-sources.json");
81
+ }
82
+ catch {
83
+ return null;
84
+ }
85
+ }
86
+ export function isDefaultTemplateSource(templateSource) {
87
+ return templateSource === TEMPLATE_REPO;
88
+ }
89
+ export function resolveTemplateClonePlan(templateSource) {
90
+ if (!isDefaultTemplateSource(templateSource)) {
91
+ return {
92
+ cloneSource: templateSource,
93
+ displaySource: describeTemplateSource(templateSource),
94
+ };
95
+ }
96
+ const linkedSources = loadLinkedSourcesManifest();
97
+ const cloneSource = linkedSources?.appTemplate?.repo || TEMPLATE_REPO;
98
+ const pinnedCommit = linkedSources?.appTemplate?.commit;
99
+ return {
100
+ cloneSource,
101
+ pinnedCommit,
102
+ displaySource: pinnedCommit
103
+ ? `${TEMPLATE_REPO_LABEL}@${pinnedCommit.slice(0, 7)}`
104
+ : TEMPLATE_REPO_LABEL,
105
+ };
106
+ }
107
+ async function cloneTemplate(templateSource, targetDir, options = {}) {
108
+ const plan = resolveTemplateClonePlan(templateSource);
109
+ if (!plan.pinnedCommit) {
110
+ await exec("git", ["clone", "--depth", "1", plan.cloneSource, targetDir]);
111
+ return plan;
112
+ }
113
+ try {
114
+ await exec("git", ["init", targetDir]);
115
+ await exec("git", [
116
+ "-C",
117
+ targetDir,
118
+ "remote",
119
+ "add",
120
+ "origin",
121
+ plan.cloneSource,
122
+ ]);
123
+ await exec("git", [
124
+ "-C",
125
+ targetDir,
126
+ "fetch",
127
+ "--depth",
128
+ "1",
129
+ "origin",
130
+ plan.pinnedCommit,
131
+ ]);
132
+ await exec("git", ["-C", targetDir, "checkout", "FETCH_HEAD"]);
133
+ return plan;
134
+ }
135
+ catch (error) {
136
+ if (options.allowTargetRemoval === false) {
137
+ await rm(join(targetDir, ".git"), { recursive: true, force: true });
138
+ throw error;
139
+ }
140
+ await rm(targetDir, { recursive: true, force: true });
141
+ await exec("git", ["clone", plan.cloneSource, targetDir]);
142
+ await exec("git", ["-C", targetDir, "checkout", plan.pinnedCommit]);
143
+ return plan;
144
+ }
145
+ }
146
+ async function copyTemplateIntoTargetDir(templateSource, targetDir) {
147
+ const templateDir = await mkdtemp(join(tmpdir(), "eai-template-"));
148
+ try {
149
+ await chmod(templateDir, 0o700);
150
+ const plan = await cloneTemplate(templateSource, templateDir);
151
+ await rm(join(templateDir, ".git"), { recursive: true, force: true });
152
+ // Current-directory init updates matching scaffold-managed files while
153
+ // preserving unrelated files and existing repository metadata.
154
+ await cp(templateDir, targetDir, { recursive: true, force: true });
155
+ return plan;
156
+ }
157
+ finally {
158
+ await rm(templateDir, { recursive: true, force: true });
159
+ }
160
+ }
161
+ export const initCommand = new Command("init")
162
+ .description("Scaffold a new application")
163
+ .argument("[name]", "Name for the app (kebab-case)")
164
+ .option("--from <repo>", "GitHub repo URL or local path for template", TEMPLATE_REPO)
165
+ .option("--skip-prompts", "Use defaults without interactive prompts", false)
166
+ .option("--current-dir", "Scaffold into the current directory instead of creating ./<name>", false)
167
+ .option("--tenant <id>", "Main company tenant ID (deprecated alias for --company-tenant)")
168
+ .option("--company-tenant <id>", "Main company tenant ID that owns this app")
169
+ .option("--parent-tenant <id>", "Immediate parent company tenant ID for the new child company")
170
+ .option("--child-tenant <name>", "Create or reuse a child company tenant display name for the app runtime boundary")
171
+ .option("--create-child-tenant", "Prompt for a child company tenant instead of using the selected company tenant")
172
+ .option("--no-gofer", "Skip installing Gofer AI CLI assets")
173
+ .option("--package-profile <profile>", "Package profile to record for block catalog discovery: external, internal, or hybrid", "external")
174
+ .addHelpText("after", `
175
+ Gofer AI CLI assets are installed by default:
176
+ .specify/ commands, scripts, templates, hooks, and memory folders
177
+ .claude/ commands and agents for Claude CLI
178
+ .system/skills and .agents/skills for Codex CLI
179
+ .gemini/commands/gofer and .gemini/extension.json for Gemini CLI
180
+ .github/prompts, .github/instructions, and .github/skills for GitHub Copilot
181
+
182
+ The default public template is pinned to the latest eai-app-template main
183
+ commit captured when this CLI release was cut. Use --from to override it with
184
+ another repo or local path.
185
+
186
+ Use --no-gofer only when you need a bare app scaffold.
187
+ `)
188
+ .action(async (nameArg, options) => {
189
+ const publicApiUrl = await resolvePublicApiUrl();
190
+ const activeTenant = await loadActiveTenantForInit(publicApiUrl);
191
+ let tenantId;
192
+ let parentTenantId;
193
+ let initOptions;
194
+ let targetDir;
195
+ let targetUsesCurrentDir;
196
+ const packageProfile = resolvePackageProfile(options.packageProfile);
197
+ if (options.skipPrompts && nameArg) {
198
+ targetUsesCurrentDir = Boolean(options.currentDir);
199
+ targetDir = await resolveInitTargetDir(nameArg, targetUsesCurrentDir);
200
+ const binding = await createTenantAppForInit(publicApiUrl, activeTenant, options.companyTenant || options.tenant, options.parentTenant, {
201
+ slug: nameArg,
202
+ displayName: toDisplayName(nameArg),
203
+ }, options.childTenant, Boolean(options.createChildTenant), false);
204
+ parentTenantId = binding.parentTenantId;
205
+ tenantId = binding.runtimeTenantId;
206
+ const capabilities = tenantId
207
+ ? await evaluateInitCapabilities(publicApiUrl, tenantId)
208
+ : defaultInitCapabilities();
209
+ initOptions = {
210
+ name: nameArg,
211
+ displayName: toDisplayName(nameArg),
212
+ description: `${toDisplayName(nameArg)} application`,
213
+ parentTenantId,
214
+ tenantId,
215
+ tenantHomeRegion: binding.runtimeTenantHomeRegion ?? activeTenant?.homeRegion,
216
+ includeChat: capabilities["ai-chat"].outcome === "allow",
217
+ includeDocs: capabilities.documents.outcome === "allow",
218
+ authProvider: "ciam",
219
+ packageProfile,
220
+ };
221
+ }
222
+ else {
223
+ const baseAnswers = await inquirer.prompt([
224
+ {
225
+ type: "input",
226
+ name: "name",
227
+ message: "App name (kebab-case):",
228
+ default: nameArg,
229
+ validate: (input) => {
230
+ if (!/^[a-z][a-z0-9-]*$/.test(input)) {
231
+ return "Must be lowercase, start with a letter, and contain only letters, numbers, and hyphens";
232
+ }
233
+ return true;
234
+ },
235
+ },
236
+ {
237
+ type: "input",
238
+ name: "displayName",
239
+ message: "Display name:",
240
+ default: (answers) => toDisplayName(answers.name),
241
+ },
242
+ {
243
+ type: "input",
244
+ name: "description",
245
+ message: "Description:",
246
+ default: (answers) => `${answers.displayName} application`,
247
+ },
248
+ ]);
249
+ const appName = String(baseAnswers.name);
250
+ if (options.currentDir) {
251
+ targetUsesCurrentDir = true;
252
+ }
253
+ else {
254
+ const locationAnswer = await inquirer.prompt([
255
+ {
256
+ type: "confirm",
257
+ name: "useCurrentDirectory",
258
+ message: `Use current folder "${basename(process.cwd())}" instead of creating ./${appName}?`,
259
+ default: basename(process.cwd()).toLowerCase() === appName,
260
+ },
261
+ ]);
262
+ targetUsesCurrentDir = Boolean(locationAnswer.useCurrentDirectory);
263
+ }
264
+ targetDir = await resolveInitTargetDir(appName, targetUsesCurrentDir);
265
+ const binding = await createTenantAppForInit(publicApiUrl, activeTenant, options.companyTenant || options.tenant, options.parentTenant, {
266
+ slug: String(baseAnswers.name),
267
+ displayName: String(baseAnswers.displayName),
268
+ }, options.childTenant, Boolean(options.createChildTenant), true);
269
+ parentTenantId = binding.parentTenantId;
270
+ tenantId = binding.runtimeTenantId;
271
+ const featureAnswers = await promptFeatureOptions(publicApiUrl, tenantId);
272
+ initOptions = {
273
+ ...baseAnswers,
274
+ parentTenantId,
275
+ tenantId,
276
+ tenantHomeRegion: binding.runtimeTenantHomeRegion ?? activeTenant?.homeRegion,
277
+ ...featureAnswers,
278
+ packageProfile,
279
+ };
280
+ }
281
+ out.heading(`Creating ${chalk.cyan(initOptions.displayName)}`);
282
+ out.blank();
283
+ // Step 1: Clone template
284
+ const cloneSpinner = ora("Cloning template...").start();
285
+ const templatePlan = resolveTemplateClonePlan(options.from);
286
+ try {
287
+ if (targetUsesCurrentDir) {
288
+ await copyTemplateIntoTargetDir(options.from, targetDir);
289
+ }
290
+ else {
291
+ await cloneTemplate(options.from, targetDir, {
292
+ allowTargetRemoval: true,
293
+ });
294
+ }
295
+ // Remove .git to start fresh
296
+ if (!targetUsesCurrentDir) {
297
+ await rm(join(targetDir, ".git"), { recursive: true, force: true });
298
+ }
299
+ cloneSpinner.succeed(`Cloned from ${chalk.dim(templatePlan.displaySource)}`);
300
+ }
301
+ catch (err) {
302
+ cloneSpinner.fail("Failed to clone template");
303
+ out.error(describeCloneFailure(options.from, err));
304
+ process.exit(1);
305
+ }
306
+ // Step 2: Update package.json
307
+ const pkgSpinner = ora("Customizing package.json...").start();
308
+ try {
309
+ const pkgPath = join(targetDir, "package.json");
310
+ const pkg = JSON.parse(await readFile(pkgPath, "utf-8"));
311
+ pkg.name = `@${GITHUB_ORG}/${initOptions.name}`;
312
+ pkg.description = initOptions.description;
313
+ pkg.version = "0.1.0";
314
+ await writeFile(pkgPath, JSON.stringify(pkg, null, 2) + "\n", "utf-8");
315
+ pkgSpinner.succeed("Updated package.json");
316
+ }
317
+ catch (_err) {
318
+ pkgSpinner.fail("Failed to update package.json");
319
+ }
320
+ // Step 3: Generate .env.local with placeholders
321
+ const envSpinner = ora("Generating .env.local...").start();
322
+ try {
323
+ const envContent = generateEnvFile(initOptions);
324
+ await writeFile(join(targetDir, ".env.local"), envContent, "utf-8");
325
+ await hydrateEnvFromLoginContext(targetDir, initOptions.name, initOptions.parentTenantId, initOptions.tenantId, initOptions.tenantHomeRegion);
326
+ envSpinner.succeed("Generated .env.local");
327
+ }
328
+ catch (_err) {
329
+ envSpinner.fail("Failed to generate .env.local");
330
+ }
331
+ // Step 4: Generate Object Types scaffold
332
+ const typesSpinner = ora("Creating Object Types scaffold...").start();
333
+ try {
334
+ const typesContent = generateObjectTypesScaffold(initOptions);
335
+ await writeFile(join(targetDir, "src", "eai.config", "object-types.ts"), typesContent, "utf-8");
336
+ typesSpinner.succeed("Created Object Types scaffold");
337
+ }
338
+ catch (_err) {
339
+ typesSpinner.fail("Failed to create Object Types scaffold");
340
+ }
341
+ // Step 5: Generate deploy workflow
342
+ const deploySpinner = ora("Creating deployment workflow...").start();
343
+ try {
344
+ const workflowDir = join(targetDir, ".github", "workflows");
345
+ await mkdir(workflowDir, { recursive: true });
346
+ const workflowContent = generateDeployWorkflow(initOptions);
347
+ await writeFile(join(workflowDir, "deploy-demo.yml"), workflowContent, "utf-8");
348
+ deploySpinner.succeed("Created deploy-demo.yml");
349
+ }
350
+ catch (_err) {
351
+ deploySpinner.fail("Failed to create deployment workflow");
352
+ }
353
+ // Step 6: Generate project CLAUDE.md
354
+ const claudeSpinner = ora("Generating CLAUDE.md...").start();
355
+ try {
356
+ const claudeContent = generateClaudeMd(initOptions);
357
+ await writeFile(join(targetDir, "CLAUDE.md"), claudeContent, "utf-8");
358
+ claudeSpinner.succeed("Generated CLAUDE.md");
359
+ }
360
+ catch (_err) {
361
+ claudeSpinner.fail("Failed to generate CLAUDE.md");
362
+ }
363
+ // Step 7: Install Gofer AI CLI assets
364
+ if (options.gofer) {
365
+ const goferSpinner = ora("Installing Gofer AI CLI assets...").start();
366
+ try {
367
+ const summary = await installGoferResources(targetDir, {
368
+ workflowProfile: "enterpriseai",
369
+ });
370
+ goferSpinner.succeed(`Installed Gofer assets (${summary.commands} commands, ${summary.agents} agents, ${summary.skills} skills)`);
371
+ }
372
+ catch (err) {
373
+ goferSpinner.fail("Failed to install Gofer AI CLI assets");
374
+ out.error(err instanceof Error ? err.message : String(err));
375
+ process.exit(1);
376
+ }
377
+ }
378
+ // Step 8: Record project manifest for future safe refreshes
379
+ const manifestSpinner = ora("Recording project manifest...").start();
380
+ try {
381
+ const initialManifest = buildInitialProjectManifest(templatePlan, initOptions.packageProfile);
382
+ await saveProjectManifest(targetDir, initialManifest);
383
+ if (options.gofer) {
384
+ const refreshPlan = await planGoferRefresh(targetDir, initialManifest, {
385
+ workflowProfile: "enterpriseai",
386
+ });
387
+ await applyGoferRefresh(refreshPlan);
388
+ }
389
+ manifestSpinner.succeed("Recorded .eai-manifest.json");
390
+ }
391
+ catch (err) {
392
+ manifestSpinner.fail("Failed to record project manifest");
393
+ out.error(err instanceof Error ? err.message : String(err));
394
+ process.exit(1);
395
+ }
396
+ // Step 9: Initialize git
397
+ const gitSpinner = ora("Initializing git...").start();
398
+ try {
399
+ await exec("git", ["init"], { cwd: targetDir });
400
+ await exec("git", ["add", "."], { cwd: targetDir });
401
+ await exec("git", [
402
+ "commit",
403
+ "-m",
404
+ `Initial scaffold from template\n\nApp: ${initOptions.displayName}\nCreated by: eai init\nTemplate: ${templatePlan.displaySource}`,
405
+ ], { cwd: targetDir });
406
+ gitSpinner.succeed("Initialized git repository");
407
+ }
408
+ catch (err) {
409
+ gitSpinner.fail("Failed to initialize git");
410
+ out.warn(describeGitInitFailure(err));
411
+ }
412
+ // Step 10: Optionally provision Entra app registration inline against the
413
+ // tenant the user selected in the tenant-binding prompt (not the active
414
+ // tenant blindly). Only runs in interactive mode when logged in and a
415
+ // tenant is bound.
416
+ let entraProvisioned = false;
417
+ if (!options.skipPrompts && initOptions.tenantId) {
418
+ const loggedIn = await isAuthenticated();
419
+ if (loggedIn) {
420
+ out.blank();
421
+ const { provision } = await inquirer.prompt([
422
+ {
423
+ type: "confirm",
424
+ name: "provision",
425
+ message: "Provision Entra app registration now?",
426
+ default: true,
427
+ },
428
+ ]);
429
+ if (provision) {
430
+ entraProvisioned = await provisionEntraInline(targetDir, initOptions.name, initOptions.tenantId, publicApiUrl);
431
+ }
432
+ }
433
+ }
434
+ out.blank();
435
+ out.success(`Created ${chalk.bold(initOptions.displayName)} at ${chalk.cyan(targetDir)}`);
436
+ out.blank();
437
+ out.heading("Next steps:");
438
+ out.blank();
439
+ if (initOptions.tenantId) {
440
+ out.dim(`Main company tenant: ${chalk.cyan(initOptions.parentTenantId)}`);
441
+ out.dim(`Bound to tenant: ${chalk.cyan(initOptions.tenantId)}`);
442
+ }
443
+ if (!entraProvisioned) {
444
+ out.dim(`Run ${chalk.cyan("eai provision entra")} inside the project to set up Entra authentication.`);
445
+ }
446
+ out.dim(`Template: ${templatePlan.displaySource}`);
447
+ if (options.gofer) {
448
+ out.dim("Gofer: Claude /0_gofer_start; Codex uses the repo-local Gofer skills; Gemini /gofer:1_gofer_research; Copilot .github prompts/skills.");
449
+ }
450
+ out.dim(`Package profile: ${initOptions.packageProfile}`);
451
+ out.dim(`CLI docs: https://github.com/${GITHUB_ORG}/eai`);
452
+ out.blank();
453
+ });
454
+ function resolvePackageProfile(value) {
455
+ if (value === "external" || value === "internal" || value === "hybrid") {
456
+ return value;
457
+ }
458
+ out.error(`Invalid --package-profile "${String(value)}". Use external, internal, or hybrid.`);
459
+ process.exit(1);
460
+ }
461
+ /**
462
+ * Provision an Entra app registration inline at the end of `eai init`, bound
463
+ * to the tenant the user selected in the tenant-binding prompt. Returns true
464
+ * on success. Non-fatal: logs a warning and returns false on any failure.
465
+ */
466
+ async function provisionEntraInline(targetDir, appName, tenantId, publicApiUrl) {
467
+ const spinner = ora("Provisioning Entra app registration...").start();
468
+ try {
469
+ const client = new PlatformAPIClient(publicApiUrl, tenantId);
470
+ const authSiteUrl = `http://localhost:3000/${appName}`;
471
+ const result = await client.provisionEntraApp({
472
+ tenantId,
473
+ appName,
474
+ redirectUris: [`${authSiteUrl}/api/auth/callback/microsoft-entra-id`],
475
+ idempotent: true,
476
+ });
477
+ if (result.tenantAuthorization?.warning ||
478
+ (result.tenantAuthorization &&
479
+ !result.tenantAuthorization.added &&
480
+ !result.tenantAuthorization.alreadyAuthorized)) {
481
+ spinner.fail("Tenant data-plane authorization incomplete.");
482
+ out.warn(`The app registration ${result.clientId} exists, but the tenant allowlist was not updated. Run \`eai provision entra --force --debug\` after platform access is fixed.`);
483
+ return false;
484
+ }
485
+ if (result.clientSecret) {
486
+ await patchEnvFile(targetDir, {
487
+ ENTRA_CLIENT_ID: result.clientId,
488
+ ENTRA_CLIENT_SECRET: result.clientSecret,
489
+ AUTH_URL: authSiteUrl,
490
+ NEXTAUTH_URL: authSiteUrl,
491
+ AUTH_TRUST_HOST: "true",
492
+ });
493
+ spinner.succeed(`Entra app registration ${result.existing ? "confirmed" : "created"}: ${chalk.dim(result.clientId)}`);
494
+ out.warn("The client secret has been written to .env.local and cannot be retrieved again.");
495
+ return true;
496
+ }
497
+ if (result.existing) {
498
+ await patchEnvFile(targetDir, {
499
+ ENTRA_CLIENT_ID: result.clientId,
500
+ AUTH_URL: authSiteUrl,
501
+ NEXTAUTH_URL: authSiteUrl,
502
+ AUTH_TRUST_HOST: "true",
503
+ });
504
+ const hydratedSecret = await hydrateCloudSecret(targetDir, appName);
505
+ spinner.succeed(`Entra app registration confirmed: ${chalk.dim(result.clientId)}`);
506
+ if (hydratedSecret) {
507
+ out.success("ENTRA_CLIENT_SECRET hydrated from cloud config.");
508
+ }
509
+ else {
510
+ out.warn("An existing registration was found. Run `eai env pull --include-secrets` if ENTRA_CLIENT_SECRET is missing locally.");
511
+ }
512
+ return true;
513
+ }
514
+ spinner.fail("Provisioning returned no credentials.");
515
+ out.warn("Run `eai provision entra` after setup to complete Entra registration.");
516
+ return false;
517
+ }
518
+ catch (err) {
519
+ if (process.env.DEBUG) {
520
+ console.error("[eai:provision]", err);
521
+ }
522
+ spinner.fail("Entra provisioning failed — skipping.");
523
+ out.warn("Run `eai provision entra` inside the project to complete Entra registration.");
524
+ return false;
525
+ }
526
+ }
527
+ async function hydrateCloudSecret(targetDir, appName) {
528
+ try {
529
+ const { patches } = await pullCloudEnvValues({
530
+ label: appName,
531
+ includeSecrets: true,
532
+ });
533
+ const secret = patches.ENTRA_CLIENT_SECRET;
534
+ if (!secret) {
535
+ return false;
536
+ }
537
+ await patchEnvFile(targetDir, { ENTRA_CLIENT_SECRET: secret });
538
+ return true;
539
+ }
540
+ catch {
541
+ return false;
542
+ }
543
+ }
544
+ async function loadActiveTenantForInit(publicApiUrl) {
545
+ try {
546
+ const ctx = await resolveActiveTenantContext({
547
+ publicApiUrl,
548
+ interactive: false,
549
+ });
550
+ return ctx.activeTenant;
551
+ }
552
+ catch {
553
+ return null;
554
+ }
555
+ }
556
+ async function assertTenantExists(publicApiUrl, tenantId) {
557
+ const client = new PlatformAPIClient(publicApiUrl, tenantId);
558
+ const res = await client.getTenant(tenantId);
559
+ if (!res.ok) {
560
+ const body = await res.text().catch(() => "");
561
+ out.error(`Tenant ${tenantId} could not be resolved (${res.status}). ${body}`.trim());
562
+ process.exit(1);
563
+ }
564
+ }
565
+ async function promptCompanyTenantForInit(publicApiUrl, activeTenant, companyFlag, interactive) {
566
+ if (companyFlag) {
567
+ await assertTenantExists(publicApiUrl, companyFlag);
568
+ return resolveMainCompanyTenantId(publicApiUrl, companyFlag);
569
+ }
570
+ if (!interactive && !activeTenant) {
571
+ out.error("A main company tenant is required. Pass `--company-tenant <id>` after completing onboarding.");
572
+ process.exit(1);
573
+ }
574
+ if (!interactive && activeTenant) {
575
+ return resolveMainCompanyTenantId(publicApiUrl, activeTenant.id);
576
+ }
577
+ const choices = [];
578
+ if (activeTenant) {
579
+ choices.push({
580
+ name: `Default (currently selected): ${activeTenant.displayName} · ${chalk.dim(activeTenant.id)}`,
581
+ value: "default",
582
+ });
583
+ }
584
+ else {
585
+ choices.push({
586
+ name: "Default (currently selected)",
587
+ value: "default",
588
+ disabled: "no active tenant — run `eai login` and complete onboarding first",
589
+ });
590
+ }
591
+ choices.push({
592
+ name: "Other main company tenant (enter ID)",
593
+ value: "other",
594
+ });
595
+ const { mode } = await inquirer.prompt([
596
+ {
597
+ type: "select",
598
+ name: "mode",
599
+ message: "Which main company tenant should own this app?",
600
+ choices,
601
+ },
602
+ ]);
603
+ if (mode === "default") {
604
+ return resolveMainCompanyTenantId(publicApiUrl, activeTenant.id);
605
+ }
606
+ const { otherId } = await inquirer.prompt([
607
+ {
608
+ type: "input",
609
+ name: "otherId",
610
+ message: "Main company tenant ID:",
611
+ validate: (input) => input.trim().length > 0 || "Main company tenant ID is required",
612
+ },
613
+ ]);
614
+ const trimmed = String(otherId).trim();
615
+ await assertTenantExists(publicApiUrl, trimmed);
616
+ return resolveMainCompanyTenantId(publicApiUrl, trimmed);
617
+ }
618
+ async function createTenantAppForInit(publicApiUrl, activeTenant, companyFlag, immediateParentFlag, appSeed, childTenantOption, createChildTenantFlag, interactive) {
619
+ const companyTenantId = await promptCompanyTenantForInit(publicApiUrl, activeTenant, companyFlag, interactive);
620
+ const defaultImmediateParentTenantId = companyFlag || !activeTenant ? companyTenantId : activeTenant.id;
621
+ const immediateParentTenantId = immediateParentFlag?.trim() || defaultImmediateParentTenantId;
622
+ if (immediateParentTenantId !== companyTenantId) {
623
+ await assertTenantExists(publicApiUrl, immediateParentTenantId);
624
+ }
625
+ const client = new PlatformAPIClient(publicApiUrl, companyTenantId);
626
+ let childTenantDisplayName = "";
627
+ try {
628
+ childTenantDisplayName =
629
+ normalizeChildTenantDisplayNameOption(childTenantOption) ?? "";
630
+ }
631
+ catch (err) {
632
+ out.error(errMsg(err));
633
+ process.exit(1);
634
+ }
635
+ let shouldCreateChildTenant = Boolean(childTenantDisplayName) || createChildTenantFlag;
636
+ if (!shouldCreateChildTenant && interactive) {
637
+ const answer = await inquirer.prompt([
638
+ {
639
+ type: "select",
640
+ name: "appTenantScope",
641
+ message: "App tenant scope:",
642
+ default: "current",
643
+ choices: [
644
+ { name: "Current company tenant", value: "current" },
645
+ { name: "New child company tenant", value: "child" },
646
+ ],
647
+ },
648
+ ]);
649
+ shouldCreateChildTenant =
650
+ String(answer.appTenantScope || "current") === "child";
651
+ }
652
+ if (shouldCreateChildTenant) {
653
+ const childDecision = await evaluateCapabilityForInit(client, "child-tenants", companyTenantId);
654
+ if (childDecision.outcome !== "allow") {
655
+ const suffix = childDecision.upgradeUrl
656
+ ? ` Upgrade: ${childDecision.upgradeUrl}`
657
+ : "";
658
+ out.error(`${childDecision.reasonMessage}${suffix}`);
659
+ process.exit(1);
660
+ }
661
+ }
662
+ if (shouldCreateChildTenant && !childTenantDisplayName && interactive) {
663
+ const answer = await inquirer.prompt([
664
+ {
665
+ type: "input",
666
+ name: "childTenantDisplayName",
667
+ message: "Child company tenant name:",
668
+ default: appSeed.displayName,
669
+ validate: (input) => input.trim().length > 0 || "Child company tenant name is required",
670
+ },
671
+ ]);
672
+ childTenantDisplayName = String(answer.childTenantDisplayName).trim();
673
+ }
674
+ if (shouldCreateChildTenant && !childTenantDisplayName) {
675
+ out.error("A child company tenant name is required. Pass `--child-tenant <name>`.");
676
+ process.exit(1);
677
+ }
678
+ const res = await client.createTenantApp(companyTenantId, {
679
+ appDisplayName: appSeed.displayName,
680
+ verticalKey: appSeed.slug,
681
+ ...(immediateParentTenantId !== companyTenantId
682
+ ? { parentTenantId: immediateParentTenantId }
683
+ : {}),
684
+ ...(childTenantDisplayName ? { childTenantDisplayName } : {}),
685
+ templateKey: "eai-app-template",
686
+ source: "eai-cli",
687
+ usecase: "generic",
688
+ });
689
+ if (!res.ok) {
690
+ const error = await parseApiError(res);
691
+ out.error(`App creation failed: ${error.message}`);
692
+ process.exit(1);
693
+ }
694
+ const payload = (await res.json());
695
+ const childTenant = payload.childTenant;
696
+ const childTenantId = childTenant && typeof childTenant === "object"
697
+ ? String(childTenant.id || "")
698
+ : "";
699
+ if (!childTenantId) {
700
+ out.info(`Created app ${chalk.cyan(appSeed.slug)} under company tenant ${chalk.cyan(immediateParentTenantId)}.`);
701
+ return {
702
+ parentTenantId: companyTenantId,
703
+ runtimeTenantId: immediateParentTenantId,
704
+ runtimeTenantHomeRegion: activeTenant?.homeRegion,
705
+ };
706
+ }
707
+ out.info(`Created app ${chalk.cyan(appSeed.slug)} under main company ${chalk.cyan(companyTenantId)} with child company ${chalk.cyan(childTenantId)}.`);
708
+ const childTenantHomeRegion = childTenant && typeof childTenant === "object"
709
+ ? childTenant.homeRegion
710
+ : undefined;
711
+ return {
712
+ parentTenantId: companyTenantId,
713
+ runtimeTenantId: childTenantId,
714
+ childTenantId,
715
+ runtimeTenantHomeRegion: typeof childTenantHomeRegion === "string"
716
+ ? childTenantHomeRegion
717
+ : activeTenant?.homeRegion,
718
+ };
719
+ }
720
+ async function hydrateEnvFromLoginContext(targetDir, appName, parentTenantId, platformTenantId, tenantHomeRegion) {
721
+ const patches = {};
722
+ const envKey = appName.replace(/-/g, "_").toUpperCase();
723
+ const regionalPublicApiUrl = publicApiUrlForHomeRegion(tenantHomeRegion);
724
+ if (regionalPublicApiUrl) {
725
+ patches.BASE_URL_PUBLIC_API = regionalPublicApiUrl;
726
+ }
727
+ else {
728
+ try {
729
+ patches.BASE_URL_PUBLIC_API = await resolvePublicApiUrl(targetDir);
730
+ }
731
+ catch {
732
+ // Best-effort bootstrap only.
733
+ }
734
+ }
735
+ try {
736
+ const profileName = getActiveProfile();
737
+ const profileConfig = await loadProfileConfig(profileName);
738
+ if (profileConfig?.authTenantName) {
739
+ patches.ENTRA_TENANT_NAME = profileConfig.authTenantName;
740
+ }
741
+ if (profileConfig?.authTenantId) {
742
+ patches.ENTRA_TENANT_ID = profileConfig.authTenantId;
743
+ }
744
+ }
745
+ catch {
746
+ // Default profile has no config file.
747
+ }
748
+ try {
749
+ const tokens = await loadTokens();
750
+ if (tokens?.tenantName) {
751
+ patches.ENTRA_TENANT_NAME = tokens.tenantName;
752
+ }
753
+ if (tokens?.tenantId) {
754
+ patches.ENTRA_TENANT_ID = tokens.tenantId;
755
+ }
756
+ }
757
+ catch {
758
+ // Best-effort bootstrap only.
759
+ }
760
+ if (parentTenantId) {
761
+ patches.EAI_PARENT_TENANT_ID = parentTenantId;
762
+ }
763
+ if (platformTenantId) {
764
+ patches.EAI_TENANT_ID = platformTenantId;
765
+ patches[`TENANT_${envKey}_ID`] = platformTenantId;
766
+ }
767
+ if (Object.keys(patches).length > 0) {
768
+ await patchEnvFile(targetDir, patches);
769
+ }
770
+ }
771
+ function toDisplayName(name) {
772
+ return name
773
+ .split("-")
774
+ .map((w) => w.charAt(0).toUpperCase() + w.slice(1))
775
+ .join(" ");
776
+ }
777
+ function describeTemplateSource(templateSource) {
778
+ if (isDefaultTemplateSource(templateSource)) {
779
+ return TEMPLATE_REPO_LABEL;
780
+ }
781
+ const githubMatch = templateSource.match(/github\.com[:/](.+?)(?:\.git)?$/i);
782
+ if (githubMatch?.[1]) {
783
+ return githubMatch[1].replace(/\/+$/, "");
784
+ }
785
+ return templateSource;
786
+ }
787
+ function describeGitInitFailure(error) {
788
+ const message = error instanceof Error ? error.message : String(error);
789
+ if (/spawn git enoent/i.test(message)) {
790
+ return "`git` was not found on your PATH, so the project was created without an initialized repository. Install Git and run `git init` inside the new project if you want version control.";
791
+ }
792
+ return message;
793
+ }
794
+ async function ensureTargetDirAvailable(targetDir, projectName) {
795
+ try {
796
+ await access(targetDir);
797
+ out.error(`Directory "${projectName}" already exists.`);
798
+ process.exit(1);
799
+ }
800
+ catch {
801
+ // good — doesn't exist
802
+ }
803
+ }
804
+ async function resolveInitTargetDir(projectName, useCurrentDir) {
805
+ if (useCurrentDir) {
806
+ return resolve(process.cwd());
807
+ }
808
+ const targetDir = resolve(process.cwd(), projectName);
809
+ await ensureTargetDirAvailable(targetDir, projectName);
810
+ return targetDir;
811
+ }
812
+ // ─── Generators ────────────────────────────────────────────────────────────
813
+ function generateEnvFile(opts) {
814
+ const envKey = opts.name.replace(/-/g, "_").toUpperCase();
815
+ const authSecret = randomBytes(32).toString("base64");
816
+ return `# =============================================================================
817
+ # EAI App: ${opts.displayName}
818
+ # Generated by: eai init
819
+ # Run 'eai env pull' to sync values from Azure App Config + Key Vault
820
+ # =============================================================================
821
+
822
+ # App Identity
823
+ NEXT_PUBLIC_APP_NAME=${opts.name}
824
+ APP_BASE_PATH=/${opts.name}
825
+ NEXT_PUBLIC_APP_BASE_PATH=/${opts.name}
826
+
827
+ # =============================================================================
828
+ # Platform API
829
+ # Run 'eai env pull' to populate from Azure App Config
830
+ # =============================================================================
831
+ BASE_URL_PUBLIC_API=
832
+
833
+ # =============================================================================
834
+ # Tenant configuration
835
+ # EAI_PARENT_TENANT_ID is the onboarding-created company tenant that owns
836
+ # the platform app entry.
837
+ # EAI_TENANT_ID is the server-side company tenant this app binds to — read by
838
+ # the template in src/app/page.tsx and src/app/api/eai/[[...rest]]/route.ts.
839
+ # TENANT_KEYS + TENANT_<KEY>_ID support the multi-tenant config resolver at
840
+ # src/app/api/eai/config/route.ts. Both keys are kept in sync by eai init.
841
+ # =============================================================================
842
+ EAI_PARENT_TENANT_ID=
843
+ EAI_TENANT_ID=
844
+ TENANT_KEYS=${opts.name}
845
+ TENANT_${envKey}_ID=
846
+
847
+ # =============================================================================
848
+ # Workflow IDs — populate after provisioning via platform dashboard
849
+ # =============================================================================
850
+ WORKFLOW_${envKey}_ID=
851
+
852
+ # =============================================================================
853
+ # Init capability selections
854
+ # =============================================================================
855
+ EAI_INIT_INCLUDE_AI_CHAT=${String(opts.includeChat)}
856
+ EAI_INIT_INCLUDE_DOCUMENTS=${String(opts.includeDocs)}
857
+ EAI_AUTH_PROVIDER=${opts.authProvider}
858
+
859
+ # =============================================================================
860
+ # Microsoft Entra ID (CIAM) — end-user auth for this app
861
+ # Run 'eai provision entra' to populate ENTRA_CLIENT_ID and ENTRA_CLIENT_SECRET
862
+ # =============================================================================
863
+ ENTRA_TENANT_NAME=
864
+ ENTRA_TENANT_ID=
865
+ ENTRA_SCOPES="email offline_access openid profile"
866
+ ENTRA_CLIENT_ID=
867
+ ENTRA_CLIENT_SECRET=
868
+
869
+ # =============================================================================
870
+ # Auth.js — auto-generated secret
871
+ # =============================================================================
872
+ AUTH_SECRET=${authSecret}
873
+ AUTH_URL=http://localhost:3000/${opts.name}
874
+ NEXTAUTH_URL=http://localhost:3000/${opts.name}
875
+ AUTH_TRUST_HOST=true
876
+
877
+ # =============================================================================
878
+ # IMPORTANT: Do NOT commit this file. Use 'eai env pull' to sync from cloud.
879
+ # Secrets belong in Azure Key Vault, config in Azure App Config.
880
+ # =============================================================================
881
+ `;
882
+ }
883
+ function generateObjectTypesScaffold(opts) {
884
+ const tenantKey = opts.name;
885
+ const documentLinkBlock = opts.includeDocs
886
+ ? ` linkTypes: [
887
+ {
888
+ name: 'documents',
889
+ targetObjectType: 'Document',
890
+ cardinality: 'one-to-many' as const,
891
+ cascadeDelete: true,
892
+ },
893
+ ],`
894
+ : ` linkTypes: [],`;
895
+ const documentTypeBlock = opts.includeDocs
896
+ ? `
897
+ {
898
+ name: 'Document',
899
+ displayName: 'Document',
900
+ description: 'Uploaded file with classification metadata',
901
+ ...postgresqlResourceStorage,
902
+ properties: [
903
+ {
904
+ name: 'fileName',
905
+ type: 'text' as const,
906
+ required: true,
907
+ description: 'Original file name',
908
+ },
909
+ {
910
+ name: 'fileUrl',
911
+ type: 'file' as const,
912
+ required: true,
913
+ description: 'URL to the uploaded file',
914
+ },
915
+ {
916
+ name: 'category',
917
+ type: 'select' as const,
918
+ required: false,
919
+ options: [
920
+ { label: 'General', value: 'general' },
921
+ { label: 'Report', value: 'report' },
922
+ { label: 'Evidence', value: 'evidence' },
923
+ ],
924
+ description: 'Document category (can be auto-classified)',
925
+ },
926
+ {
927
+ name: 'uploadedAt',
928
+ type: 'date' as const,
929
+ required: false,
930
+ description: 'When the document was uploaded',
931
+ },
932
+ ],
933
+ linkTypes: [],
934
+ actions: [],
935
+ storageBackend: 'postgresql' as const,
936
+ schemaVersion: 1,
937
+ storageMetadataStatus: 'ready' as const,
938
+ storageBinding: {
939
+ sql: {
940
+ databaseAlias: 'resourceapi-postgres',
941
+ tenantSchemaStrategy: 'per-tenant-schema' as const,
942
+ tableName: 'documents',
943
+ },
944
+ },
945
+ status: 'published' as const,
946
+ },`
947
+ : "";
948
+ return `/**
949
+ * Object Type definitions for ${opts.displayName}
950
+ *
951
+ * Each object type maps to a platform resource with typed validation, actions, and relationship links.
952
+ *
953
+ * Commands:
954
+ * eai types validate Check definitions against platform schema
955
+ * eai types seed Push to platform via PublicAPI
956
+ * eai types diff Compare local vs remote state
957
+ *
958
+ * ┌──────────────────────────────────────────────────────────────┐
959
+ * │ Field Types │
960
+ * ├────────────┬─────────────────────────────────────────────────┤
961
+ * │ text │ String value (names, emails, IDs) │
962
+ * │ number │ Integer or float (counts, amounts, scores) │
963
+ * │ boolean │ True/false flag (isVerified, isActive) │
964
+ * │ date │ ISO 8601 datetime (submittedAt, createdAt) │
965
+ * │ select │ Enum — requires \`options\` array │
966
+ * │ json │ Arbitrary JSON object (metadata, config) │
967
+ * │ file │ File reference URL (attachments, uploads) │
968
+ * │ relationship│ Reference to another resource by ID │
969
+ * ├────────────┼─────────────────────────────────────────────────┤
970
+ * │ Link Types (cardinality) │
971
+ * ├────────────┼─────────────────────────────────────────────────┤
972
+ * │ one-to-one │ Single reference (e.g., profile → user) │
973
+ * │ one-to-many│ Parent → children (e.g., order → items) │
974
+ * │ many-to-one│ Child → parent (e.g., item → order) │
975
+ * │ many-to-many│ Bidirectional (e.g., tags ↔ articles) │
976
+ * ├────────────┼─────────────────────────────────────────────────┤
977
+ * │ Action Side Effects │
978
+ * ├────────────┼─────────────────────────────────────────────────┤
979
+ * │ set_field │ Set a property to a specific value │
980
+ * │ set_timestamp │ Set a date field to current time │
981
+ * │ set_user │ Set a field to the current user's ID │
982
+ * ├────────────┼─────────────────────────────────────────────────┤
983
+ * │ Roles │
984
+ * ├────────────┼─────────────────────────────────────────────────┤
985
+ * │ tenant-viewer│ Basic access (read and lightweight submit) │
986
+ * │ tenant-builder│ Extended access (view all, edit, actions) │
987
+ * │ tenant-admin│ Full access (delete, configure) │
988
+ * └────────────┴─────────────────────────────────────────────────┘
989
+ */
990
+
991
+ const postgresqlResourceStorage = {
992
+ schemaVersion: 1,
993
+ storageBackend: 'postgresql' as const,
994
+ storageMetadataStatus: 'ready' as const,
995
+ storageBinding: {
996
+ sql: {
997
+ databaseAlias: 'resourceapi-postgres',
998
+ tenantSchemaStrategy: 'per-tenant-database' as const,
999
+ schemaName: 'resources',
1000
+ tableName: 'tenant_resources',
1001
+ },
1002
+ },
1003
+ };
1004
+
1005
+ export const objectTypes = {
1006
+ '${tenantKey}': [
1007
+ {
1008
+ name: 'Record',
1009
+ displayName: 'Record',
1010
+ description: 'A sample record — replace with your domain model',
1011
+ ...postgresqlResourceStorage,
1012
+ properties: [
1013
+ {
1014
+ name: 'title',
1015
+ type: 'text' as const,
1016
+ required: true,
1017
+ indexed: true,
1018
+ description: 'Title of this record',
1019
+ },
1020
+ {
1021
+ name: 'description',
1022
+ type: 'text' as const,
1023
+ required: false,
1024
+ description: 'Detailed description',
1025
+ },
1026
+ {
1027
+ name: 'priority',
1028
+ type: 'number' as const,
1029
+ required: false,
1030
+ defaultValue: 0,
1031
+ description: 'Priority level (0 = normal)',
1032
+ },
1033
+ {
1034
+ name: 'isActive',
1035
+ type: 'boolean' as const,
1036
+ required: true,
1037
+ defaultValue: true,
1038
+ description: 'Whether this record is active',
1039
+ },
1040
+ {
1041
+ name: 'dueDate',
1042
+ type: 'date' as const,
1043
+ required: false,
1044
+ description: 'Target completion date',
1045
+ },
1046
+ {
1047
+ name: 'status',
1048
+ type: 'select' as const,
1049
+ required: true,
1050
+ defaultValue: 'draft',
1051
+ options: [
1052
+ { label: 'Draft', value: 'draft' },
1053
+ { label: 'In Progress', value: 'in-progress' },
1054
+ { label: 'Complete', value: 'complete' },
1055
+ { label: 'Archived', value: 'archived' },
1056
+ ],
1057
+ description: 'Current lifecycle status',
1058
+ },
1059
+ {
1060
+ name: 'metadata',
1061
+ type: 'json' as const,
1062
+ required: false,
1063
+ description: 'Arbitrary metadata (tags, notes, etc.)',
1064
+ },
1065
+ {
1066
+ name: 'assignedTo',
1067
+ type: 'relationship' as const,
1068
+ required: false,
1069
+ indexed: true,
1070
+ description: 'User ID of the assignee',
1071
+ },
1072
+ ],
1073
+ ${documentLinkBlock}
1074
+ actions: [
1075
+ {
1076
+ name: 'submit',
1077
+ displayName: 'Submit',
1078
+ requiredRole: 'tenant-viewer' as const,
1079
+ validationRules: {
1080
+ requiredFields: ['title'],
1081
+ requiredStatus: 'draft',
1082
+ },
1083
+ sideEffects: [
1084
+ { type: 'set_field' as const, field: 'status', value: 'in-progress' },
1085
+ { type: 'set_timestamp' as const, field: 'dueDate' },
1086
+ { type: 'set_user' as const, field: 'assignedTo' },
1087
+ ],
1088
+ },
1089
+ {
1090
+ name: 'complete',
1091
+ displayName: 'Mark Complete',
1092
+ requiredRole: 'tenant-builder' as const,
1093
+ validationRules: {
1094
+ requiredStatus: 'in-progress',
1095
+ },
1096
+ sideEffects: [
1097
+ { type: 'set_field' as const, field: 'status', value: 'complete' },
1098
+ { type: 'set_field' as const, field: 'isActive', value: false },
1099
+ ],
1100
+ },
1101
+ ],
1102
+ storageBackend: 'postgresql' as const,
1103
+ schemaVersion: 1,
1104
+ storageMetadataStatus: 'ready' as const,
1105
+ storageBinding: {
1106
+ sql: {
1107
+ databaseAlias: 'resourceapi-postgres',
1108
+ tenantSchemaStrategy: 'per-tenant-schema' as const,
1109
+ tableName: 'records',
1110
+ },
1111
+ },
1112
+ status: 'published' as const,
1113
+ },
1114
+ ${documentTypeBlock}
1115
+ ],
1116
+
1117
+ // ── Dual-tenant example (uncomment if using dual tenant structure) ──
1118
+ // '${tenantKey}-customer': [ ... ],
1119
+ // '${tenantKey}-staff': [ ... ],
1120
+ };
1121
+ `;
1122
+ }
1123
+ function defaultInitCapabilities() {
1124
+ return {
1125
+ "child-tenants": {
1126
+ outcome: "deny",
1127
+ reasonCode: "capability_service_unavailable",
1128
+ reasonMessage: "Child-tenant entitlement could not be confirmed right now.",
1129
+ upgradeUrl: null,
1130
+ },
1131
+ "ai-chat": {
1132
+ outcome: "allow",
1133
+ reasonCode: "default_cli_fallback",
1134
+ reasonMessage: "AI chat defaults to enabled when capability evaluation is unavailable.",
1135
+ upgradeUrl: null,
1136
+ },
1137
+ documents: {
1138
+ outcome: "allow",
1139
+ reasonCode: "default_cli_fallback",
1140
+ reasonMessage: "Document management defaults to enabled when capability evaluation is unavailable.",
1141
+ upgradeUrl: null,
1142
+ },
1143
+ "auth-b2b": {
1144
+ outcome: "deny",
1145
+ reasonCode: "template_scaffold_unavailable",
1146
+ reasonMessage: "B2B auth scaffolding is not currently available in eai init.",
1147
+ upgradeUrl: null,
1148
+ },
1149
+ "auth-dual": {
1150
+ outcome: "deny",
1151
+ reasonCode: "template_scaffold_unavailable",
1152
+ reasonMessage: "Dual-auth scaffolding is not currently available in eai init.",
1153
+ upgradeUrl: null,
1154
+ },
1155
+ };
1156
+ }
1157
+ async function evaluateCapabilityForInit(client, targetCapability, tenantId) {
1158
+ try {
1159
+ return await client.evaluateCapability({
1160
+ tenantId,
1161
+ targetCapability,
1162
+ requestedOperation: targetCapability === "child-tenants" ? "create" : "enable",
1163
+ });
1164
+ }
1165
+ catch {
1166
+ return defaultInitCapabilities()[targetCapability];
1167
+ }
1168
+ }
1169
+ async function evaluateInitCapabilities(publicApiUrl, tenantId) {
1170
+ const client = new PlatformAPIClient(publicApiUrl, tenantId);
1171
+ const [childTenants, aiChat, documents, authB2B, authDual] = await Promise.all([
1172
+ evaluateCapabilityForInit(client, "child-tenants", tenantId),
1173
+ evaluateCapabilityForInit(client, "ai-chat", tenantId),
1174
+ evaluateCapabilityForInit(client, "documents", tenantId),
1175
+ evaluateCapabilityForInit(client, "auth-b2b", tenantId),
1176
+ evaluateCapabilityForInit(client, "auth-dual", tenantId),
1177
+ ]);
1178
+ return {
1179
+ "child-tenants": childTenants,
1180
+ "ai-chat": aiChat,
1181
+ documents,
1182
+ "auth-b2b": authB2B,
1183
+ "auth-dual": authDual,
1184
+ };
1185
+ }
1186
+ function buildAuthProviderChoices(capabilities) {
1187
+ const b2bDisabled = capabilities["auth-b2b"].outcome === "allow"
1188
+ ? "application template scaffolding is not available yet"
1189
+ : capabilities["auth-b2b"].reasonMessage;
1190
+ const dualDisabled = capabilities["auth-dual"].outcome === "allow"
1191
+ ? "application template scaffolding is not available yet"
1192
+ : capabilities["auth-dual"].reasonMessage;
1193
+ return [
1194
+ { name: "Entra ID CIAM", value: "ciam" },
1195
+ {
1196
+ name: "Entra ID B2B (corporate SSO)",
1197
+ value: "b2b",
1198
+ disabled: b2bDisabled,
1199
+ },
1200
+ { name: "Dual (CIAM + B2B)", value: "dual", disabled: dualDisabled },
1201
+ ];
1202
+ }
1203
+ async function promptFeatureOptions(publicApiUrl, tenantId) {
1204
+ const capabilities = await evaluateInitCapabilities(publicApiUrl, tenantId);
1205
+ let includeChat = false;
1206
+ if (capabilities["ai-chat"].outcome === "allow") {
1207
+ const answer = await inquirer.prompt([
1208
+ {
1209
+ type: "confirm",
1210
+ name: "includeChat",
1211
+ message: "Include AI chat?",
1212
+ default: true,
1213
+ },
1214
+ ]);
1215
+ includeChat = Boolean(answer.includeChat);
1216
+ }
1217
+ else {
1218
+ out.warn(`AI chat disabled: ${capabilities["ai-chat"].reasonMessage}`);
1219
+ }
1220
+ let includeDocs = false;
1221
+ if (capabilities.documents.outcome === "allow") {
1222
+ const answer = await inquirer.prompt([
1223
+ {
1224
+ type: "confirm",
1225
+ name: "includeDocs",
1226
+ message: "Include document management?",
1227
+ default: true,
1228
+ },
1229
+ ]);
1230
+ includeDocs = Boolean(answer.includeDocs);
1231
+ }
1232
+ else {
1233
+ out.warn(`Document management disabled: ${capabilities.documents.reasonMessage}`);
1234
+ }
1235
+ const authChoices = buildAuthProviderChoices(capabilities);
1236
+ const authProviderAnswer = await inquirer.prompt([
1237
+ {
1238
+ type: "select",
1239
+ name: "authProvider",
1240
+ message: "Auth provider:",
1241
+ choices: authChoices,
1242
+ default: "ciam",
1243
+ },
1244
+ ]);
1245
+ return {
1246
+ includeChat,
1247
+ includeDocs,
1248
+ authProvider: authProviderAnswer.authProvider,
1249
+ };
1250
+ }
1251
+ function generateDeployWorkflow(opts) {
1252
+ return `# Deploy ${opts.displayName} to Azure App Service
1253
+ # Triggers on push to main branch
1254
+ #
1255
+ # Required GitHub Secrets (in "demo" environment):
1256
+ # AZUREAPPSERVICE_CLIENTID — Azure AD app registration client ID
1257
+ # AZUREAPPSERVICE_TENANTID — Azure AD tenant ID
1258
+ # AZUREAPPSERVICE_SUBSCRIPTIONID — Azure subscription ID
1259
+ # AZURE_RESOURCE_GROUP — Azure resource group name
1260
+ # AZURE_WEBAPP_NAME — Azure App Service name
1261
+
1262
+ name: Deploy ${opts.displayName}
1263
+
1264
+ on:
1265
+ push:
1266
+ branches: [main]
1267
+ workflow_dispatch:
1268
+
1269
+ env:
1270
+ APP_NAME: ${opts.name}
1271
+ NODE_VERSION: '20.x'
1272
+
1273
+ jobs:
1274
+ build-and-deploy:
1275
+ runs-on: ubuntu-latest
1276
+ environment: demo
1277
+ permissions:
1278
+ id-token: write
1279
+ contents: read
1280
+
1281
+ steps:
1282
+ - uses: actions/checkout@v4
1283
+
1284
+ - name: Set up Node.js
1285
+ uses: actions/setup-node@v4
1286
+ with:
1287
+ node-version: \${{ env.NODE_VERSION }}
1288
+ cache: 'npm'
1289
+
1290
+ - name: Install dependencies
1291
+ run: npm ci
1292
+
1293
+ - name: Build Object Types JSON
1294
+ run: npm run build:object-types
1295
+
1296
+ - name: Build
1297
+ run: npm run build
1298
+ env:
1299
+ APP_BASE_PATH: /\${{ env.APP_NAME }}
1300
+
1301
+ - name: Package standalone output
1302
+ run: |
1303
+ mkdir -p deploy/\${{ env.APP_NAME }}
1304
+ cp -r .next/standalone/. deploy/\${{ env.APP_NAME }}/
1305
+ cp -r .next/static deploy/\${{ env.APP_NAME }}/.next/
1306
+ cp -r public deploy/\${{ env.APP_NAME }}/ 2>/dev/null || true
1307
+ cd deploy && zip -r ../app-content.zip \${{ env.APP_NAME }}
1308
+
1309
+ - name: Azure Login
1310
+ uses: azure/login@v2
1311
+ with:
1312
+ client-id: \${{ secrets.AZUREAPPSERVICE_CLIENTID }}
1313
+ tenant-id: \${{ secrets.AZUREAPPSERVICE_TENANTID }}
1314
+ subscription-id: \${{ secrets.AZUREAPPSERVICE_SUBSCRIPTIONID }}
1315
+
1316
+ - name: Deploy to Azure
1317
+ run: |
1318
+ az webapp deploy \\
1319
+ --resource-group \${{ secrets.AZURE_RESOURCE_GROUP }} \\
1320
+ --name \${{ secrets.AZURE_WEBAPP_NAME }} \\
1321
+ --src-path app-content.zip \\
1322
+ --type zip \\
1323
+ --target-path /home/site/wwwroot/\${{ env.APP_NAME }}
1324
+
1325
+ - name: Restart App Service
1326
+ run: |
1327
+ az webapp restart \\
1328
+ --resource-group \${{ secrets.AZURE_RESOURCE_GROUP }} \\
1329
+ --name \${{ secrets.AZURE_WEBAPP_NAME }}
1330
+ `;
1331
+ }
1332
+ function generateClaudeMd(opts) {
1333
+ return `# ${opts.displayName}
1334
+
1335
+ An application built on the Enterprise AI platform.
1336
+
1337
+ ## Tech Stack
1338
+
1339
+ - **Framework**: Next.js 15+ with App Router
1340
+ - **Language**: TypeScript (strict mode)
1341
+ - **UI**: React 18+, Tailwind CSS, Shadcn/ui
1342
+ - **Auth**: Auth.js with Microsoft Entra ID (CIAM)
1343
+ - **Data**: Platform SDK → data service (typed resource storage)
1344
+ - **AI**: Platform SDK → AI service (RAG chat, document classification)
1345
+
1346
+ ## Platform Architecture
1347
+
1348
+ \`\`\`
1349
+ Browser → Next.js App → BFF Proxy (/api/eai/*) → EAI Platform API
1350
+ \`\`\`
1351
+
1352
+ Tokens are injected server-side by the BFF proxy. Never exposed to the browser.
1353
+
1354
+ ## App Router Rule
1355
+
1356
+ For \`src/app/**/route.ts\` files, export only:
1357
+
1358
+ - HTTP methods such as \`GET\`, \`POST\`, \`PUT\`, and \`PATCH\`
1359
+ - supported route config fields such as \`dynamic\`, \`runtime\`, and \`revalidate\`
1360
+
1361
+ Do not export helper functions, dependency interfaces, or test seams from \`route.ts\`. Put those in a sibling \`handler.ts\` or a module under \`src/lib/\`, then keep \`route.ts\` as a thin wrapper.
1362
+
1363
+ ## Object Types
1364
+
1365
+ Defined in \`src/eai.config/object-types.ts\`. Each type maps to a platform resource with typed validation, actions, and relationship links.
1366
+
1367
+ **Field types**: text, number, boolean, date, select, json, file, relationship
1368
+ **Link cardinality**: one-to-one, one-to-many, many-to-one, many-to-many
1369
+ **Action roles**: tenant-viewer, tenant-builder, tenant-admin
1370
+ **Side effects**: set_field, set_timestamp, set_user
1371
+
1372
+ ## Data Access
1373
+
1374
+ \`\`\`typescript
1375
+ // React hook (client components)
1376
+ import { useResources } from '@/hooks/useResources';
1377
+ const { list, get, create, update, delete: remove } = useResources<MyData>('MyType');
1378
+
1379
+ // Platform SDK (server-side)
1380
+ import { EAIPlatformClient } from '@enterpriseaigroup/platform-sdk';
1381
+ const client = new EAIPlatformClient({ tenantId: 'my-tenant' });
1382
+ await client.resources.create('MyType', { title: 'Hello' });
1383
+ \`\`\`
1384
+
1385
+ ## EAI CLI Commands
1386
+
1387
+ | Command | Purpose |
1388
+ |---------|---------|
1389
+ | \`eai dev\` | Start local dev server |
1390
+ | \`eai tenant select\` | Choose the active tenant for platform commands |
1391
+ | \`eai types validate\` | Validate Object Types |
1392
+ | \`eai types seed\` | Push types to platform |
1393
+ | \`eai types diff\` | Compare local vs remote |
1394
+ | \`eai resources list <type>\` | List resources |
1395
+ | \`eai chat stream <msg>\` | Test AI chat |
1396
+ | \`eai env pull\` | Sync cloud config |
1397
+ | \`eai deploy trigger\` | Trigger deployment |
1398
+ | \`eai verify\` | Platform connectivity check |
1399
+ | \`eai doctor\` | Diagnose issues |
1400
+
1401
+ ## App Delivery Checklist
1402
+
1403
+ | Step | Action | Verification |
1404
+ |------|--------|-------------|
1405
+ | 1 | Define object types in \`src/eai.config/object-types.ts\` | \`eai types validate\` passes |
1406
+ | 2 | Set up tenant config in \`src/eai.config/\` | Config registered in index.ts |
1407
+ | 3 | Create data access hooks in \`src/hooks/\` | Hooks use Platform SDK |
1408
+ | 4 | Build UI pages in \`src/app/(presentation)/\` | Pages render with data |
1409
+ | 5 | Configure AI chat/docs (if needed) | Chat streams, docs upload |
1410
+ | 6 | Seed object types | \`eai types seed\` succeeds |
1411
+ | 7 | Configure deployment | \`deploy-demo.yml\` has correct APP_NAME |
1412
+ | 8 | Deploy | \`eai deploy trigger\` → app loads at \`/${opts.name}\` |
1413
+ | 9 | Verify | \`eai verify\` all checks pass |
1414
+
1415
+ ## Environment Variables
1416
+
1417
+ See \`.env.local\` for required variables. Use \`eai env pull\` to sync from Azure App Config.
1418
+
1419
+ Key variables:
1420
+ - \`BASE_URL_PUBLIC_API\` — Platform API gateway URL
1421
+ - \`WORKFLOW_*_ID\` — Platform workflow IDs
1422
+ - \`ENTRA_*\` — Microsoft Entra ID (CIAM) auth config
1423
+ - \`AUTH_SECRET\` — Auth.js session encryption key
1424
+
1425
+ ## Key Files
1426
+
1427
+ | File | Purpose |
1428
+ |------|---------|
1429
+ | \`src/eai.config/object-types.ts\` | Data model definitions |
1430
+ | \`src/eai.config/default.ts\` | Tenant configuration |
1431
+ | \`src/auth.ts\` | Auth.js configuration |
1432
+ | \`src/app/api/eai/[[...rest]]/route.ts\` | BFF proxy (token injection) |
1433
+ | \`packages/platform-sdk/\` | Local typed API client source until the SDK is promoted to a shared package |
1434
+ | \`.github/workflows/deploy-demo.yml\` | Deployment workflow |
1435
+ `;
1436
+ }
1437
+ //# sourceMappingURL=init.js.map