@atmem/architect 0.0.0-stage → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (512) hide show
  1. package/CONSTITUTION.md +144 -0
  2. package/LICENSE +202 -0
  3. package/NOTICE +6 -0
  4. package/README.md +31 -2
  5. package/agent-skills/discovery/SKILL.md +48 -0
  6. package/agent-skills/discovery/topics.json +139 -0
  7. package/agent-skills/generation-capabilities.json +760 -0
  8. package/agent-skills/service-lifecycle.json +21 -0
  9. package/agent-skills/specialists/architecture/SKILL.md +15 -0
  10. package/agent-skills/specialists/aws/SKILL.md +17 -0
  11. package/agent-skills/specialists/azure/SKILL.md +7 -0
  12. package/agent-skills/specialists/composition/SKILL.md +17 -0
  13. package/agent-skills/specialists/devops/SKILL.md +10 -0
  14. package/agent-skills/specialists/finops/SKILL.md +7 -0
  15. package/agent-skills/specialists/gcp/SKILL.md +7 -0
  16. package/agent-skills/specialists/ibm/SKILL.md +7 -0
  17. package/agent-skills/specialists/manifest.json +13 -0
  18. package/agent-skills/specialists/pulumi/SKILL.md +7 -0
  19. package/agent-skills/specialists/security/SKILL.md +7 -0
  20. package/agent-skills/specialists/terraform/SKILL.md +14 -0
  21. package/agent-skills/upstream/aws/LICENSE +175 -0
  22. package/agent-skills/upstream/aws/SKILL.md +125 -0
  23. package/agent-skills/upstream/azure/LICENSE +21 -0
  24. package/agent-skills/upstream/azure/SKILL.md +387 -0
  25. package/agent-skills/upstream/gcp/LICENSE +202 -0
  26. package/agent-skills/upstream/gcp/SKILL.md +159 -0
  27. package/agent-skills/upstream/manifest.json +57 -0
  28. package/agent-skills/upstream/pulumi/LICENSE +201 -0
  29. package/agent-skills/upstream/pulumi/SKILL.md +501 -0
  30. package/agent-skills/upstream/terraform/LICENSE +373 -0
  31. package/agent-skills/upstream/terraform/SKILL.md +316 -0
  32. package/agent-skills/workflows/workflows.json +601 -0
  33. package/cli/architect.mjs +3 -0
  34. package/cli/runtime.mjs +115 -0
  35. package/dist/assets/html2canvas.esm-QH1iLAAe.js +22 -0
  36. package/dist/assets/index-BTLHaa3J.css +1 -0
  37. package/dist/assets/index-CQ2C1gKF.js +21338 -0
  38. package/dist/assets/index.es-DTyqIdaO.js +18 -0
  39. package/dist/assets/purify.es-CAi2OJFm.js +3 -0
  40. package/dist/assets/visual-export-Ox0j5xj5.js +173 -0
  41. package/dist/favicon.svg +2 -0
  42. package/dist/fonts/DM-Sans-OFL.txt +93 -0
  43. package/dist/fonts/Manrope-OFL.txt +93 -0
  44. package/dist/fonts/NotoSans-Regular.ttf +0 -0
  45. package/dist/fonts/OFL.txt +94 -0
  46. package/dist/fonts/dm-sans-latin-wght-normal.woff2 +0 -0
  47. package/dist/fonts/manrope-latin-wght-normal.woff2 +0 -0
  48. package/dist/index.html +4 -0
  49. package/dist/licenses/atmem-APACHE-2.0.txt +202 -0
  50. package/dist/licenses/aws-architect-LICENSE.txt +17 -0
  51. package/dist/licenses/aws-mcp-LICENSE.txt +175 -0
  52. package/dist/licenses/aws-mcp-NOTICE.txt +1 -0
  53. package/dist/licenses/cloud-emulation-notices.txt +36619 -0
  54. package/dist/licenses/dependency-notices.txt +6379 -0
  55. package/dist/licenses/emulation-notices.txt +717 -0
  56. package/dist/licenses/github-copilot-sdk-LICENSE.txt +21 -0
  57. package/dist/licenses/memory-dependency-notices.txt +3319 -0
  58. package/dist/licenses/openarchflow-LICENSE.txt +21 -0
  59. package/dist/licenses/python-dependency-notices.txt +11951 -0
  60. package/docs/upstream-lock.json +26 -0
  61. package/knowledge/engineering-practices.json +536 -0
  62. package/package.json +30 -4
  63. package/packaging/uv-release-lock.json +54 -0
  64. package/public/licenses/atmem-APACHE-2.0.txt +202 -0
  65. package/public/licenses/aws-architect-LICENSE.txt +17 -0
  66. package/public/licenses/aws-mcp-LICENSE.txt +175 -0
  67. package/public/licenses/aws-mcp-NOTICE.txt +1 -0
  68. package/public/licenses/cloud-emulation-notices.txt +36619 -0
  69. package/public/licenses/dependency-notices.txt +6379 -0
  70. package/public/licenses/emulation-notices.txt +717 -0
  71. package/public/licenses/github-copilot-sdk-LICENSE.txt +21 -0
  72. package/public/licenses/memory-dependency-notices.txt +3319 -0
  73. package/public/licenses/openarchflow-LICENSE.txt +21 -0
  74. package/public/licenses/python-dependency-notices.txt +11951 -0
  75. package/scripts/terraform-render.mjs +8 -0
  76. package/server/__init__.py +0 -0
  77. package/server/abstraction.py +28 -0
  78. package/server/agent_runtime.py +153 -0
  79. package/server/app.py +257 -0
  80. package/server/architect.py +112 -0
  81. package/server/architecture_activity.py +67 -0
  82. package/server/attachments.py +101 -0
  83. package/server/cloud-emulation-requirements.txt +29 -0
  84. package/server/codex_app_server.py +219 -0
  85. package/server/codex_engineering_backend.py +266 -0
  86. package/server/codex_worker_policy.py +193 -0
  87. package/server/contracts.py +315 -0
  88. package/server/copilot_worker.py +16 -0
  89. package/server/dependency_mirror.py +54 -0
  90. package/server/design_patch.py +43 -0
  91. package/server/emulation-requirements.txt +8 -0
  92. package/server/emulation_adapters.py +20 -0
  93. package/server/emulation_routes.py +98 -0
  94. package/server/emulation_worker.py +351 -0
  95. package/server/engineering_artifacts.py +221 -0
  96. package/server/engineering_assets/application-runtime.json +4372 -0
  97. package/server/engineering_assets/architecture_work.schema.json +79 -0
  98. package/server/engineering_assets/materialize_runtime.py +62 -0
  99. package/server/engineering_assets/prepare_tools.py +96 -0
  100. package/server/engineering_assets/sql_validation.py +59 -0
  101. package/server/engineering_contexts.py +120 -0
  102. package/server/engineering_delivery.py +210 -0
  103. package/server/engineering_finalization.py +210 -0
  104. package/server/engineering_handoff.py +172 -0
  105. package/server/engineering_jobs.py +206 -0
  106. package/server/engineering_knowledge.py +75 -0
  107. package/server/engineering_reconciliation.py +159 -0
  108. package/server/engineering_routes.py +483 -0
  109. package/server/engineering_sessions.py +273 -0
  110. package/server/engineering_tools.py +166 -0
  111. package/server/generation_lint.py +18 -0
  112. package/server/local_providers.py +185 -0
  113. package/server/local_validation.py +236 -0
  114. package/server/memory-requirements.lock +181 -0
  115. package/server/memory-requirements.txt +6 -0
  116. package/server/memory_context.py +58 -0
  117. package/server/memory_routes.py +141 -0
  118. package/server/memory_service.py +306 -0
  119. package/server/memory_worker.py +129 -0
  120. package/server/openai_voice.py +80 -0
  121. package/server/orca_handoff.py +90 -0
  122. package/server/packaged_app.py +9 -0
  123. package/server/pricing.py +190 -0
  124. package/server/process_control_observation.py +31 -0
  125. package/server/prompts.py +136 -0
  126. package/server/public_faq_emulation_worker.py +44 -0
  127. package/server/requirements.lock +1618 -0
  128. package/server/requirements.txt +68 -0
  129. package/server/runtime_dependency_locks.py +27 -0
  130. package/server/runtime_evidence.py +93 -0
  131. package/server/settings.py +14 -0
  132. package/server/skills.py +103 -0
  133. package/server/storage_emulation_worker.py +160 -0
  134. package/server/structured_emulation_worker.py +48 -0
  135. package/server/terraform_routes.py +118 -0
  136. package/server/upstream/__init__.py +0 -0
  137. package/server/upstream/agent/__init__.py +1 -0
  138. package/server/upstream/agent/aws_architect.py +600 -0
  139. package/server/upstream/agent/config/__init__.py +1 -0
  140. package/server/upstream/agent/config/agent_config.py +82 -0
  141. package/server/upstream/agent/config/prompts.py +138 -0
  142. package/server/upstream/agent/rate_limiter.py +62 -0
  143. package/server/upstream/utils/__init__.py +1 -0
  144. package/server/upstream/utils/file_writer.py +43 -0
  145. package/server/validation_applicability.py +85 -0
  146. package/server/validation_jobs.py +252 -0
  147. package/server/validation_workers.py +48 -0
  148. package/server/voice_routes.py +91 -0
  149. package/server/voice_worker.py +26 -0
  150. package/server/windows_snapshot.py +119 -0
  151. package/specs/028-convergence-evaluation/evidence/20261110-ibm-invoice-native/registry-structured/qualification.json +72 -0
  152. package/specs/028-convergence-evaluation/evidence/20261110-invoice-runtime/durable-current/receipt.json +61 -0
  153. package/specs/029-general-purpose-engine/evidence/20261111-runtime-dependencies/sdk/receipt.json +22 -0
  154. package/src/ArchitectureActivity.jsx +54 -0
  155. package/src/ArchitectureWorkPanel.jsx +39 -0
  156. package/src/ArtifactChecks.jsx +49 -0
  157. package/src/BlockRequirements.jsx +13 -0
  158. package/src/BrainActivity.jsx +11 -0
  159. package/src/ChatMessage.jsx +29 -0
  160. package/src/ChatResizeHandle.jsx +6 -0
  161. package/src/CodePreview.jsx +8 -0
  162. package/src/ComponentReview.jsx +31 -0
  163. package/src/DeliveryViews.jsx +59 -0
  164. package/src/EmulationPanel.jsx +44 -0
  165. package/src/EngagementViews.jsx +387 -0
  166. package/src/EngineeringPanel.jsx +151 -0
  167. package/src/FileTree.jsx +7 -0
  168. package/src/FinalChecklist.jsx +15 -0
  169. package/src/HelpNote.jsx +3 -0
  170. package/src/ImplementationDelivery.jsx +91 -0
  171. package/src/JourneyViews.jsx +403 -0
  172. package/src/LocationChoices.jsx +12 -0
  173. package/src/MemoryPanel.jsx +58 -0
  174. package/src/OpenAIVoicePanel.jsx +66 -0
  175. package/src/OutputsView.jsx +71 -0
  176. package/src/ProjectChecks.jsx +44 -0
  177. package/src/TerraformView.jsx +57 -0
  178. package/src/WorkbenchDialogs.jsx +532 -0
  179. package/src/activity-presentation.mjs +28 -0
  180. package/src/ai-qualification-scenarios.mjs +31 -0
  181. package/src/approval-application-files.mjs +32 -0
  182. package/src/approval-applications.mjs +82 -0
  183. package/src/approval-spec-kit.mjs +30 -0
  184. package/src/architecture-activity.css +28 -0
  185. package/src/architecture-activity.mjs +63 -0
  186. package/src/architecture-work.mjs +176 -0
  187. package/src/artifact-work.mjs +103 -0
  188. package/src/async-documents.mjs +191 -0
  189. package/src/atflow.css +1140 -0
  190. package/src/atforma.css +748 -0
  191. package/src/atmem-tokens.css +79 -0
  192. package/src/aws-preflight.mjs +60 -0
  193. package/src/aws-public-faq.mjs +102 -0
  194. package/src/aws-validation-scenarios.mjs +10 -0
  195. package/src/aws-validation.mjs +48 -0
  196. package/src/azure-plan-mocks.mjs +25 -0
  197. package/src/azure-structured.mjs +133 -0
  198. package/src/bedrock-summary.mjs +152 -0
  199. package/src/bounded-rag.mjs +60 -0
  200. package/src/brand.css +9 -0
  201. package/src/canvas-view.mjs +28 -0
  202. package/src/capability-composition.mjs +44 -0
  203. package/src/chat-attachments.mjs +13 -0
  204. package/src/cloud-provider-locks.mjs +9 -0
  205. package/src/cloud-storage-scenarios.mjs +2 -0
  206. package/src/component-review.mjs +55 -0
  207. package/src/composition-spec-kit.mjs +30 -0
  208. package/src/consultation-context.mjs +15 -0
  209. package/src/consultation.mjs +52 -0
  210. package/src/container-contracts.mjs +5 -0
  211. package/src/container-inspection.mjs +75 -0
  212. package/src/container-runtime.mjs +30 -0
  213. package/src/container-security-inspection.mjs +49 -0
  214. package/src/container-terraform.mjs +109 -0
  215. package/src/conversation.mjs +18 -0
  216. package/src/core.mjs +863 -0
  217. package/src/cross-cloud-storage.mjs +100 -0
  218. package/src/delivery-capabilities.mjs +25 -0
  219. package/src/delivery.mjs +58 -0
  220. package/src/deployment-ownership.mjs +10 -0
  221. package/src/deployment-region.mjs +11 -0
  222. package/src/derive.mjs +31 -0
  223. package/src/design-build-flow.mjs +10 -0
  224. package/src/diagram-attention.mjs +24 -0
  225. package/src/discovery.mjs +359 -0
  226. package/src/document.mjs +170 -0
  227. package/src/emulation-feedback.mjs +61 -0
  228. package/src/emulation-guidance.mjs +37 -0
  229. package/src/engagement.mjs +274 -0
  230. package/src/engineering-client.mjs +73 -0
  231. package/src/engineering-defaults.mjs +17 -0
  232. package/src/engineering.css +31 -0
  233. package/src/enterprise-application.mjs +76 -0
  234. package/src/enterprise-aws-host-infrastructure.mjs +62 -0
  235. package/src/enterprise-aws-host-tests.mjs +15 -0
  236. package/src/enterprise-aws-infrastructure-tests.mjs +38 -0
  237. package/src/enterprise-aws-infrastructure.mjs +138 -0
  238. package/src/enterprise-google-infrastructure.mjs +84 -0
  239. package/src/enterprise-google-tests.mjs +25 -0
  240. package/src/estimate.mjs +190 -0
  241. package/src/existing-references.mjs +18 -0
  242. package/src/external-identities.mjs +17 -0
  243. package/src/faq-lambda-build.mjs +28 -0
  244. package/src/final-package.mjs +34 -0
  245. package/src/gcp-structured.mjs +104 -0
  246. package/src/generation-provider.mjs +7 -0
  247. package/src/generation-quality.mjs +69 -0
  248. package/src/handoff.mjs +141 -0
  249. package/src/ibm-registry.mjs +12 -0
  250. package/src/ibm-structured.mjs +103 -0
  251. package/src/identifiers.mjs +15 -0
  252. package/src/implementation-map.mjs +14 -0
  253. package/src/implementation-outcome.mjs +8 -0
  254. package/src/incomplete-terraform.mjs +9 -0
  255. package/src/integrations.ts +137 -0
  256. package/src/interface-contracts.mjs +30 -0
  257. package/src/invoice-application.mjs +66 -0
  258. package/src/invoice-aws-operations.mjs +136 -0
  259. package/src/invoice-aws.mjs +143 -0
  260. package/src/invoice-azure-operations.mjs +147 -0
  261. package/src/invoice-azure.mjs +134 -0
  262. package/src/invoice-builder.mjs +35 -0
  263. package/src/invoice-dependencies.mjs +43 -0
  264. package/src/invoice-gcp-operations.mjs +178 -0
  265. package/src/invoice-gcp.mjs +104 -0
  266. package/src/invoice-ibm-operations.mjs +278 -0
  267. package/src/invoice-ibm.mjs +142 -0
  268. package/src/invoice-operations.mjs +143 -0
  269. package/src/invoice-plan.mjs +45 -0
  270. package/src/invoice-region.mjs +6 -0
  271. package/src/invoice-spec-kit.mjs +61 -0
  272. package/src/invoice-state.mjs +7 -0
  273. package/src/invoice-terraform.mjs +29 -0
  274. package/src/invoice-tests.mjs +122 -0
  275. package/src/journey-workspace.css +106 -0
  276. package/src/journey.mjs +97 -0
  277. package/src/levels.mjs +145 -0
  278. package/src/local-agent.mjs +184 -0
  279. package/src/main.jsx +2481 -0
  280. package/src/model-policy-preflight.mjs +34 -0
  281. package/src/openai-voice.mjs +102 -0
  282. package/src/output-bundle.mjs +13 -0
  283. package/src/ownership-inspection.mjs +28 -0
  284. package/src/pack.mjs +201 -0
  285. package/src/pricing.mjs +85 -0
  286. package/src/production-state.mjs +8 -0
  287. package/src/project-copy.mjs +10 -0
  288. package/src/project-file.mjs +160 -0
  289. package/src/project-links.mjs +3 -0
  290. package/src/protected-state.mjs +43 -0
  291. package/src/public-faq-builder.mjs +19 -0
  292. package/src/public-faq-clouds.mjs +251 -0
  293. package/src/public-faq.mjs +122 -0
  294. package/src/pulumi.mjs +123 -0
  295. package/src/python-container.mjs +25 -0
  296. package/src/python-runtime.mjs +50 -0
  297. package/src/rag-handler.mjs +43 -0
  298. package/src/rag-web-assets.mjs +52 -0
  299. package/src/rag-web.mjs +68 -0
  300. package/src/records.mjs +177 -0
  301. package/src/resources.mjs +163 -0
  302. package/src/review.mjs +252 -0
  303. package/src/runtime/EnterpriseDocument.java +89 -0
  304. package/src/runtime/approved_http_destination.py +72 -0
  305. package/src/runtime/aws-lambda-qualification-lock.json +7 -0
  306. package/src/runtime/aws-python-lock.json +82 -0
  307. package/src/runtime/aws-web-python-lock.json +887 -0
  308. package/src/runtime/aws_json_model.py +42 -0
  309. package/src/runtime/azure-python-lock.json +863 -0
  310. package/src/runtime/azure-sources.json +8 -0
  311. package/src/runtime/azure-test-lock.json +23 -0
  312. package/src/runtime/azure_acceptance.py +192 -0
  313. package/src/runtime/azure_structured.py +153 -0
  314. package/src/runtime/bounded_rag.py +126 -0
  315. package/src/runtime/catalog_admin.py +70 -0
  316. package/src/runtime/cloud-sql-proxy-lock.json +8 -0
  317. package/src/runtime/cloud-sql-proxy-security-review.json +30 -0
  318. package/src/runtime/connector_cli.py +50 -0
  319. package/src/runtime/connector_sync.py +70 -0
  320. package/src/runtime/durable-python-lock.json +247 -0
  321. package/src/runtime/durable_workflow.py +325 -0
  322. package/src/runtime/enterprise-application-manifest.json +110 -0
  323. package/src/runtime/enterprise-application-sources.json +266 -0
  324. package/src/runtime/enterprise-auth-python-lock.json +592 -0
  325. package/src/runtime/enterprise-aws-host-bootstrap-source.json +1 -0
  326. package/src/runtime/enterprise-aws-host-probe-source.json +1 -0
  327. package/src/runtime/enterprise-aws-task-template.json +235 -0
  328. package/src/runtime/enterprise-document-lock.json +18 -0
  329. package/src/runtime/enterprise-document.Dockerfile +15 -0
  330. package/src/runtime/enterprise-runtime-aws-python-lock.json +1115 -0
  331. package/src/runtime/enterprise-runtime-azure-python-lock.json +1106 -0
  332. package/src/runtime/enterprise-runtime-gcp-python-lock.json +1060 -0
  333. package/src/runtime/enterprise-runtime-ibm-python-lock.json +1096 -0
  334. package/src/runtime/enterprise-runtime-python-lock.json +1058 -0
  335. package/src/runtime/enterprise-runtime.Dockerfile +15 -0
  336. package/src/runtime/enterprise-web-app.js +1 -0
  337. package/src/runtime/enterprise-web-entry.js +105 -0
  338. package/src/runtime/enterprise-web-lock.json +29 -0
  339. package/src/runtime/enterprise-web-notices.txt +229 -0
  340. package/src/runtime/enterprise-web.css +4 -0
  341. package/src/runtime/enterprise-web.html +8 -0
  342. package/src/runtime/enterprise_audit.py +91 -0
  343. package/src/runtime/enterprise_audit_schema.sql +25 -0
  344. package/src/runtime/enterprise_auth_schema.sql +67 -0
  345. package/src/runtime/enterprise_auth_store.py +241 -0
  346. package/src/runtime/enterprise_aws_host_bootstrap.py +120 -0
  347. package/src/runtime/enterprise_aws_host_probe.py +105 -0
  348. package/src/runtime/enterprise_aws_hosts.py +136 -0
  349. package/src/runtime/enterprise_aws_jobs.py +300 -0
  350. package/src/runtime/enterprise_aws_objects.py +93 -0
  351. package/src/runtime/enterprise_aws_transfer.py +83 -0
  352. package/src/runtime/enterprise_azure_batch_api.py +128 -0
  353. package/src/runtime/enterprise_azure_host.py +599 -0
  354. package/src/runtime/enterprise_azure_jobs.py +294 -0
  355. package/src/runtime/enterprise_azure_objects.py +234 -0
  356. package/src/runtime/enterprise_azure_pool.py +161 -0
  357. package/src/runtime/enterprise_azure_transfer.py +122 -0
  358. package/src/runtime/enterprise_configuration.py +136 -0
  359. package/src/runtime/enterprise_document.py +116 -0
  360. package/src/runtime/enterprise_document_cli.py +32 -0
  361. package/src/runtime/enterprise_document_contract.py +54 -0
  362. package/src/runtime/enterprise_document_job.py +109 -0
  363. package/src/runtime/enterprise_document_jobs.py +122 -0
  364. package/src/runtime/enterprise_document_jobs_schema.sql +23 -0
  365. package/src/runtime/enterprise_extraction_cache.py +186 -0
  366. package/src/runtime/enterprise_extraction_schema.sql +17 -0
  367. package/src/runtime/enterprise_google_jobs.py +275 -0
  368. package/src/runtime/enterprise_google_transfer.py +85 -0
  369. package/src/runtime/enterprise_http.py +212 -0
  370. package/src/runtime/enterprise_identity.py +52 -0
  371. package/src/runtime/enterprise_knowledge.py +152 -0
  372. package/src/runtime/enterprise_models.py +94 -0
  373. package/src/runtime/enterprise_native.py +181 -0
  374. package/src/runtime/enterprise_oauth.py +132 -0
  375. package/src/runtime/enterprise_operator.py +160 -0
  376. package/src/runtime/enterprise_parser_service.py +136 -0
  377. package/src/runtime/enterprise_parser_transport.py +68 -0
  378. package/src/runtime/enterprise_queries.py +255 -0
  379. package/src/runtime/enterprise_queries_schema.sql +27 -0
  380. package/src/runtime/enterprise_query_service.py +111 -0
  381. package/src/runtime/enterprise_secrets.py +110 -0
  382. package/src/runtime/enterprise_sessions.py +95 -0
  383. package/src/runtime/enterprise_sources.py +260 -0
  384. package/src/runtime/enterprise_web.py +39 -0
  385. package/src/runtime/enterprise_worker.py +68 -0
  386. package/src/runtime/export_contract_acceptance.py +18 -0
  387. package/src/runtime/faq-output-contract.json +40 -0
  388. package/src/runtime/faq-web-app.js +41 -0
  389. package/src/runtime/faq-web.css +1 -0
  390. package/src/runtime/faq-web.html +6 -0
  391. package/src/runtime/gcp-sources.json +9 -0
  392. package/src/runtime/gcp_acceptance.py +110 -0
  393. package/src/runtime/gcp_structured.py +150 -0
  394. package/src/runtime/http_acceptance.py +39 -0
  395. package/src/runtime/iap-web-app.js +36 -0
  396. package/src/runtime/iap-web-source.json +1 -0
  397. package/src/runtime/ibm-python-lock.json +856 -0
  398. package/src/runtime/ibm-sources.json +9 -0
  399. package/src/runtime/ibm_acceptance.py +133 -0
  400. package/src/runtime/ibm_structured.py +113 -0
  401. package/src/runtime/invoice-azapi-provider-lock.json +7 -0
  402. package/src/runtime/invoice-ibm-provider-lock.json +7 -0
  403. package/src/runtime/invoice-parser-lock.json +1199 -0
  404. package/src/runtime/invoice-parser-python-lock.json +56 -0
  405. package/src/runtime/invoice-parser.Dockerfile +190 -0
  406. package/src/runtime/invoice-sources.json +58 -0
  407. package/src/runtime/invoice-test-sources.json +24 -0
  408. package/src/runtime/invoice-web.css +2 -0
  409. package/src/runtime/invoice-web.html +12 -0
  410. package/src/runtime/invoice-web.js +112 -0
  411. package/src/runtime/invoice_configuration.py +17 -0
  412. package/src/runtime/invoice_document.py +95 -0
  413. package/src/runtime/invoice_extraction.py +96 -0
  414. package/src/runtime/invoice_http.py +129 -0
  415. package/src/runtime/invoice_identity.py +5 -0
  416. package/src/runtime/invoice_maintenance.py +40 -0
  417. package/src/runtime/invoice_native.py +77 -0
  418. package/src/runtime/invoice_object_store.py +153 -0
  419. package/src/runtime/invoice_operations.py +108 -0
  420. package/src/runtime/invoice_operator.py +79 -0
  421. package/src/runtime/invoice_operator_core.py +39 -0
  422. package/src/runtime/invoice_operator_job.py +147 -0
  423. package/src/runtime/invoice_parser_cli.py +17 -0
  424. package/src/runtime/invoice_parser_identity.py +39 -0
  425. package/src/runtime/invoice_parser_service.py +89 -0
  426. package/src/runtime/invoice_parser_transport.py +89 -0
  427. package/src/runtime/invoice_processing.py +24 -0
  428. package/src/runtime/invoice_retention.py +16 -0
  429. package/src/runtime/invoice_runtime_secrets.py +43 -0
  430. package/src/runtime/invoice_stage.py +80 -0
  431. package/src/runtime/invoice_web.py +39 -0
  432. package/src/runtime/invoice_worker.py +50 -0
  433. package/src/runtime/lambda_faq.py +5 -0
  434. package/src/runtime/parser-requirements.lock +4 -0
  435. package/src/runtime/policy_review.py +18 -0
  436. package/src/runtime/postgres-qualification-lock.json +21 -0
  437. package/src/runtime/public-faq-sources.json +22 -0
  438. package/src/runtime/public_catalog_admin.py +122 -0
  439. package/src/runtime/public_catalog_store.py +125 -0
  440. package/src/runtime/public_faq.py +144 -0
  441. package/src/runtime/public_faq_app.py +49 -0
  442. package/src/runtime/python-container-lock.json +18 -0
  443. package/src/runtime/rag-sources.json +10 -0
  444. package/src/runtime/rag_acceptance.py +60 -0
  445. package/src/runtime/rag_aws_adapter.py +95 -0
  446. package/src/runtime/rds-ca-source.json +9 -0
  447. package/src/runtime/rds-global-ca.pem +2888 -0
  448. package/src/runtime/state-contract-check-source.json +4 -0
  449. package/src/runtime/state_contract_check.py +338 -0
  450. package/src/runtime/structured-source.json +1 -0
  451. package/src/runtime/structured-web-app.js +71 -0
  452. package/src/runtime/structured-web-source.json +1 -0
  453. package/src/runtime/structured_http.py +105 -0
  454. package/src/runtime/structured_output.py +48 -0
  455. package/src/runtime/web-python-lock.json +802 -0
  456. package/src/runtime/web_user_admin.py +44 -0
  457. package/src/runtime/workflow_application.py +62 -0
  458. package/src/runtime/workflow_bindings.py +128 -0
  459. package/src/runtime/workflow_configuration.py +40 -0
  460. package/src/runtime/workflow_connection.py +105 -0
  461. package/src/runtime/workflow_contract.py +54 -0
  462. package/src/runtime/workflow_database.py +94 -0
  463. package/src/runtime/workflow_errors.py +6 -0
  464. package/src/runtime/workflow_http.py +178 -0
  465. package/src/runtime/workflow_identity.py +69 -0
  466. package/src/runtime/workflow_payload.py +118 -0
  467. package/src/runtime/workflow_process_stage.py +88 -0
  468. package/src/runtime/workflow_profile.py +91 -0
  469. package/src/runtime/workflow_review.py +106 -0
  470. package/src/runtime/workflow_role_bootstrap.py +104 -0
  471. package/src/runtime/workflow_schema.sql +72 -0
  472. package/src/runtime/workflow_worker.py +142 -0
  473. package/src/runtime-settings.mjs +15 -0
  474. package/src/s3-access.mjs +14 -0
  475. package/src/source-contracts.mjs +17 -0
  476. package/src/spec-kit.mjs +186 -0
  477. package/src/state-custody.mjs +32 -0
  478. package/src/state-inspection.mjs +45 -0
  479. package/src/state-spec-kit.mjs +13 -0
  480. package/src/storage-tests.mjs +25 -0
  481. package/src/structured-api.mjs +133 -0
  482. package/src/structured-contract.mjs +19 -0
  483. package/src/structured-operation-policy.mjs +2 -0
  484. package/src/structured-web.mjs +17 -0
  485. package/src/style.css +1 -0
  486. package/src/system-description.mjs +26 -0
  487. package/src/terraform-admission.mjs +66 -0
  488. package/src/terraform-composition.mjs +83 -0
  489. package/src/terraform-expressions.mjs +46 -0
  490. package/src/terraform-validation-coverage.mjs +11 -0
  491. package/src/terraform.mjs +128 -0
  492. package/src/text-statistics.mjs +51 -0
  493. package/src/upstream/openarchflow/format-payload.ts +26 -0
  494. package/src/upstream/openarchflow/import/mermaid.ts +205 -0
  495. package/src/upstream/openarchflow/import/sql-ddl.ts +109 -0
  496. package/src/upstream/openarchflow/layout.ts +54 -0
  497. package/src/upstream/openarchflow/providers/aws.ts +196 -0
  498. package/src/upstream/openarchflow/providers/azure.ts +126 -0
  499. package/src/upstream/openarchflow/providers/cloudnative.ts +71 -0
  500. package/src/upstream/openarchflow/providers/generic.ts +227 -0
  501. package/src/upstream/openarchflow/providers/integration.ts +22 -0
  502. package/src/upstream/openarchflow/providers/types.ts +2 -0
  503. package/src/upstream/openarchflow/templates.ts +937 -0
  504. package/src/upstream-catalog.mjs +10 -0
  505. package/src/useChatScroll.jsx +37 -0
  506. package/src/useEmulation.jsx +36 -0
  507. package/src/useEngineeringStatus.mjs +17 -0
  508. package/src/validation-receipt.mjs +10 -0
  509. package/src/visual-export.mjs +92 -0
  510. package/src/voice-conversation.mjs +117 -0
  511. package/src/work-intake.mjs +24 -0
  512. package/src/workflow-runtime-inventory.mjs +3 -0
@@ -0,0 +1,58 @@
1
+ """Operator-configured external RAG/memory retrieval; never persists returned context."""
2
+ from concurrent.futures import ThreadPoolExecutor
3
+ import json
4
+ import os
5
+ import re
6
+ from urllib.parse import urlsplit
7
+ import urllib.request
8
+ from .settings import setting
9
+
10
+
11
+ def providers():
12
+ values=json.loads(setting('MEMORY_CONTEXT_PROVIDERS') or '[]')
13
+ if not isinstance(values,list)or len(values)>4:raise ValueError('Configure at most four context providers')
14
+ seen=set()
15
+ for value in values:
16
+ if not isinstance(value,dict)or set(value)-{'id','label','url','tokenEnv','enabled','kind'}:raise ValueError('Invalid context provider configuration')
17
+ ident=value.get('id','');url=urlsplit(value.get('url',''))
18
+ if not re.fullmatch(r'[a-z][a-z0-9-]{0,63}',ident)or ident in seen or url.scheme not in {'http','https'}or not url.hostname or url.username or url.password or url.fragment or url.query:raise ValueError('Context providers need unique IDs and credential-free HTTP endpoints')
19
+ token=value.get('tokenEnv')
20
+ if token and not re.fullmatch(r'[A-Z][A-Z0-9_]{0,99}',token):raise ValueError('Use an environment variable for provider credentials')
21
+ seen.add(ident)
22
+ return values
23
+
24
+
25
+ def describe():
26
+ return [{'id':value['id'],'label':str(value.get('label')or value['id'])[:80],'kind':value.get('kind','rag'),'enabled':value.get('enabled',True),'configured':True}for value in providers()]
27
+
28
+
29
+ class NoRedirect(urllib.request.HTTPRedirectHandler):
30
+ def redirect_request(self,*args,**kwargs):return None
31
+
32
+
33
+ def retrieve(project,owner,query,safe):
34
+ configured=[value for value in providers()if value.get('enabled',True)]
35
+ if not configured:return [],[]
36
+ def fetch(value):
37
+ ident=value['id'];headers={'Content-Type':'application/json'}
38
+ if value.get('tokenEnv'):
39
+ token=os.getenv(value['tokenEnv'])
40
+ if not token:return [],{'id':ident,'status':'credential_missing'}
41
+ headers['Authorization']='Bearer '+token
42
+ request=urllib.request.Request(value['url'],data=json.dumps({'query':query[:4000],'userId':owner,'projectId':project,'limit':6}).encode(),headers=headers,method='POST')
43
+ try:
44
+ with urllib.request.build_opener(NoRedirect).open(request,timeout=4)as response:data=response.read(100001)
45
+ if len(data)>100000:raise ValueError('Context exceeds bound')
46
+ result=json.loads(data);rows=result.get('records')
47
+ if not isinstance(rows,list)or len(rows)>6:raise ValueError('Invalid context response')
48
+ context=[]
49
+ for row in rows:
50
+ scope=row.get('scope','project')
51
+ if scope not in {'project','user'}or row.get('userId')!=owner or(scope=='project'and row.get('projectId')!=project)or(scope=='user'and row.get('projectId')not in {None,''}):raise ValueError('Context scope mismatch')
52
+ text=row.get('text');source=row.get('source');record_id=row.get('id')
53
+ if not isinstance(text,str)or not 0<len(text)<=4000 or not safe(text)or not isinstance(source,dict)or not isinstance(record_id,str)or len(record_id)>160 or not safe(source):raise ValueError('Invalid context provenance')
54
+ context.append({'id':ident+':'+record_id,'scope':scope,'text':text,'sourceDate':row.get('createdAt'),'key':row.get('key'),'provider':ident,'source':source,'external':True,'boundary':'retrieved_context_only'})
55
+ return context,{'id':ident,'status':'ready','records':len(context)}
56
+ except Exception:return [],{'id':ident,'status':'unavailable'}
57
+ with ThreadPoolExecutor(max_workers=4)as pool:results=list(pool.map(fetch,configured))
58
+ return [row for rows,_ in results for row in rows],[state for _,state in results]
@@ -0,0 +1,141 @@
1
+ """All memory requests pass the existing loopback + bearer middleware."""
2
+ import asyncio
3
+ from fastapi import APIRouter, HTTPException
4
+ from pydantic import Field, StrictBool
5
+ from typing import Literal
6
+ from .contracts import Strict
7
+ from .memory_service import service
8
+ from . import skills
9
+ from .pricing import aws_s3, storage_quote, lambda_quote, google_public_quote
10
+
11
+ router=APIRouter()
12
+ class Target(Strict):
13
+ projectId:str=Field(pattern=r'^[A-Za-z0-9-]{8,64}$')
14
+ class Snapshot(Target):
15
+ file:dict
16
+ class Setting(Target):
17
+ enabled:StrictBool
18
+ class Profile(Target):
19
+ field:Literal['explanation','experience','iac','preferences']
20
+ value:str=Field(min_length=1,max_length=1000)
21
+ class Forget(Target):
22
+ scope:Literal['user','project']
23
+ recordId:str=Field(pattern=r'^rec_[a-f0-9]{32}$')
24
+ class Skill(Target):
25
+ skillId:str=Field(max_length=80)
26
+ enabled:StrictBool
27
+ class Price(Target):
28
+ provider:Literal['aws','azure','gcp','ibm']='aws'
29
+ region:str=Field(max_length=40)
30
+
31
+ async def invoke(fn,*args,**kwargs):
32
+ try:return await asyncio.to_thread(fn,*args,**kwargs)
33
+ except ValueError as exc:raise HTTPException(422,str(exc))
34
+ except Exception:raise HTTPException(503,'AtMem is unavailable; your project still works. Run npm run setup:memory if needed.')
35
+
36
+ @router.post('/api/memory/sync')
37
+ async def sync(payload:Snapshot):
38
+ return await invoke(service().sync,payload.projectId,payload.file)
39
+
40
+ @router.post('/api/memory/inspect')
41
+ async def inspect(payload:Target):
42
+ memory=service()
43
+ result=await invoke(memory.inspect,payload.projectId)
44
+ result['skills']=skills.public(skills.catalogue(memory,payload.projectId))
45
+ return result
46
+
47
+ @router.post('/api/memory/settings')
48
+ async def settings(payload:Setting):
49
+ return await invoke(service().configure,payload.projectId,payload.enabled)
50
+
51
+ @router.post('/api/memory/profile')
52
+ async def profile(payload:Profile):
53
+ return await invoke(service().profile,payload.projectId,payload.field,payload.value)
54
+
55
+ @router.post('/api/memory/forget-preview')
56
+ async def preview(payload:Forget):
57
+ result=await invoke(service().record_detail,payload.projectId,payload.scope,payload.recordId,True)
58
+ return {**result,'notice':'Removes this memory and its history. Project files remain.'}
59
+
60
+ @router.post('/api/memory/forget')
61
+ async def forget(payload:Forget):
62
+ return await invoke(service().forget,payload.projectId,payload.scope,payload.recordId)
63
+
64
+ @router.post('/api/memory/skill')
65
+ async def skill(payload:Skill):
66
+ memory=service()
67
+ if payload.skillId not in {s['id'] for s in skills.registry()}:raise HTTPException(422,'Unknown skill')
68
+ with memory.lock,memory.db() as db:db.execute('INSERT OR REPLACE INTO skill_settings VALUES (?,?)',(payload.skillId,int(payload.enabled)))
69
+ return {'enabled':payload.enabled}
70
+
71
+ @router.post('/api/pricing/aws-s3')
72
+ async def price(payload:Price):
73
+ try:return await asyncio.to_thread(aws_s3,payload.region)
74
+ except Exception:raise HTTPException(503,'AWS storage pricing is unavailable or the region is not supported. No price was invented.')
75
+
76
+ @router.post('/api/pricing/storage')
77
+ async def storage(payload:Price):
78
+ try:return await asyncio.to_thread(storage_quote,payload.provider,payload.region)
79
+ except Exception:raise HTTPException(503,'The exact provider/region price could not be verified. No rate was invented.')
80
+
81
+
82
+ class LambdaPrice(Target):
83
+ region:str=Field(max_length=40)
84
+ architecture:Literal['x86_64','arm64']='x86_64'
85
+
86
+ @router.post('/api/pricing/lambda')
87
+ async def lambda_price(payload:LambdaPrice):
88
+ try:return await asyncio.to_thread(lambda_quote,payload.region,payload.architecture)
89
+ except Exception:raise HTTPException(503,'The regional Lambda price is unavailable. Retry pricing; no rate was invented.')
90
+
91
+
92
+ class GooglePrice(Target):
93
+ service:Literal['cloud-run','cloud-sql']
94
+ region:str=Field(default='',max_length=40)
95
+ planningReference:StrictBool=False
96
+
97
+ @router.post('/api/pricing/google')
98
+ async def google_price(payload:GooglePrice):
99
+ try:return await asyncio.to_thread(google_public_quote,payload.service,payload.region,payload.planningReference)
100
+ except ValueError as error:raise HTTPException(422,str(error)) from None
101
+ except Exception:raise HTTPException(503,'Google pricing could not be verified. Retry pricing.') from None
102
+
103
+
104
+ class MemoryPage(Target):
105
+ scope:Literal['user','project','knowledge']='project'
106
+ status:Literal['active','superseded','quarantined','all']='active'
107
+ query:str=Field(default='',max_length=200)
108
+ cursor:str|None=Field(default=None,max_length=500)
109
+ limit:int=Field(default=50,ge=1,le=100,strict=True)
110
+
111
+ class ProfileName(Strict):
112
+ name:str=Field(min_length=1,max_length=80)
113
+
114
+ @router.post('/api/memory/records')
115
+ async def memory_records(payload:MemoryPage):
116
+ return await invoke(service().browse,payload.projectId,payload.scope,status=payload.status,query=payload.query,cursor=payload.cursor,limit=payload.limit)
117
+
118
+ @router.post('/api/memory/record')
119
+ async def memory_record(payload:Forget):
120
+ return await invoke(service().record_detail,payload.projectId,payload.scope,payload.recordId)
121
+
122
+ @router.post('/api/memory/user-profile')
123
+ async def user_profile(payload:ProfileName):
124
+ return await invoke(service().rename_profile,payload.name)
125
+
126
+
127
+ class ContextRequest(Target):
128
+ query:str=Field(min_length=1,max_length=4000)
129
+
130
+ @router.post('/api/memory/context')
131
+ async def memory_context(payload:ContextRequest):
132
+ memory=service()
133
+ records,status=await invoke(memory.recall,payload.projectId,payload.query)
134
+ return {'records':records,'status':status,'userId':memory.owner,'projectId':payload.projectId,'boundary':'retrieval_only'}
135
+
136
+
137
+ @router.post('/api/memory/overview')
138
+ async def memory_overview(payload:Target):
139
+ memory=service();result=await invoke(memory.overview,payload.projectId)
140
+ result['skills']=skills.public(skills.catalogue(memory,payload.projectId))
141
+ return result
@@ -0,0 +1,306 @@
1
+ from .settings import setting, home as product_home
2
+ """AtMem AI Architect's authenticated single-user scope policy over the real AtMem core SDK.
3
+
4
+ Application queue/receipts live in state.sqlite; memory and supersession live in AtMem.
5
+ No unfiltered dashboard, shared ~/.atmem store, or model-selected subject is exposed.
6
+ """
7
+ import hashlib
8
+ import json
9
+ import os
10
+ from pathlib import Path
11
+ import re
12
+ import sqlite3
13
+ import subprocess
14
+ import threading
15
+ import uuid
16
+ from contextlib import contextmanager
17
+ from datetime import datetime, timezone
18
+
19
+ ROOT = Path(__file__).resolve().parent.parent
20
+ SECRET_KEY = re.compile(r'^(password|secret|api_?key|access_?key|token|client_?secret)$', re.I)
21
+ SECRET_VALUE = re.compile(r'AKIA[0-9A-Z]{16}|sk-(?:ant-)?[A-Za-z0-9_-]{20,}|ghp_[A-Za-z0-9]{36}|AIza[\w-]{35}|-----BEGIN .*PRIVATE KEY-----')
22
+
23
+
24
+ def safe(value):
25
+ if isinstance(value, str):
26
+ return not SECRET_VALUE.search(value)
27
+ if isinstance(value, list):
28
+ return all(safe(v) for v in value)
29
+ if isinstance(value, dict):
30
+ return all(not (SECRET_KEY.match(k) and v) and safe(v) for k, v in value.items())
31
+ return True
32
+
33
+
34
+ def digest(value):
35
+ return hashlib.sha256(json.dumps(value, sort_keys=True, ensure_ascii=False).encode()).hexdigest()
36
+
37
+
38
+ def timestamp():
39
+ return datetime.now(timezone.utc).isoformat()
40
+
41
+
42
+ class MemoryService:
43
+ def __init__(self, home=None, worker=None):
44
+ self.home = Path(home or product_home()) / 'memory'
45
+ self.home.mkdir(parents=True, exist_ok=True, mode=0o700)
46
+ self.worker = str(worker or setting('MEMORY_PYTHON') or ROOT / '.memory-venv' / ('Scripts/python.exe' if os.name == 'nt' else 'bin/python'))
47
+ self.lock = threading.RLock()
48
+ self.error = None
49
+ with self.db() as db:
50
+ db.executescript('''
51
+ CREATE TABLE IF NOT EXISTS identity (id TEXT PRIMARY KEY);
52
+ CREATE TABLE IF NOT EXISTS profiles (id TEXT PRIMARY KEY,name TEXT NOT NULL);
53
+ CREATE TABLE IF NOT EXISTS settings (project TEXT PRIMARY KEY, enabled INTEGER NOT NULL DEFAULT 1);
54
+ CREATE TABLE IF NOT EXISTS snapshots (project TEXT PRIMARY KEY, revision INTEGER, entities TEXT, digest TEXT);
55
+ CREATE TABLE IF NOT EXISTS queue (seq INTEGER PRIMARY KEY AUTOINCREMENT, event_id TEXT UNIQUE, project TEXT, scope TEXT, key TEXT, text TEXT, source TEXT, state TEXT, created TEXT);
56
+ CREATE TABLE IF NOT EXISTS activity (id TEXT PRIMARY KEY, project TEXT, created TEXT, payload TEXT);
57
+ CREATE TABLE IF NOT EXISTS skill_settings (id TEXT PRIMARY KEY, enabled INTEGER);
58
+ ''')
59
+ row = db.execute('SELECT id FROM identity').fetchone()
60
+ if 'reason' not in {r[1] for r in db.execute('PRAGMA table_info(queue)')}:
61
+ db.execute("ALTER TABLE queue ADD COLUMN reason TEXT DEFAULT ''")
62
+ self.owner = row[0] if row else str(uuid.uuid4())
63
+ if not row:
64
+ db.execute('INSERT INTO identity VALUES (?)', (self.owner,))
65
+ db.execute("INSERT OR IGNORE INTO profiles VALUES (?,?)",(self.owner,'Default profile'))
66
+
67
+ @contextmanager
68
+ def db(self):
69
+ db = sqlite3.connect(self.home / 'state.sqlite', timeout=15)
70
+ db.execute('PRAGMA secure_delete=ON')
71
+ try:
72
+ with db:
73
+ yield db
74
+ finally:
75
+ db.close()
76
+
77
+ def project(self, project):
78
+ if not isinstance(project, str) or not re.fullmatch(r'[A-Za-z0-9-]{8,64}', project):
79
+ raise ValueError('Invalid project identity')
80
+ return project
81
+
82
+ def subject(self, scope, project):
83
+ return 'atforma-' + digest([self.owner, scope, project if scope == 'project' else 'shared'])[:40]
84
+
85
+ def enabled(self, project):
86
+ with self.db() as db:
87
+ row = db.execute('SELECT enabled FROM settings WHERE project=?', (project,)).fetchone()
88
+ return not row or bool(row[0])
89
+
90
+ def configure(self, project, enabled):
91
+ self.project(project)
92
+ with self.lock, self.db() as db:
93
+ db.execute('INSERT OR REPLACE INTO settings VALUES (?,?)', (project, int(enabled)))
94
+ if not enabled:
95
+ db.execute("UPDATE queue SET state='cancelled' WHERE project=? AND state='pending'", (project,))
96
+ return {'enabled': enabled}
97
+
98
+ def call(self, operations):
99
+ operations=[{**op,'owner':self.owner,'actor':'user:'+self.owner if (op.get('subject')==self.subject('user','') or op.get('action')=='forget') else 'atmem-project-sync','actorType':'user' if (op.get('subject')==self.subject('user','') or op.get('action')=='forget') else 'project-sync'}for op in operations]
100
+ result = subprocess.run([self.worker, '-I', str(ROOT / 'server/memory_worker.py')],
101
+ input=json.dumps({'database': str(self.home / 'memories.db'), 'operations': operations}),
102
+ text=True, capture_output=True, timeout=25, cwd=str(self.home))
103
+ try:
104
+ payload = json.loads(result.stdout)
105
+ except (ValueError, TypeError):
106
+ raise RuntimeError('AtMem runtime unavailable; run npm run setup:memory') from None
107
+ if result.returncode or 'error' in payload:
108
+ raise RuntimeError('AtMem rejected the operation (' + payload.get('error', 'worker failed') + ')')
109
+ self.error = None
110
+ return payload['results']
111
+
112
+ def enqueue(self, project, scope, key, text, event_id=None, source=''):
113
+ if not safe(text) or len(text) > 1900:
114
+ raise ValueError('Memory content is too long or looks like a credential')
115
+ event_id = event_id or digest([project, scope, key, text])
116
+ with self.db() as db:
117
+ db.execute("INSERT OR IGNORE INTO queue(event_id,project,scope,key,text,source,state,created) VALUES (?,?,?,?,?,?,'pending',?)", (event_id, project, scope, key, text, source, timestamp()))
118
+
119
+ def flush(self):
120
+ with self.lock:
121
+ with self.db() as db:
122
+ rows = db.execute("SELECT seq,event_id,project,scope,key,text,source FROM queue WHERE state='pending' ORDER BY seq LIMIT 500").fetchall()
123
+ if not rows:
124
+ return True
125
+ try:
126
+ # The worker durably receipts each event so a partial batch can replay safely.
127
+ results = self.call([{'action': 'remember', 'subject': self.subject(scope, project), 'key': key, 'text': text, 'eventId': event, 'source': source} for seq, event, project, scope, key, text, source in rows])
128
+ with self.db() as db:
129
+ for row, result in zip(rows, results):
130
+ db.execute("UPDATE queue SET state=?,reason=?,text='',source='' WHERE seq=?", ('rejected' if result.get('refused') else 'synced', json.dumps(result.get('refused',[])), row[0]))
131
+ return True
132
+ except (OSError, RuntimeError, subprocess.TimeoutExpired):
133
+ self.error = 'AtMem unavailable — using this project only; eligible changes queued'
134
+ return False
135
+
136
+ @staticmethod
137
+ def entities(file):
138
+ values = {}
139
+ design = file.get('design') or {}
140
+ # The editable project already holds the diagram, comments and conversation brief.
141
+ # Only durable, confirmed facts belong in long-term memory.
142
+ for category in ('requirements', 'assumptions', 'openQuestions'):
143
+ for item in file.get(category, [])[:300]:
144
+ if category != 'requirements' or item.get('source') != 'user' or item.get('priority') != 'must' or str(item.get('id','')).startswith('drv-'):
145
+ continue
146
+ key = str(item.get('id', ''))
147
+ content = item.get('statement') or item.get('question')
148
+ if key and content:
149
+ values[f'{category}.{key}'] = f'{category} [{key}]: {content}; status: {item.get("status", "recorded")}'[:1800]
150
+ for item in file.get('discovery', {}).get('facts', [])[:300]:
151
+ if isinstance(item, dict) and item.get('name') == 'budget.per_month' and not item.get('conflictsWith'):
152
+ name = str(item['name'])
153
+ values['fact.' + name] = f'Project fact {name}: {item.get("value")} {item.get("unit", "")}; stated {item.get("madeAt", "unknown")}' + ('; unresolved conflict: confirm with user' if item.get('conflictsWith') else '')
154
+ decisions = file.get('decisions', [])
155
+ for item in decisions[:200]:
156
+ if item.get('status') != 'Accepted':
157
+ continue
158
+ subject = str(item.get('subject') or item.get('id') or 'decision')
159
+ if subject.startswith('design.'):
160
+ continue
161
+ values['decision.' + subject] = f'Project decision {subject}: {item.get("decision") or item.get("title", "")}; status: {item.get("status", "Proposed")}; reason: {item.get("reason") or item.get("rationale") or "not recorded"}'[:1800]
162
+ return values
163
+
164
+ def sync(self, project, file):
165
+ self.project(project)
166
+ if not isinstance(file, dict) or file.get('format') not in {'atmem.ai-architect.project','atforma.project'} or file.get('meta', {}).get('id') != project or not safe(file):
167
+ raise ValueError('Invalid project snapshot or credential-bearing data')
168
+ revision = file.get('meta', {}).get('revision')
169
+ if not isinstance(revision, int) or revision < 1:
170
+ raise ValueError('Invalid project revision')
171
+ with self.lock:
172
+ if not self.enabled(project):
173
+ return {'enabled': False, 'status': 'disabled'}
174
+ entities = self.entities(file)
175
+ with self.db() as db:
176
+ old = db.execute('SELECT revision,entities,digest FROM snapshots WHERE project=?', (project,)).fetchone()
177
+ if old and revision < old[0]:
178
+ return {'status': 'conflict', 'detail': 'Older project revision; memory was not changed'}
179
+ previous = json.loads(old[1]) if old else {}
180
+ change_id = str(uuid.uuid4())
181
+ with self.db() as db:
182
+ # Snapshot update and outbox insertion are one transaction: no lost change on crash.
183
+ for key in previous.keys() | entities.keys():
184
+ text = entities.get(key, f'{key} was removed from this project; do not treat the earlier value as current.')
185
+ if previous.get(key) == entities.get(key):
186
+ continue
187
+ db.execute("INSERT INTO queue(event_id,project,scope,key,text,source,state,created) VALUES (?,?,?,?,?,?,'pending',?)", (digest([change_id,key]), project, 'project', key, text, 'project snapshot r' + str(revision), timestamp()))
188
+ db.execute('INSERT OR REPLACE INTO snapshots VALUES (?,?,?,?)', (project, revision, json.dumps(entities), digest(file)))
189
+ self.flush()
190
+ return self.status(project)
191
+
192
+ def status(self, project):
193
+ with self.db() as db:
194
+ counts = dict(db.execute('SELECT state,count(*) FROM queue WHERE project=? GROUP BY state', (project,)).fetchall())
195
+ return {'enabled': self.enabled(project), 'status': 'disabled' if not self.enabled(project) else 'unavailable' if self.error else 'ready', 'pending': counts.get('pending', 0), 'rejected': counts.get('rejected', 0), 'engine': 'AtMem 2.3.10 core SDK', 'policy': 'AtMem AI Architect single-user scope and opt-out policy', 'detail': self.error}
196
+
197
+ def profile(self, project, field, value):
198
+ if field not in {'explanation', 'experience', 'iac', 'preferences'} or not value.strip() or len(value) > 1000:
199
+ raise ValueError('Choose a profile field and enter up to 1,000 characters')
200
+ with self.lock:
201
+ if not self.enabled(project):
202
+ raise ValueError('Memory is disabled for this project')
203
+ # User presses Remember; these are confirmed preferences, not model inferences.
204
+ self.enqueue(project, 'user', 'profile.' + field, f'User-confirmed {field}: {value.strip()}', event_id=str(uuid.uuid4()))
205
+ self.flush()
206
+ return self.status(project)
207
+
208
+ def overview(self,project):
209
+ from .memory_context import describe
210
+ self.project(project)
211
+ with self.lock,self.db()as db:
212
+ activity=[{'id':row[0],'createdAt':row[1],**json.loads(row[2])}for row in db.execute('SELECT id,created,payload FROM activity WHERE project=? ORDER BY created DESC LIMIT 20',(project,))]
213
+ return {**self.status(project),'activity':activity,'userProfile':self.user_profile(),'contextProviders':describe()}
214
+
215
+ def inspect(self, project):
216
+ from .memory_context import describe
217
+ self.project(project)
218
+ with self.lock:
219
+ if self.enabled(project):
220
+ self.flush()
221
+ subjects = [self.subject('user', project), self.subject('project', project), self.subject('knowledge', project)]
222
+ try:
223
+ results = self.call([{'action': 'page', 'subject': s,'status':'all','limit':50} for s in subjects])
224
+ records = [page['records'] for page in results]
225
+ except (OSError, RuntimeError, subprocess.TimeoutExpired):
226
+ self.error = 'AtMem unavailable — using this project only; eligible changes queued'
227
+ records = [[], [], []]
228
+ with self.db() as db:
229
+ activity = [{'id': r[0], 'createdAt': r[1], **json.loads(r[2])} for r in db.execute('SELECT id,created,payload FROM activity WHERE project=? ORDER BY created DESC LIMIT 20', (project,))]
230
+ events = [{'key':r[0],'status':r[1],'reason':r[2],'createdAt':r[3]} for r in db.execute("SELECT key,state,reason,created FROM queue WHERE project=? AND state IN ('pending','rejected') ORDER BY seq DESC LIMIT 20",(project,))]
231
+ return {**self.status(project), 'profile': records[0], 'project': records[1], 'knowledge': records[2], 'activity': activity, 'events':events,'userProfile':self.user_profile(),'contextProviders':describe()}
232
+
233
+ def user_profile(self):
234
+ with self.db()as db:name=db.execute('SELECT name FROM profiles WHERE id=?',(self.owner,)).fetchone()[0]
235
+ return {'id':self.owner,'name':name,'kind':'local','identitySource':'local-installation'}
236
+
237
+ def rename_profile(self,name):
238
+ if not isinstance(name,str)or not name.strip()or len(name)>80:raise ValueError('Enter a profile name up to 80 characters')
239
+ with self.lock,self.db()as db:db.execute('UPDATE profiles SET name=? WHERE id=?',(name.strip(),self.owner))
240
+ return self.user_profile()
241
+
242
+ def browse(self,project,scope='project',**options):
243
+ self.project(project)
244
+ if scope not in {'user','project','knowledge'}:raise ValueError('Invalid memory scope')
245
+ with self.lock:return self.call([{'action':'page','subject':self.subject(scope,project),**options}])[0]
246
+
247
+ def record_detail(self,project,scope,record_id,preview=False):
248
+ self.project(project)
249
+ if scope not in {'user','project'}:raise ValueError('Invalid memory scope')
250
+ with self.lock:return self.call([{'action':'forget-preview'if preview else 'record','subject':self.subject(scope,project),'recordId':record_id}])[0]
251
+
252
+ def forget(self, project, scope, record_id):
253
+ if scope not in {'user', 'project'}:
254
+ raise ValueError('Invalid memory scope')
255
+ with self.lock:
256
+ result = self.call([{'action': 'forget', 'subject': self.subject(scope, project), 'recordId': record_id}])[0]
257
+ key = result.pop('key')
258
+ with self.db() as db:
259
+ # Remove plaintext outbox copies too, and cancel replay of this exact key.
260
+ if scope == 'user':
261
+ db.execute('DELETE FROM queue WHERE scope=? AND key=?', (scope, key))
262
+ else:
263
+ db.execute('DELETE FROM queue WHERE project=? AND scope=? AND key=?', (project, scope, key))
264
+ return result
265
+
266
+ def recall(self, project, query):
267
+ self.project(project)
268
+ with self.lock:
269
+ if not self.enabled(project):
270
+ return [], self.status(project)
271
+ if not self.flush():
272
+ return [], self.status(project)
273
+ try:
274
+ rows = self.call([{'action': 'recall', 'subject': self.subject(s, project), 'query': query, 'limit': 6} for s in ('user', 'project')])
275
+ context = [{'scope': scope, 'id': r['id'], 'text': r['content'], 'sourceDate': r['created_at'], 'key': r.get('fact_key')} for scope, records in zip(('user','project'), rows) for r in records]
276
+ from .memory_context import retrieve
277
+ external,provider_status=retrieve(project,self.owner,query,safe)
278
+ return context+external,{**self.status(project),'contextProviders':provider_status}
279
+ except (OSError, RuntimeError, subprocess.TimeoutExpired):
280
+ self.error = 'AtMem unavailable — using this project only; eligible changes queued'
281
+ return [], self.status(project)
282
+
283
+ def record_turn(self, project, payload):
284
+ payload={**payload,'userId':self.owner,'actor':'atmem-architect','actorType':'agent'}
285
+ ident = str(uuid.uuid4())
286
+ with self.lock, self.db() as db:
287
+ db.execute('INSERT INTO activity VALUES (?,?,?,?)', (ident, project, timestamp(), json.dumps(payload)))
288
+ db.execute('DELETE FROM activity WHERE project=? AND id NOT IN (SELECT id FROM activity WHERE project=? ORDER BY created DESC LIMIT 100)', (project, project))
289
+ if self.enabled(project) and payload.get('recordIds'):
290
+ try:
291
+ self.call([{'action': 'log', 'subject': self.subject('project', project), 'eventType': 'atforma.turn', 'payload': payload}])
292
+ except (OSError, RuntimeError, subprocess.TimeoutExpired):
293
+ pass
294
+ return ident
295
+
296
+
297
+ _instance = None
298
+ _instance_home = None
299
+ _guard = threading.Lock()
300
+ def service():
301
+ global _instance, _instance_home
302
+ home = str(product_home())
303
+ with _guard:
304
+ if _instance is None or _instance_home != home:
305
+ _instance, _instance_home = MemoryService(home), home
306
+ return _instance
@@ -0,0 +1,129 @@
1
+ """Isolated pinned AtMem SDK process. JSON over stdio; no model/cloud tools."""
2
+ import json
3
+ import sys
4
+ import sqlite3
5
+ import base64
6
+ import re
7
+ from importlib.metadata import version
8
+ from atmem import Memory
9
+
10
+
11
+ def public_record(record, owner=None, memory=None):
12
+ episode=memory.store.get_episode(record['subject_id'],record['episode_id'])if memory and record.get('episode_id')else None
13
+ raw=(episode or {}).get('raw') or record.get('raw') or {}
14
+ return {**{key:record.get(key)for key in ('id','content','status','fact_key','created_at','updated_at','supersedes_id','source_type')},
15
+ 'governance':{'userId':raw.get('user_id'), 'actor':raw.get('actor'), 'actorType':raw.get('actor_type'),
16
+ 'source':raw.get('source_url') or raw.get('interpreter'), 'ownerUserId':owner}}
17
+
18
+
19
+ def page_records(memory,subject,op):
20
+ # Pinned SDK adapter: use its policy-aware connection, never reopen the database.
21
+ from atmem.store.sqlite import _record_from_row
22
+ db=memory.store._conn
23
+ limit=max(1,min(int(op.get('limit',50)),100));query=str(op.get('query','')).strip()[:200]
24
+ status=op.get('status','active')
25
+ statuses=('active','superseded','quarantined') if status=='all' else (status,)
26
+ if any(value not in {'active','superseded','quarantined'}for value in statuses):raise ValueError('Invalid memory status')
27
+ before=None
28
+ if op.get('cursor'):
29
+ before=json.loads(base64.urlsafe_b64decode(op['cursor']).decode())
30
+ if not isinstance(before,list)or len(before)!=2 or any(not isinstance(v,str)or len(v)>100 for v in before):raise ValueError('Invalid page cursor')
31
+ candidates=[];total=0
32
+ for selected in statuses:
33
+ clauses=['subject_id=?','status=?'];args=[subject,selected]
34
+ if query:
35
+ if query.startswith('rec_'):
36
+ clauses.append('id=?');args.append(query)
37
+ else:
38
+ terms=re.findall(r'[^\W_]+',query,flags=re.UNICODE)[:12]
39
+ if not terms:raise ValueError('Enter a search word or record ID')
40
+ if not memory.store._fts_enabled:raise ValueError('Indexed search is unavailable for this store')
41
+ expression=' AND '.join('"'+word.replace('"','')+'"'for word in terms)
42
+ clauses.append('id IN (SELECT record_id FROM records_fts WHERE records_fts MATCH ? AND subject_id=?)')
43
+ args.extend([expression,subject])
44
+ where=' AND '.join(clauses)
45
+ total+=db.execute('SELECT COUNT(*) FROM records WHERE '+where,args).fetchone()[0]
46
+ if before:where+=' AND (created_at,id)<(?,?)';args.extend(before)
47
+ rows=db.execute('SELECT * FROM records WHERE '+where+' ORDER BY created_at DESC,id DESC LIMIT ?',(*args,limit+1)).fetchall()
48
+ candidates.extend(_record_from_row(row)for row in rows)
49
+ candidates.sort(key=lambda row:(row['created_at'],row['id']),reverse=True)
50
+ more=len(candidates)>limit;rows=candidates[:limit]
51
+ cursor=base64.urlsafe_b64encode(json.dumps([rows[-1]['created_at'],rows[-1]['id']]).encode()).decode()if more and rows else None
52
+ return {'records':[public_record(row,op.get('owner'),memory)for row in rows],'total':total,'hasMore':more,'nextCursor':cursor,'limit':limit}
53
+
54
+
55
+ def keyed_records(memory,subject,record_id,limit=10001):
56
+ record=memory.store.get_record(subject,record_id)
57
+ if not record or record['status']=='tombstoned':raise ValueError('Memory is unavailable in this scope')
58
+ if not record.get('fact_key'):return record,[record]
59
+ from atmem.store.sqlite import _record_from_row
60
+ rows=memory.store._conn.execute("SELECT * FROM records WHERE subject_id=? AND fact_key IS ? AND status IN ('active','superseded','quarantined') ORDER BY created_at DESC,id DESC LIMIT ?",(subject,record.get('fact_key'),limit)).fetchall()
61
+ return record,[_record_from_row(row)for row in rows]
62
+
63
+
64
+ def run(payload):
65
+ if version('atmem') != '2.3.10':
66
+ raise RuntimeError('AtMem AI Architect requires the tested AtMem 2.3.10 runtime')
67
+ memory = Memory(payload['database'], auto_vectors=False)
68
+ receipts = sqlite3.connect(payload['database'] + '.receipts.sqlite')
69
+ receipts.execute('CREATE TABLE IF NOT EXISTS receipts (id TEXT PRIMARY KEY, result TEXT)')
70
+ results = []
71
+ try:
72
+ for op in payload['operations']:
73
+ subject = op['subject']
74
+ action = op['action']
75
+ if action == 'remember':
76
+ previous = receipts.execute('SELECT result FROM receipts WHERE id=?', (op['eventId'],)).fetchone()
77
+ if previous:
78
+ results.append(json.loads(previous[0]))
79
+ continue
80
+ value = memory.remember(subject, message=op['text'], source_type='user_message',
81
+ interpreted_fact=op['text'], interpreted_fact_key=op['key'], actor=op.get('actor','atforma'),
82
+ raw={'interpreter': 'atforma-project-event-v1', 'event_id': op['eventId'], 'source_url': op.get('source', ''), 'user_id':op.get('owner'), 'actor':op.get('actor'), 'actor_type':op.get('actorType')})
83
+ receipt = {'refused': value.get('refused', []), 'ids': [r['id'] for r in value.get('records', [])] + value.get('duplicate_ids', [])}
84
+ receipts.execute('INSERT INTO receipts VALUES (?,?)', (op['eventId'], json.dumps(receipt)))
85
+ receipts.commit()
86
+ results.append(receipt)
87
+ elif action == 'recall':
88
+ results.append(memory.recall(subject, op['query'], limit=op.get('limit', 6)))
89
+ elif action == 'page':
90
+ results.append(page_records(memory,subject,op))
91
+ elif action == 'record':
92
+ record=memory.store.get_record(subject,op['recordId'])
93
+ if not record or record['status']=='tombstoned':raise ValueError('Record unavailable in this scope')
94
+ audit=memory.store._conn.execute('SELECT actor,event_type,created_at FROM audit_log WHERE subject_id=? AND record_id=? ORDER BY created_at DESC,sequence DESC LIMIT 50',(subject,op['recordId'])).fetchall()
95
+ results.append({'record':public_record(record,op.get('owner'),memory),'audit':[dict(row)for row in audit]})
96
+ elif action == 'forget-preview':
97
+ record,rows=keyed_records(memory,subject,op['recordId'],101)
98
+ total=memory.store._conn.execute("SELECT COUNT(*) FROM records WHERE subject_id=? AND fact_key IS ? AND status!='tombstoned'",(subject,record.get('fact_key'))).fetchone()[0]if record.get('fact_key')else 1
99
+ results.append({'records':[public_record(row,op.get('owner'),memory)for row in rows[:100]],'total':total})
100
+ elif action == 'list':
101
+ results.append(memory.list(subject, include_inactive=True))
102
+ elif action == 'forget':
103
+ # Forget the entire keyed preference history so old values cannot resurface.
104
+ record,records=keyed_records(memory,subject,op['recordId'])
105
+ if len(records)>10000:raise ValueError('History exceeds the synchronous removal limit; no records were removed')
106
+ deletion_receipts = []
107
+ for r in records:
108
+ deletion_receipts.append(memory.forget_record(subject,r['id'],actor=op.get('actor','user'))['receipt'])
109
+ results.append({'deleted': True, 'receipts': deletion_receipts, 'key': record.get('fact_key')})
110
+ elif action == 'audit':
111
+ report = memory.audit(subject)
112
+ results.append({'valid': report['audit_chain_valid'], 'events': report['audit_log'][-40:]})
113
+ elif action == 'log':
114
+ results.append(memory.log_action(subject, op['eventType'], op['payload'], actor='atmem-architect:'+op.get('owner','unknown')))
115
+ else:
116
+ raise ValueError('Unknown memory operation')
117
+ return {'version': version('atmem'), 'results': results}
118
+ finally:
119
+ memory.close()
120
+ receipts.close()
121
+
122
+
123
+ if __name__ == '__main__':
124
+ try:
125
+ print(json.dumps(run(json.load(sys.stdin))))
126
+ except Exception as exc:
127
+ # No text/credentials from an exception cross this process boundary.
128
+ print(json.dumps({'error': type(exc).__name__}))
129
+ sys.exit(1)