@atmem/architect 0.0.0-stage → 0.2.0-alpha.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (498) hide show
  1. package/CONSTITUTION.md +144 -0
  2. package/README.md +33 -2
  3. package/agent-skills/discovery/SKILL.md +48 -0
  4. package/agent-skills/discovery/topics.json +139 -0
  5. package/agent-skills/generation-capabilities.json +760 -0
  6. package/agent-skills/service-lifecycle.json +21 -0
  7. package/agent-skills/specialists/architecture/SKILL.md +15 -0
  8. package/agent-skills/specialists/aws/SKILL.md +17 -0
  9. package/agent-skills/specialists/azure/SKILL.md +7 -0
  10. package/agent-skills/specialists/composition/SKILL.md +17 -0
  11. package/agent-skills/specialists/devops/SKILL.md +10 -0
  12. package/agent-skills/specialists/finops/SKILL.md +7 -0
  13. package/agent-skills/specialists/gcp/SKILL.md +7 -0
  14. package/agent-skills/specialists/ibm/SKILL.md +7 -0
  15. package/agent-skills/specialists/manifest.json +13 -0
  16. package/agent-skills/specialists/pulumi/SKILL.md +7 -0
  17. package/agent-skills/specialists/security/SKILL.md +7 -0
  18. package/agent-skills/specialists/terraform/SKILL.md +14 -0
  19. package/agent-skills/upstream/aws/LICENSE +175 -0
  20. package/agent-skills/upstream/aws/SKILL.md +125 -0
  21. package/agent-skills/upstream/azure/LICENSE +21 -0
  22. package/agent-skills/upstream/azure/SKILL.md +387 -0
  23. package/agent-skills/upstream/gcp/LICENSE +202 -0
  24. package/agent-skills/upstream/gcp/SKILL.md +159 -0
  25. package/agent-skills/upstream/manifest.json +57 -0
  26. package/agent-skills/upstream/pulumi/LICENSE +201 -0
  27. package/agent-skills/upstream/pulumi/SKILL.md +501 -0
  28. package/agent-skills/upstream/terraform/LICENSE +373 -0
  29. package/agent-skills/upstream/terraform/SKILL.md +316 -0
  30. package/agent-skills/workflows/workflows.json +601 -0
  31. package/cli/architect.mjs +3 -0
  32. package/cli/runtime.mjs +115 -0
  33. package/dist/assets/html2canvas.esm-QH1iLAAe.js +22 -0
  34. package/dist/assets/index-B97MkVMs.css +1 -0
  35. package/dist/assets/index-qtCM2D7O.js +21271 -0
  36. package/dist/assets/index.es-C6C0sneB.js +18 -0
  37. package/dist/assets/purify.es-CAi2OJFm.js +3 -0
  38. package/dist/assets/visual-export-DjbjgQbA.js +173 -0
  39. package/dist/favicon.svg +2 -0
  40. package/dist/fonts/DM-Sans-OFL.txt +93 -0
  41. package/dist/fonts/Manrope-OFL.txt +93 -0
  42. package/dist/fonts/NotoSans-Regular.ttf +0 -0
  43. package/dist/fonts/OFL.txt +94 -0
  44. package/dist/fonts/dm-sans-latin-wght-normal.woff2 +0 -0
  45. package/dist/fonts/manrope-latin-wght-normal.woff2 +0 -0
  46. package/dist/index.html +4 -0
  47. package/dist/licenses/aws-architect-LICENSE.txt +17 -0
  48. package/dist/licenses/aws-mcp-LICENSE.txt +175 -0
  49. package/dist/licenses/aws-mcp-NOTICE.txt +1 -0
  50. package/dist/licenses/cloud-emulation-notices.txt +36619 -0
  51. package/dist/licenses/dependency-notices.txt +6379 -0
  52. package/dist/licenses/emulation-notices.txt +717 -0
  53. package/dist/licenses/github-copilot-sdk-LICENSE.txt +21 -0
  54. package/dist/licenses/memory-dependency-notices.txt +3319 -0
  55. package/dist/licenses/openarchflow-LICENSE.txt +21 -0
  56. package/dist/licenses/python-dependency-notices.txt +11951 -0
  57. package/docs/upstream-lock.json +26 -0
  58. package/knowledge/engineering-practices.json +536 -0
  59. package/package.json +30 -4
  60. package/packaging/uv-release-lock.json +54 -0
  61. package/public/licenses/aws-architect-LICENSE.txt +17 -0
  62. package/public/licenses/aws-mcp-LICENSE.txt +175 -0
  63. package/public/licenses/aws-mcp-NOTICE.txt +1 -0
  64. package/public/licenses/cloud-emulation-notices.txt +36619 -0
  65. package/public/licenses/dependency-notices.txt +6379 -0
  66. package/public/licenses/emulation-notices.txt +717 -0
  67. package/public/licenses/github-copilot-sdk-LICENSE.txt +21 -0
  68. package/public/licenses/memory-dependency-notices.txt +3319 -0
  69. package/public/licenses/openarchflow-LICENSE.txt +21 -0
  70. package/public/licenses/python-dependency-notices.txt +11951 -0
  71. package/scripts/terraform-render.mjs +8 -0
  72. package/server/__init__.py +0 -0
  73. package/server/abstraction.py +28 -0
  74. package/server/agent_runtime.py +153 -0
  75. package/server/app.py +257 -0
  76. package/server/architect.py +112 -0
  77. package/server/architecture_activity.py +67 -0
  78. package/server/attachments.py +101 -0
  79. package/server/cloud-emulation-requirements.txt +29 -0
  80. package/server/codex_app_server.py +219 -0
  81. package/server/codex_engineering_backend.py +266 -0
  82. package/server/codex_worker_policy.py +170 -0
  83. package/server/contracts.py +315 -0
  84. package/server/copilot_worker.py +16 -0
  85. package/server/dependency_mirror.py +54 -0
  86. package/server/design_patch.py +43 -0
  87. package/server/emulation-requirements.txt +8 -0
  88. package/server/emulation_adapters.py +20 -0
  89. package/server/emulation_routes.py +98 -0
  90. package/server/emulation_worker.py +351 -0
  91. package/server/engineering_artifacts.py +215 -0
  92. package/server/engineering_assets/application-runtime.json +4372 -0
  93. package/server/engineering_assets/architecture_work.schema.json +79 -0
  94. package/server/engineering_assets/materialize_runtime.py +62 -0
  95. package/server/engineering_assets/prepare_tools.py +96 -0
  96. package/server/engineering_assets/sql_validation.py +59 -0
  97. package/server/engineering_contexts.py +120 -0
  98. package/server/engineering_delivery.py +210 -0
  99. package/server/engineering_finalization.py +210 -0
  100. package/server/engineering_handoff.py +163 -0
  101. package/server/engineering_jobs.py +206 -0
  102. package/server/engineering_knowledge.py +75 -0
  103. package/server/engineering_reconciliation.py +159 -0
  104. package/server/engineering_routes.py +469 -0
  105. package/server/engineering_sessions.py +273 -0
  106. package/server/engineering_tools.py +166 -0
  107. package/server/generation_lint.py +18 -0
  108. package/server/local_providers.py +181 -0
  109. package/server/local_validation.py +236 -0
  110. package/server/memory-requirements.lock +181 -0
  111. package/server/memory-requirements.txt +6 -0
  112. package/server/memory_routes.py +82 -0
  113. package/server/memory_service.py +273 -0
  114. package/server/memory_worker.py +66 -0
  115. package/server/openai_voice.py +80 -0
  116. package/server/packaged_app.py +9 -0
  117. package/server/pricing.py +84 -0
  118. package/server/process_control_observation.py +31 -0
  119. package/server/prompts.py +123 -0
  120. package/server/public_faq_emulation_worker.py +44 -0
  121. package/server/requirements.lock +1618 -0
  122. package/server/requirements.txt +68 -0
  123. package/server/runtime_dependency_locks.py +27 -0
  124. package/server/runtime_evidence.py +93 -0
  125. package/server/settings.py +14 -0
  126. package/server/skills.py +103 -0
  127. package/server/storage_emulation_worker.py +160 -0
  128. package/server/structured_emulation_worker.py +48 -0
  129. package/server/terraform_routes.py +118 -0
  130. package/server/upstream/__init__.py +0 -0
  131. package/server/upstream/agent/__init__.py +1 -0
  132. package/server/upstream/agent/aws_architect.py +600 -0
  133. package/server/upstream/agent/config/__init__.py +1 -0
  134. package/server/upstream/agent/config/agent_config.py +82 -0
  135. package/server/upstream/agent/config/prompts.py +138 -0
  136. package/server/upstream/agent/rate_limiter.py +62 -0
  137. package/server/upstream/utils/__init__.py +1 -0
  138. package/server/upstream/utils/file_writer.py +43 -0
  139. package/server/validation_applicability.py +85 -0
  140. package/server/validation_jobs.py +252 -0
  141. package/server/validation_workers.py +48 -0
  142. package/server/voice_routes.py +91 -0
  143. package/server/voice_worker.py +26 -0
  144. package/specs/028-convergence-evaluation/evidence/20261110-ibm-invoice-native/registry-structured/qualification.json +72 -0
  145. package/specs/028-convergence-evaluation/evidence/20261110-invoice-runtime/durable-current/receipt.json +61 -0
  146. package/specs/029-general-purpose-engine/evidence/20261111-runtime-dependencies/sdk/receipt.json +22 -0
  147. package/src/ArchitectureActivity.jsx +54 -0
  148. package/src/ArchitectureWorkPanel.jsx +46 -0
  149. package/src/ArtifactChecks.jsx +49 -0
  150. package/src/BlockRequirements.jsx +13 -0
  151. package/src/BrainActivity.jsx +11 -0
  152. package/src/ChatMessage.jsx +19 -0
  153. package/src/ChatResizeHandle.jsx +6 -0
  154. package/src/CodePreview.jsx +8 -0
  155. package/src/ComponentReview.jsx +31 -0
  156. package/src/DeliveryViews.jsx +59 -0
  157. package/src/EmulationPanel.jsx +44 -0
  158. package/src/EngagementViews.jsx +385 -0
  159. package/src/EngineeringPanel.jsx +151 -0
  160. package/src/ImplementationDelivery.jsx +55 -0
  161. package/src/JourneyViews.jsx +400 -0
  162. package/src/MemoryPanel.jsx +46 -0
  163. package/src/OpenAIVoicePanel.jsx +65 -0
  164. package/src/OutputsView.jsx +65 -0
  165. package/src/TerraformView.jsx +57 -0
  166. package/src/WorkbenchDialogs.jsx +532 -0
  167. package/src/activity-presentation.mjs +28 -0
  168. package/src/ai-qualification-scenarios.mjs +31 -0
  169. package/src/approval-application-files.mjs +32 -0
  170. package/src/approval-applications.mjs +82 -0
  171. package/src/approval-spec-kit.mjs +30 -0
  172. package/src/architecture-activity.css +28 -0
  173. package/src/architecture-activity.mjs +63 -0
  174. package/src/architecture-work.mjs +176 -0
  175. package/src/artifact-work.mjs +103 -0
  176. package/src/async-documents.mjs +191 -0
  177. package/src/atflow.css +1140 -0
  178. package/src/atforma.css +748 -0
  179. package/src/atmem-tokens.css +79 -0
  180. package/src/aws-preflight.mjs +60 -0
  181. package/src/aws-public-faq.mjs +102 -0
  182. package/src/aws-validation-scenarios.mjs +10 -0
  183. package/src/aws-validation.mjs +48 -0
  184. package/src/azure-plan-mocks.mjs +25 -0
  185. package/src/azure-structured.mjs +133 -0
  186. package/src/bedrock-summary.mjs +152 -0
  187. package/src/bounded-rag.mjs +60 -0
  188. package/src/brand.css +9 -0
  189. package/src/canvas-view.mjs +28 -0
  190. package/src/capability-composition.mjs +44 -0
  191. package/src/chat-attachments.mjs +13 -0
  192. package/src/cloud-provider-locks.mjs +9 -0
  193. package/src/cloud-storage-scenarios.mjs +2 -0
  194. package/src/component-review.mjs +55 -0
  195. package/src/composition-spec-kit.mjs +30 -0
  196. package/src/consultation-context.mjs +15 -0
  197. package/src/consultation.mjs +52 -0
  198. package/src/container-contracts.mjs +5 -0
  199. package/src/container-inspection.mjs +75 -0
  200. package/src/container-runtime.mjs +30 -0
  201. package/src/container-security-inspection.mjs +49 -0
  202. package/src/container-terraform.mjs +109 -0
  203. package/src/conversation.mjs +17 -0
  204. package/src/core.mjs +863 -0
  205. package/src/cross-cloud-storage.mjs +100 -0
  206. package/src/delivery-capabilities.mjs +25 -0
  207. package/src/delivery.mjs +58 -0
  208. package/src/deployment-ownership.mjs +10 -0
  209. package/src/deployment-region.mjs +11 -0
  210. package/src/derive.mjs +31 -0
  211. package/src/design-build-flow.mjs +10 -0
  212. package/src/diagram-attention.mjs +24 -0
  213. package/src/discovery.mjs +359 -0
  214. package/src/document.mjs +170 -0
  215. package/src/emulation-feedback.mjs +61 -0
  216. package/src/emulation-guidance.mjs +37 -0
  217. package/src/engagement.mjs +274 -0
  218. package/src/engineering-client.mjs +73 -0
  219. package/src/engineering-defaults.mjs +17 -0
  220. package/src/engineering.css +31 -0
  221. package/src/enterprise-application.mjs +76 -0
  222. package/src/enterprise-aws-host-infrastructure.mjs +62 -0
  223. package/src/enterprise-aws-host-tests.mjs +15 -0
  224. package/src/enterprise-aws-infrastructure-tests.mjs +38 -0
  225. package/src/enterprise-aws-infrastructure.mjs +138 -0
  226. package/src/enterprise-google-infrastructure.mjs +84 -0
  227. package/src/enterprise-google-tests.mjs +25 -0
  228. package/src/estimate.mjs +188 -0
  229. package/src/existing-references.mjs +18 -0
  230. package/src/external-identities.mjs +17 -0
  231. package/src/faq-lambda-build.mjs +28 -0
  232. package/src/gcp-structured.mjs +104 -0
  233. package/src/generation-provider.mjs +7 -0
  234. package/src/generation-quality.mjs +69 -0
  235. package/src/handoff.mjs +141 -0
  236. package/src/ibm-registry.mjs +12 -0
  237. package/src/ibm-structured.mjs +103 -0
  238. package/src/identifiers.mjs +15 -0
  239. package/src/implementation-map.mjs +14 -0
  240. package/src/implementation-outcome.mjs +8 -0
  241. package/src/incomplete-terraform.mjs +9 -0
  242. package/src/integrations.ts +137 -0
  243. package/src/interface-contracts.mjs +30 -0
  244. package/src/invoice-application.mjs +66 -0
  245. package/src/invoice-aws-operations.mjs +136 -0
  246. package/src/invoice-aws.mjs +143 -0
  247. package/src/invoice-azure-operations.mjs +147 -0
  248. package/src/invoice-azure.mjs +134 -0
  249. package/src/invoice-builder.mjs +35 -0
  250. package/src/invoice-dependencies.mjs +43 -0
  251. package/src/invoice-gcp-operations.mjs +178 -0
  252. package/src/invoice-gcp.mjs +104 -0
  253. package/src/invoice-ibm-operations.mjs +278 -0
  254. package/src/invoice-ibm.mjs +142 -0
  255. package/src/invoice-operations.mjs +143 -0
  256. package/src/invoice-plan.mjs +45 -0
  257. package/src/invoice-region.mjs +6 -0
  258. package/src/invoice-spec-kit.mjs +61 -0
  259. package/src/invoice-state.mjs +7 -0
  260. package/src/invoice-terraform.mjs +29 -0
  261. package/src/invoice-tests.mjs +122 -0
  262. package/src/journey-workspace.css +72 -0
  263. package/src/journey.mjs +87 -0
  264. package/src/levels.mjs +145 -0
  265. package/src/local-agent.mjs +184 -0
  266. package/src/main.jsx +2458 -0
  267. package/src/model-policy-preflight.mjs +34 -0
  268. package/src/openai-voice.mjs +102 -0
  269. package/src/output-bundle.mjs +11 -0
  270. package/src/ownership-inspection.mjs +28 -0
  271. package/src/pack.mjs +201 -0
  272. package/src/pricing.mjs +31 -0
  273. package/src/production-state.mjs +8 -0
  274. package/src/project-copy.mjs +10 -0
  275. package/src/project-file.mjs +160 -0
  276. package/src/project-links.mjs +3 -0
  277. package/src/protected-state.mjs +43 -0
  278. package/src/public-faq-builder.mjs +19 -0
  279. package/src/public-faq-clouds.mjs +251 -0
  280. package/src/public-faq.mjs +122 -0
  281. package/src/pulumi.mjs +123 -0
  282. package/src/python-container.mjs +25 -0
  283. package/src/python-runtime.mjs +50 -0
  284. package/src/rag-handler.mjs +43 -0
  285. package/src/rag-web-assets.mjs +52 -0
  286. package/src/rag-web.mjs +68 -0
  287. package/src/records.mjs +177 -0
  288. package/src/resources.mjs +163 -0
  289. package/src/review.mjs +252 -0
  290. package/src/runtime/EnterpriseDocument.java +89 -0
  291. package/src/runtime/approved_http_destination.py +72 -0
  292. package/src/runtime/aws-lambda-qualification-lock.json +7 -0
  293. package/src/runtime/aws-python-lock.json +82 -0
  294. package/src/runtime/aws-web-python-lock.json +887 -0
  295. package/src/runtime/aws_json_model.py +42 -0
  296. package/src/runtime/azure-python-lock.json +863 -0
  297. package/src/runtime/azure-sources.json +8 -0
  298. package/src/runtime/azure-test-lock.json +23 -0
  299. package/src/runtime/azure_acceptance.py +192 -0
  300. package/src/runtime/azure_structured.py +153 -0
  301. package/src/runtime/bounded_rag.py +126 -0
  302. package/src/runtime/catalog_admin.py +70 -0
  303. package/src/runtime/cloud-sql-proxy-lock.json +8 -0
  304. package/src/runtime/cloud-sql-proxy-security-review.json +30 -0
  305. package/src/runtime/connector_cli.py +50 -0
  306. package/src/runtime/connector_sync.py +70 -0
  307. package/src/runtime/durable-python-lock.json +247 -0
  308. package/src/runtime/durable_workflow.py +325 -0
  309. package/src/runtime/enterprise-application-manifest.json +110 -0
  310. package/src/runtime/enterprise-application-sources.json +266 -0
  311. package/src/runtime/enterprise-auth-python-lock.json +592 -0
  312. package/src/runtime/enterprise-aws-host-bootstrap-source.json +1 -0
  313. package/src/runtime/enterprise-aws-host-probe-source.json +1 -0
  314. package/src/runtime/enterprise-aws-task-template.json +235 -0
  315. package/src/runtime/enterprise-document-lock.json +18 -0
  316. package/src/runtime/enterprise-document.Dockerfile +15 -0
  317. package/src/runtime/enterprise-runtime-aws-python-lock.json +1115 -0
  318. package/src/runtime/enterprise-runtime-azure-python-lock.json +1106 -0
  319. package/src/runtime/enterprise-runtime-gcp-python-lock.json +1060 -0
  320. package/src/runtime/enterprise-runtime-ibm-python-lock.json +1096 -0
  321. package/src/runtime/enterprise-runtime-python-lock.json +1058 -0
  322. package/src/runtime/enterprise-runtime.Dockerfile +15 -0
  323. package/src/runtime/enterprise-web-app.js +1 -0
  324. package/src/runtime/enterprise-web-entry.js +105 -0
  325. package/src/runtime/enterprise-web-lock.json +29 -0
  326. package/src/runtime/enterprise-web-notices.txt +229 -0
  327. package/src/runtime/enterprise-web.css +4 -0
  328. package/src/runtime/enterprise-web.html +8 -0
  329. package/src/runtime/enterprise_audit.py +91 -0
  330. package/src/runtime/enterprise_audit_schema.sql +25 -0
  331. package/src/runtime/enterprise_auth_schema.sql +67 -0
  332. package/src/runtime/enterprise_auth_store.py +241 -0
  333. package/src/runtime/enterprise_aws_host_bootstrap.py +120 -0
  334. package/src/runtime/enterprise_aws_host_probe.py +105 -0
  335. package/src/runtime/enterprise_aws_hosts.py +136 -0
  336. package/src/runtime/enterprise_aws_jobs.py +300 -0
  337. package/src/runtime/enterprise_aws_objects.py +93 -0
  338. package/src/runtime/enterprise_aws_transfer.py +83 -0
  339. package/src/runtime/enterprise_azure_batch_api.py +128 -0
  340. package/src/runtime/enterprise_azure_host.py +599 -0
  341. package/src/runtime/enterprise_azure_jobs.py +294 -0
  342. package/src/runtime/enterprise_azure_objects.py +234 -0
  343. package/src/runtime/enterprise_azure_pool.py +161 -0
  344. package/src/runtime/enterprise_azure_transfer.py +122 -0
  345. package/src/runtime/enterprise_configuration.py +136 -0
  346. package/src/runtime/enterprise_document.py +116 -0
  347. package/src/runtime/enterprise_document_cli.py +32 -0
  348. package/src/runtime/enterprise_document_contract.py +54 -0
  349. package/src/runtime/enterprise_document_job.py +109 -0
  350. package/src/runtime/enterprise_document_jobs.py +122 -0
  351. package/src/runtime/enterprise_document_jobs_schema.sql +23 -0
  352. package/src/runtime/enterprise_extraction_cache.py +186 -0
  353. package/src/runtime/enterprise_extraction_schema.sql +17 -0
  354. package/src/runtime/enterprise_google_jobs.py +275 -0
  355. package/src/runtime/enterprise_google_transfer.py +85 -0
  356. package/src/runtime/enterprise_http.py +212 -0
  357. package/src/runtime/enterprise_identity.py +52 -0
  358. package/src/runtime/enterprise_knowledge.py +152 -0
  359. package/src/runtime/enterprise_models.py +94 -0
  360. package/src/runtime/enterprise_native.py +181 -0
  361. package/src/runtime/enterprise_oauth.py +132 -0
  362. package/src/runtime/enterprise_operator.py +160 -0
  363. package/src/runtime/enterprise_parser_service.py +136 -0
  364. package/src/runtime/enterprise_parser_transport.py +68 -0
  365. package/src/runtime/enterprise_queries.py +255 -0
  366. package/src/runtime/enterprise_queries_schema.sql +27 -0
  367. package/src/runtime/enterprise_query_service.py +111 -0
  368. package/src/runtime/enterprise_secrets.py +110 -0
  369. package/src/runtime/enterprise_sessions.py +95 -0
  370. package/src/runtime/enterprise_sources.py +260 -0
  371. package/src/runtime/enterprise_web.py +39 -0
  372. package/src/runtime/enterprise_worker.py +68 -0
  373. package/src/runtime/export_contract_acceptance.py +18 -0
  374. package/src/runtime/faq-output-contract.json +40 -0
  375. package/src/runtime/faq-web-app.js +41 -0
  376. package/src/runtime/faq-web.css +1 -0
  377. package/src/runtime/faq-web.html +6 -0
  378. package/src/runtime/gcp-sources.json +9 -0
  379. package/src/runtime/gcp_acceptance.py +110 -0
  380. package/src/runtime/gcp_structured.py +150 -0
  381. package/src/runtime/http_acceptance.py +39 -0
  382. package/src/runtime/iap-web-app.js +36 -0
  383. package/src/runtime/iap-web-source.json +1 -0
  384. package/src/runtime/ibm-python-lock.json +856 -0
  385. package/src/runtime/ibm-sources.json +9 -0
  386. package/src/runtime/ibm_acceptance.py +133 -0
  387. package/src/runtime/ibm_structured.py +113 -0
  388. package/src/runtime/invoice-azapi-provider-lock.json +7 -0
  389. package/src/runtime/invoice-ibm-provider-lock.json +7 -0
  390. package/src/runtime/invoice-parser-lock.json +1199 -0
  391. package/src/runtime/invoice-parser-python-lock.json +56 -0
  392. package/src/runtime/invoice-parser.Dockerfile +190 -0
  393. package/src/runtime/invoice-sources.json +58 -0
  394. package/src/runtime/invoice-test-sources.json +24 -0
  395. package/src/runtime/invoice-web.css +2 -0
  396. package/src/runtime/invoice-web.html +12 -0
  397. package/src/runtime/invoice-web.js +112 -0
  398. package/src/runtime/invoice_configuration.py +17 -0
  399. package/src/runtime/invoice_document.py +95 -0
  400. package/src/runtime/invoice_extraction.py +96 -0
  401. package/src/runtime/invoice_http.py +129 -0
  402. package/src/runtime/invoice_identity.py +5 -0
  403. package/src/runtime/invoice_maintenance.py +40 -0
  404. package/src/runtime/invoice_native.py +77 -0
  405. package/src/runtime/invoice_object_store.py +153 -0
  406. package/src/runtime/invoice_operations.py +108 -0
  407. package/src/runtime/invoice_operator.py +79 -0
  408. package/src/runtime/invoice_operator_core.py +39 -0
  409. package/src/runtime/invoice_operator_job.py +147 -0
  410. package/src/runtime/invoice_parser_cli.py +17 -0
  411. package/src/runtime/invoice_parser_identity.py +39 -0
  412. package/src/runtime/invoice_parser_service.py +89 -0
  413. package/src/runtime/invoice_parser_transport.py +89 -0
  414. package/src/runtime/invoice_processing.py +24 -0
  415. package/src/runtime/invoice_retention.py +16 -0
  416. package/src/runtime/invoice_runtime_secrets.py +43 -0
  417. package/src/runtime/invoice_stage.py +80 -0
  418. package/src/runtime/invoice_web.py +39 -0
  419. package/src/runtime/invoice_worker.py +50 -0
  420. package/src/runtime/lambda_faq.py +5 -0
  421. package/src/runtime/parser-requirements.lock +4 -0
  422. package/src/runtime/policy_review.py +18 -0
  423. package/src/runtime/postgres-qualification-lock.json +21 -0
  424. package/src/runtime/public-faq-sources.json +22 -0
  425. package/src/runtime/public_catalog_admin.py +122 -0
  426. package/src/runtime/public_catalog_store.py +125 -0
  427. package/src/runtime/public_faq.py +144 -0
  428. package/src/runtime/public_faq_app.py +49 -0
  429. package/src/runtime/python-container-lock.json +18 -0
  430. package/src/runtime/rag-sources.json +10 -0
  431. package/src/runtime/rag_acceptance.py +60 -0
  432. package/src/runtime/rag_aws_adapter.py +95 -0
  433. package/src/runtime/rds-ca-source.json +9 -0
  434. package/src/runtime/rds-global-ca.pem +2888 -0
  435. package/src/runtime/state-contract-check-source.json +4 -0
  436. package/src/runtime/state_contract_check.py +338 -0
  437. package/src/runtime/structured-source.json +1 -0
  438. package/src/runtime/structured-web-app.js +71 -0
  439. package/src/runtime/structured-web-source.json +1 -0
  440. package/src/runtime/structured_http.py +105 -0
  441. package/src/runtime/structured_output.py +48 -0
  442. package/src/runtime/web-python-lock.json +802 -0
  443. package/src/runtime/web_user_admin.py +44 -0
  444. package/src/runtime/workflow_application.py +62 -0
  445. package/src/runtime/workflow_bindings.py +128 -0
  446. package/src/runtime/workflow_configuration.py +40 -0
  447. package/src/runtime/workflow_connection.py +105 -0
  448. package/src/runtime/workflow_contract.py +54 -0
  449. package/src/runtime/workflow_database.py +94 -0
  450. package/src/runtime/workflow_errors.py +6 -0
  451. package/src/runtime/workflow_http.py +178 -0
  452. package/src/runtime/workflow_identity.py +69 -0
  453. package/src/runtime/workflow_payload.py +118 -0
  454. package/src/runtime/workflow_process_stage.py +88 -0
  455. package/src/runtime/workflow_profile.py +91 -0
  456. package/src/runtime/workflow_review.py +106 -0
  457. package/src/runtime/workflow_role_bootstrap.py +104 -0
  458. package/src/runtime/workflow_schema.sql +72 -0
  459. package/src/runtime/workflow_worker.py +142 -0
  460. package/src/runtime-settings.mjs +15 -0
  461. package/src/s3-access.mjs +14 -0
  462. package/src/source-contracts.mjs +17 -0
  463. package/src/spec-kit.mjs +186 -0
  464. package/src/state-custody.mjs +32 -0
  465. package/src/state-inspection.mjs +45 -0
  466. package/src/state-spec-kit.mjs +13 -0
  467. package/src/storage-tests.mjs +25 -0
  468. package/src/structured-api.mjs +133 -0
  469. package/src/structured-contract.mjs +19 -0
  470. package/src/structured-operation-policy.mjs +2 -0
  471. package/src/structured-web.mjs +17 -0
  472. package/src/style.css +1 -0
  473. package/src/system-description.mjs +26 -0
  474. package/src/terraform-admission.mjs +66 -0
  475. package/src/terraform-composition.mjs +83 -0
  476. package/src/terraform-expressions.mjs +46 -0
  477. package/src/terraform-validation-coverage.mjs +11 -0
  478. package/src/terraform.mjs +128 -0
  479. package/src/text-statistics.mjs +51 -0
  480. package/src/upstream/openarchflow/format-payload.ts +26 -0
  481. package/src/upstream/openarchflow/import/mermaid.ts +205 -0
  482. package/src/upstream/openarchflow/import/sql-ddl.ts +109 -0
  483. package/src/upstream/openarchflow/layout.ts +54 -0
  484. package/src/upstream/openarchflow/providers/aws.ts +196 -0
  485. package/src/upstream/openarchflow/providers/azure.ts +126 -0
  486. package/src/upstream/openarchflow/providers/cloudnative.ts +71 -0
  487. package/src/upstream/openarchflow/providers/generic.ts +227 -0
  488. package/src/upstream/openarchflow/providers/integration.ts +22 -0
  489. package/src/upstream/openarchflow/providers/types.ts +2 -0
  490. package/src/upstream/openarchflow/templates.ts +937 -0
  491. package/src/upstream-catalog.mjs +10 -0
  492. package/src/useChatScroll.jsx +36 -0
  493. package/src/useEmulation.jsx +36 -0
  494. package/src/validation-receipt.mjs +10 -0
  495. package/src/visual-export.mjs +92 -0
  496. package/src/voice-conversation.mjs +117 -0
  497. package/src/work-intake.mjs +24 -0
  498. package/src/workflow-runtime-inventory.mjs +3 -0
@@ -0,0 +1,151 @@
1
+ import {ArchitectureWorkPanel} from './ArchitectureWorkPanel.jsx';
2
+ import React,{useEffect,useRef,useState} from 'react';
3
+ import {engineeringCall,engineeringConversation,mergeEngineeringEvents} from './engineering-client.mjs';
4
+ import './engineering.css';
5
+ import {ArtifactChecks} from './ArtifactChecks.jsx';
6
+ import {verifyArtifactWork} from './artifact-work.mjs';
7
+ import {hasArchitectureDesign,buildIntent,BUILD_AND_TEST_REQUEST} from './design-build-flow.mjs';
8
+
9
+ export function EngineeringPanel({projectId,session,connection,saveProject,onConnections,project,onWorkModelChange,onIntentContext,onDesign,onDelivery,buildRequest,onBuildRequestHandled,contextBusy=false}){
10
+ const draftKey=`atmem-engineering-draft-v1:${projectId}`;
11
+ const [job,setJob]=useState(null),[events,setEvents]=useState([]),[draft,setDraft]=useState(()=>{try{return localStorage.getItem(draftKey)||'';}catch{return '';}}),
12
+ [busy,setBusy]=useState(false),[error,setError]=useState(''),[loading,setLoading]=useState(true),[artifact,setArtifact]=useState(null);
13
+ const [draftError,setDraftError]=useState('');
14
+ const [restoreBlocked,setRestoreBlocked]=useState(false),[restoreAttempt,setRestoreAttempt]=useState(0);
15
+ useEffect(()=>{try{localStorage.setItem(draftKey,draft);setDraftError('');}catch{setDraftError('This draft could not be saved in your browser. Keep this view open or copy it before leaving.');}},[draftKey,draft]);
16
+ const live=useRef(true),cursor=useRef(0),actionLock=useRef(false);
17
+ const finalization=events.filter(event=>event.runId===job?.run&&event.kind.startsWith('finalization_')).at(-1);
18
+ useEffect(()=>{live.current=true;return()=>{live.current=false;};},[]);
19
+ const call=(action,payload={},options)=>engineeringCall(session,action,{projectId,...(job?{sessionId:job.id}:{}),...payload},options);
20
+ useEffect(()=>{
21
+ if(!job)return;
22
+ const controller=new AbortController();let stopped=false;
23
+ engineeringCall(session,'artifacts',{projectId,sessionId:job.id},{signal:controller.signal}).then(result=>{
24
+ if(!stopped)setArtifact(result.artifacts.find(item=>item.runId===job.run)||result.artifacts[0]||null);
25
+ }).catch(e=>{if(!stopped&&e.name!=='AbortError')setError(e.message);});
26
+ return()=>{stopped=true;controller.abort();};
27
+ },[job?.id,job?.run,finalization?.artifactId,projectId,session.token]);
28
+ useEffect(()=>{
29
+ const controller=new AbortController();let stopped=false;
30
+ setLoading(true);setRestoreBlocked(false);
31
+ (async()=>{let restored=false;try{
32
+ const result=await engineeringCall(session,'list',{projectId},{signal:controller.signal});
33
+ const previous=result.sessions.at(-1);
34
+ if(previous){
35
+ restored=true;
36
+ if(!stopped)setJob(previous);
37
+ const recovered=await engineeringCall(session,'recover',{projectId,sessionId:previous.id},{signal:controller.signal});
38
+ if(!stopped)setJob(recovered);
39
+ }
40
+ }catch(e){if(!stopped&&e.name!=='AbortError'&&(e.status!==404||restored)){setError(e.message);setRestoreBlocked(true);}}finally{if(!stopped)setLoading(false);}})();
41
+ return()=>{stopped=true;controller.abort();};
42
+ },[projectId,session.token,restoreAttempt]);
43
+ useEffect(()=>{
44
+ if(!job)return;
45
+ const controller=new AbortController();let stopped=false,timer;
46
+ async function poll(){try{
47
+ const result=await engineeringCall(session,'events',{projectId,sessionId:job.id,after:cursor.current},{signal:controller.signal});
48
+ if(stopped)return;
49
+ setEvents(current=>mergeEngineeringEvents(current,result.events));
50
+ if(result.events.length)cursor.current=result.events.at(-1).sequence;
51
+ setJob(result.session);
52
+ }catch(e){if(!stopped&&e.name!=='AbortError')setError(e.message);}finally{if(!stopped)timer=setTimeout(poll,1000);}}
53
+ void poll();return()=>{stopped=true;clearTimeout(timer);controller.abort();};
54
+ },[job?.id,projectId,session.token]);
55
+ useEffect(()=>{if(job&&onIntentContext){try{onIntentContext(projectId,job.id,events);}catch(e){setError(e.message);}}},[job?.id,events,onIntentContext]);
56
+ async function act(operation){
57
+ if(actionLock.current)return;
58
+ actionLock.current=true;setBusy(true);setError('');
59
+ try{await operation();}catch(e){if(live.current)setError(e.message);}finally{actionLock.current=false;if(live.current)setBusy(false);}
60
+ }
61
+ const exactSelection=connection?.provider==='codex'&&connection.model&&connection.model!=='default'&&connection.effort;
62
+ const running=job?.state==='running',uncertain=job?.state==='starting';
63
+ const conversation=engineeringConversation(events);
64
+ const hasDesign=hasArchitectureDesign(project),canSubmit=running?!!draft.trim():!!buildIntent(project,draft);
65
+ const consumedBuild=useRef(null);
66
+ function submitIntent(event,requestedText){
67
+ event?.preventDefault();
68
+ const submitted=requestedText??(running?draft:buildIntent(project,draft));
69
+ if(!submitted||submitted.length>80000||loading||restoreBlocked||actionLock.current||uncertain||contextBusy||(!job&&(!exactSelection||!hasDesign)))return false;
70
+ void act(async()=>{
71
+ let current=job;
72
+ let saved=await saveProject();
73
+ if(!/^[a-f0-9]{64}$/.test(saved?.sha256||''))throw Error('The server did not confirm the saved design context. Your draft is retained.');
74
+ if(!current){
75
+ current=await call('create',{model:connection.model,effort:connection.effort});
76
+ if(live.current)setJob(current);
77
+ // Native session creation can outlast pending autosaves. Confirm the
78
+ // context immediately before submitting, without replaying any intent.
79
+ saved=await saveProject();
80
+ if(!/^[a-f0-9]{64}$/.test(saved?.sha256||''))throw Error('The server did not confirm the saved design context. Your draft is retained.');
81
+ }
82
+ // The new session ID is explicit: React state may not have rendered yet.
83
+ const next=await call(current.state==='running'?'steer':'start',{sessionId:current.id,text:submitted,contextSha256:saved.sha256});
84
+ if(live.current){setJob(next);setArtifact(null);setDraft(value=>value===submitted?'':value);}
85
+ });
86
+ return true;
87
+ }
88
+ useEffect(()=>{
89
+ if(!buildRequest||buildRequest.projectId!==projectId||consumedBuild.current===buildRequest.id||loading||restoreBlocked||contextBusy||uncertain||busy||(!job&&!exactSelection))return;
90
+ if(submitIntent(null,buildRequest.intent==='test'?BUILD_AND_TEST_REQUEST:buildIntent(project,''))){
91
+ consumedBuild.current=buildRequest.id;onBuildRequestHandled?.(buildRequest.id);
92
+ }
93
+ },[buildRequest,projectId,loading,restoreBlocked,contextBusy,uncertain,busy,exactSelection,job?.id]);
94
+ async function linkMappings(){
95
+ const result=await call('reconciliation',{artifactId:artifact.id});
96
+ if(result.status==='proposal_missing')throw Error(result.message);
97
+ const verified=await verifyArtifactWork(result);
98
+ if(verified.payload.artifactId!==artifact.id||verified.payload.artifactSha256!==artifact.sha256||verified.payload.sessionId!==job.id)throw Error('The mapping receipt does not match this captured package.');
99
+ onWorkModelChange({kind:'artifact',verified},projectId);
100
+ }
101
+ return <div className="engineering-panel">
102
+ <h2>Generate and verify</h2>
103
+ <p>Generate the agreed design and run applicable local checks here. Review results and corrections before opening Delivery.</p>
104
+ {onDesign&&<button onClick={onDesign}>Return to Design</button>}
105
+
106
+ {buildRequest?.projectId===projectId&&<p role="status">{restoreBlocked?'Your implementation request is waiting. Retry loading earlier work before starting.':uncertain?'Your implementation request is waiting. Recover the existing request first to avoid duplicate work.':contextBusy?'Your implementation request is waiting for the current design changes.':!job&&!exactSelection?'Your implementation request is waiting here. Choose a model and reasoning level below; it will then start automatically.':'Your implementation request is queued.'} <button onClick={()=>onBuildRequestHandled?.(buildRequest.id)}>Cancel queued request</button></p>}
107
+ {restoreBlocked&&<button disabled={loading||busy} onClick={()=>{setError('');setRestoreAttempt(value=>value+1);}}>Retry loading earlier work</button>}
108
+ {loading?<p role="status">Finding your project’s work…</p>:<>
109
+ {job?<>
110
+ <p role="status">{running?'Working':uncertain?'Recovering acceptance of your last request':job.last_status?({completed:'Work completed',interrupted:'Work stopped',failed:'Work needs attention'}[job.last_status]||job.last_status):'Ready'} · {job.model} · {job.effort}</p>
111
+ <p className="muted">Each request includes your saved design. Earlier versions remain in the work history.</p>
112
+ </>:<>
113
+ <p>{exactSelection?`${connection.model} · ${connection.effort}`:'Choose a Codex model and reasoning level to start.'}</p>
114
+ {!exactSelection&&<button onClick={onConnections}>Choose model</button>}
115
+ {contextBusy&&<p role="status">Finish the current design changes before starting new work.</p>}
116
+ </>}
117
+ {conversation.length>0&&<section className="engineering-conversation" role="log" aria-label="Project conversation" aria-live="polite">{conversation.map(entry=><article key={entry.id} className={`engineering-entry ${entry.role}`}>
118
+ <strong>{entry.role==='user'?'You':'Architect'}</strong>
119
+ {entry.status==='pending'&&<span> · Sending update</span>}
120
+ {entry.status==='uncertain'&&<span> · Delivery uncertain; recover before resending</span>}
121
+ <pre>{entry.text}</pre>
122
+ </article>)}</section>}
123
+ {!hasDesign&&!job?<p>Start with the Board or Requirements. Add the components or responsibilities before building an implementation.</p>:<form onSubmit={submitIntent}>
124
+ <label htmlFor="engineering-intent">{running?'Add an implementation update':hasDesign?'Additional instructions (optional)':'Continue implementation'}</label>
125
+ <textarea id="engineering-intent" rows={4} value={draft} onChange={e=>setDraft(e.target.value)}/>
126
+ {draft.length>80000&&<p role="alert">This update exceeds 80,000 characters. Edit it before sending; your draft is retained.</p>}
127
+ <button disabled={busy||restoreBlocked||uncertain||contextBusy||!canSubmit||draft.length>80000||(!job&&!exactSelection)}>{running?'Send update':hasDesign?'Generate and verify':'Continue implementation'}</button>
128
+ </form>}
129
+ {job&&<>
130
+ {finalization&&<p role="status"><strong>Recorded verification update: </strong>{finalization.text}</p>}
131
+ <div className="engineering-actions">
132
+ <button disabled={busy} onClick={()=>act(async()=>{const next=await call('recover');if(live.current)setJob(next);})}>Refresh connection status</button>
133
+ {running&&<button disabled={busy} onClick={()=>act(async()=>{const next=await call('interrupt');if(live.current)setJob(next);})}>Stop work</button>}
134
+ {!running&&!uncertain&&job.last_status&&<button disabled={busy} onClick={()=>act(async()=>{const captured=await call('capture');if(live.current)setArtifact(captured);})}>Refresh package snapshot</button>}
135
+ </div>
136
+ <details><summary>Engineering progress ({events.length})</summary><ol>{events.filter(event=>!['message','accepted','steering_submitted'].includes(event.kind)).map(event=><li key={event.sequence}>{event.kind}{event.text?` · ${event.text}`:''}</li>)}</ol></details>
137
+ </>}
138
+ {artifact&&<div className="engineering-artifact"><p>Implementation draft · {artifact.files.filter(file=>file.kind==='file').length} {artifact.files.filter(file=>file.kind==='file').length===1?'file':'files'} · work {artifact.turnStatus}. Capture does not establish full project acceptance.</p>
139
+ {artifact.runId!==job?.run&&<p>This package is from an earlier turn. It does not cover the current work.</p>}
140
+ {onDelivery&&<button disabled={busy} onClick={onDelivery}>Review and download handoff</button>}
141
+
142
+ {!running&&!uncertain&&job?.last_status==='completed'&&artifact.runId===job.run&&<button disabled={busy} onClick={()=>act(async()=>{await call('recheck',{runId:job.run,artifactId:artifact.id});const next=await call('state');if(live.current)setJob(next);})}>Recheck and repair</button>}
143
+ {onWorkModelChange&&!running&&!uncertain&&job?.last_status==='completed'&&artifact.runId===job.run&&<button disabled={busy||contextBusy} onClick={()=>act(linkMappings)}>Link proposed mappings</button>}
144
+ <ArtifactChecks key={artifact.id} session={session} projectId={projectId} sessionId={job.id} artifact={artifact}/>
145
+ </div>}
146
+ </>}
147
+ {(hasDesign||job)&&<ArchitectureWorkPanel project={project} onChange={onWorkModelChange} busy={busy||contextBusy}/>}
148
+ {error&&<p role="alert">{error}</p>}
149
+ {draftError&&<p role="alert">{draftError}</p>}
150
+ </div>;
151
+ }
@@ -0,0 +1,55 @@
1
+ import React,{useEffect,useState} from 'react';
2
+ import {engineeringCall,verifiedHandoffDownload} from './engineering-client.mjs';
3
+ import {ArtifactChecks} from './ArtifactChecks.jsx';
4
+
5
+ export function ImplementationDelivery({project,session,onBuild,onSave,contextBusy=false}){
6
+ const [loaded,setLoaded]=useState(null),[error,setError]=useState(''),[retry,setRetry]=useState(0),[busy,setBusy]=useState(false);
7
+ const report=loaded?.project===project?loaded.report:null;
8
+ useEffect(()=>{
9
+ const controller=new AbortController();setError('');setLoaded(null);
10
+ engineeringCall(session,'delivery',{projectId:project.id},{signal:controller.signal}).then(value=>{
11
+ if(!controller.signal.aborted)setLoaded({project,report:value});
12
+ }).catch(e=>{if(!controller.signal.aborted){if(e.status===404&&e.message.startsWith('Save or restore this project'))setLoaded({project,report:{artifact:null}});else setError(e.message);}});
13
+ return()=>controller.abort();
14
+ },[project,session.token,retry]);
15
+ async function download(){
16
+ if(!report?.artifact||busy||contextBusy)return;
17
+ setBusy(true);setError('');
18
+ try{
19
+ let current=report;
20
+ if(onSave){
21
+ const saved=await onSave(project);
22
+ if(!/^[a-f0-9]{64}$/.test(saved?.sha256||''))throw Error('The current design save was not confirmed. Nothing was downloaded.');
23
+ current=await engineeringCall(session,'delivery',{projectId:project.id});
24
+ setLoaded({project,report:current});
25
+ if(current.savedFileSha256!==saved.sha256)
26
+ throw Error('The saved design changed after confirmation. Review the refreshed Delivery information before downloading.');
27
+ const confirmedSameDesign=current.relation==='matches_saved_design'&&current.savedFileSha256===saved.sha256;
28
+ if(current.artifact?.id!==report.artifact.id||current.session?.id!==report.session.id||(current.savedDesignSha256!==report.savedDesignSha256&&!confirmedSameDesign))
29
+ throw Error('The saved design or package changed. Review the refreshed Delivery information before downloading.');
30
+ }
31
+ const payload={projectId:project.id,sessionId:current.session.id,artifactId:current.artifact.id};
32
+ const blob=await verifiedHandoffDownload(session,{...payload,savedDesignSha256:current.savedDesignSha256},current.artifact);
33
+ const url=URL.createObjectURL(blob),link=document.createElement('a');link.href=url;
34
+ link.download=`architect-handoff-${report.artifact.id}.zip`;link.click();setTimeout(()=>URL.revokeObjectURL(url),1000);
35
+ }catch(e){setError(e.message)}finally{setBusy(false)}
36
+ }
37
+ return <section aria-label="Implementation delivery">
38
+ <h3>Project package</h3>
39
+ {!report&&!error&&<p role="status">Finding the captured implementation and its checks…</p>}
40
+ {report&&!report.artifact&&<><p>No implementation package has been captured for this project yet. Next: open Review to generate the project and inspect its checks. Return here for the final package.</p>{onBuild&&<button className="btn primary" disabled={contextBusy} onClick={onBuild}>Go to Review</button>}</>}
41
+ {report?.artifact&&<>
42
+ <p>{report.relation==='matches_saved_design'?'This package used the latest saved design.':report.relation==='design_changed'?'The saved design has changed since this implementation. New or changed requirements need implementation and checks.':report.relation==='earlier_turn'?'This is an earlier package. A later implementation turn has not produced a completed package yet.':'The submitted design receipt is unavailable. Its relationship to the current design is unknown.'} Capture and local checks do not establish full project acceptance.</p>
43
+ <p>{report.artifact.files.filter(file=>file.kind==='file').length} files · {report.artifact.model} · {report.artifact.effort}</p>
44
+ {report.canPackage&&<button className="btn primary" disabled={busy||contextBusy} onClick={()=>download()}>Download project package (ZIP)</button>}
45
+ {report.relation!=='matches_saved_design'&&onBuild&&<button className="btn" disabled={busy||contextBusy} onClick={onBuild}>Review latest design</button>}
46
+ <p>The handoff includes the captured files, their original ZIP, submitted and latest saved requirements/design, and recorded local checks. Missing implementation or Spec Kit content remains work to complete.</p>
47
+ <ArtifactChecks key={report.artifact.id} session={session} projectId={project.id} sessionId={report.session.id} artifact={report.artifact} readOnly/>
48
+ <details><summary>Package files and source receipt</summary><p>Artifact SHA-256: {report.artifact.sha256}</p><ul>{report.artifact.files.filter(file=>file.kind==='file').map(file=><li key={file.path}>{file.path}</li>)}</ul></details>
49
+ </>}
50
+ {busy&&<p role="status">Preparing and verifying your handoff download…</p>}
51
+ {contextBusy&&<p role="status">Finish the current design changes before downloading a combined handoff.</p>}
52
+ {error&&<p role="alert">{error}</p>}
53
+ <button className="link" disabled={busy} onClick={()=>setRetry(value=>value+1)}>Refresh delivery</button>
54
+ </section>;
55
+ }
@@ -0,0 +1,400 @@
1
+ // Review, Estimate and Deploy steps of the AtMem AI Architect journey.
2
+ import React from "react";
3
+ import { ATTRIBUTES, acceptRisk, blockers } from "./review.mjs";
4
+ import { DISCLAIMER, INPUTS, PROJECT_SIZES, setProjectSize, setPrice, setUsage } from "./estimate.mjs";
5
+ import { deploymentSteps } from "./document.mjs";
6
+ import { GATE } from "./engagement.mjs";
7
+ import { DetailedCharges, ConsultingView, ResourcesView } from "./DeliveryViews.jsx";
8
+ import { resourcePlan } from "./resources.mjs";
9
+
10
+ const money = (v, c) => (v == null ? "—" : `${c || ""} ${v.toLocaleString("en", { maximumFractionDigits: 2 })}`.trim());
11
+
12
+ function Accept({ onAccept }) {
13
+ const [open, setOpen] = React.useState(false),
14
+ [reason, setReason] = React.useState(""),
15
+ [owner, setOwner] = React.useState("");
16
+ if (!open)
17
+ return (
18
+ <button className="link small" onClick={() => setOpen(true)}>
19
+ Accept risk
20
+ </button>
21
+ );
22
+ return (
23
+ <div className="revise">
24
+ <input aria-label="Why accept" placeholder="Why is this acceptable?" value={reason} onChange={(e) => setReason(e.target.value)} />
25
+ <input aria-label="Risk owner" placeholder="Owner" value={owner} onChange={(e) => setOwner(e.target.value)} />
26
+ <button className="btn" disabled={!reason.trim() || !owner.trim()} onClick={() => onAccept(reason, owner)}>
27
+ Accept
28
+ </button>
29
+ </div>
30
+ );
31
+ }
32
+
33
+ export function ReviewView({ project, findings, onChange, onOpen, onAddRequirement }) {
34
+ const names = Object.fromEntries(project.nodes.map((n) => [n.id, n.data.label]));
35
+ const block = blockers(findings);
36
+ const open = findings.filter((f) => f.status === "open");
37
+ return (
38
+ <section className="doc" aria-label="Review">
39
+ <header className="doc-head">
40
+ <h2>Review</h2>
41
+ <p className="muted">
42
+ {block.length
43
+ ? `${block.length} blocker${block.length > 1 ? "s" : ""} to fix before deployment.`
44
+ : open.length
45
+ ? `No blockers. ${open.length} thing${open.length > 1 ? "s" : ""} worth a look.`
46
+ : "Nothing open. Rules run on every change."}
47
+ </p>
48
+ </header>
49
+ <details className="extra"><summary>Agreed choices and consequences</summary>{(project.decisions||[]).filter(d=>d.status==='Accepted').map(d=><article key={d.id||d.subject}><strong>{d.title||d.subject}</strong><p>{d.decision}</p>{d.context&&<p>{d.context}</p>}{d.consequences&&<p>{d.consequences}</p>}</article>)}</details>
50
+ {ATTRIBUTES.map(([id, label]) => {
51
+ const fs = findings.filter((f) => f.attribute === id);
52
+ if (!fs.length) return null;
53
+ return (
54
+ <div key={id} className="finding-group">
55
+ <h3>{label}</h3>
56
+ {fs.map((f) => (
57
+ <article key={f.key} className={`finding sev-${f.severity} ${f.status}`}>
58
+ <div className="finding-head">
59
+ <span className={`sev ${f.severity}`}>{f.severity}</span>
60
+ <strong>{f.statement}</strong>
61
+ </div>
62
+ <p className="muted">{f.rationale}</p>
63
+ <p>{f.action}</p>
64
+ <div className="finding-foot">
65
+ {f.components.map((c) => (
66
+ <button key={c} className="chip" onClick={() => onOpen(c)}>
67
+ {names[c] || c}
68
+ </button>
69
+ ))}
70
+ <span className="muted small">{f.source}</span>
71
+ {["AVL-001", "PRF-001"].includes(f.rule) && f.status === "open" && (
72
+ <button className="link small" onClick={() => onAddRequirement(f.rule === "AVL-001" ? "availability" : "performance")}>
73
+ Add target
74
+ </button>
75
+ )}
76
+ {f.status === "accepted" ? (
77
+ <span className="small">
78
+ Accepted by {f.acceptance.owner}: {f.acceptance.reason}
79
+ </span>
80
+ ) : (
81
+ <Accept onAccept={(reason, owner) => onChange(acceptRisk(project, f, reason, owner))} />
82
+ )}
83
+ </div>
84
+ </article>
85
+ ))}
86
+ </div>
87
+ );
88
+ })}
89
+ </section>
90
+ );
91
+ }
92
+
93
+ export function EstimateView({ project, result, onChange, onEstimate, busy=false }) {
94
+ const e = result;
95
+ return (
96
+ <section className="doc" aria-label="Estimate">
97
+ <header className="doc-head">
98
+ <h2>Costs</h2>
99
+ <p className="muted">Choose an expected project size. We use it to estimate usage; you can refine the assumptions later. {DISCLAIMER}</p>
100
+ </header>
101
+ <fieldset disabled={busy}><legend>How large do you expect this project to be?</legend>
102
+ <div className="row">{PROJECT_SIZES.map(size=><button type="button" className="btn" key={size.id} aria-pressed={project.estimate?.projectSize===size.id} onClick={()=>{const next=setProjectSize(project,size.id);onChange(next);onEstimate?.(next);}}>{size.label}</button>)}</div>
103
+ <p className="muted small">Small: 10,000 requests / 10 GB; Medium: 100,000 / 100 GB; Large: 1 million / 1 TB; Extra Large: 10 million / 10 TB per month. Existing usage figures take priority. Model assumptions: 3,000 tokens per request and 730 endpoint hours; training usage needs separate agreement.</p>
104
+ </fieldset>
105
+ {busy&&<p role="status">Architect is preparing the estimate…</p>}
106
+ {onEstimate&&project.estimate?.projectSize&&<button className="link" disabled={busy} onClick={()=>onEstimate(project)}>Refresh estimate with Architect</button>}
107
+ <div className="totals">
108
+ <div>
109
+ <small className="muted">Estimated subtotal / month</small>
110
+ <strong>{e.lines.some((l) => l.cost != null) ? money(e.expected, e.currency) : "—"}</strong>
111
+ </div>
112
+ <div>
113
+ <small className="muted">Range</small>
114
+ <span>
115
+ {e.lines.some((l) => l.cost != null) ? `${money(e.low, e.currency)} – ${money(e.high, e.currency)}` : "—"}
116
+ </span>
117
+ </div>
118
+ <div>
119
+ <small className="muted">Status</small>
120
+ <span className={e.complete ? "ok-text" : "warn-text"}>
121
+ {e.complete ? "All entered charges estimated" : e.mixedCurrencies ? "Currency needs review" : "Some charges not yet estimated"}
122
+ </span>
123
+ </div>
124
+ {e.budget && (
125
+ <div>
126
+ <small className="muted">Budget</small>
127
+ <span className={e.budget.comparable && e.expected > e.budget.amount ? "bad-text" : ""}>
128
+ {e.budget.currency} {e.budget.amount.toLocaleString("en")}
129
+ {e.budget.comparable ? (e.expected > e.budget.amount ? " · over" : " · within") : " · not compared"}
130
+ </span>
131
+ </div>
132
+ )}
133
+ </div>
134
+ <p className="muted small">The subtotal includes priced charges only. Architect needs to resolve unpriced services before this becomes a full estimate.</p>
135
+ {e.drivers.length > 0 && (
136
+ <p className="small">
137
+ Biggest drivers: {e.drivers.map((d) => `${d.component} (${money(d.cost, d.price.currency)})`).join(", ")}
138
+ </p>
139
+ )}
140
+ {e.lines.some(l=>l.cost==null)&&<p role="status">{e.lines.filter(l=>l.cost==null).length} charges await {e.lines.some(l=>l.quantity==null)?'usage assumptions or service pricing':'service pricing'}. {onEstimate?'Ask Architect using the estimate action above; detailed inputs are optional below.':'Service prices must be connected before these charges can be calculated.'}</p>}
141
+ <details className="extra"><summary>Cost breakdown and price sources</summary><div className="resource-schedule" aria-label="Estimate breakdown">{e.lines.map(l=><article key={l.id}><strong>{l.component} · {l.driver}</strong><span>{l.cost==null?'Not yet estimated':money(l.cost,l.price.currency)+'/month'}</span><small>{l.quantity??'Usage unresolved'} {l.unit}{l.price&&<> · {l.price.source}{l.price.url&&<> · <a href={l.price.url} target="_blank" rel="noreferrer">price source</a></>}</>}</small></article>)}</div></details>
142
+ <details className="extra"><summary>Adjust usage assumptions and prices</summary>
143
+ {e.lines.some((l) => !l.detailed) && <>
144
+ <div className="doc-sub">
145
+ <h3>Usage</h3>
146
+ </div>
147
+ <div className="usage">
148
+ {INPUTS.filter((i) => e.lines.some((l) => l.inputs.includes(i.id))).map((i) => {
149
+ const u = e.usage[i.id];
150
+ return (
151
+ <label key={i.id} className="field">
152
+ {i.label}
153
+ <input
154
+ aria-label={i.label}
155
+ inputMode="decimal"
156
+ placeholder={u.value != null ? String(u.value) : "unknown"}
157
+ value={project.estimate?.usage?.[i.id] ?? ""}
158
+ onChange={(ev) => onChange(setUsage(project, i.id, ev.target.value))}
159
+ />
160
+ <small className={u.source === "needed" ? "warn-text" : "muted"}>
161
+ {u.source === "needed" ? "needed by a line below" : `${u.value?.toLocaleString("en")} ${i.unit} · ${u.source}`}
162
+ </small>
163
+ {i.hint && <small className="muted">{i.hint}</small>}
164
+ </label>
165
+ );
166
+ })}
167
+ </div>
168
+ </>}
169
+ {e.lines.some((l) => !l.detailed) &&
170
+ <div className="doc-sub">
171
+ <h3>Lines</h3>
172
+ <span className="muted small">Price per unit, with where it came from.</span>
173
+ </div>
174
+ }
175
+ {e.lines.some((l) => !l.detailed) ? (
176
+ <div className="lines">
177
+ {e.lines.filter((l) => !l.detailed).map((l) => {
178
+ const p = project.estimate?.prices?.[l.id] || {};
179
+ const set = (patch) => onChange(setPrice(project, l.id, patch));
180
+ return (
181
+ <div key={l.id} className={`line ${l.status.replace(" ", "-")}`}>
182
+ <span>
183
+ <strong>{l.component}</strong>
184
+ <small className="muted">
185
+ {l.driver} · {l.quantity == null ? `needs ${l.missing.map((m) => INPUTS.find((i) => i.id === m).label.toLowerCase()).join(", ")}` : `${l.quantity.toLocaleString("en")} ${l.unit}`}
186
+ </small>
187
+ </span>
188
+ <input
189
+ aria-label={`${l.component} unit price`}
190
+ inputMode="decimal"
191
+ placeholder={`price / ${l.unit}`}
192
+ value={p.price ?? ""}
193
+ onChange={(ev) => set({ price: ev.target.value === "" ? undefined : Number(ev.target.value) })}
194
+ />
195
+ <input aria-label={`${l.component} currency`} className="cur" value={p.currency || "USD"} onChange={(ev) => set({ currency: ev.target.value.toUpperCase().slice(0, 3) })} />
196
+ <input aria-label={`${l.component} price source`} placeholder="source or URL" value={p.url || (p.source && p.source !== "entered by you" ? p.source : "")} onChange={(ev) => set({ url: ev.target.value })} />
197
+ <span className="cost">{l.cost == null ? <em className="muted">{l.status}</em> : money(l.cost, l.price.currency)}</span>
198
+ </div>
199
+ );
200
+ })}
201
+ </div>
202
+ ) : (
203
+ !project.nodes.length && <p className="muted">Sketch a design first; lines appear for each component that has a running cost.</p>
204
+ )}
205
+ {e.notCosted.length > 0 && <p className="muted small">Not costed in this release: {e.notCosted.join(", ")}.</p>}
206
+ <div className="row small">
207
+ <label className="inline">
208
+ Low ×
209
+ <input aria-label="Low factor" value={e.factors.low} onChange={(ev) => onChange({ ...project, estimate: { ...(project.estimate || {}), low: Number(ev.target.value) || 0 } })} />
210
+ </label>
211
+ <label className="inline">
212
+ High ×
213
+ <input aria-label="High factor" value={e.factors.high} onChange={(ev) => onChange({ ...project, estimate: { ...(project.estimate || {}), high: Number(ev.target.value) || 0 } })} />
214
+ </label>
215
+ </div>
216
+ </details>
217
+ <details className="extra"><summary>Advanced charge worksheet</summary><DetailedCharges project={project} onChange={onChange} /></details>
218
+ {e.lines.some((l) => l.detailed) && <div className="resource-schedule" aria-label="Detailed cost breakdown">{e.lines.filter((l) => l.detailed).map((l) => <article key={l.id}><strong>{l.component} · {l.driver}</strong><span>{l.quantity ?? "?"} {l.unit} × {l.price ? money(l.price.price, l.price.currency) : "price needed"} = {l.cost == null ? l.status : money(l.cost, l.price.currency)}/month</span></article>)}</div>}
219
+ <details className="extra"><summary>What we still need for a full estimate · {e.gaps.length} worksheet gaps</summary><ul>{e.gaps.map((g,i) => <li key={i}>{g}</li>)}</ul><p className="muted small">Check networking, security, logging, backups, support, licences, taxes and delivery effort. A detailed worksheet still needs validation against the selected services.</p></details>
220
+ <details className="extra"><summary>Optional delivery effort estimate</summary><ConsultingView project={project} onChange={onChange} /></details>
221
+ </section>
222
+ );
223
+ }
224
+
225
+ export function DeployView({ project, findings, environment, onEnvironment, onPlan, onPulumi, onDocument, onPack, onTerraform, onChange }) {
226
+ const block = blockers(findings);
227
+ const infrastructure = resourcePlan(project);
228
+ const gate = project.gate || {};
229
+ return (
230
+ <section className="doc" aria-label="Deploy">
231
+ <header className="doc-head">
232
+ <h2>Deploy</h2>
233
+ <p className="muted">A reviewable plan and document. AtMem AI Architect never provisions anything on its own.</p>
234
+ </header>
235
+ <div className="ready no">
236
+ <strong>{block.length ? "Not ready for deployment" : "No automated review blockers"}</strong>
237
+ {!block.length && <p className="small">{infrastructure.gaps.length ? `${infrastructure.gaps.length} infrastructure and integration tasks remain.` : "Infrastructure and account validation are still required."}</p>}
238
+ {block.length > 0 && (
239
+ <ul>
240
+ {block.map((f) => (
241
+ <li key={f.key}>{f.statement}</li>
242
+ ))}
243
+ </ul>
244
+ )}
245
+ </div>
246
+ <div className="row">
247
+ <div className="seg">
248
+ {["staging", "production"].map((env) => (
249
+ <button key={env} className={environment === env ? "on" : ""} onClick={() => onEnvironment(env)}>
250
+ {env[0].toUpperCase() + env.slice(1)}
251
+ </button>
252
+ ))}
253
+ </div>
254
+ <button className="btn primary" onClick={onDocument}>
255
+ Deployment document
256
+ </button>
257
+ <button className="btn primary" onClick={onPack}>Download delivery pack</button>
258
+ <button className="btn" onClick={onTerraform}>Terraform sketch</button>
259
+ <button className="btn" onClick={onPlan}>
260
+ Export {environment} plan
261
+ </button>
262
+ <button className="btn ghost" onClick={onPulumi}>
263
+ Pulumi
264
+ </button>
265
+ </div>
266
+ <p className="muted small">The delivery pack includes the specification, diagram, decisions, estimates, resource schedule, editable project and Terraform sketch, all from the current snapshot. Change the project and regenerate it.</p>
267
+ <p className="warn-text small">Deployment access and execution are not connected. Resource coverage and implementation work are listed below; automated review alone cannot establish deployment readiness.</p>
268
+ <ResourcesView project={project} />
269
+ <div className="doc-sub">
270
+ <h3>Draft steps</h3>
271
+ <span className="muted small">Validate against the provider's documentation before use.</span>
272
+ </div>
273
+ <ol className="steps-list">
274
+ {deploymentSteps(project).map((s) => (
275
+ <li key={s}>{s}</li>
276
+ ))}
277
+ </ol>
278
+ <details className="extra">
279
+ <summary>Scale gate — scale only when value exceeds cost and risk</summary>
280
+ {GATE.map((g) => (
281
+ <label key={g.id} className="field">
282
+ {g.label}
283
+ <textarea
284
+ rows={2}
285
+ aria-label={g.label}
286
+ placeholder={g.hint}
287
+ value={gate[g.id] || ""}
288
+ onChange={(e) => onChange({ ...project, gate: { ...gate, [g.id]: e.target.value } })}
289
+ />
290
+ </label>
291
+ ))}
292
+ </details>
293
+ </section>
294
+ );
295
+ }
296
+
297
+ // Test run companion card: what's in scope and whether the success measures passed.
298
+ export function TestCard({ project, run, onOpen }) {
299
+ const tested = run && run.revision === project.revision && run.status !== "running";
300
+ const results = Object.fromEntries((tested ? run.steps : []).flatMap((s) => (s.output?.measures || []).map((m) => [m.label, m])));
301
+ const outputs = project.nodes.filter((n) => n.data.measures?.length);
302
+ return (
303
+ <aside className="deploy build" aria-label="Test">
304
+ <h3>Test run</h3>
305
+ <p className="small">Runs each block in order with built-in sample data, on this computer. No AI model is called, nothing touches a cloud account, and it costs nothing.</p>
306
+ <p className="muted small">Faded blocks are outside the prototype scope.</p>
307
+ {outputs.length ? (
308
+ <ul className="checks">
309
+ {outputs.flatMap((n) =>
310
+ n.data.measures.map((m) => {
311
+ const r = results[m.label];
312
+ return (
313
+ <li key={n.id + m.label} className={r ? (r.pass ? "ok" : "bad") : ""}>
314
+ <button className="link-plain" onClick={() => onOpen(n.id)}>
315
+ {m.label} {m.op} {String(m.target)}
316
+ {r && <span className="muted"> · {String(r.value)}</span>}
317
+ </button>
318
+ </li>
319
+ );
320
+ }),
321
+ )}
322
+ </ul>
323
+ ) : (
324
+ <p className="muted small">Success measures live on a final check block.</p>
325
+ )}
326
+ </aside>
327
+ );
328
+ }
329
+
330
+ const when = (iso) => {
331
+ if (!iso) return "";
332
+ const d = new Date(iso);
333
+ const mins = Math.round((Date.now() - d) / 60000);
334
+ if (mins < 1) return "just now";
335
+ if (mins < 60) return `${mins} min ago`;
336
+ if (mins < 60 * 24) return `${Math.round(mins / 60)} h ago`;
337
+ return d.toLocaleDateString();
338
+ };
339
+
340
+ // Projects saved under your account on this computer, with a rubbish bin.
341
+ export function ProjectsDialog({ list, currentId, onOpen, onNew, onBin, onRestore, onPurge, folder }) {
342
+ const [confirm, setConfirm] = React.useState(null);
343
+ return (
344
+ <div className="projects">
345
+ <div className="row-between">
346
+ <h2>Projects</h2>
347
+ <button className="button run-button" onClick={onNew}>
348
+ New project
349
+ </button>
350
+ </div>
351
+ {list.projects.length ? (
352
+ <ul className="project-list">
353
+ {list.projects.map((p) => (
354
+ <li key={p.id} className={p.id === currentId ? "current" : ""}>
355
+ <button className="open" onClick={() => onOpen(p.id)} disabled={p.id === currentId}>
356
+ <strong>{p.name}</strong>
357
+ <small>
358
+ {p.id === currentId ? "open now" : when(p.updatedAt)} · {p.blocks} block{p.blocks === 1 ? "" : "s"}
359
+ </small>
360
+ </button>
361
+ <button className="icon bin" aria-label={`Move ${p.name} to the bin`} title="Move to bin" onClick={() => onBin(p.id)}>
362
+ 🗑
363
+ </button>
364
+ </li>
365
+ ))}
366
+ </ul>
367
+ ) : (
368
+ <p className="muted">No saved projects yet. Your current one saves itself as you work.</p>
369
+ )}
370
+ {list.bin.length > 0 && (
371
+ <details className="bin-list">
372
+ <summary>Rubbish bin · {list.bin.length}</summary>
373
+ <ul className="project-list">
374
+ {list.bin.map((p) => (
375
+ <li key={p.id}>
376
+ <span className="open">
377
+ <strong>{p.name}</strong>
378
+ <small>binned {when(p.binnedAt)}</small>
379
+ </span>
380
+ <button className="btn" onClick={() => onRestore(p.id)}>
381
+ Restore
382
+ </button>
383
+ {confirm === p.id ? (
384
+ <button className="btn danger" onClick={() => (onPurge(p.id), setConfirm(null))}>
385
+ Delete forever?
386
+ </button>
387
+ ) : (
388
+ <button className="btn ghost danger" onClick={() => setConfirm(p.id)}>
389
+ Delete
390
+ </button>
391
+ )}
392
+ </li>
393
+ ))}
394
+ </ul>
395
+ </details>
396
+ )}
397
+ <p className="modal-fine">Saved in {folder || "~/.atforma"} under your account on this computer.</p>
398
+ </div>
399
+ );
400
+ }