cct-cli 0.7.9.0__py3-none-any.whl

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 (325) hide show
  1. calc_terminal/__init__.py +14 -0
  2. calc_terminal/__main__.py +14 -0
  3. calc_terminal/activity.py +1334 -0
  4. calc_terminal/agent.py +3387 -0
  5. calc_terminal/agent_runtime.py +519 -0
  6. calc_terminal/ai_context.py +447 -0
  7. calc_terminal/ai_modes.py +752 -0
  8. calc_terminal/ai_personalization.py +286 -0
  9. calc_terminal/ai_preview_feedback.py +213 -0
  10. calc_terminal/aicore.py +2572 -0
  11. calc_terminal/anim.py +367 -0
  12. calc_terminal/app.py +3685 -0
  13. calc_terminal/art.py +639 -0
  14. calc_terminal/atomsim.py +368 -0
  15. calc_terminal/attachments.py +743 -0
  16. calc_terminal/benchmark_system.py +414 -0
  17. calc_terminal/browser/__init__.py +36 -0
  18. calc_terminal/browser/browser_state.py +346 -0
  19. calc_terminal/browser/devserver.py +176 -0
  20. calc_terminal/browser/engine.py +494 -0
  21. calc_terminal/browser/navigation.py +84 -0
  22. calc_terminal/browser/preview.py +429 -0
  23. calc_terminal/browser/preview_entry.py +95 -0
  24. calc_terminal/browser/project_detector.py +144 -0
  25. calc_terminal/browser/server.py +449 -0
  26. calc_terminal/browser/state.py +75 -0
  27. calc_terminal/browser/watcher.py +99 -0
  28. calc_terminal/browser_gui/__init__.py +1 -0
  29. calc_terminal/browser_gui/__main__.py +3 -0
  30. calc_terminal/browser_gui/launcher.py +173 -0
  31. calc_terminal/browser_gui/playwright_browser.py +117 -0
  32. calc_terminal/browser_gui/qt_browser.py +1501 -0
  33. calc_terminal/browser_gui/webview_browser.py +57 -0
  34. calc_terminal/capabilities/__init__.py +35 -0
  35. calc_terminal/capabilities/adapters/__init__.py +33 -0
  36. calc_terminal/capabilities/adapters/bioinformatics.py +204 -0
  37. calc_terminal/capabilities/adapters/browser_adapter.py +205 -0
  38. calc_terminal/capabilities/adapters/filesystem.py +206 -0
  39. calc_terminal/capabilities/adapters/git_adapter.py +202 -0
  40. calc_terminal/capabilities/adapters/jupyter_adapter.py +138 -0
  41. calc_terminal/capabilities/adapters/ml_frameworks.py +158 -0
  42. calc_terminal/capabilities/adapters/platforms.py +200 -0
  43. calc_terminal/capabilities/adapters/python_exec.py +93 -0
  44. calc_terminal/capabilities/adapters/quantum_adapter.py +150 -0
  45. calc_terminal/capabilities/adapters/scientific_comp.py +123 -0
  46. calc_terminal/capabilities/adapters/structural_bio.py +161 -0
  47. calc_terminal/capabilities/adapters/terminal.py +99 -0
  48. calc_terminal/capabilities/bus.py +178 -0
  49. calc_terminal/capabilities/discovery.py +207 -0
  50. calc_terminal/capabilities/schema.py +221 -0
  51. calc_terminal/cat.ico +0 -0
  52. calc_terminal/cat_browser.py +2018 -0
  53. calc_terminal/chat_store.py +703 -0
  54. calc_terminal/cli.py +1178 -0
  55. calc_terminal/code_editor.py +640 -0
  56. calc_terminal/collaboration.py +723 -0
  57. calc_terminal/commands_data.py +139 -0
  58. calc_terminal/compatibility_engine.py +352 -0
  59. calc_terminal/compute/__init__.py +31 -0
  60. calc_terminal/compute/fabric.py +350 -0
  61. calc_terminal/config.py +227 -0
  62. calc_terminal/core/__init__.py +41 -0
  63. calc_terminal/core/checkpoint.py +156 -0
  64. calc_terminal/core/input/__init__.py +45 -0
  65. calc_terminal/core/mode_registry.py +300 -0
  66. calc_terminal/core/project_graph.py +172 -0
  67. calc_terminal/core/recovery.py +129 -0
  68. calc_terminal/core/security_layer.py +112 -0
  69. calc_terminal/core/task_graph.py +202 -0
  70. calc_terminal/core/unified_runtime.py +184 -0
  71. calc_terminal/core/verification.py +257 -0
  72. calc_terminal/customization.py +1566 -0
  73. calc_terminal/derivations.py +153 -0
  74. calc_terminal/device_control.py +263 -0
  75. calc_terminal/diagnostics/__init__.py +27 -0
  76. calc_terminal/diagnostics/doctor_engine.py +382 -0
  77. calc_terminal/diagnostics/self_test.py +247 -0
  78. calc_terminal/doctor.py +519 -0
  79. calc_terminal/easter_eggs.py +274 -0
  80. calc_terminal/editor/__init__.py +1 -0
  81. calc_terminal/editor/actions.py +263 -0
  82. calc_terminal/editor/commands.py +160 -0
  83. calc_terminal/editor/shortcuts.py +226 -0
  84. calc_terminal/engine.py +259 -0
  85. calc_terminal/errors.py +120 -0
  86. calc_terminal/event_stream.py +146 -0
  87. calc_terminal/eventbus.py +133 -0
  88. calc_terminal/extensions.py +733 -0
  89. calc_terminal/fallback_cli.py +1321 -0
  90. calc_terminal/first_run.py +265 -0
  91. calc_terminal/fomoji_auth.py +1043 -0
  92. calc_terminal/formulas.py +82 -0
  93. calc_terminal/fs_cache.py +121 -0
  94. calc_terminal/fs_watcher.py +277 -0
  95. calc_terminal/game.py +193 -0
  96. calc_terminal/gen1.py +5 -0
  97. calc_terminal/generators.py +245 -0
  98. calc_terminal/gestures/__init__.py +42 -0
  99. calc_terminal/gestures/bindings.py +175 -0
  100. calc_terminal/gestures/manager.py +477 -0
  101. calc_terminal/goodbye.py +363 -0
  102. calc_terminal/gpu3d.py +290 -0
  103. calc_terminal/graphs.py +358 -0
  104. calc_terminal/hardware_analyzer.py +440 -0
  105. calc_terminal/host/__init__.py +30 -0
  106. calc_terminal/host/browser_manager.py +187 -0
  107. calc_terminal/host/desktop.py +1386 -0
  108. calc_terminal/host/launcher.py +395 -0
  109. calc_terminal/host/terminal.py +279 -0
  110. calc_terminal/identity.py +216 -0
  111. calc_terminal/input/__init__.py +54 -0
  112. calc_terminal/input/capabilities.py +258 -0
  113. calc_terminal/input/focus.py +87 -0
  114. calc_terminal/input/gestures.py +64 -0
  115. calc_terminal/input/pointer.py +114 -0
  116. calc_terminal/input/touch.py +345 -0
  117. calc_terminal/keys.py +84 -0
  118. calc_terminal/live_automation.py +165 -0
  119. calc_terminal/mathtext.py +433 -0
  120. calc_terminal/mcp.py +386 -0
  121. calc_terminal/memory.py +337 -0
  122. calc_terminal/memory_v2.py +479 -0
  123. calc_terminal/metrics.py +333 -0
  124. calc_terminal/mode_detection.py +146 -0
  125. calc_terminal/model.py +2431 -0
  126. calc_terminal/model_router.py +665 -0
  127. calc_terminal/models/__init__.py +0 -0
  128. calc_terminal/models/active_state.py +187 -0
  129. calc_terminal/models/dynamic_registry.py +584 -0
  130. calc_terminal/models/manager.py +781 -0
  131. calc_terminal/models/model_metadata.json +3526 -0
  132. calc_terminal/models/profiles.py +194 -0
  133. calc_terminal/models/registry.py +265 -0
  134. calc_terminal/models/schema.py +197 -0
  135. calc_terminal/models/validator.py +287 -0
  136. calc_terminal/models/verification_engine.py +368 -0
  137. calc_terminal/native_picker.py +215 -0
  138. calc_terminal/ollama_catalog.py +279 -0
  139. calc_terminal/ollama_download.py +233 -0
  140. calc_terminal/orchestrator.py +304 -0
  141. calc_terminal/package_research.py +322 -0
  142. calc_terminal/packages.py +1024 -0
  143. calc_terminal/pc_specs.py +116 -0
  144. calc_terminal/permissions.py +334 -0
  145. calc_terminal/pet.py +106 -0
  146. calc_terminal/pipeline.py +505 -0
  147. calc_terminal/platform/__init__.py +491 -0
  148. calc_terminal/platform/desktop.py +491 -0
  149. calc_terminal/platform/web.py +781 -0
  150. calc_terminal/preview/__init__.py +1 -0
  151. calc_terminal/preview/dev_server.py +303 -0
  152. calc_terminal/preview/diagnostics.py +131 -0
  153. calc_terminal/preview/live_reload.py +66 -0
  154. calc_terminal/preview/manager.py +129 -0
  155. calc_terminal/project_stats.py +209 -0
  156. calc_terminal/projects.py +328 -0
  157. calc_terminal/providers/__init__.py +0 -0
  158. calc_terminal/providers/adapters/__init__.py +80 -0
  159. calc_terminal/providers/adapters/anthropic_adapter.py +127 -0
  160. calc_terminal/providers/adapters/base.py +106 -0
  161. calc_terminal/providers/adapters/chinese_adapters.py +420 -0
  162. calc_terminal/providers/adapters/gemini_adapter.py +101 -0
  163. calc_terminal/providers/adapters/ollama_adapter.py +83 -0
  164. calc_terminal/providers/adapters/openai_adapter.py +159 -0
  165. calc_terminal/providers/adapters/other_adapters.py +246 -0
  166. calc_terminal/providers/anthropic_provider.py +172 -0
  167. calc_terminal/providers/auto_update.py +416 -0
  168. calc_terminal/providers/base_provider.py +105 -0
  169. calc_terminal/providers/discovery_manager.py +207 -0
  170. calc_terminal/providers/gemini_provider.py +178 -0
  171. calc_terminal/providers/lifecycle.py +767 -0
  172. calc_terminal/providers/ollama_adapter.py +707 -0
  173. calc_terminal/providers/openai_provider.py +254 -0
  174. calc_terminal/providers/provider_manager.py +1827 -0
  175. calc_terminal/providers/providers.json +4075 -0
  176. calc_terminal/reactionsim.py +279 -0
  177. calc_terminal/registry.py +337 -0
  178. calc_terminal/report.py +162 -0
  179. calc_terminal/research/__init__.py +45 -0
  180. calc_terminal/research/artifact_intel.py +126 -0
  181. calc_terminal/research/data_lineage.py +123 -0
  182. calc_terminal/research/experiment_ledger.py +303 -0
  183. calc_terminal/research/reproducibility.py +131 -0
  184. calc_terminal/resilience/__init__.py +47 -0
  185. calc_terminal/resilience/agent_state.py +121 -0
  186. calc_terminal/resilience/capability_matcher.py +174 -0
  187. calc_terminal/resilience/circuit_breaker.py +158 -0
  188. calc_terminal/resilience/failover_engine.py +230 -0
  189. calc_terminal/resilience/health_monitor.py +192 -0
  190. calc_terminal/resilience/ollama_adapter.py +125 -0
  191. calc_terminal/resilience/orchestrator.py +312 -0
  192. calc_terminal/resilience/types.py +134 -0
  193. calc_terminal/sandbox.py +98 -0
  194. calc_terminal/scires.py +558 -0
  195. calc_terminal/security_scanner.py +126 -0
  196. calc_terminal/session.py +294 -0
  197. calc_terminal/sim3d.py +206 -0
  198. calc_terminal/solver.py +276 -0
  199. calc_terminal/sound.py +127 -0
  200. calc_terminal/task_reports.py +287 -0
  201. calc_terminal/terminal_host.py +201 -0
  202. calc_terminal/terminal_identity.py +411 -0
  203. calc_terminal/test_ai_mode_reliability.py +344 -0
  204. calc_terminal/test_browser.py +368 -0
  205. calc_terminal/test_code_editor_upgrade.py +485 -0
  206. calc_terminal/test_customization.py +1148 -0
  207. calc_terminal/test_customization_ui.py +612 -0
  208. calc_terminal/test_dynamic_registry.py +304 -0
  209. calc_terminal/test_extensions.py +436 -0
  210. calc_terminal/test_overhaul.py +557 -0
  211. calc_terminal/test_project_detect.py +255 -0
  212. calc_terminal/test_root_cause_fix.py +527 -0
  213. calc_terminal/test_stability.py +532 -0
  214. calc_terminal/test_terminal_identity.py +132 -0
  215. calc_terminal/test_v079_speed.py +460 -0
  216. calc_terminal/theme.py +1107 -0
  217. calc_terminal/timeline.py +139 -0
  218. calc_terminal/todos.py +246 -0
  219. calc_terminal/tool_call_normalizer.py +419 -0
  220. calc_terminal/tui.py +104 -0
  221. calc_terminal/ui/__init__.py +8 -0
  222. calc_terminal/ui/activity_panel.py +231 -0
  223. calc_terminal/ui/activity_stream_panel.py +238 -0
  224. calc_terminal/ui/animations.py +122 -0
  225. calc_terminal/ui/app.py +7271 -0
  226. calc_terminal/ui/attach_panel.py +597 -0
  227. calc_terminal/ui/attachments.py +424 -0
  228. calc_terminal/ui/backup_panel.py +810 -0
  229. calc_terminal/ui/browser_shell.py +887 -0
  230. calc_terminal/ui/cat_agent.py +357 -0
  231. calc_terminal/ui/chats_panel.py +899 -0
  232. calc_terminal/ui/command_palette.py +125 -0
  233. calc_terminal/ui/command_palette_modal.py +166 -0
  234. calc_terminal/ui/composer.py +1141 -0
  235. calc_terminal/ui/context_menu.py +197 -0
  236. calc_terminal/ui/conversation.py +1435 -0
  237. calc_terminal/ui/customization_panel.py +1229 -0
  238. calc_terminal/ui/dashboard.py +404 -0
  239. calc_terminal/ui/design_system.py +557 -0
  240. calc_terminal/ui/diff_panel.py +213 -0
  241. calc_terminal/ui/editor.py +2102 -0
  242. calc_terminal/ui/empty_state.py +302 -0
  243. calc_terminal/ui/events.py +487 -0
  244. calc_terminal/ui/extensions_panel.py +815 -0
  245. calc_terminal/ui/footer.py +166 -0
  246. calc_terminal/ui/gestures_panel.py +383 -0
  247. calc_terminal/ui/goodbye_screen.py +100 -0
  248. calc_terminal/ui/header.py +1034 -0
  249. calc_terminal/ui/help_panel.py +254 -0
  250. calc_terminal/ui/live_activities.py +914 -0
  251. calc_terminal/ui/mcp_panel.py +570 -0
  252. calc_terminal/ui/memory_center.py +524 -0
  253. calc_terminal/ui/mode_colors_panel.py +525 -0
  254. calc_terminal/ui/nav_screens.py +747 -0
  255. calc_terminal/ui/ollama_panel.py +536 -0
  256. calc_terminal/ui/palette.py +221 -0
  257. calc_terminal/ui/permission_panel.py +269 -0
  258. calc_terminal/ui/personalization_panel.py +517 -0
  259. calc_terminal/ui/personalize_center.py +1568 -0
  260. calc_terminal/ui/preview_panel.py +441 -0
  261. calc_terminal/ui/resizers.py +402 -0
  262. calc_terminal/ui/sidebar.py +1285 -0
  263. calc_terminal/ui/statusbar.py +168 -0
  264. calc_terminal/ui/theme_css.py +1396 -0
  265. calc_terminal/ui/thinking.py +226 -0
  266. calc_terminal/ui/timeline_panel.py +102 -0
  267. calc_terminal/ui/todo_panel.py +193 -0
  268. calc_terminal/ui/viewport.py +136 -0
  269. calc_terminal/ui/vision_panel.py +489 -0
  270. calc_terminal/ui/welcome_modal.py +343 -0
  271. calc_terminal/ui/widgets.py +160 -0
  272. calc_terminal/ui/workspace.py +831 -0
  273. calc_terminal/viewers/__init__.py +1 -0
  274. calc_terminal/viewers/document_viewer.py +252 -0
  275. calc_terminal/viewers/image_viewer.py +241 -0
  276. calc_terminal/viewers/pdf_viewer.py +203 -0
  277. calc_terminal/viewers/presentation_viewer.py +164 -0
  278. calc_terminal/viewers/registry.py +120 -0
  279. calc_terminal/viewers/spreadsheet_viewer.py +204 -0
  280. calc_terminal/vision/__init__.py +89 -0
  281. calc_terminal/vision/analysis.py +194 -0
  282. calc_terminal/vision/annotations.py +297 -0
  283. calc_terminal/vision/capture.py +171 -0
  284. calc_terminal/vision/context.py +231 -0
  285. calc_terminal/vision/correlation.py +169 -0
  286. calc_terminal/vision/cursor.py +258 -0
  287. calc_terminal/vision/events.py +66 -0
  288. calc_terminal/vision/frame_pipeline.py +259 -0
  289. calc_terminal/vision/priority.py +218 -0
  290. calc_terminal/vision/provider.py +180 -0
  291. calc_terminal/vision/safety.py +149 -0
  292. calc_terminal/vision/session.py +281 -0
  293. calc_terminal/vision/verify.py +162 -0
  294. calc_terminal/vision.py +514 -0
  295. calc_terminal/vscode_integration.py +113 -0
  296. calc_terminal/web/__init__.py +8 -0
  297. calc_terminal/web/cat_runtime.py +710 -0
  298. calc_terminal/web/server.py +2891 -0
  299. calc_terminal/web/static/css/app.css +3152 -0
  300. calc_terminal/web/static/icons/badge-72.png +0 -0
  301. calc_terminal/web/static/icons/cat.ico +0 -0
  302. calc_terminal/web/static/icons/icon-128.png +0 -0
  303. calc_terminal/web/static/icons/icon-144.png +0 -0
  304. calc_terminal/web/static/icons/icon-152.png +0 -0
  305. calc_terminal/web/static/icons/icon-192.png +0 -0
  306. calc_terminal/web/static/icons/icon-384.png +0 -0
  307. calc_terminal/web/static/icons/icon-512.png +0 -0
  308. calc_terminal/web/static/icons/icon-72.png +0 -0
  309. calc_terminal/web/static/icons/icon-96.png +0 -0
  310. calc_terminal/web/static/icons/icon.svg +34 -0
  311. calc_terminal/web/static/icons/new-project.png +0 -0
  312. calc_terminal/web/static/icons/open-project.png +0 -0
  313. calc_terminal/web/static/index.html +734 -0
  314. calc_terminal/web/static/js/app.js +2403 -0
  315. calc_terminal/web/static/manifest.json +88 -0
  316. calc_terminal/web/static/sw.js +230 -0
  317. calc_terminal/workflow_engine.py +769 -0
  318. calc_terminal/workspace.py +593 -0
  319. calc_terminal/workspace_index.py +385 -0
  320. cct_cli-0.7.9.0.dist-info/METADATA +210 -0
  321. cct_cli-0.7.9.0.dist-info/RECORD +325 -0
  322. cct_cli-0.7.9.0.dist-info/WHEEL +5 -0
  323. cct_cli-0.7.9.0.dist-info/entry_points.txt +4 -0
  324. cct_cli-0.7.9.0.dist-info/licenses/LICENSE +21 -0
  325. cct_cli-0.7.9.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,153 @@
1
+ """
2
+ Real calculus derivations for chemical kinetics rate laws.
3
+
4
+ These are NOT random numericals — they are the actual step-by-step
5
+ derivation of the integrated rate law from the differential rate law,
6
+ using proper mathematical notation (stacked fractions via mathtext,
7
+ "x" for multiplication, integral signs, etc.), the way it is worked
8
+ out on paper / on a board.
9
+
10
+ Each function returns a dict consumed by engine.render_derivation():
11
+ topic, goal, steps: [(label, [compose-parts]), ...], result, note
12
+ """
13
+
14
+ from .mathtext import frac_part as F, sub, sup
15
+
16
+ MUL = "\u00d7" # x (never "*")
17
+ INT = "\u222b" # integral sign
18
+ DDT = "d[R]/dt"
19
+
20
+
21
+ def zero_order_derivation():
22
+ steps = [
23
+ ("Rate law (differential form)",
24
+ [f"Rate = \u2212d[R]/dt = k[R]", sup(0), " = k"]),
25
+ ("Separate the variables",
26
+ ["\u2212d[R] = k ", "dt"]),
27
+ ("Integrate both sides",
28
+ [INT, " ", "from [R]", sub(0), " to [R]", " \u2212d[R] = k ", INT, " from 0 to t dt"]),
29
+ ("Evaluate the integral",
30
+ ["\u2212([R] \u2212 [R]", sub(0), ") = k(t \u2212 0)"]),
31
+ ("Rearrange for [R]",
32
+ ["[R] = [R]", sub(0), " \u2212 kt"]),
33
+ ("Solve for k (rearranged form)",
34
+ ["k = ", F(f"[R]{sub(0)} \u2212 [R]", "t")]),
35
+ ]
36
+ return {
37
+ "topic": "Derivation \u00b7 Zero Order Integrated Rate Law",
38
+ "goal": "Derive [R] = [R]\u2080 \u2212 kt starting from the differential rate law of a zero order reaction.",
39
+ "steps": steps,
40
+ "result": f"[R] = [R]{sub(0)} \u2212 kt (equivalently k = ([R]{sub(0)} \u2212 [R]) / t )",
41
+ "note": "For a zero order reaction the rate is independent of concentration, so [R] falls "
42
+ "LINEARLY with time \u2014 a straight line of slope \u2212k when [R] is plotted against t.",
43
+ }
44
+
45
+
46
+ def first_order_derivation():
47
+ steps = [
48
+ ("Rate law (differential form)",
49
+ ["Rate = \u2212d[R]/dt = k[R]"]),
50
+ ("Separate the variables",
51
+ ["\u2212", F("d[R]", "[R]"), " = k dt"]),
52
+ ("Integrate both sides",
53
+ [INT, " from [R]", sub(0), " to [R] \u2212", F("d[R]", "[R]"), " = k ", INT, " from 0 to t dt"]),
54
+ ("Evaluate the integral (\u222bd[R]/[R] = ln[R])",
55
+ ["\u2212(ln[R] \u2212 ln[R]", sub(0), ") = kt"]),
56
+ ("Combine logarithms",
57
+ ["ln(", f"[R]{sub(0)}", "/[R]) = kt"]),
58
+ ("Solve for k, convert ln \u2192 log",
59
+ ["k = ", F("1", "t"), " ln(", f"[R]{sub(0)}", "/[R]) = ", F("2.303", "t"),
60
+ f" log{sub(10)}([R]{sub(0)}/[R])"]),
61
+ ]
62
+ return {
63
+ "topic": "Derivation \u00b7 First Order Integrated Rate Law",
64
+ "goal": "Derive k = (2.303/t) log([R]\u2080/[R]) starting from the differential rate law of a first order reaction.",
65
+ "steps": steps,
66
+ "result": f"k = (2.303/t) \u00d7 log{sub(10)}([R]{sub(0)}/[R]) (equivalently [R] = [R]{sub(0)} e{sup('-kt')} )",
67
+ "note": "Because the exponent is linear in t, a plot of ln[R] (or log[R]) against t is a straight "
68
+ "line of slope \u2212k \u2014 the diagnostic test for first order kinetics.",
69
+ }
70
+
71
+
72
+ def second_order_derivation():
73
+ steps = [
74
+ ("Rate law (differential form)",
75
+ ["Rate = \u2212d[R]/dt = k[R]", sup(2)]),
76
+ ("Separate the variables",
77
+ ["\u2212", F("d[R]", "[R]" + sup(2)), " = k dt"]),
78
+ ("Integrate both sides",
79
+ [INT, " from [R]", sub(0), " to [R] \u2212", F("d[R]", "[R]" + sup(2)), " = k ", INT, " from 0 to t dt"]),
80
+ ("Evaluate the integral (\u222bd[R]/[R]\u00b2 = \u22121/[R])",
81
+ [F("1", "[R]"), " \u2212 ", F("1", f"[R]{sub(0)}"), " = kt"]),
82
+ ("Rearrange",
83
+ [F("1", "[R]"), " = ", F("1", f"[R]{sub(0)}"), " + kt"]),
84
+ ]
85
+ return {
86
+ "topic": "Derivation \u00b7 Second Order Integrated Rate Law",
87
+ "goal": "Derive 1/[R] = 1/[R]\u2080 + kt starting from the differential rate law of a second order reaction.",
88
+ "steps": steps,
89
+ "result": f"1/[R] = 1/[R]{sub(0)} + kt",
90
+ "note": "A plot of 1/[R] against t is a straight line of slope +k \u2014 the diagnostic test for "
91
+ "second order kinetics (unlike zero order, which is linear in [R] itself).",
92
+ }
93
+
94
+ def third_order_derivation():
95
+ steps = [
96
+ ("Rate law (differential form)",
97
+ ["Rate = \u2212d[R]/dt = k[R]", sup(3)]),
98
+ ("Separate the variables",
99
+ ["\u2212", F("d[R]", "[R]" + sup(3)), " = k dt"]),
100
+ ("Integrate both sides",
101
+ [INT, " from [R]", sub(0), " to [R] \u2212", F("d[R]", "[R]" + sup(3)), " = k ", INT, " from 0 to t dt"]),
102
+ ("Evaluate the integral (\u222bdx/x\u00b3 = \u22121/(2x\u00b2))",
103
+ [F("1", "2[R]" + sup(2)), " \u2212 ", F("1", f"2[R]{sub(0)}" + sup(2)), " = kt"]),
104
+ ("Rearrange",
105
+ [F("1", "[R]" + sup(2)), " = ", F("1", f"[R]{sub(0)}" + sup(2)), " + 2kt"]),
106
+ ]
107
+ return {
108
+ "topic": "Derivation \u00b7 Third Order Integrated Rate Law",
109
+ "goal": "Derive 1/[R]\u00b2 = 1/[R]\u2080\u00b2 + 2kt starting from the differential rate law of a third order reaction.",
110
+ "steps": steps,
111
+ "result": f"1/[R]{sup(2)} = 1/[R]{sub(0)}{sup(2)} + 2kt",
112
+ "note": "A plot of 1/[R]\u00b2 against t is a straight line of slope +2k \u2014 the diagnostic test for "
113
+ "third order kinetics.",
114
+ }
115
+
116
+ def half_life_first_derivation():
117
+ steps = [
118
+ ("Start from the first order integrated law",
119
+ ["k = ", F("2.303", "t"), f" log{sub(10)}([R]{sub(0)}/[R])"]),
120
+ (f"At t = t{sub('1/2')}, [R] = [R]",
121
+ [f"[R] = [R]{sub(0)}/2 \u21d2 [R]{sub(0)}/[R] = 2"]),
122
+ ("Substitute and simplify",
123
+ ["k = ", F("2.303", f"t{sub('1/2')}"), f" log{sub(10)}(2)"]),
124
+ ("Use log\u2081\u2080(2) = 0.301",
125
+ ["k = ", F("2.303 \u00d7 0.301", f"t{sub('1/2')}"), f" = ", F("0.693", f"t{sub('1/2')}")]),
126
+ ("Solve for t\u2081/\u2082",
127
+ [f"t{sub('1/2')}", " = ", F("0.693", "k")]),
128
+ ]
129
+ return {
130
+ "topic": "Derivation \u00b7 First Order Half-Life",
131
+ "goal": "Derive t\u00bd = 0.693/k from the first order integrated rate law.",
132
+ "steps": steps,
133
+ "result": f"t{sub('1/2')} = 0.693 / k",
134
+ "note": "Notice [R]\u2080 cancels out completely \u2014 first order half-life does NOT depend on the "
135
+ "starting concentration, unlike zero or second order.",
136
+ }
137
+
138
+
139
+ DERIVATIONS = {
140
+ "zero": zero_order_derivation,
141
+ "first": first_order_derivation,
142
+ "second": second_order_derivation,
143
+ "third": third_order_derivation,
144
+ "halflife": half_life_first_derivation,
145
+ }
146
+
147
+ DERIVATION_KEYWORDS = [
148
+ (r"zero\s*order", "zero"),
149
+ (r"second\s*order", "second"),
150
+ (r"third\s*order", "third"),
151
+ (r"half.?life", "halflife"),
152
+ (r"first\s*order", "first"),
153
+ ]
@@ -0,0 +1,263 @@
1
+ """
2
+ CCT — device_control.py: Responsible Device Control (v0.7.7 spec
3
+ section 14).
4
+
5
+ An extensible automation framework for interacting with the user's own
6
+ authorized devices, designed so that:
7
+
8
+ * every capability is a registered provider (Desktop / Android / iOS /
9
+ Browser / Terminal / Simulation) with an explicit availability
10
+ check — nothing claims to drive a device it can't;
11
+ * every action that affects a real device requires explicit user
12
+ approval (permissions.manager's "device_control" key + the same
13
+ inline permission-card flow installs use) and is recorded in the
14
+ activity log (eventbus -> session timeline) with the action, target,
15
+ and outcome — spec section 14's "every action ... clearly visible
16
+ in the activity log";
17
+ * the framework itself never executes anything: providers return a
18
+ plan (what command/API call would run, what it affects) and the
19
+ CALLER (the permission flow) decides. This keeps "device control"
20
+ honest — the same separation the spec asks for between automation
21
+ and user control.
22
+
23
+ Built-in providers, stated plainly:
24
+ * terminal — runs commands on the user's machine (delegates to the
25
+ existing shell_commands permission; the same
26
+ subprocess runner agent.py's run_terminal tool uses).
27
+ * simulation— CCT's own in-app simulations (atom, orbital, reaction):
28
+ sandboxed by construction, still approval-gated.
29
+ * desktop / android / ios / browser — EXTENSION POINTS, not working
30
+ drivers: they register with `available()` returning
31
+ False until a provider module implements them
32
+ (e.g. adb for Android, Playwright for browser). The
33
+ framework is complete; the drivers are future work —
34
+ the spec's "where platform APIs allow" is honored by
35
+ not faking support we don't have.
36
+ """
37
+
38
+ if __name__ == "__main__":
39
+ print("This is a library file and is not meant to be run directly.")
40
+ import sys
41
+ sys.exit(1)
42
+
43
+ import shutil
44
+ import time
45
+
46
+ from . import eventbus
47
+
48
+ ACTIVITY_LOG = [] # [{ts, provider, action, target, decision, outcome}]
49
+ MAX_LOG = 200
50
+
51
+
52
+ # -------------------------------------------------------------- providers --
53
+ class DeviceProvider:
54
+ """Base class for a device-control capability. Subclasses implement
55
+ `available()` and `plan(action, params)`; the permission flow calls
56
+ `plan()` FIRST, shows the user what would happen, and only then
57
+ `execute()` (which providers implement only if they can really
58
+ do the thing)."""
59
+
60
+ key = "unnamed"
61
+ label = "Unnamed provider"
62
+ description = ""
63
+
64
+ def available(self):
65
+ return False
66
+
67
+ def plan(self, action, params):
68
+ """Returns {"action": str, "target": str, "effect": str,
69
+ "command": [argv] or None} — the user-visible description of
70
+ what WOULD happen. Never None."""
71
+ return {"action": action, "target": "", "effect": "not implemented",
72
+ "command": None}
73
+
74
+ def execute(self, plan):
75
+ """Actually performs the planned action. Only called after the
76
+ user approved `plan`. Providers that can't execute return a
77
+ refusal dict instead of faking it."""
78
+ return {"ok": False, "note": f"provider '{self.key}' has no executor"}
79
+
80
+
81
+ class TerminalProvider(DeviceProvider):
82
+ """Terminal automation — runs commands through the exact same
83
+ subprocess runner agent.py's run_terminal tool uses."""
84
+
85
+ key = "terminal"
86
+ label = "Terminal"
87
+ description = "Run commands on this machine (shell, git, python, docker...)."
88
+
89
+ def available(self):
90
+ return True
91
+
92
+ def plan(self, action, params):
93
+ # Accept either "command" or the generic "target" param — the
94
+ # CLI /devices flow hands over {"target": "<command>"}.
95
+ cmd = str(params.get("command") or params.get("target") or "").strip()
96
+ return {"action": action,
97
+ "target": cmd,
98
+ "effect": f"Runs in your terminal: $ {cmd}",
99
+ "command": cmd}
100
+
101
+ def execute(self, plan):
102
+ import subprocess
103
+ cmd = plan.get("command")
104
+ if not cmd:
105
+ return {"ok": False, "note": "no command in plan"}
106
+ from . import workspace
107
+ cwd = workspace.root_dir() or None
108
+ try:
109
+ proc = subprocess.run(
110
+ cmd, shell=True, cwd=cwd, capture_output=True, text=True,
111
+ timeout=min(max(float(plan.get("timeout", 60) or 60), 1.0), 300.0),
112
+ encoding="utf-8", errors="replace")
113
+ except subprocess.TimeoutExpired:
114
+ return {"ok": False, "note": "command timed out"}
115
+ except OSError as e:
116
+ return {"ok": False, "note": f"could not run: {e}"}
117
+ return {"ok": proc.returncode == 0, "exit_code": proc.returncode,
118
+ "output": ((proc.stdout or "") + (proc.stderr or "")).strip()}
119
+
120
+
121
+ class SimulationProvider(DeviceProvider):
122
+ """CCT's own in-app simulations — sandboxed by construction but
123
+ still approval-gated (spec: every action affecting the user's
124
+ environment is visible and approved)."""
125
+
126
+ key = "simulation"
127
+ label = "Simulation"
128
+ description = "CAT's in-app simulations (atom, orbital, reaction sims)."
129
+
130
+ def available(self):
131
+ return True
132
+
133
+ def plan(self, action, params):
134
+ sim = str(params.get("simulation", params.get("target", ""))).strip()
135
+ return {"action": action,
136
+ "target": sim,
137
+ "effect": f"Runs the in-app '{sim}' simulation (no system changes)",
138
+ "command": None}
139
+
140
+ def execute(self, plan):
141
+ # In-app simulations render in the terminal/UI directly — the
142
+ # caller (app.py / ui/app.py) starts them after approval; this
143
+ # provider only needs to confirm the plan is runnable.
144
+ return {"ok": True, "note": "simulation started by caller"}
145
+
146
+
147
+ class _ScaffoldedProvider(DeviceProvider):
148
+ """Extension-point providers (desktop/android/ios/browser): they
149
+ exist so the framework is complete and the permission/logging
150
+ machinery is real, but `available()` stays False until an actual
151
+ driver module is implemented."""
152
+
153
+ def available(self):
154
+ return False
155
+
156
+ def plan(self, action, params):
157
+ return {"action": action,
158
+ "target": str(params.get("target", "")),
159
+ "effect": f"{self.label} automation is not available in this build "
160
+ "(no driver module registered).",
161
+ "command": None}
162
+
163
+
164
+ class _Desktop(_ScaffoldedProvider):
165
+ key = "desktop"
166
+ label = "Desktop"
167
+ description = "Desktop automation (mouse/keyboard/windows) — extension point."
168
+
169
+
170
+ class _Android(_ScaffoldedProvider):
171
+ key = "android"
172
+ label = "Android"
173
+ description = "Android automation via adb — extension point (drivers: adb)."
174
+
175
+ def available(self):
176
+ return bool(shutil.which("adb")) and False # scaffolded: no driver yet
177
+
178
+
179
+ class _IOS(_ScaffoldedProvider):
180
+ key = "ios"
181
+ label = "iOS"
182
+ description = "iOS automation where platform APIs allow — extension point."
183
+
184
+
185
+ class _Browser(_ScaffoldedProvider):
186
+ key = "browser"
187
+ label = "Browser"
188
+ description = "Browser automation — extension point (drivers: playwright/selenium)."
189
+
190
+
191
+ PROVIDERS = {
192
+ p.key: p for p in (
193
+ TerminalProvider(), SimulationProvider(), _Desktop(), _Android(),
194
+ _IOS(), _Browser())
195
+ }
196
+
197
+
198
+ # ------------------------------------------------------------- registry --
199
+ def register_provider(provider):
200
+ """Extension API: register a DeviceProvider subclass instance under
201
+ its own key (replaces any provider with the same key)."""
202
+ PROVIDERS[provider.key] = provider
203
+ return provider
204
+
205
+
206
+ def available_providers():
207
+ """[{key, label, description, available}] for the /devices view."""
208
+ return [{"key": p.key, "label": p.label, "description": p.description,
209
+ "available": p.available()}
210
+ for p in PROVIDERS.values()]
211
+
212
+
213
+ def provider(key):
214
+ return PROVIDERS.get(key)
215
+
216
+
217
+ # --------------------------------------------------------------- logging --
218
+ def log_action(provider_key, action, target, decision, outcome=""):
219
+ entry = {"ts": time.time(), "provider": provider_key, "action": action,
220
+ "target": target, "decision": decision, "outcome": outcome}
221
+ ACTIVITY_LOG.append(entry)
222
+ del ACTIVITY_LOG[:-MAX_LOG]
223
+ eventbus.bus.publish(eventbus.DEVICE_ACTION, provider=provider_key,
224
+ action=action, target=target, decision=decision,
225
+ detail=outcome or action)
226
+ return entry
227
+
228
+
229
+ def activity(limit=50):
230
+ """Newest first."""
231
+ return list(reversed(ACTIVITY_LOG))[:limit]
232
+
233
+
234
+ # -------------------------------------------------------------- the gate --
235
+ def plan_action(provider_key, action, params):
236
+ """The one entry point the permission flows call: resolves the
237
+ provider, builds the user-visible plan. Returns
238
+ {"ok": bool, "plan": {..}, "reason": str}. Callers then run the
239
+ existing permission-card flow (device_control key) and only call
240
+ execute_approved() if the user says yes."""
241
+ p = provider(provider_key)
242
+ if p is None:
243
+ return {"ok": False, "plan": None, "reason": f"unknown provider '{provider_key}'"}
244
+ if not p.available():
245
+ return {"ok": False, "plan": None, "reason": f"{p.label} automation is not available in this build"}
246
+ return {"ok": True, "plan": p.plan(action, params), "reason": ""}
247
+
248
+
249
+ def execute_approved(provider_key, plan, params):
250
+ """Runs a provider's plan AFTER the user approved it. Logs the
251
+ action with its outcome either way."""
252
+ p = provider(provider_key)
253
+ if p is None:
254
+ log_action(provider_key, (plan or {}).get("action", "?"),
255
+ (plan or {}).get("target", ""), "denied", "unknown provider")
256
+ return {"ok": False, "note": "unknown provider"}
257
+ result = p.execute(plan)
258
+ outcome = "approved"
259
+ if not result.get("ok"):
260
+ outcome += " \u2014 " + str(result.get("note", "execution failed"))
261
+ log_action(provider_key, (plan or {}).get("action", "?"),
262
+ (plan or {}).get("target", ""), "approved", outcome)
263
+ return result
@@ -0,0 +1,27 @@
1
+ """
2
+ CAT Diagnostics Package per §32, §33.
3
+ """
4
+
5
+ from __future__ import annotations
6
+
7
+ from calc_terminal.diagnostics.doctor_engine import (
8
+ DimensionHealth,
9
+ DoctorReport,
10
+ DoctorEngine,
11
+ doctor_engine,
12
+ )
13
+ from calc_terminal.diagnostics.self_test import (
14
+ SubsystemTestResult,
15
+ SelfTestReport,
16
+ run_self_test,
17
+ )
18
+
19
+ __all__ = [
20
+ "DimensionHealth",
21
+ "DoctorReport",
22
+ "DoctorEngine",
23
+ "doctor_engine",
24
+ "SubsystemTestResult",
25
+ "SelfTestReport",
26
+ "run_self_test",
27
+ ]