@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,91 @@
1
+ """Local-only, session-authenticated dictation. The app boundary owns HTTP auth."""
2
+ import asyncio, base64, io, json, os, shutil, wave
3
+ from pathlib import Path
4
+ from fastapi import APIRouter, HTTPException, Request
5
+ from .settings import setting
6
+
7
+ router=APIRouter()
8
+ ROOT=Path(__file__).resolve().parent
9
+
10
+ def configuration():
11
+ binary=shutil.which('whisper')
12
+ model=Path(setting('WHISPER_MODEL') or Path.home()/'.cache'/'whisper'/'tiny.en.pt')
13
+ if not binary or not model.is_file():return None
14
+ try: python=Path(binary).read_text().splitlines()[0].removeprefix('#!').strip()
15
+ except (OSError,IndexError,UnicodeError):return None
16
+ if not python.startswith('/') or not Path(python).is_file():return None
17
+ return python,model
18
+
19
+ class LocalSpeech:
20
+ def __init__(self):self.process=None;self.lock=asyncio.Lock()
21
+ async def close(self):
22
+ p=self.process;self.process=None
23
+ if p and p.returncode is None:
24
+ p.terminate()
25
+ try:await asyncio.wait_for(p.wait(),3)
26
+ except asyncio.TimeoutError:p.kill();await p.wait()
27
+ async def ready(self):
28
+ config=configuration()
29
+ if not config:raise HTTPException(503,'Local voice is not prepared. Run python3 scripts/setup-voice.py, then try again.')
30
+ if self.process and self.process.returncode is None:return
31
+ python,model=config
32
+ self.process=await asyncio.create_subprocess_exec(python,str(ROOT/'voice_worker.py'),str(model),
33
+ stdin=asyncio.subprocess.PIPE,stdout=asyncio.subprocess.PIPE,stderr=asyncio.subprocess.DEVNULL,
34
+ limit=100000)
35
+ try:
36
+ hello=json.loads(await asyncio.wait_for(self.process.stdout.readline(),30))
37
+ if hello.get('ready') is not True:raise ValueError('worker startup')
38
+ except BaseException:
39
+ await self.close();raise
40
+ async def prepare(self):
41
+ async with self.lock:await self.ready()
42
+ async def transcribe(self,pcm):
43
+ # A first partial can arrive while the page is warming the model. Wait for
44
+ # that preparation instead of turning an ordinary warmup into a mic failure.
45
+ try:await asyncio.wait_for(self.lock.acquire(),35)
46
+ except asyncio.TimeoutError:raise HTTPException(503,'Local transcription is busy. Finish or stop another recording, then try again.')
47
+ try:
48
+ try:
49
+ await self.ready()
50
+ self.process.stdin.write((json.dumps({'pcm':base64.b64encode(pcm).decode()})+'\n').encode())
51
+ await self.process.stdin.drain()
52
+ result=json.loads(await asyncio.wait_for(self.process.stdout.readline(),25))
53
+ if not isinstance(result.get('text'),str):raise ValueError('worker reply')
54
+ return result['text']
55
+ except HTTPException:raise
56
+ except BaseException:
57
+ await self.close();raise
58
+ finally:self.lock.release()
59
+
60
+ engine=LocalSpeech()
61
+
62
+ @router.get('/api/voice/status')
63
+ async def status():
64
+ return {'available':configuration() is not None,'engine':'local-whisper','audioStored':False,'maxSeconds':60}
65
+
66
+ @router.post('/api/voice/prepare')
67
+ async def prepare():
68
+ try:await engine.prepare();return {'ready':True}
69
+ except HTTPException:raise
70
+ except Exception:raise HTTPException(503,'Local speech recognition could not start. Check the Whisper installation.')
71
+
72
+ @router.post('/api/voice/transcribe')
73
+ async def transcribe(request:Request):
74
+ if request.headers.get('content-type','').split(';')[0]!='audio/wav':
75
+ raise HTTPException(415,'Send mono 16 kHz PCM WAV audio.')
76
+ body=await request.body()
77
+ if len(body)>1_920_100:raise HTTPException(413,'Voice clips are limited to 60 seconds.')
78
+ try:
79
+ with wave.open(io.BytesIO(body),'rb') as audio:
80
+ if (audio.getnchannels(),audio.getsampwidth(),audio.getframerate(),audio.getcomptype())!=(1,2,16000,'NONE'):
81
+ raise ValueError('format')
82
+ frames=audio.getnframes()
83
+ if not 1600<=frames<=960000:raise ValueError('duration')
84
+ pcm=audio.readframes(frames)
85
+ if len(pcm)!=frames*2:raise ValueError('truncated')
86
+ except (ValueError,EOFError,wave.Error):raise HTTPException(422,'Invalid audio. Use a mono 16 kHz PCM WAV clip of up to 60 seconds.')
87
+ try:
88
+ text=await engine.transcribe(pcm)
89
+ return {'text':text,'engine':'local-whisper','audioStored':False}
90
+ except HTTPException:raise
91
+ except Exception:raise HTTPException(503,'Local transcription was interrupted. Your message has not been sent.')
@@ -0,0 +1,26 @@
1
+ """Private local worker: bounded PCM requests via stdin, text via stdout. No audio files."""
2
+ import base64, json, os, sys
3
+ import numpy as np
4
+ import torch
5
+ import whisper
6
+
7
+ torch.set_num_threads(4)
8
+ model = whisper.load_model(sys.argv[1], device='cpu') # Exact existing checkpoint; never downloads.
9
+ print(json.dumps({'ready': True}), flush=True)
10
+ for line in sys.stdin:
11
+ try:
12
+ payload=json.loads(line)
13
+ raw=base64.b64decode(payload['pcm'], validate=True)
14
+ if not 3200 <= len(raw) <= 1_920_000 or len(raw)%2:
15
+ raise ValueError('audio size')
16
+ samples=np.frombuffer(raw,dtype='<i2').astype(np.float32)/32768
17
+ if np.sqrt(np.mean(samples*samples)) < .003:
18
+ text=''
19
+ else:
20
+ result=model.transcribe(samples,language='en',fp16=False,temperature=0,
21
+ condition_on_previous_text=False,verbose=None)
22
+ text=' '.join(s['text'].strip() for s in result.get('segments',[])
23
+ if s.get('no_speech_prob',0)<.8).strip()
24
+ print(json.dumps({'text':text[:12000]}),flush=True)
25
+ except Exception:
26
+ print(json.dumps({'error':'Local transcription failed.'}),flush=True)
@@ -0,0 +1,119 @@
1
+ """Bounded Windows snapshots with held, no-reparse, read-sharing-only handles.
2
+
3
+ All handles stay open until the complete tree is audited. Writers, replacements,
4
+ reparse points, hard links and non-disk objects fail closed; nothing is executed.
5
+ References: Microsoft CreateFileW and GetFileInformationByHandle documentation.
6
+ """
7
+ import ctypes
8
+ from ctypes import wintypes as w
9
+ import hashlib
10
+ import io
11
+ import os
12
+ from pathlib import Path
13
+ import stat
14
+ import zipfile
15
+ from .engineering_sessions import SessionError
16
+
17
+
18
+ def snapshot(workspace, *, excluded, max_bytes, max_files):
19
+ if os.name != 'nt':
20
+ raise SessionError('Windows snapshot handles require Windows')
21
+ kernel = ctypes.WinDLL('kernel32', use_last_error=True)
22
+ class Info(ctypes.Structure):
23
+ _fields_ = [('attributes', w.DWORD), ('created', w.FILETIME),
24
+ ('accessed', w.FILETIME), ('written', w.FILETIME),
25
+ ('volume', w.DWORD), ('size_hi', w.DWORD), ('size_lo', w.DWORD),
26
+ ('links', w.DWORD), ('index_hi', w.DWORD), ('index_lo', w.DWORD)]
27
+ kernel.CreateFileW.argtypes = [w.LPCWSTR,w.DWORD,w.DWORD,w.LPVOID,w.DWORD,w.DWORD,w.HANDLE]
28
+ kernel.CreateFileW.restype = w.HANDLE
29
+ kernel.CloseHandle.argtypes = [w.HANDLE]
30
+ kernel.CloseHandle.restype = w.BOOL
31
+ kernel.GetFileInformationByHandle.argtypes = [w.HANDLE,ctypes.POINTER(Info)]
32
+ kernel.GetFileInformationByHandle.restype = w.BOOL
33
+ kernel.GetFileType.argtypes = [w.HANDLE]
34
+ kernel.GetFileType.restype = w.DWORD
35
+ kernel.GetFinalPathNameByHandleW.argtypes = [w.HANDLE,w.LPWSTR,w.DWORD,w.DWORD]
36
+ kernel.GetFinalPathNameByHandleW.restype = w.DWORD
37
+ kernel.ReadFile.argtypes = [w.HANDLE,w.LPVOID,w.DWORD,ctypes.POINTER(w.DWORD),w.LPVOID]
38
+ kernel.ReadFile.restype = w.BOOL
39
+ invalid = ctypes.c_void_p(-1).value
40
+ held, entries, exclusions, observed = [], [], [], {}
41
+ output, total = io.BytesIO(), 0
42
+ root = Path(workspace).absolute()
43
+ if str(root).startswith('\\\\'):
44
+ raise SessionError('Windows capture requires a local disk workspace')
45
+ def fail():
46
+ raise SessionError('Artifact contains a changed, linked or unavailable Windows entry; no package was saved')
47
+ def information(handle):
48
+ info=Info()
49
+ if not kernel.GetFileInformationByHandle(handle,ctypes.byref(info)):fail()
50
+ if info.attributes & 0x400 or kernel.GetFileType(handle)!=1:fail()
51
+ return info
52
+ def identity(info):
53
+ return (info.volume,info.index_hi,info.index_lo,info.attributes,info.links,
54
+ info.size_hi,info.size_lo,info.created.dwHighDateTime,info.created.dwLowDateTime,
55
+ info.written.dwHighDateTime,info.written.dwLowDateTime)
56
+ def open_entry(path):
57
+ # No FILE_SHARE_WRITE or FILE_SHARE_DELETE: retain every handle through audit.
58
+ handle=kernel.CreateFileW('\\\\?\\'+str(path),0x80000000,1,None,3,0x02200000,None)
59
+ if handle==invalid:fail()
60
+ held.append(handle)
61
+ info=information(handle)
62
+ actual=ctypes.create_unicode_buffer(32768)
63
+ length=kernel.GetFinalPathNameByHandleW(handle,actual,len(actual),0)
64
+ if not length or length>=len(actual) or os.path.normcase(actual.value)!=os.path.normcase('\\\\?\\'+str(path)):fail()
65
+ return handle,info
66
+ def names(path):
67
+ result=[]
68
+ for name in sorted(os.listdir(path)):
69
+ if name in excluded:continue
70
+ if name in {'.','..'} or name.endswith((' ','.')) or any(ord(c)<32 or c in '\\/:"<>|?*' for c in name):fail()
71
+ result.append(name)
72
+ return result
73
+ def walk(path,relative,handle,info,archive):
74
+ nonlocal total
75
+ observed[relative]=(path,handle,identity(info),None)
76
+ if info.attributes & 0x10:
77
+ children=names(path)
78
+ observed[relative]=(path,handle,identity(info),children)
79
+ exclusions.extend((relative+'/' if relative else '')+name for name in sorted(os.listdir(path)) if name in excluded)
80
+ for name in children:
81
+ child_relative=(relative+'/' if relative else '')+name
82
+ child,child_info=open_entry(path/name)
83
+ directory=bool(child_info.attributes & 0x10)
84
+ if len(entries)>=max_files:raise SessionError('Artifact entry limit exceeded; no partial package was saved')
85
+ if directory:
86
+ entries.append({'path':child_relative+'/','kind':'directory'})
87
+ item=zipfile.ZipInfo(child_relative+'/');item.external_attr=(stat.S_IFDIR|0o755)<<16
88
+ archive.writestr(item,b'')
89
+ walk(path/name,child_relative,child,child_info,archive)
90
+ else:
91
+ size=(info.size_hi<<32)|info.size_lo
92
+ if info.links!=1 or total+size>max_bytes:fail()
93
+ content=bytearray()
94
+ while True:
95
+ buffer=ctypes.create_string_buffer(min(1_000_000,max_bytes-total-len(content)+1))
96
+ read=w.DWORD()
97
+ if not kernel.ReadFile(handle,buffer,len(buffer),ctypes.byref(read),None):fail()
98
+ if not read.value:break
99
+ content.extend(buffer.raw[:read.value])
100
+ if total+len(content)>max_bytes:fail()
101
+ if len(content)!=size or identity(information(handle))!=identity(info):fail()
102
+ entries.append({'path':relative,'kind':'file','bytes':size,'sha256':hashlib.sha256(content).hexdigest()})
103
+ item=zipfile.ZipInfo(relative);item.compress_type=zipfile.ZIP_DEFLATED
104
+ mode=0o755 if path.suffix.lower() in {'.sh','.exe'} else 0o644
105
+ item.external_attr=(stat.S_IFREG|mode)<<16
106
+ archive.writestr(item,content)
107
+ total+=size
108
+ try:
109
+ handle,info=open_entry(root)
110
+ if not info.attributes & 0x10:fail()
111
+ with zipfile.ZipFile(output,'w',compression=zipfile.ZIP_DEFLATED)as archive:
112
+ walk(root,'',handle,info,archive)
113
+ for path,handle,expected,children in observed.values():
114
+ if identity(information(handle))!=expected or children is not None and names(path)!=children:fail()
115
+ return output.getvalue(),entries,exclusions
116
+ except OSError:
117
+ fail()
118
+ finally:
119
+ for handle in reversed(held):kernel.CloseHandle(handle)
@@ -0,0 +1,72 @@
1
+ {
2
+ "kind": "ibm-generated-source-local-qualification",
3
+ "checks": [
4
+ {
5
+ "name": "block_776f726b7370616365-dependency-closure",
6
+ "passed": true,
7
+ "exitCode": 0,
8
+ "error": null,
9
+ "logSha256": "7cdf86c11be8cd2bd27e079b9eaf3e1a49e67fd3859d15322472a4c2cd670aaf"
10
+ },
11
+ {
12
+ "name": "block_776f726b7370616365-runtime",
13
+ "passed": true,
14
+ "exitCode": 0,
15
+ "error": null,
16
+ "logSha256": "e4a87143fa2b5fcad8312a350ec9bfa971d8e09a657b9949f2ca21c087789bda"
17
+ },
18
+ {
19
+ "name": "provider-init",
20
+ "passed": true,
21
+ "exitCode": 0,
22
+ "error": null,
23
+ "logSha256": "4dd3e891182a46feed67ba9f9071884ed31574ba3279bc8fbc1a8b86867d69e3"
24
+ },
25
+ {
26
+ "name": "provider-schema",
27
+ "passed": true,
28
+ "exitCode": 0,
29
+ "error": null,
30
+ "logSha256": "624bd9c40454b477e270d3078d4f93fae51fe8cd939b1b0da055f03794c336fe"
31
+ },
32
+ {
33
+ "name": "provider-mocks",
34
+ "passed": true,
35
+ "exitCode": 0,
36
+ "error": null,
37
+ "logSha256": "bb92f233a7936f4de6a41314bb2881369aaa623d150a82eb78f43a7b339798c5"
38
+ }
39
+ ],
40
+ "passed": true,
41
+ "cloudOperations": false,
42
+ "artifactHashes": {
43
+ "applications/block_776f726b7370616365/ibm_structured.py": "e1ee0f1bc06f4b6f15954d9d53e4ce0f218cf791ea6098b95a7fccb77b112fda",
44
+ "applications/block_776f726b7370616365/ibm_acceptance.py": "1dae539a44bc4878a9ce5b1552f2e8758512625058247a88e3762c9464c20379",
45
+ "applications/block_776f726b7370616365/structured_output.py": "432c730c54bd7dcae7b52fb73edc67d2e7b44b890e68254fdee832cb4c2304bc",
46
+ "applications/block_776f726b7370616365/structured_http.py": "fae1e7d092c1d17e90cb2af41aeb19ce786b38a1a813427197b1ad56dd0006ab",
47
+ "applications/block_776f726b7370616365/http_acceptance.py": "bd9ed35d684e1b3139b13f2cda948e1008b71d518080257382139c12e7cfa44e",
48
+ "applications/block_776f726b7370616365/export_contract_acceptance.py": "da3e116e83592fac21287eebb23805c5b2c876464b84348586a0d0fa417b8445",
49
+ "applications/block_776f726b7370616365/policy_review.py": "66d56df0dcab7df4ef85c35cc8a0ddbc7e71f8b31179db4916898c9ea5c4e947",
50
+ "applications/block_776f726b7370616365/web/index.html": "acc94cd6ca367c30b16b313ec6f79e33b9c0525fdf1e7c9078a9ee3d106b3b55",
51
+ "applications/block_776f726b7370616365/web/app.css": "b8a25941eaaa678e871b7f0b9ce6c9729680955bc55cf8ac231b12d18bb4bb8c",
52
+ "applications/block_776f726b7370616365/web/app.js": "35e3cf9badd3d69a8653e1787e3a0b40ec6bbfaaf1d8e33f9dbbe78643a8184a",
53
+ "applications/block_776f726b7370616365/output-contract.json": "ddbb7e23a60d0d9b3504a5ae419d756e03d12e955f20c188f81c4e5800fa33bf",
54
+ "applications/block_776f726b7370616365/requirements.lock": "5f1c4a8a5e6913bcabb02f7ecfbbeed46d662d0d69e75be289285906607b28ac",
55
+ "applications/block_776f726b7370616365/dependency-sources.json": "4c9fc025adc10ff43708c84f34cfa50a9f36eeb7ea77ae0a240bcc7c3f73ebe7",
56
+ "applications/block_776f726b7370616365/test-requirements.lock": "54894d4de170917d97979422e764854555ad23ff16c253128540602cc1791bf0",
57
+ "applications/block_776f726b7370616365/test-dependency-sources.json": "8a4c9c3daff2e034da95e9dad9916d46cb7eb1b228b2f940c7e200698f9c1a64",
58
+ "applications/block_776f726b7370616365/container-base.json": "b2adfde9b3215f7f0299806e211b49438be95ea3c2b995e905452cce2dfd0650",
59
+ "applications/block_776f726b7370616365/Dockerfile": "89e80555673c3d5b8c46d6101a2c256a5fd1ab94350a1fd971338b06c3ee9f72",
60
+ "applications/block_776f726b7370616365/.dockerignore": "29166c81d104dea78a0a4ea844ed15161843c68c726baf32952ab72f84f12bf4",
61
+ "applications/block_776f726b7370616365/BUILD.md": "ba89ea7d249c8237b4e5e9502af0757a7f345ef3140254395b8088caec8f5118",
62
+ ".terraform.lock.hcl": "022cd3d744cf400f91bc98094840a94eb8e652d67447d744db359be463a3cdb1",
63
+ "main.tf.json": "acc18e4f2a10015ef140d8cf6939e5a9f65a5bc9a73b25c3cbb46dc6547bcda6",
64
+ "resource-schedule.json": "5b9c183deb64cca36f410bd55f2a70ff2167767edade395ace2be57becf6c72c",
65
+ "deployment.tfvars.json.example": "dc09b358146fd0298f748de15b209642373629566d0d52c30a1d8879610573c0",
66
+ ".gitignore": "8168883c9173f4d7fe176e5e8ebdc1dfb569fd81efd2e3da0a207e7f27e1dd95",
67
+ "tests/ibm-structured.tftest.hcl": "621fbc196133d3f2ddae78a882842554109a00ba53cc5ef858056dc0cb20e3b2",
68
+ "README.md": "cf23af0d5732b986f63655295688e84c4ac24be2605f32ee55c52fc4ab80e75a",
69
+ "generation-quality.json": "d85052d36245473287c2de14b11f4851006097694ffbe32ceed8bf1cd83fef6d"
70
+ },
71
+ "boundary": "Emitted Python 3.13 source, real cryptographic/ASGI tests with scripted provider key/model/policy transport and denied external sockets; native Terraform schemas and mock plans. No container image startup/scan, provider account plan, identity sign-in/MFA/revocation, real model-quality test or deployment."
72
+ }
@@ -0,0 +1,61 @@
1
+ {
2
+ "kind": "local-durable-workflow-core",
3
+ "recordedAt": "2026-11-09T23:58:36.893280+00:00",
4
+ "passed": true,
5
+ "tests": 54,
6
+ "seconds": 12.997,
7
+ "python": "3.13.14 (main, Jun 10 2026, 12:24:04) [Clang 21.0.0 (clang-2100.0.123.102)]",
8
+ "postgresVersion": "17.11",
9
+ "schemaVersion": 1,
10
+ "schemaSha256": "fe15a655c14eeda37bc3e4e60f0270de7bcb86d79ea9da4577246dca15806e59",
11
+ "queueVersion": "3.10.0",
12
+ "sourceHashes": {
13
+ "scripts/initialize-durable-fixture.py": "1bbca33ca680b2ed69f75ccc9da2bdd8aaf02c79e00a6b9979f71f1c88ace82f",
14
+ "scripts/qualify-durable-runtime.py": "a106ff913b0146b108b3d94a5199b4abe8011fcc7f72a9d1113cc6c886424b8a",
15
+ "scripts/setup-durable-runtime.py": "d916a93910a1ac2e24ac63f6ab96561f0a5d98727383b010376f3d467271131f",
16
+ "scripts/start-durable-fixture.py": "eb4f609c5bd00bde2ca560d495f80c62fdf88088a65bf564239ee216d991a2cc",
17
+ "src/runtime/approved_http_destination.py": "dbe62ce035d16c8e2988d2672d25be8597d963bab6b0fc969aa59b240d0aa442",
18
+ "src/runtime/durable-python-lock.json": "dbaa350d227c74f4acf046a27d878f3fa78ce762a5c58ba832b70c20a083cf87",
19
+ "src/runtime/durable_workflow.py": "5d31e1de487d2522c706cfbebcad5e880ce762a859b8804b23e86bb3df074675",
20
+ "src/runtime/postgres-qualification-lock.json": "bc475f763854dc4b1ea3afc930ad312aad1b76d93f69fad8244207c6aadf0b45",
21
+ "src/runtime/workflow_contract.py": "e662aeb89bcd4eac9c34b32b6a154de8a1758ae089eee71f0642d27e1b413eb4",
22
+ "src/runtime/workflow_database.py": "178b03c7b10bd56b6eb431366b57416dc8059db1a2cec4657de2f2c4cc8d0799",
23
+ "src/runtime/workflow_errors.py": "753d82e5a788ac459cb2b106c078af86cd90077886cda42767a36f62159fd19b",
24
+ "src/runtime/workflow_process_stage.py": "b1d6f7fd8aa679107f2ae4c1ec885c1693ee84422e6cb1af20d6f43a06ff31f6",
25
+ "src/runtime/workflow_schema.sql": "fe15a655c14eeda37bc3e4e60f0270de7bcb86d79ea9da4577246dca15806e59",
26
+ "src/runtime/workflow_worker.py": "c1a6f368eb42128a9648f4c324a5891c87daf6b9723951e74fb3f07963640f69",
27
+ "tests/runtime/durable_crash_acceptance.py": "bd1c0acd58972da8b04db1b2d0f0fa570a2223791ce399ebe750d59f1d92e197",
28
+ "tests/runtime/durable_fixture_tasks.py": "f9a20d3aad51ab69e4e4092c20d6f84b097fcbef5c9a3eccf4baa0420cd82515",
29
+ "tests/runtime/durable_http_acceptance.py": "4ef564c4e4a1120867789f48d85d21e5d19f06a978e5c01cb5a3ec96ddb75c17",
30
+ "tests/runtime/durable_postgres_acceptance.py": "6e8a9d26eb41611963245ab8d4fad3767d908843050ca47021128a9c55d94be3",
31
+ "tests/runtime/durable_privileges_acceptance.py": "fff2903ef7c7a9f951e980691f6e812b0dc55f0bece9d08b100c01282e730ebb",
32
+ "tests/runtime/durable_recovery_acceptance.py": "008ddb5739ac6a4d71f20e374ffb69ccf04a9f18bb2225b12367cdf6763dcaf9",
33
+ "tests/runtime/durable_restricted_worker_acceptance.py": "2934ffab683c87d3467f6a74ede7ae6c1b00613c53de900b7dc3d8f706168f77",
34
+ "tests/runtime/durable_stage_acceptance.py": "56319b3d6ff64bddc84a27535d495f41fd5a42c29be62221940198203f05acee",
35
+ "tests/runtime/durable_tls_deadline_acceptance.py": "65f28bb754b6ca944353623afb39a4665705d8c09fd0cb9763e35a935d759ed1",
36
+ "tests/runtime/durable_worker_acceptance.py": "9f8bcce3760186a37c8ca35b8ca8d7de14f0ba49f0dd6691fac178fd4cff55aa",
37
+ "tests/runtime/durable_worker_process.py": "ab224adac36773db78cc7f732319a03ea31c1a8153b791c75a0189d5aee466f8",
38
+ "tests/runtime/invoice_document_acceptance.py": "a170a5af6aeedde0a86f516a50286bcaf3eb7bb743b97c38bc8c78e8a3331410",
39
+ "tests/runtime/invoice_extraction_acceptance.py": "783b00b4cb127cfe6594a0b22bc10ffc1ee68a03b477c60c87be1837e7b01bce",
40
+ "tests/runtime/invoice_http_acceptance.py": "078595b3e5c4f026916204e82b769b08dba73265a7bd99b9b2d3e129346112ab",
41
+ "tests/runtime/invoice_storage_acceptance.py": "b4a0ae395d3299353f1a97eac4989e5522e015f677605d4f2c24d1a4f202ef13",
42
+ "tests/runtime/workflow_stage_child_fixture.py": "14747c71b2b7bfbe71c6d05026dfb79c655f9d4b35af8439eaced4b3d57a3f50",
43
+ "tests/runtime/workflow_tls_destination_fixture.py": "9924ccafb80af31250d6f2fa9913731a46ba6ee9bc0b90661f2daa211944e79a"
44
+ },
45
+ "sourcesUnchangedDuringChecks": true,
46
+ "checks": [
47
+ {
48
+ "check": "dependency-check",
49
+ "exitCode": 0,
50
+ "log": "dependency-check.log"
51
+ },
52
+ {
53
+ "check": "workflow-acceptance",
54
+ "exitCode": 0,
55
+ "log": "workflow-acceptance.log"
56
+ }
57
+ ],
58
+ "evidenceBoundary": "Real local PostgreSQL, native queue workers, restricted local DB logins, SIGKILL replacements, loopback TLS and child process deadlines; synthetic processors and destinations. No native cloud/IdP/PDF/model/vendor, complete project, backup/restore, full matrix or deployment claim.",
59
+ "cloudOperations": false,
60
+ "full28CaseAcceptanceComplete": false
61
+ }
@@ -0,0 +1,22 @@
1
+ {
2
+ "passed": true,
3
+ "catalogSha256": "7d5397350e80330d09d1b2a8e838936d82b0dc3159680d26d064f459b0a269af",
4
+ "artifactSha256": "4dbff53c715e9f644d41a82e4cdc9e61f45048d80be8af3c11bf0c7d7bfb3c69",
5
+ "oracleSha256": "f8c997f0ed93feb6a44738bc8fcf0aa62d8aa40668e7ac922354eecd38514af4",
6
+ "results": [
7
+ {
8
+ "runtime": "lambda-python312-tests",
9
+ "status": "passed",
10
+ "imageId": "sha256:cdb746c1eb56b61de56e1b5e78f6194392eb00494a1bb257a592852e72d8314b",
11
+ "platform": "linux/arm64"
12
+ },
13
+ {
14
+ "runtime": "python-tests",
15
+ "status": "passed",
16
+ "imageId": "sha256:48d884813cf44e927cf64c5529dd630dd3b18338c6dc727991eef9b71e934a20",
17
+ "platform": "linux/amd64"
18
+ }
19
+ ],
20
+ "cloudOperations": false,
21
+ "scope": "Pinned pure-Python wheel dependency closure with explicit selected botocore service data, actual Lambda Python3.12 ARM64 and Python3.13 AMD64 execution. SDK operation/model/endpoints and local signed GET/mode/timestamp/denial/throttle/failure/one-attempt timeout contracts. This is SDK artifact qualification, not generated application safety gates, cloud account state, deployment or all-SDK service compatibility."
22
+ }
@@ -0,0 +1,54 @@
1
+ import {BrainActivity} from './BrainActivity.jsx';
2
+ import React,{useEffect,useRef,useState,useId} from 'react';
3
+ import {mergeArchitectureActivity,readArchitectureActivity} from './architecture-activity.mjs';
4
+ import {architectureSteps,architectureActivityLabel} from './activity-presentation.mjs';
5
+ import {ChatMessage} from './ChatMessage.jsx';
6
+ import './architecture-activity.css';
7
+ // A view of observed work, never a completion claim about the client's system.
8
+ function TurnActivity({label,latest,steps=[],model,effort,working=false,failed=false,open,onOpenChange,onStop,children}){
9
+ const [expanded,setExpanded]=useState(false),id=useId();const shown=open??expanded;
10
+ const change=value=>{setExpanded(value);onOpenChange?.(value);};
11
+ useEffect(()=>{if(failed)change(true);},[failed]);
12
+ return <div className={'turn-activity'+(failed?' has-error':'')}>
13
+ <div className="turn-activity-row">
14
+ <button type="button" className="turn-activity-toggle" aria-expanded={shown} aria-controls={id} title={[model,effort].filter(Boolean).join(' · ')} onClick={()=>{change(!shown);}}>
15
+ <span aria-hidden="true" className={'turn-state-icon'+(working?' has-brain':'')}>{working?<BrainActivity size={22}/>:failed?'!':'›'}</span>
16
+ <span className="turn-activity-label" role="status" aria-live="polite">{label}</span>{latest&&<span className="turn-latest"> · {latest}</span>}
17
+ <span className="turn-chevron" aria-hidden="true">{shown?'⌄':'›'}</span>
18
+ </button>
19
+ {onStop&&working&&<button type="button" className="turn-inline-action" onClick={onStop}>Stop</button>}
20
+ </div>
21
+ <div id={id} hidden={!shown} className="turn-activity-details">
22
+ {(model||effort)&&<p className="turn-selection">{[model,effort].filter(Boolean).join(' · ')}</p>}
23
+ <ol>{steps.map(step=><li key={step.id} data-step={step.id}>{step.message?<ChatMessage text={step.text}/>:<p>{step.text}</p>}{step.detail&&<small>{step.detail}</small>}</li>)}</ol>
24
+ {children}
25
+ </div>
26
+ </div>;
27
+ }
28
+
29
+ export function ArchitectureTurn({turn,projectId,session,active,working,onStop,historyNumber}){
30
+ const [open,setOpen]=useState(false),[events,setEvents]=useState([]),[status,setStatus]=useState(null),[error,setError]=useState('');const cursor=useRef(0),observed=useRef([]);
31
+ useEffect(()=>{
32
+ if((!open&&!active)||!session?.architectureActivityEnabled)return;
33
+ let stopped=false,timer;const controller=new AbortController();
34
+ async function poll(){try{
35
+ const value=await readArchitectureActivity(session,projectId,turn.id,cursor.current,controller.signal);
36
+ if(stopped)return;const merged=mergeArchitectureActivity(observed.current,value.events);observed.current=merged;setEvents(merged);setStatus(value.state);setError('');
37
+ if(value.events.length)cursor.current=value.events.at(-1).sequence;
38
+ if(value.state==='running'||value.events.length===200)timer=setTimeout(poll,value.events.length===200?0:700);
39
+ }catch(e){if(!stopped&&e.name!=='AbortError'){setError(e.status===404?'Details not recorded for this turn.':e.message);if(e.status===404&&working)timer=setTimeout(poll,1000);}}}
40
+ void poll();return()=>{stopped=true;controller.abort();clearTimeout(timer);};
41
+ },[open,active,projectId,turn.id,turn.clientStatus,session?.token,session?.architectureActivityEnabled,working]);
42
+ const steps=architectureSteps(events),label=architectureActivityLabel(turn,status,active),failed=status==='failed'||turn.clientStatus==='failed';
43
+ return <div className="conversation-activity" data-turn={turn.id}><TurnActivity label={historyNumber?'Activity '+historyNumber+' · '+label:label} latest={active?steps.at(-1)?.text:undefined} steps={steps} model={turn.model} effort={turn.effort} working={active} failed={failed} open={open} onOpenChange={setOpen} onStop={active?onStop:undefined}>
44
+ {error&&<p role="status">{error}</p>}
45
+ {!session?.architectureActivityEnabled&&<p>Live details are unavailable from this service. The reply remains in chat.</p>}
46
+ {turn.detailsAvailable===false&&<p>Some activity details were not recorded. The returned response remains in chat.</p>}
47
+ </TurnActivity></div>;
48
+ }
49
+ export function EarlierArchitectureActivity({entries,projectId,session}){
50
+ const [open,setOpen]=useState(false);
51
+ return <details className="legacy-activity" open={open} onToggle={e=>setOpen(e.currentTarget.open)}><summary>{entries.length} earlier {entries.length===1?'turn':'turns'} · activity history</summary>
52
+ {open&&<><p>Recorded before activity was linked to individual replies.</p>{entries.toReversed().map(({turn,number})=><ArchitectureTurn key={projectId+':'+turn.id} turn={turn} projectId={projectId} session={session} active={false} working={false} historyNumber={number}/>)}</>}
53
+ </details>;
54
+ }
@@ -0,0 +1,39 @@
1
+ import React,{useState,useMemo} from 'react';
2
+ import {architectureWork,workContextIdentity} from './architecture-work.mjs';
3
+ import {artifactWorkProjection} from './artifact-work.mjs';
4
+ const labels={current:'Context current',changed:'Review again',missing:'Missing reference',unreviewed:'Not reviewed'};
5
+ function WorkPanel({project,onChange,busy=false}){
6
+ const [error,setError]=useState('');
7
+ const result=useMemo(()=>{try{return {model:project?architectureWork(project):null,artifacts:project?artifactWorkProjection(project):null};}catch(e){return {error:e.message};}},[project]);
8
+ if(!project)return null;
9
+ if(result.error)return <p role="alert">Work context could not be read: {result.error}</p>;
10
+ const model=result.model;
11
+ const intents=model.entities.filter(e=>e.kind==='intent'&&e.value?.text?.trim()).length,requirements=model.entities.filter(e=>e.kind==='requirement').length;
12
+ const sourceName=id=>model.entities.find(e=>e.id===id)?.title||project.extensions?.architectureWork?.snapshots.findLast(s=>s.ref===id)?.value.title||id;
13
+ const priority={changed:0,missing:0,unreviewed:1,current:2};
14
+ const mappings=model.entities.filter(e=>['responsibility','delivery-unit','interface','implementation','assumption','decision','evidence','requirement','removed'].includes(e.kind)).sort((a,b)=>priority[a.contextStatus]-priority[b.contextStatus]);
15
+ function apply(change){onChange(change,project.id);setError('');}
16
+ return <details className="architecture-work"><summary>Architecture work context · {mappings.filter(e=>e.contextStatus==='changed'||e.contextStatus==='missing').length} need review</summary>
17
+ <p>Requirements, responsibilities, interfaces and implementation mappings share their change context. A current context is a recorded review; it does not establish that an implementation or test passed.</p>
18
+ <p>{intents} intent {intents===1?'source':'sources'} · {requirements} {requirements===1?'requirement':'requirements'}. Free-form engineering updates affect every mapping until reconciled.</p>
19
+ {mappings.length?<ul aria-label="Architecture work mappings">{mappings.map(e=><li key={e.id} data-work-ref={e.id}>
20
+ <strong>{e.title}</strong><span> · {e.kind} · {labels[e.contextStatus]}</span>
21
+ {e.value&&<details><summary>Sources and mapping details</summary><pre>{JSON.stringify({value:e.value,dependsOn:e.dependsOn,review:e.review},null,2)}</pre></details>}
22
+ {e.value?.source&&<small> · {e.value.source} · {e.value.agreement||'recorded'}</small>}
23
+ {e.changedRefs.length>0&&<p>Changed: {e.changedRefs.map(sourceName).join(', ')}</p>}
24
+ {e.missingRefs.length>0&&<p>Missing: {e.missingRefs.map(sourceName).join(', ')}</p>}
25
+ {onChange&&e.contextStatus!=='missing'&&<button disabled={busy} onClick={()=>{try{apply({kind:'review',ref:e.id,expectedContext:workContextIdentity(project,e.id)});}catch(e){setError(e.message);}}}>Record context review: {e.title}</button>}
26
+ </li>)}</ul>:<p>No responsibilities or implementation mappings recorded yet. Engineering can propose them without changing the existing diagram.</p>}
27
+ {result.artifacts.mappings.length>0&&<section aria-label="Linked artifact mappings">
28
+ <h3>Linked artifacts</h3><p>File and context references remain proposed. They do not establish that a test passed or that the implementation meets every requirement.</p>
29
+ <ul>{result.artifacts.mappings.map(m=><li key={m.id} data-artifact-mapping={m.artifactId}>
30
+ <strong>{m.contextStatus==='current'?'Saved context matches':m.contextStatus==='superseded'?'Earlier artifact retained':'Design changed; regenerate mappings'}</strong>
31
+ <span> · {m.records.length} proposed mappings · context revision {m.contextRevision}</span>
32
+ <details><summary>Artifact and file references</summary><pre>{JSON.stringify({artifactId:m.artifactId,artifactSha256:m.artifactSha256,contextSha256:m.contextSha256,files:m.files,changedRefs:m.changedRefs,scope:m.scope},null,2)}</pre></details>
33
+ </li>)}</ul>
34
+ </section>}
35
+ {error&&<p role="alert">{error}</p>}
36
+ </details>;
37
+ }
38
+
39
+ export const ArchitectureWorkPanel=React.memo(WorkPanel);
@@ -0,0 +1,49 @@
1
+ import React,{useEffect,useRef,useState} from 'react';
2
+ import {engineeringCall} from './engineering-client.mjs';
3
+
4
+ export function ArtifactChecks({session,projectId,sessionId,artifact,readOnly=false}){
5
+ const [catalog,setCatalog]=useState([]),[available,setAvailable]=useState(false),[checks,setChecks]=useState([]),
6
+ [error,setError]=useState(''),[busy,setBusy]=useState(false);
7
+ const live=useRef(true),locked=useRef(false);
8
+ const payload={projectId,sessionId,artifactId:artifact.id};
9
+ useEffect(()=>{live.current=true;return()=>{live.current=false;};},[]);
10
+ useEffect(()=>{
11
+ const controller=new AbortController();let stopped=false,timer;
12
+ async function poll(){try{
13
+ const [configuration,result]=await Promise.all([
14
+ engineeringCall(session,'validators',{projectId,sessionId},{signal:controller.signal}),
15
+ engineeringCall(session,'validation/list',payload,{signal:controller.signal})]);
16
+ if(stopped)return;
17
+ setCatalog(configuration.validators);setAvailable(configuration.available);setChecks(result.checks);
18
+ }catch(e){if(!stopped&&e.name!=='AbortError')setError(e.message);}
19
+ finally{if(!stopped)timer=setTimeout(poll,1200);}}
20
+ void poll();return()=>{stopped=true;clearTimeout(timer);controller.abort();};
21
+ },[projectId,sessionId,artifact.id,session.token]);
22
+ async function act(action,values){
23
+ if(locked.current)return;locked.current=true;setBusy(true);setError('');
24
+ try{const body=action==='validation/recover'?{projectId,sessionId,...values}:{...payload,...values};const result=await engineeringCall(session,action,body);if(live.current)setChecks(current=>[...current.filter(check=>check.id!==result.id),result]);}
25
+ catch(e){if(live.current)setError(e.message);}finally{locked.current=false;if(live.current)setBusy(false);}
26
+ }
27
+ return <section className="artifact-checks" aria-label="Captured package checks">
28
+ <h3>Check results</h3>
29
+ {!available&&<p>Independent checks have not run: no check runner is configured.</p>}
30
+ {!readOnly&&catalog.map(validator=>{
31
+ const previous=checks.filter(check=>check.validatorId===validator.id&&check.contractSha256===validator.contractSha256).at(-1);
32
+ const active=previous&&previous.state!=='finished';
33
+ return <button key={validator.id} disabled={busy||!available||validator.available===false||active} onClick={()=>void act('validation/start',{validatorId:validator.id,retry:!!previous})}>
34
+ {previous?.state==='finished'?'Run again: ':''}{validator.label}{validator.available===false?' · unavailable':''}{active?' · '+previous.state:''}
35
+ </button>;
36
+ })}
37
+ <ol>{checks.map(check=>{
38
+ const definition=catalog.find(validator=>validator.id===check.validatorId),outdated=!definition||(definition.contractSha256!=null&&definition.contractSha256!==check.contractSha256);
39
+ return <li key={check.id}>
40
+ <strong>{check.label} · {check.state==='finished'?check.result?.status||'incomplete':check.state.replaceAll('_',' ')}</strong>
41
+ {outdated&&<p>From a previous check definition; retained as historical evidence.</p>}
42
+ {check.result?.testsReported!=null&&<p>{check.result.testsReported} tests reported · {check.result.skipped||0} skipped</p>}
43
+ {!readOnly&&check.state==='recovery_required'&&<button disabled={busy} onClick={()=>void act('validation/recover',{checkId:check.id})}>Recover check</button>}
44
+ {check.result&&<><details><summary>Check output</summary><pre>{check.result.output||check.result.reason||'No output reported.'}</pre></details></>}
45
+ </li>;
46
+ })}</ol>
47
+ {error&&<p role="alert">{error}</p>}
48
+ </section>;
49
+ }
@@ -0,0 +1,13 @@
1
+ import React,{useState} from 'react';
2
+ function RequirementCard({requirement,busy,onSave}){
3
+ const [editing,setEditing]=useState(false),[text,setText]=useState(requirement.statement),[error,setError]=useState('');
4
+ async function save(e){e.preventDefault();try{await onSave(requirement.id,text);setEditing(false);setError('');}catch(e){setError(e.message);}}
5
+ return <article className="block-requirement" aria-label={`Requirement ${requirement.id}`}>
6
+ {editing?<form onSubmit={save}><label>Requirement<textarea aria-label="Requirement text" maxLength={1000} value={text} onChange={e=>setText(e.target.value)}/></label><div className="block-review-actions"><button className="btn primary" disabled={busy||!text.trim()}>Save & re-evaluate</button><button type="button" className="btn ghost" disabled={busy} onClick={()=>setEditing(false)}>Cancel</button></div>{error&&<p role="alert">{error}</p>}</form>:<><p>{requirement.statement}</p><button className="link" disabled={busy} onClick={()=>{setText(requirement.statement);setEditing(true);}}>Edit requirement</button></>}
7
+ {requirement.measure&&<small>Acceptance target: {requirement.measure.metric} {requirement.measure.op} {String(requirement.measure.target)} {requirement.measure.unit}</small>}
8
+ </article>;
9
+ }
10
+ export function BlockRequirements({project,nodeId,busy,onSave}){
11
+ const needs=(project.needs||[]).filter(r=>r.links?.includes(nodeId));
12
+ return <section className="block-requirements" aria-label="Block requirements"><strong>Requirements for this block</strong>{needs.length?needs.map(r=><RequirementCard key={r.id} requirement={r} busy={busy} onSave={onSave}/>):<p className="muted">No requirements linked yet.</p>}<small>Saving updates local checks and requests an Architect review when connected. Linked blocks will need review again.</small></section>;
13
+ }
@@ -0,0 +1,11 @@
1
+ import React,{useId} from 'react';
2
+ // Brain artwork supplied by the user. Crop the wordmark for legibility at icon size.
3
+ export function BrainActivity({size=24,active=true}){
4
+ const mask=useId();
5
+ return <svg className={`brain-activity${active?' is-active':''}`} width={size} height={size} viewBox="-150 -135 300 255" aria-hidden="true" focusable="false">
6
+ <defs><mask id={mask} maskUnits="userSpaceOnUse" x="-200" y="-200" width="400" height="400"><rect x="-200" y="-200" width="400" height="400" fill="#fff"/>{[false,true].map(mirror=><path key={String(mirror)} d="M124 -31 Q98 -30 90 -54 M79 -88 Q72 -66 50 -60" transform={mirror?'scale(-1 1)':undefined} stroke="#000" strokeWidth="9" strokeLinecap="round" fill="none"/>)}</mask></defs>
7
+ <g mask={`url(#${mask})`} fill="#F3A2B4">{[false,true].map(mirror=><path key={String(mirror)} d="M7 -104 A41.2 41.2 0 0 1 78.8 -87.95 A40.71 40.71 0 0 1 124.2 -31.16 A38 38 0 0 1 116.93 36.3 A42.22 42.22 0 0 1 60.09 85.83 A29.75 29.75 0 0 1 7 84 Z" transform={mirror?'scale(-1 1)':undefined}/>)}</g>
8
+ {[-47,47].map(x=><g key={x}><circle cx={x} cy="26" r="35" fill="#F3F7F7" stroke="#101314" strokeWidth="12"/><circle cx={x+5} cy="21" r="10.5" fill="#101314"/></g>)}
9
+ <path d="M-12 18 Q0 0 12 18" fill="none" stroke="#101314" strokeWidth="12" strokeLinecap="round"/>
10
+ </svg>;
11
+ }
@@ -0,0 +1,29 @@
1
+ import React, {useId, useState} from 'react';
2
+ // Small, non-HTML Markdown renderer: no remote images, raw HTML or executable URLs.
3
+ function inline(text){return text.split(/(\*\*[^*]+\*\*|`[^`]+`|\[[^\]]+\]\(https?:\/\/[^\s)]+\))/g).map((part,i)=>{
4
+ if(part.startsWith('**')&&part.endsWith('**'))return <strong key={i}>{part.slice(2,-2)}</strong>;
5
+ if(part.startsWith('`')&&part.endsWith('`'))return <code key={i}>{part.slice(1,-1)}</code>;
6
+ const link=part.match(/^\[([^\]]+)\]\((https?:\/\/[^\s)]+)\)$/);if(link)return <a key={i} href={link[2]} target="_blank" rel="noopener noreferrer">{link[1]}</a>;
7
+ return part;
8
+ });}
9
+ export function messagePreview(text){
10
+ const words=text.trim().split(/\s+/);if(words.length<=20)return text;
11
+ const questions=text.split(/\n+/).map(line=>line.trim()).filter(line=>line.includes('?')).map(line=>line.match(/(?:^|[.!]\s+)([^.!]*\?)/)?.[1]||line.slice(0,line.indexOf('?')+1));
12
+ const question=questions.at(-1);if(question&&question.split(/\s+/).length<=20)return question;
13
+ return words.slice(0,20).join(' ')+'…';
14
+ }
15
+ export function ChatMessage({text='',concise=false}){
16
+ const [expanded,setExpanded]=useState(false);
17
+ const detailId=useId();
18
+ if(concise&&text.trim().split(/\s+/).length>20)return <div className="concise-answer"><div id={detailId}><ChatMessage text={expanded?text:messagePreview(text)}/></div><button type="button" className="link message-details" aria-expanded={expanded} aria-controls={detailId} onClick={()=>setExpanded(value=>!value)}>{expanded?'Less details':'More details'}</button></div>;
19
+
20
+ const lines=text.split('\n'),blocks=[];let i=0;
21
+ while(i<lines.length){
22
+ if(!lines[i].trim()){i++;continue;}
23
+ if(lines[i].startsWith('```')){const code=[];i++;while(i<lines.length&&!lines[i].startsWith('```'))code.push(lines[i++]);i++;blocks.push(<pre key={blocks.length}><code>{code.join('\n')}</code></pre>);continue;}
24
+ const heading=lines[i].match(/^#{1,6}\s+(.+)$/);if(heading){blocks.push(<h4 key={blocks.length}>{inline(heading[1])}</h4>);i++;continue;}
25
+ const list=lines[i].match(/^(?:[-*]|\d+[.)])\s+/);if(list){const ordered=/^\d/.test(list[0]),items=[];while(i<lines.length&&/^(?:[-*]|\d+[.)])\s+/.test(lines[i]))items.push(<li key={items.length}>{inline(lines[i++].replace(/^(?:[-*]|\d+[.)])\s+/,''))}</li>);blocks.push(ordered?<ol key={blocks.length}>{items}</ol>:<ul key={blocks.length}>{items}</ul>);continue;}
26
+ const paragraph=[];while(i<lines.length&&lines[i].trim()&&!/^(?:```|#{1,6}\s|[-*]\s|\d+[.)]\s)/.test(lines[i]))paragraph.push(lines[i++]);blocks.push(<p key={blocks.length}>{paragraph.map((line,j)=><React.Fragment key={j}>{j>0&&<br/>}{inline(line)}</React.Fragment>)}</p>);
27
+ }
28
+ return <div className="chat-markdown">{blocks}</div>;
29
+ }
@@ -0,0 +1,6 @@
1
+ import React from 'react';
2
+ export function ChatResizeHandle({width,onChange}){
3
+ const max=()=>Math.max(320,Math.min(900,window.innerWidth-360));
4
+ const resize=value=>onChange(Math.round(Math.max(320,Math.min(max(),value))));
5
+ return <div className="chat-resize-handle" role="separator" aria-label="Resize chat panel" aria-orientation="vertical" aria-valuemin={320} aria-valuemax={max()} aria-valuenow={width} tabIndex={0} title="Drag to resize chat. Arrow keys resize; double-click resets." onDoubleClick={()=>resize(360)} onKeyDown={e=>{if(['ArrowLeft','ArrowRight','Home','End'].includes(e.key)){e.preventDefault();resize(e.key==='Home'?320:e.key==='End'?max():width+(e.key==='ArrowLeft'?32:-32));}}} onPointerDown={e=>{if(e.button!==0)return;e.preventDefault();e.currentTarget.setPointerCapture(e.pointerId);}} onPointerMove={e=>{if(e.currentTarget.hasPointerCapture(e.pointerId))resize(e.currentTarget.closest('.app').getBoundingClientRect().right-e.clientX);}} onPointerUp={e=>{if(e.currentTarget.hasPointerCapture(e.pointerId))e.currentTarget.releasePointerCapture(e.pointerId);}}/>;
6
+ }