@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,59 @@
1
+ import React from "react";
2
+ import { consultingEstimate, WORK_PHASES, setDetail } from "./estimate.mjs";
3
+ import { resourcePlan } from "./resources.mjs";
4
+ const amount = (n, c) => n == null ? "Not estimated" : `${c} ${n.toLocaleString("en", { maximumFractionDigits: 2 })}`;
5
+ const number = (s) => s === "" || !Number.isFinite(Number(s)) || Number(s) < 0 ? undefined : Number(s);
6
+
7
+ export function DetailedCharges({ project, onChange }) {
8
+ const lines = project.estimate?.details || [];
9
+ const components = project.nodes.filter((n) => n.data.kind !== "note");
10
+ const change = (details) => onChange({ ...project, estimate: { ...(project.estimate || {}), details } });
11
+ return <details className="extra" aria-label="Detailed cloud charges">
12
+ <summary>Model detailed cloud costs</summary>
13
+ <p className="muted small">Add each billable dimension: for example input tokens, output tokens, requests, compute, storage and transfer. Detailed lines replace the coarse ROM line for that component. Enter a zero-cost line and explain why for an existing or free component.</p>
14
+ {lines.map((l, index) => {
15
+ const set = (patch) => onChange(setDetail(project, l.id, patch));
16
+ return <fieldset className="charge-editor" key={l.id}>
17
+ <legend>Charge {index + 1}</legend>
18
+ <div className="delivery-fields">
19
+ <label className="field">Component<select aria-label={`Charge ${index + 1} component`} value={l.componentId} onChange={(e) => set({ componentId: e.target.value })}>
20
+ {!components.some((n) => n.id === l.componentId) && <option value={l.componentId}>Removed component — reassign</option>}
21
+ {components.map((n) => <option key={n.id} value={n.id}>{n.data.label}</option>)}
22
+ </select></label>
23
+ {[['description','Charge description'],['quantity','Monthly quantity'],['unit','Unit'],['price','Unit price'],['currency','Currency'],['service','Service or SKU'],['region','Price region'],['source','Price source or quote'],['date','Price date']].map(([key,label]) => <label className="field" key={key}>{label}<input aria-label={`Charge ${index + 1} ${label.toLowerCase()}`} type={key === 'date' ? 'date' : 'text'} inputMode={['quantity','price'].includes(key) ? 'decimal' : undefined} value={l[key] ?? ''} onChange={(e) => set({ [key]: ['quantity','price'].includes(key) ? number(e.target.value) : key === 'currency' ? e.target.value.toUpperCase().slice(0,3) : e.target.value })} /></label>)}
24
+ </div>
25
+ <button className="btn ghost danger" onClick={() => change(lines.filter((x) => x.id !== l.id))}>Remove charge {index + 1}</button>
26
+ </fieldset>;
27
+ })}
28
+ <button className="btn" disabled={!components.length} onClick={() => change([...lines, { id: `charge-${crypto.randomUUID()}`, componentId: components[0].id, description: "", unit: "", currency: "USD", source: "", date: new Date().toISOString().slice(0,10), region: "", service: "" }])}>Add cloud charge</button>
29
+ </details>;
30
+ }
31
+
32
+ export function ConsultingView({ project, onChange }) {
33
+ const c = project.estimate?.consulting || {}, result = consultingEstimate(project);
34
+ const set = (patch) => onChange({ ...project, estimate: { ...(project.estimate || {}), consulting: { ...c, ...patch } } });
35
+ return <details className="extra" aria-label="Consulting and build estimate">
36
+ <summary>Consulting and build estimate · one-off</summary>
37
+ <p className="muted small">Enter person-days and your day rate; no rates or effort are assumed. Give the basis, scope and exclusions. Use zero days with a reason if a phase is out of scope. Person-days are effort, not calendar duration.</p>
38
+ <label className="field">Consulting currency<input aria-label="Consulting currency" value={c.currency || "USD"} onChange={(e) => set({ currency: e.target.value.toUpperCase().slice(0,3) })} /></label>
39
+ <div className="totals"><div><small>Expected one-off subtotal</small><strong>{amount(result.expected, result.currency)}</strong></div><div><small>Range</small><span>{result.low == null ? '—' : `${amount(result.low, result.currency)} – ${amount(result.high, result.currency)}`}</span></div><div><small>Status</small><span>{result.complete ? "All work packages estimated" : "Incomplete — work packages need estimates"}</span></div></div>
40
+ {WORK_PHASES.map(([id,label]) => {
41
+ const phase = c.phases?.[id] || {};
42
+ const edit = (patch) => set({ phases: { ...(c.phases || {}), [id]: { ...phase, ...patch } } });
43
+ return <fieldset className="charge-editor" key={id}><legend>{label}</legend><div className="delivery-fields">
44
+ {[['lowDays','Low days'],['days','Expected days'],['highDays','High days'],['rate','Day rate']].map(([key,name]) => <label className="field" key={key}>{name}<input aria-label={`${label} ${name.toLowerCase()}`} inputMode="decimal" value={phase[key] ?? ''} onChange={(e) => edit({ [key]: number(e.target.value) })} /></label>)}
45
+ <label className="field delivery-basis">Basis, scope and exclusions<textarea rows={2} aria-label={`${label} basis`} value={phase.basis || ''} onChange={(e) => edit({ basis: e.target.value })} /></label>
46
+ </div></fieldset>;
47
+ })}
48
+ <p className="muted small">Separate from cloud running costs. Taxes, licences, ongoing support and migration are excluded unless explicitly included.</p>
49
+ </details>;
50
+ }
51
+
52
+ export function ResourcesView({ project }) {
53
+ const plan = resourcePlan(project);
54
+ return <details className="extra" aria-label="Cloud resource schedule"><summary>Resources and infrastructure coverage · {plan.rows.length} components</summary>
55
+ <p className="muted small">Derived from the current diagram. Generic services need confirmation. S3 foundation code covers buckets and their controls; drawn wires still need application integration and IAM.</p>
56
+ <div className="resource-schedule">{plan.rows.map((r) => <article key={r.id}><strong>{r.label}</strong><span>{r.provider.toUpperCase()} · {r.service} · {r.region}</span><small>{r.existing ? "Existing system" : r.selection} · {r.terraform}</small><small>{r.resources.join(', ') || 'Resource types to confirm'}</small><small>Cost dimensions: {r.costDrivers}</small></article>)}</div>
57
+ {plan.gaps.length > 0 && <p className="warn-text small">{plan.gaps.length} resource or integration tasks remain. The full list is included in the delivery pack.</p>}
58
+ </details>;
59
+ }
@@ -0,0 +1,44 @@
1
+ import {emulationGuidance,emulationRepairTask} from './emulation-guidance.mjs';
2
+ import {toProjectFile} from './project-file.mjs';
3
+ import {BrainActivity} from "./BrainActivity.jsx";
4
+ import React,{useState} from 'react';
5
+ import {Play,X,CheckCircle2,AlertCircle} from 'lucide-react';
6
+ import {emulationFeedback,emulationEvidenceSummary} from './emulation-feedback.mjs';
7
+ export function EmulationPanel({project,session,emulation,onDiscuss,discussionBusy=false,onOpenComponent,onClose,onBuild}){
8
+ const {result,previous,running}=emulation;
9
+ const [expanded,setExpanded]=useState(false),[taskError,setTaskError]=useState('');
10
+ const readiness=emulationGuidance(project,result)||emulation.preflight;
11
+ const guidance=readiness?.action==='build-and-test'&&!onBuild?{...readiness,next:'Application implementation is unavailable in this session. Download the repair task for the missing code and tests; testing can resume once that implementation is available.'}:readiness;
12
+ const feedback=emulationFeedback(project,result),thinking=discussionBusy&&!!result;
13
+ const title=running?'Testing this design…':thinking?'Architect is reviewing…':guidance?guidance.title:result?.status==='passed'?'Local checks passed':result?'Let’s resolve the next step':previous?'Design changed — rerun needed.':'Local implementation checks';
14
+ function saveReport(){const url=URL.createObjectURL(new Blob([JSON.stringify(result,null,2)],{type:'application/json'}));const a=document.createElement('a');a.href=url;a.download=`atmem-local-checks-r${project.revision}.json`;a.click();setTimeout(()=>URL.revokeObjectURL(url),1000);}
15
+ function saveTask(){try{toProjectFile(project);const url=URL.createObjectURL(new Blob([emulationRepairTask(project,result)],{type:'text/markdown'}));const a=document.createElement('a');a.href=url;a.download='architect-repair-task.md';a.click();setTimeout(()=>URL.revokeObjectURL(url),1000);setTaskError('');}catch(error){setTaskError(error.message);}}
16
+ const icon=(label,Icon,action,options={})=><button type="button" className={`emulation-icon ${options.active?'active':''}`} aria-label={label} title={label} onClick={action} disabled={options.disabled} aria-pressed={options.toggle?options.active:undefined}><Icon size={19}/></button>;
17
+ return <aside className={`emulation-panel ${running||thinking?'is-working':''}`} aria-label="Local checks">
18
+ <div className="emulation-heading"><span className={`emulation-orb ${running||thinking?'working':''}`}><BrainActivity size={34} active={running||thinking}/></span><div><span className="emulation-eyebrow">LOCAL CHECKS</span><h3 aria-live="polite">{title}</h3></div>{onClose&&icon('Close local checks',X,onClose)}</div>
19
+ <div className="emulation-controls row">
20
+ <button type="button" className="btn primary" aria-label="Run local checks" aria-busy={running||thinking} title={running?'Local checks running':thinking?'Architect is reviewing':emulation.preflight?'Complete the next step below before testing':'Run local checks'} disabled={running||thinking||!session?.token||!!emulation.preflight} onClick={()=>emulation.run()}>{running||thinking?<BrainActivity size={24}/>:<Play size={19}/>} Run local checks</button>
21
+ {running&&<button type="button" className="btn" onClick={emulation.stop}>Stop waiting</button>}
22
+ {result&&onDiscuss&&<button type="button" className="btn" disabled={discussionBusy||running} onClick={()=>onDiscuss(result,'question')}>Ask Architect about these results</button>}
23
+ <button type="button" className="btn" aria-expanded={expanded} onClick={()=>setExpanded(!expanded)}>{expanded?'Hide details':'Check details and settings'}</button>
24
+ </div>
25
+ <div className="emulation-track" aria-label="Local check progress"><span className={running?'current':result?'complete':''}>Test</span><i/><span className={thinking?'current':''}>Review</span><i/><span>Improve</span><i/><span>Retest</span></div>
26
+ {running&&<div className="emulation-progress" role="progressbar" aria-label="Running local checks"><span/></div>}
27
+ <p className="emulation-caption">{running?'Checking the generated code. Keep exploring the diagram.':thinking?'Your architect is working through the evidence in chat.':guidance?guidance.reason:result?emulationEvidenceSummary(result):'Runs local checks on the generated implementation and shows the results here. Monitoring needs its own implementation and configuration.'}</p>
28
+ {guidance&&!running&&!thinking&&<div className="emulation-next-step"><p><strong>Next:</strong> {guidance.next}</p>{guidance.action==='build-and-test'&&onBuild?<button className="btn primary" disabled={discussionBusy} onClick={onBuild}>Implement and check</button>:guidance.owner==='engineering'?<button className="btn primary" onClick={saveTask}>Download repair task</button>:guidance.needsModel?<button className="btn primary" disabled={discussionBusy} onClick={()=>onDiscuss?.(result,'correction')}>Work through this with Architect</button>:<button className="btn ghost" onClick={()=>setExpanded(true)}>See test details</button>}{guidance.componentId&&onOpenComponent&&<button className="link" onClick={()=>onOpenComponent(guidance.componentId)}>Review affected block</button>}{taskError&&<p role="alert">{taskError}</p>}</div>}
29
+ {emulation.retestLimitReached&&<p role="status">Two automatic retests are complete. Review the latest correction, then choose Run local checks to continue.</p>}
30
+ {expanded&&<div className="emulation-evidence">
31
+ <label><input type="checkbox" checked={emulation.coach} onChange={event=>emulation.setCoach(event.target.checked)}/> Ask Architect to explain new check results automatically</label>
32
+ <label><input type="checkbox" checked={emulation.autoRetest} onChange={event=>emulation.setAutoRetest(event.target.checked)}/> Rerun checks after an accepted correction (up to two attempts)</label>
33
+ <p>Corrections follow Draw as we talk and remain undoable. Stop waiting ends your wait; server work can continue until its time limit.</p>
34
+ {result?.artifactDigest&&<button type="button" className="btn" onClick={saveReport}>Download check report (JSON)</button>}
35
+ {feedback&&<p>{feedback.question}</p>}{result?.message&&<p>{result.message}</p>}
36
+ {result?.backend&&<p>{result.backend} {result.backendVersion} · r{result.designRevision} · {result.environment}</p>}
37
+ {result?.checks?.map((c,i)=><div className="emulation-check" key={i}>{c.passed?<CheckCircle2 size={16}/>:<AlertCircle size={16}/>}<span>{c.name}{c.message&&<small>{c.message}</small>}</span></div>)}
38
+ {result?.blockers?.map((b,i)=><p key={i}>{b}</p>)}
39
+ {!!result?.capabilities?.length&&<details><summary>What was checked</summary><ul>{result.capabilities.map((item,i)=><li key={i}>{item.service}: {item.mode}</li>)}</ul></details>}
40
+ {!!result?.emulatorPatches?.length&&<details><summary>Emulator compatibility fixes</summary><ul>{result.emulatorPatches.map(item=><li key={item.id}>{item.id}: {item.reason}</li>)}</ul></details>}
41
+ {!!result?.limitations?.length&&<details open><summary>Still requires cloud verification</summary><ul>{result.limitations.map((v,i)=><li key={i}>{v}</li>)}</ul></details>}
42
+ </div>}
43
+ </aside>;
44
+ }
@@ -0,0 +1,385 @@
1
+ import {BrainActivity} from "./BrainActivity.jsx";
2
+ import {systemDescription,requirementExplanation} from './system-description.mjs';
3
+ import { resolveCommentRevision } from "./consultation.mjs";
4
+ // Consultant views: Discover (qualify), Options and Decisions (design), Build card.
5
+ import React from "react";
6
+ import { requirementNumber } from "./derive.mjs";
7
+ import { Plus, Trash2 } from "lucide-react";
8
+ import {
9
+ BRIEF_FIELDS,
10
+ CRITERIA,
11
+ GATE,
12
+ LEVELS,
13
+ OPTIONS,
14
+ STATUSES,
15
+ VERDICTS,
16
+ defaultAssessment,
17
+ newDecision,
18
+ optionScore,
19
+ } from "./engagement.mjs";
20
+ import { OPTION_NAMES } from "./pack.mjs";
21
+ import {
22
+ decisionHistory,
23
+ measureProblem,
24
+ reviseDecision,
25
+ } from "./records.mjs";
26
+
27
+ const area = (props) => <textarea rows={2} {...props} />;
28
+
29
+ // One understood topic: read as text; edit only when asked.
30
+ function Known({ topic, value, onSave }) {
31
+ const [editing, setEditing] = React.useState(false);
32
+ return (
33
+ <div className={`known-item ${topic.state}`}>
34
+ <dt>
35
+ {topic.label}
36
+ {topic.state === "assumed" && <em> · assumed</em>}
37
+ {!editing && (
38
+ <button className="link small" aria-label={`Edit ${topic.label}`} onClick={() => setEditing(true)}>
39
+ Edit
40
+ </button>
41
+ )}
42
+ </dt>
43
+ {editing ? (
44
+ <dd>
45
+ <textarea autoFocus rows={2} aria-label={topic.label} defaultValue={value} onBlur={(e) => (onSave(e.target.value), setEditing(false))} />
46
+ </dd>
47
+ ) : (
48
+ <dd>{value}</dd>
49
+ )}
50
+ </div>
51
+ );
52
+ }
53
+
54
+ // What we've understood from the chat, as a small card on the board.
55
+ export function DiscoverView({ project, onChange, topics, open = true, onToggle }) {
56
+ const brief = project.brief || {};
57
+ const useCases = project.useCases || [];
58
+ const setCase = (i, patch) =>
59
+ onChange({ ...project, useCases: useCases.map((u, j) => (j === i ? { ...u, ...patch } : u)) });
60
+ const facts = (project.facts || []).filter((f) => f.name !== "cloud.preference" && f.name !== "data.sensitive");
61
+ const heard = topics.filter((t) => t.state !== "open");
62
+ if (!open) return null;
63
+ return (
64
+ <section className="notes-card" aria-label="Discover">
65
+ <div className="doc-sub">
66
+ <h3>What we know so far</h3>
67
+ </div>
68
+ {heard.length > 0 && (
69
+ <>
70
+ <p className="muted small">Your words — edit anything.</p>
71
+ {facts.length > 0 && (
72
+ <div className="facts">
73
+ {facts.map((f) => (
74
+ <span key={f.id} className={`chip ${f.conflictsWith ? "missing" : ""}`} title={`${f.text} (${f.madeAt})`}>
75
+ {typeof f.value === "number" ? f.value.toLocaleString("en") : String(f.value)} {f.unit}
76
+ <button aria-label={`Forget ${f.unit}`} onClick={() => onChange({ ...project, facts: project.facts.filter((x) => x.id !== f.id) })}>
77
+ ×
78
+ </button>
79
+ </span>
80
+ ))}
81
+ </div>
82
+ )}
83
+ <dl className="known">
84
+ {heard.map((t) => (
85
+ <Known
86
+ key={t.id}
87
+ topic={t}
88
+ value={brief[t.id] || ""}
89
+ onSave={(value) => onChange({ ...project, brief: { ...brief, [t.id]: value } })}
90
+ />
91
+ ))}
92
+ </dl>
93
+ <p className="muted small">
94
+ Still to cover, whenever you're ready:{" "}
95
+ {topics.filter((t) => t.state === "open").map((t) => t.label.toLowerCase()).join(", ") || "nothing — that's everything for now."}
96
+ </p>
97
+ </>
98
+ )}
99
+ <details className="extra">
100
+ <summary>Comparing ideas? Qualify use cases</summary>
101
+ <div className="cases compact">
102
+ {useCases.map((u, i) => (
103
+ <div key={u.id} className={`case verdict-${u.verdict.replace(" ", "-").toLowerCase()}`}>
104
+ <input aria-label="Use case" placeholder="Idea" value={u.title} onChange={(e) => setCase(i, { title: e.target.value })} />
105
+ <div className="seg verdicts">
106
+ {VERDICTS.map((v) => (
107
+ <button key={v} className={u.verdict === v ? "on" : ""} onClick={() => setCase(i, { verdict: v })}>
108
+ {v}
109
+ </button>
110
+ ))}
111
+ </div>
112
+ <button className="icon" aria-label="Remove use case" onClick={() => onChange({ ...project, useCases: useCases.filter((_, j) => j !== i) })}>
113
+ <Trash2 size={13} />
114
+ </button>
115
+ </div>
116
+ ))}
117
+ <button
118
+ className="link small"
119
+ onClick={() =>
120
+ onChange({
121
+ ...project,
122
+ useCases: [...useCases, { id: `uc-${Date.now()}`, title: "", value: "Medium", risk: "Medium", fit: "Medium", verdict: "Park", reason: "" }],
123
+ })
124
+ }
125
+ >
126
+ + Add use case
127
+ </button>
128
+ </div>
129
+ </details>
130
+ </section>
131
+ );
132
+ }
133
+
134
+ export function OptionsView({ project, onDiscuss, onPreview, onChoose, onContinue, busy }) {
135
+ const notes = project.assessment?.notes || {};
136
+ const ready = Object.values(notes).some(Boolean);
137
+ const selected = [...(project.decisions||[])].reverse().find(d=>d.subject==='platform.cloud'&&d.status==='Accepted')?.decision;
138
+ return <section className="doc" aria-label="Choices">
139
+ <header className="doc-head"><h2>Choices</h2><p className="muted">Compare the approaches below, then choose a cloud to continue. Next we’ll discuss country and data residency.</p></header>
140
+ <button className="btn" onClick={() => onDiscuss('Help me compare AWS, Azure, Google Cloud and IBM for this design. Ask one useful question about my priorities, then refine the comparison from my answer. Populate optionAssessment when enough is known. Keep the diagram unchanged.')}>Discuss cloud options</button>
141
+ {selected && <p className="cloud-selection" role="status"><strong>Selected: {OPTION_NAMES[selected]}</strong> · You can change your choice below. <button className="btn primary" disabled={busy} onClick={onContinue}>Continue with {OPTION_NAMES[selected]} →</button></p>}
142
+ <DecisionsView project={project} onDiscuss={onDiscuss} embedded/>
143
+ <h3>Cloud alternatives</h3>
144
+ {!ready && <p className="muted">We’ll clarify what matters to you and explain the tradeoffs here as we go.</p>}
145
+ {['current','aws','azure','gcp','ibm'].filter(id => notes[id]).map(id => <article className="consultation-summary" key={id}>
146
+ <h3>{OPTION_NAMES[id]}{selected===id ? " · Selected" : ""}</h3><p>{notes[id].replace(/^(?:AtMem AI Architect|At[Ff]orma) proposal — confirm: /,'')}</p>
147
+ <button className="link" onClick={() => onDiscuss(`Explain how ${OPTION_NAMES[id]} fits our design and the main tradeoff. Ask one question to help me decide; keep this as a discussion until I explicitly choose.`)}>Discuss this option</button>
148
+ {id!=="current" && <><button className="link" onClick={()=>onPreview(id)}>Preview service architecture</button><button className="btn primary" disabled={busy||selected===id} onClick={()=>onChoose(id)}>{selected===id ? `${OPTION_NAMES[id]} selected` : `Choose ${OPTION_NAMES[id]} & continue →`}</button></>}
149
+ </article>)}
150
+ </section>;
151
+ }
152
+
153
+ export function DecisionsView({ project, onDiscuss, embedded=false }) {
154
+ const all = project.decisions || [];
155
+ const choices = all.filter(d => !d.subject?.startsWith('design.'));
156
+ const current = choices.filter(d => d.status !== 'Superseded');
157
+ const sketches = all.filter(d => d.subject?.startsWith('design.'));
158
+ const labels = {'platform.cloud':'Cloud provider','cloud.region':'Region','data.country':'Country / data residency','infrastructure.tool':'Infrastructure tool'};
159
+ return <section className={embedded?undefined:"doc"} aria-label="Decisions">
160
+ <header className="doc-head"><h2>Choices we’ve made</h2><p className="muted">AtMem AI Architect records your choices and explains why they fit. You can revisit them in chat.</p></header>
161
+ <button className="btn" onClick={() => onDiscuss('Review our current design and explicit choices. Explain the next choice we need to make and ask me one useful question. Do not treat a sketch or a suggestion as an accepted decision.')}>Discuss the next choice</button>
162
+ {!current.length && <p className="muted">No choices confirmed yet. We’ll work through them together as the design develops.</p>}
163
+ {current.map(d => <article className="consultation-summary" key={d.id}>
164
+ <h3>{labels[d.subject] || d.title}</h3><p>{OPTION_NAMES[d.decision] || d.decision || 'Still being discussed'}</p>
165
+ <small className="muted">{d.status === 'Accepted' ? 'Confirmed in our conversation' : 'Proposed — still to discuss'}</small>
166
+ {d.context && <p>{d.context}</p>}{d.consequences && <p>{d.consequences}</p>}
167
+ <button className="link" onClick={() => onDiscuss(`Let’s revisit our choice about ${labels[d.subject] || d.title}: ${d.decision}. Explain the tradeoff and ask what I would like to change before updating it.`)}>Revisit in chat</button>
168
+ {choices.some(h => h.subject===d.subject && h.status==='Superseded') && <details className="extra"><summary>Earlier choices</summary>{choices.filter(h => h.subject===d.subject && h.status==='Superseded').map(h=><p key={h.id}>{h.decision} {h.reason && `— ${h.reason}`}</p>)}</details>}
169
+ </article>)}
170
+ {!!sketches.length && <details className="extra"><summary>Diagram change history</summary>{sketches.map(d=><p key={d.id}>{d.title} · {d.decision}</p>)}</details>}
171
+ </section>;
172
+ }
173
+
174
+ export function BuildCard({ project, run, onChange, onOpen, environment, onEnvironment, onPlan, onPulumi, onPack }) {
175
+ const scope = project.nodes.filter((n) => n.data.poc);
176
+ const tested = run && run.revision === project.revision && run.status !== "running";
177
+ const results = Object.fromEntries(
178
+ (tested ? run.steps : []).flatMap((s) => (s.output?.measures || []).map((m) => [m.label, m])),
179
+ );
180
+ const outputs = project.nodes.filter((n) => n.data.measures?.length);
181
+ const gate = project.gate || {};
182
+ const unowned = (project.decisions || []).filter((d) => !d.owner?.trim()).length;
183
+ return (
184
+ <aside className="deploy build" aria-label="Build">
185
+ <h3>Prototype</h3>
186
+ <p className="muted small">
187
+ {scope.length}/{project.nodes.length} blocks in scope · faded blocks are out
188
+ </p>
189
+ <h4>Success criteria</h4>
190
+ {outputs.length ? (
191
+ <ul className="checks">
192
+ {outputs.flatMap((n) =>
193
+ n.data.measures.map((m) => {
194
+ const r = results[m.label];
195
+ return (
196
+ <li key={n.id + m.label} className={r ? (r.pass ? "ok" : "bad") : ""}>
197
+ <button className="link-plain" onClick={() => onOpen(n.id)}>
198
+ {m.label} {m.op} {String(m.target)}
199
+ {r && <span className="muted"> · {String(r.value)}</span>}
200
+ </button>
201
+ </li>
202
+ );
203
+ }),
204
+ )}
205
+ </ul>
206
+ ) : (
207
+ <p className="muted small">Add measures to the final check block.</p>
208
+ )}
209
+ <h4>Scale gate</h4>
210
+ {GATE.map((g) => (
211
+ <label key={g.id} className="field">
212
+ {g.label}
213
+ {area({
214
+ "aria-label": g.label,
215
+ placeholder: g.hint,
216
+ value: gate[g.id] || "",
217
+ onChange: (e) => onChange({ ...project, gate: { ...gate, [g.id]: e.target.value } }),
218
+ })}
219
+ </label>
220
+ ))}
221
+ {unowned > 0 && <p className="warn-text small">{unowned} decision{unowned > 1 ? "s" : ""} without an owner</p>}
222
+ <div className="seg">
223
+ {["staging", "production"].map((env) => (
224
+ <button key={env} className={environment === env ? "on" : ""} onClick={() => onEnvironment(env)}>
225
+ {env[0].toUpperCase() + env.slice(1)}
226
+ </button>
227
+ ))}
228
+ </div>
229
+ <div className="row">
230
+ <button className="btn" onClick={onPlan}>
231
+ Export {environment} plan
232
+ </button>
233
+ <button className="btn ghost" onClick={onPulumi}>
234
+ Pulumi
235
+ </button>
236
+ </div>
237
+ <button className="btn primary" onClick={onPack}>
238
+ Client pack
239
+ </button>
240
+ </aside>
241
+ );
242
+ }
243
+
244
+ export function MeasuresEditor({ measures = [], disabled, onChange }) {
245
+ const set = (i, patch) => onChange(measures.map((m, j) => (j === i ? { ...m, ...patch } : m)));
246
+ return (
247
+ <div className="measures">
248
+ <h4>Success measures</h4>
249
+ {measures.map((m, i) => (
250
+ <div key={i} className="measure">
251
+ <input aria-label="Measure label" disabled={disabled} value={m.label} onChange={(e) => set(i, { label: e.target.value })} />
252
+ <input aria-label="Measure field" disabled={disabled} className="mono" value={m.path} onChange={(e) => set(i, { path: e.target.value })} />
253
+ <select aria-label="Measure operator" disabled={disabled} value={m.op} onChange={(e) => set(i, { op: e.target.value })}>
254
+ <option>{">="}</option>
255
+ <option>{"<="}</option>
256
+ <option>{"=="}</option>
257
+ </select>
258
+ <input
259
+ aria-label="Measure target"
260
+ disabled={disabled}
261
+ value={String(m.target)}
262
+ onChange={(e) => {
263
+ const v = e.target.value;
264
+ set(i, { target: v === "true" ? true : v === "false" ? false : v !== "" && !isNaN(Number(v)) ? Number(v) : v });
265
+ }}
266
+ />
267
+ <button className="icon" aria-label="Remove measure" disabled={disabled} onClick={() => onChange(measures.filter((_, j) => j !== i))}>
268
+ <Trash2 size={13} />
269
+ </button>
270
+ </div>
271
+ ))}
272
+ <button
273
+ className="btn ghost"
274
+ disabled={disabled}
275
+ onClick={() => onChange([...measures, { label: "New measure", path: "status", op: "==", target: "passed" }])}
276
+ >
277
+ <Plus size={13} /> Add measure
278
+ </button>
279
+ </div>
280
+ );
281
+ }
282
+
283
+ function RequirementComments({ requirement, comments, onSave, onRemove, target, number, onReview, onResolve, reviewing, onDiscuss }) {
284
+ const [open,setOpen]=React.useState(false), [text,setText]=React.useState(''), [quote,setQuote]=React.useState('');
285
+ const editor=React.useRef(null);
286
+ React.useEffect(()=>{if(target?.id===requirement.id){setQuote(target.quote);setOpen(true);}},[target,requirement.id]);
287
+ React.useEffect(()=>{if(open){editor.current?.focus();editor.current?.scrollIntoView({block:'nearest'});}},[open,target]);
288
+ const save=review=>{onSave(text.trim(),quote,review);setText('');setOpen(false);};
289
+ return <aside className="requirement-comments" aria-label={`Comments on ${requirement.id}`}>
290
+ {comments.filter(c=>!['reviewed','dismissed'].includes(c.status)).map(c=><div className="requirement-comment" key={c.id}>
291
+ <strong>Your feedback on {number}</strong>{c.selectedText && <blockquote>{c.selectedText}</blockquote>}<p>{c.text}</p>
292
+ {c.status==='proposed' ? <div className="requirement-revision">
293
+ <h5>Suggested revision — not applied yet</h5><p className="revision-label">Current wording</p><p>{c.before}</p>
294
+ <p className="revision-label">Proposed wording</p><p className="revision-after">{c.after}</p><p>{c.explanation}</p>
295
+ <button className="requirement-add-comment" onClick={()=>onResolve(c.id,true)}>Apply this revision</button>
296
+ <button className="link" onClick={()=>onResolve(c.id,false)}>Keep current wording</button>
297
+ </div> : <><p className="comment-status">{c.reviewMessage || 'Saved feedback. Ask AtMem AI Architect to suggest wording, then review the change here.'}</p><button className="requirement-add-comment" disabled={reviewing} onClick={()=>onReview([c])}>{reviewing?<><BrainActivity/> Preparing suggestions…</>:'Suggest a revision'}</button><button className="link" onClick={()=>onDiscuss(`Help me clarify my feedback on ${number} (${requirement.id}): ${c.text}. Ask one question before proposing a change.`)}>Discuss feedback</button></>}
298
+ <button className="link" onClick={()=>onRemove(c.id)} aria-label={`Remove comment ${c.id}`}>Remove</button>
299
+ </div>)}
300
+ {comments.some(c=>['reviewed','dismissed'].includes(c.status)) && <details className="comment-history"><summary>Feedback history</summary>{comments.filter(c=>['reviewed','dismissed'].includes(c.status)).map(c=><div key={c.id}><p>{c.text}</p><small>{c.status==='reviewed'?'Revision applied':'Original wording kept'}</small>{c.after&&<p>{c.after}</p>}</div>)}</details>}
301
+ {!open ? <button className="requirement-add-comment" onClick={()=>{setQuote('');setOpen(true);}}>Comment or request a change</button> : <div className="comment-composer">
302
+ <strong>Feedback on {number}</strong>{quote && <blockquote>{quote}</blockquote>}
303
+ <textarea ref={editor} aria-label={`Comment on ${requirement.id}`} value={text} maxLength={500} onChange={e=>setText(e.target.value)} placeholder="What doesn’t fit, what’s missing, or what would you like explained?" />
304
+ <p className="comment-status">AtMem AI Architect will suggest new wording below. You decide whether to apply it.</p>
305
+ <button className="btn" disabled={!text.trim()||reviewing} onClick={()=>save(true)}>Suggest a revision</button>
306
+ <button className="link" disabled={!text.trim()} onClick={()=>save(false)}>Save for later</button>
307
+ <button className="link" onClick={()=>{setOpen(false);setText('');}}>Cancel</button>
308
+ </div>}
309
+ </aside>;
310
+ }
311
+
312
+ export function RequirementsView({ project, onDiscuss, onChange, onReview, reviewing, onUpload, onOpenProject }) {
313
+ const [commentMenu,setCommentMenu]=React.useState(null), [commentTarget,setCommentTarget]=React.useState(null);
314
+ React.useEffect(()=>{
315
+ if(!commentMenu)return;
316
+ const dismiss=()=>setCommentMenu(null);
317
+ const key=e=>{if(e.key==='Escape')dismiss();};
318
+ document.addEventListener('pointerdown',dismiss);document.addEventListener('keydown',key);window.addEventListener('resize',dismiss);
319
+ return ()=>{document.removeEventListener('pointerdown',dismiss);document.removeEventListener('keydown',key);window.removeEventListener('resize',dismiss);};
320
+ },[commentMenu]);
321
+ function textMenu(event,r) {
322
+ const selection=window.getSelection();
323
+ if(!selection?.rangeCount || selection.isCollapsed)return;
324
+ const range=selection.getRangeAt(0), element=event.currentTarget;
325
+ if(!element.contains(range.startContainer) || !element.contains(range.endContainer))return;
326
+ const quote=selection.toString().trim();if(!quote)return;
327
+ event.preventDefault();event.stopPropagation();
328
+ setCommentMenu({id:r.id,quote:quote.slice(0,1500),x:Math.max(8,Math.min(event.clientX,window.innerWidth-250)),y:Math.max(8,Math.min(event.clientY,window.innerHeight-70))});
329
+ }
330
+ const needs = project.needs || [];
331
+ const comments = project.extensions?.requirementComments || [];
332
+ const pending = comments.filter(c=>c.status==='open' && needs.some(r=>r.id===c.requirementId));
333
+ const saveComments = value => onChange({...project,extensions:{...project.extensions,requirementComments:value}});
334
+
335
+ const names = Object.fromEntries(project.nodes.map(n => [n.id, n.data.label]));
336
+ const titles = {suggested:'Suggestions still to discuss',functional:'Functional requirements',security:'Security and access',compliance:'Data governance and compliance',availability:'Availability and recovery',reliability:'Reliability',performance:'Performance',scalability:'Capacity and growth',maintainability:'Operations and maintainability',cost:'Cost constraints',other:'Quality requirements'};
337
+ const groups = new Map();
338
+ for (const r of needs) {
339
+ const key = r.source==='agent' ? 'suggested' : r.kind === 'functional' ? 'functional' : r.category || 'other';
340
+ if (!groups.has(key)) groups.set(key, []);
341
+ groups.get(key).push(r);
342
+ }
343
+ const questions = (project.openQuestions || []).filter(q=>q.status==='open');
344
+ const purpose = project.brief?.application || project.requirements;
345
+ const system=systemDescription(project);
346
+ return <section className="doc requirements-document" aria-label="Requirements">
347
+ <div className="requirements-actions"><button className="btn" onClick={() => onDiscuss('Summarise where we have reached from the current board and our discussion. Distinguish what I have confirmed from your proposals and unresolved questions. Then ask ONE useful question to develop the requirements further, and update the summary as we discuss.')}>Let’s discuss more in chat</button>
348
+ {!!pending.length && <button className="btn" disabled={reviewing} onClick={()=>onReview(pending.slice(0,6))}>{reviewing?'Reviewing comments…':'Suggest revisions for saved feedback'} ({Math.min(6,pending.length)})</button>}
349
+ </div>
350
+ {commentMenu && <div className="ctx-menu requirement-text-menu" role="menu" aria-label="Selected text actions" style={{left:commentMenu.x,top:commentMenu.y}} onPointerDown={e=>e.stopPropagation()}>
351
+ <button role="menuitem" ref={node=>node?.focus({preventScroll:true})} onClick={()=>{setCommentTarget({...commentMenu,nonce:Date.now()});setCommentMenu(null);}}>Comment on selected text</button>
352
+ </div>}
353
+ <article className="requirements-paper" aria-label="Requirements document">
354
+ <header className="requirements-cover">
355
+ <p className="document-kicker">AtMem AI Architect · Working requirements</p>
356
+ <h2>{project.name || 'Solution requirements'}</h2><div className="row">{onUpload&&<button className="btn" onClick={onUpload}>Upload requirements or diagram</button>}{onOpenProject&&<button className="btn" onClick={onOpenProject}>Open saved project file</button>}</div><p className="muted small">Start from Word (.docx), PDF, text, Markdown, draw.io or images. Send the attached material in chat; Architect extracts requirements, proposes the diagram and asks about unclear points.</p>
357
+ <p className="document-subtitle">Where we’ve reached</p>
358
+ <p>This document brings together the requirements developed from our board and discussion. Proposed requirements remain open for review as the design evolves.</p>
359
+ <p className="document-meta">Design revision {project.revision || 1} · Working draft</p>
360
+ </header>
361
+ <section className="requirements-chapter"><h3>Purpose and scope</h3>
362
+ <p>{purpose || 'We are developing the scope together. Describe the outcome you want in chat, and this document will grow with the design.'}</p>
363
+ </section>
364
+ <section className="requirements-chapter"><h3>How the system works</h3><p>{system.overview}</p>{system.flows.map((f,i)=><div className="system-interaction" key={f.id}><h4>{i+1}. {f.title}</h4><p>{f.description}</p><p>{f.contract}</p><p className="document-meta">Proposed verification: {f.validation}</p></div>)}</section>
365
+ <section className="requirements-chapter"><h3>Component responsibilities and design rationale</h3>{system.components.map(c=><section key={c.id} className="system-component"><h4>{c.name}</h4><p className="document-meta">{c.service} · {c.placement}</p><p>{c.purpose}</p><p>{c.boundary}</p><h5>Inputs and outputs</h5><ul>{[...c.inputs,...c.outputs].map((v,i)=><li key={i}>{v}</li>)}</ul>{!c.inputs.length&&!c.outputs.length&&<p>No connections are drawn for this component.</p>}<h5>Contribution to requirements</h5>{c.requirements.length?<ul>{c.requirements.map(r=><li key={r}>{r}</li>)}</ul>:<p>No requirement is explicitly linked to this component yet.</p>}<h5>Implementation and verification</h5><p>{c.implementation}</p><p className="document-meta">Engineering considerations, to be confirmed during implementation:</p><ul>{c.engineering.map(v=><li key={v}>{v}</li>)}</ul></section>)}</section>
366
+ {[...groups].sort(([a],[b])=>(a==='suggested')-(b==='suggested')).map(([key,rows])=>{const Tag=key==='suggested'?'details':'section';return <Tag className="requirements-chapter" key={key}>
367
+ {key==='suggested'?<summary>Suggestions still to discuss ({rows.length})</summary>:<h3>{titles[key] || 'Additional requirements'}</h3>}
368
+ {key==='suggested'&&<p className="document-meta">These are early considerations, not agreed requirements. We’ll discuss the most relevant ones as the design develops.</p>}
369
+ {rows.map(r=><div className="requirement-paragraph" key={r.id}>
370
+ <h4 className="requirement-number">{requirementNumber(project,r.id)}</h4>
371
+ <p className="requirement-text" onContextMenu={event=>textMenu(event,r)}>{r.statement}</p>
372
+ {r.measure && <p className="acceptance-target">Acceptance target: {r.measure.metric} {r.measure.op} {r.measure.target} {r.measure.unit || ''}.</p>}
373
+ <p className="document-meta">{r.source === 'agent' ? 'Proposed for discussion' : 'Recorded from our discussion'}{r.links?.length ? ` · Related design: ${r.links.map(id=>names[id] || 'earlier component').join(', ')}` : ''}</p>
374
+ <div className="requirement-reason"><p><strong>{r.rationale?"Why this matters.":"Design explanation (guidance)."}</strong> {requirementExplanation(r)}</p>{r.basis&&<p className="document-meta">Basis: {r.basis}</p>}<button className="link document-discuss" onClick={()=>onDiscuss(`Explain why ${requirementNumber(project,r.id)} (${r.id}) is needed: ${r.statement}. Use the actual board and discussion as evidence, distinguish assumptions, explain the consequence of leaving it out, and ask whether it fits my needs.`)}>Explain why we need this</button></div>
375
+ <RequirementComments onReview={onReview} reviewing={reviewing} onDiscuss={onDiscuss} onResolve={(id,accept)=>onChange(resolveCommentRevision(project,id,accept))} target={commentTarget} number={requirementNumber(project,r.id)} requirement={r} comments={comments.filter(c=>c.requirementId===r.id)} onSave={(text,selectedText,review)=>{const comment={id:crypto.randomUUID(),requirementId:r.id,text,selectedText,statement:r.statement,status:'open',createdAt:new Date().toISOString()};saveComments([...comments,comment]);if(review)onReview([comment]);}} onRemove={id=>saveComments(comments.filter(c=>c.id!==id))} />
376
+ </div>)}
377
+ <button className="link document-discuss" onClick={()=>onDiscuss(`Let's discuss the ${titles[key] || key} section of our requirements document further. Current requirements: ${rows.map(r=>`${r.id}: ${r.statement}`).join('; ')}. Ask one useful question and refine the document from my answer.`)}>Discuss this section further in chat</button>
378
+ </Tag>;})}
379
+ {!needs.length && <section className="requirements-chapter"><h3>Requirements to develop</h3><p>As we discuss the idea and shape the board, AtMem AI Architect will summarise the functional requirements, constraints and acceptance targets here.</p></section>}
380
+ {!!project.assumptions?.length && <section className="requirements-chapter"><h3>Assumptions to validate</h3>{project.assumptions.map(a=><p key={a.id}>{a.statement}</p>)}</section>}
381
+ {!!questions.length && <section className="requirements-chapter"><h3>Open questions</h3>{questions.map(q=><p key={q.id}>{q.question}</p>)}<button className="link document-discuss" onClick={()=>onDiscuss(`Help resolve the open questions in our requirements document, one at a time. Start with the question that most affects the design.`)}>Let’s work through these in chat</button></section>}
382
+ <footer className="document-footer">AtMem AI Architect · Requirements derived from the current design and discussion</footer>
383
+ </article>
384
+ </section>;
385
+ }