devtorch-core 3.0.1__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 (193) hide show
  1. devtorch_core/__init__.py +158 -0
  2. devtorch_core/aggphi_textual.py +275 -0
  3. devtorch_core/alerts/__init__.py +23 -0
  4. devtorch_core/alerts/base.py +46 -0
  5. devtorch_core/alerts/config.py +60 -0
  6. devtorch_core/alerts/dispatcher.py +110 -0
  7. devtorch_core/alerts/jira.py +96 -0
  8. devtorch_core/alerts/linear.py +72 -0
  9. devtorch_core/alerts/pagerduty.py +66 -0
  10. devtorch_core/alerts/slack.py +81 -0
  11. devtorch_core/alerts/teams.py +70 -0
  12. devtorch_core/audit/__init__.py +43 -0
  13. devtorch_core/audit/exporter.py +297 -0
  14. devtorch_core/audit/privacy.py +101 -0
  15. devtorch_core/audit/scrubber.py +149 -0
  16. devtorch_core/audit/service.py +67 -0
  17. devtorch_core/audit/signing.py +127 -0
  18. devtorch_core/broadcast/__init__.py +4 -0
  19. devtorch_core/broadcast/broadcaster.py +100 -0
  20. devtorch_core/broadcast/watcher.py +71 -0
  21. devtorch_core/capability.py +639 -0
  22. devtorch_core/cloud/__init__.py +1 -0
  23. devtorch_core/cloud/client_config.py +472 -0
  24. devtorch_core/cloud/client_configs/.claude-opencode-fallback.json +8 -0
  25. devtorch_core/cloud/client_configs/.claude-stdio.json +13 -0
  26. devtorch_core/cloud/client_configs/.cursor-mcp.json +13 -0
  27. devtorch_core/cloud/client_configs/.opencode-bridge.json +13 -0
  28. devtorch_core/cloud/client_configs/.opencode.json +15 -0
  29. devtorch_core/cloud/client_configs/.vscode-mcp.json +13 -0
  30. devtorch_core/cloud/devtorch-mcp-bridge.js +357 -0
  31. devtorch_core/cloud/mcp_client.py +229 -0
  32. devtorch_core/cloud/setup.py +144 -0
  33. devtorch_core/cloud/sync.py +143 -0
  34. devtorch_core/cloud/sync_bundle.py +603 -0
  35. devtorch_core/cloud/sync_conflicts.py +159 -0
  36. devtorch_core/cloud/sync_state.py +159 -0
  37. devtorch_core/cloud/team_sync.py +283 -0
  38. devtorch_core/codex/__init__.py +9 -0
  39. devtorch_core/codex/__main__.py +97 -0
  40. devtorch_core/codex/capture.py +208 -0
  41. devtorch_core/codex/proxy.py +412 -0
  42. devtorch_core/concept_catalog.py +209 -0
  43. devtorch_core/consolidation/__init__.py +3 -0
  44. devtorch_core/consolidation/synthesizer.py +87 -0
  45. devtorch_core/consolidation/workflow.py +175 -0
  46. devtorch_core/daemon/__init__.py +27 -0
  47. devtorch_core/daemon/supervisor.py +293 -0
  48. devtorch_core/daemon/watcher.py +244 -0
  49. devtorch_core/dashboard_api.py +2012 -0
  50. devtorch_core/deltaf.py +97 -0
  51. devtorch_core/disclosure.py +50 -0
  52. devtorch_core/divergence/__init__.py +3 -0
  53. devtorch_core/divergence/detector.py +166 -0
  54. devtorch_core/gateway/__init__.py +32 -0
  55. devtorch_core/gateway/key_manager.py +124 -0
  56. devtorch_core/gateway/metrics_webhook.py +252 -0
  57. devtorch_core/gateway/policy.py +262 -0
  58. devtorch_core/gateway/server.py +727 -0
  59. devtorch_core/gateway/sso.py +233 -0
  60. devtorch_core/gcc.py +1246 -0
  61. devtorch_core/github/__init__.py +35 -0
  62. devtorch_core/github/app.py +240 -0
  63. devtorch_core/github/comment_builder.py +113 -0
  64. devtorch_core/github/pat.py +76 -0
  65. devtorch_core/github/pr_parser.py +82 -0
  66. devtorch_core/github/pr_reporter.py +555 -0
  67. devtorch_core/gitlab/__init__.py +177 -0
  68. devtorch_core/hitl/__init__.py +4 -0
  69. devtorch_core/hitl/channels.py +129 -0
  70. devtorch_core/hitl/orchestrator.py +95 -0
  71. devtorch_core/hooks/__init__.py +17 -0
  72. devtorch_core/hooks/claude_code.py +228 -0
  73. devtorch_core/hooks/git_capture.py +341 -0
  74. devtorch_core/hooks/git_commit.py +182 -0
  75. devtorch_core/hooks/installer.py +733 -0
  76. devtorch_core/hooks/pre_commit.py +157 -0
  77. devtorch_core/hooks/runner.py +344 -0
  78. devtorch_core/identity/__init__.py +4 -0
  79. devtorch_core/identity/agent.py +86 -0
  80. devtorch_core/identity/providers.py +85 -0
  81. devtorch_core/invariants.py +182 -0
  82. devtorch_core/mcp/__init__.py +10 -0
  83. devtorch_core/mcp/auth.py +177 -0
  84. devtorch_core/mcp/server.py +1049 -0
  85. devtorch_core/metrics/__init__.py +35 -0
  86. devtorch_core/metrics/aggregate.py +215 -0
  87. devtorch_core/metrics/calibrate.py +198 -0
  88. devtorch_core/metrics/calibration.py +125 -0
  89. devtorch_core/metrics/credibility.py +288 -0
  90. devtorch_core/metrics/delivery_time.py +70 -0
  91. devtorch_core/metrics/dhs.py +126 -0
  92. devtorch_core/metrics/mcs.py +96 -0
  93. devtorch_core/metrics/roi.py +88 -0
  94. devtorch_core/metrics/session_writer.py +81 -0
  95. devtorch_core/metrics/shadow_ai.py +117 -0
  96. devtorch_core/metrics/sprint_writer.py +243 -0
  97. devtorch_core/observability/__init__.py +78 -0
  98. devtorch_core/observability/datadog.py +157 -0
  99. devtorch_core/observability/formatter.py +119 -0
  100. devtorch_core/observability/report.py +264 -0
  101. devtorch_core/observability/servicenow.py +147 -0
  102. devtorch_core/observability/splunk.py +218 -0
  103. devtorch_core/observability/webhook.py +227 -0
  104. devtorch_core/parser/__init__.py +30 -0
  105. devtorch_core/parser/blocks.py +216 -0
  106. devtorch_core/parser/inference.py +159 -0
  107. devtorch_core/parser/thinking.py +112 -0
  108. devtorch_core/projects.py +169 -0
  109. devtorch_core/prompt_artifact.py +76 -0
  110. devtorch_core/proxy/__init__.py +9 -0
  111. devtorch_core/proxy/routes/__init__.py +1 -0
  112. devtorch_core/proxy/routes/anthropic.py +264 -0
  113. devtorch_core/proxy/routes/azure_openai.py +336 -0
  114. devtorch_core/proxy/routes/gemini.py +331 -0
  115. devtorch_core/proxy/routes/groq.py +284 -0
  116. devtorch_core/proxy/routes/ollama.py +279 -0
  117. devtorch_core/proxy/routes/openai.py +287 -0
  118. devtorch_core/proxy/server.py +356 -0
  119. devtorch_core/query/__init__.py +15 -0
  120. devtorch_core/query/grep.py +181 -0
  121. devtorch_core/query/hybrid.py +86 -0
  122. devtorch_core/query/semantic.py +157 -0
  123. devtorch_core/rdp.py +105 -0
  124. devtorch_core/reasoning/__init__.py +4 -0
  125. devtorch_core/reasoning/entry.py +31 -0
  126. devtorch_core/reasoning/store.py +122 -0
  127. devtorch_core/reasoning_plus/__init__.py +70 -0
  128. devtorch_core/reasoning_plus/augmenter.py +326 -0
  129. devtorch_core/reasoning_plus/capture.py +51 -0
  130. devtorch_core/reasoning_plus/config.py +256 -0
  131. devtorch_core/reasoning_plus/context.py +262 -0
  132. devtorch_core/reasoning_plus/learning/__init__.py +72 -0
  133. devtorch_core/reasoning_plus/learning/analytics.py +141 -0
  134. devtorch_core/reasoning_plus/learning/api.py +313 -0
  135. devtorch_core/reasoning_plus/learning/chain.py +285 -0
  136. devtorch_core/reasoning_plus/learning/composer.py +74 -0
  137. devtorch_core/reasoning_plus/learning/cross_project.py +234 -0
  138. devtorch_core/reasoning_plus/learning/embeddings.py +209 -0
  139. devtorch_core/reasoning_plus/learning/extractor.py +207 -0
  140. devtorch_core/reasoning_plus/learning/models.py +116 -0
  141. devtorch_core/reasoning_plus/learning/provenance.py +126 -0
  142. devtorch_core/reasoning_plus/learning/recorder.py +81 -0
  143. devtorch_core/reasoning_plus/learning/relevance.py +122 -0
  144. devtorch_core/reasoning_plus/learning/state.py +86 -0
  145. devtorch_core/reasoning_plus/learning/store.py +160 -0
  146. devtorch_core/reasoning_plus/learning/theta_learning_bridge.py +94 -0
  147. devtorch_core/reasoning_plus/prompt.py +90 -0
  148. devtorch_core/rep.py +134 -0
  149. devtorch_core/rep_network/__init__.py +25 -0
  150. devtorch_core/rep_network/merge.py +70 -0
  151. devtorch_core/rep_network/node.py +137 -0
  152. devtorch_core/rep_network/server.py +140 -0
  153. devtorch_core/rep_network/sync.py +207 -0
  154. devtorch_core/sensitivity.py +182 -0
  155. devtorch_core/serve.py +258 -0
  156. devtorch_core/session/__init__.py +39 -0
  157. devtorch_core/session/disagreement.py +188 -0
  158. devtorch_core/session/models.py +114 -0
  159. devtorch_core/session/orchestrator.py +182 -0
  160. devtorch_core/session/planner.py +169 -0
  161. devtorch_core/session/simulator.py +132 -0
  162. devtorch_core/signing.py +290 -0
  163. devtorch_core/sis.py +197 -0
  164. devtorch_core/storage.py +308 -0
  165. devtorch_core/templates/__init__.py +6 -0
  166. devtorch_core/templates/engine.py +122 -0
  167. devtorch_core/templates/go.py +18 -0
  168. devtorch_core/templates/infra.py +19 -0
  169. devtorch_core/templates/library/__init__.py +18 -0
  170. devtorch_core/templates/library/api_design.md +27 -0
  171. devtorch_core/templates/library/bug_fix.md +27 -0
  172. devtorch_core/templates/library/decision_record.md +27 -0
  173. devtorch_core/templates/library/engine.py +228 -0
  174. devtorch_core/templates/library/security_review.md +30 -0
  175. devtorch_core/templates/python.py +19 -0
  176. devtorch_core/templates/react.py +18 -0
  177. devtorch_core/templates/typescript.py +18 -0
  178. devtorch_core/theta.py +221 -0
  179. devtorch_core/theta_synthesis.py +268 -0
  180. devtorch_core/topics.py +320 -0
  181. devtorch_core/variance.py +219 -0
  182. devtorch_core/wrapper/__init__.py +52 -0
  183. devtorch_core/wrapper/anthropic.py +487 -0
  184. devtorch_core/wrapper/base.py +562 -0
  185. devtorch_core/wrapper/bedrock.py +342 -0
  186. devtorch_core/wrapper/gemini.py +422 -0
  187. devtorch_core/wrapper/ollama.py +527 -0
  188. devtorch_core/wrapper/openai.py +461 -0
  189. devtorch_core-3.0.1.dist-info/METADATA +867 -0
  190. devtorch_core-3.0.1.dist-info/RECORD +193 -0
  191. devtorch_core-3.0.1.dist-info/WHEEL +5 -0
  192. devtorch_core-3.0.1.dist-info/entry_points.txt +2 -0
  193. devtorch_core-3.0.1.dist-info/top_level.txt +1 -0
@@ -0,0 +1,244 @@
1
+ """
2
+ Filesystem watcher for the DevTorch background daemon (S26).
3
+
4
+ Monitors project files for create/modify/delete events and emits them as
5
+ `fs_change` events to `.GCC/events.log.jsonl`.
6
+
7
+ Uses `watchdog` when available; otherwise falls back to a simple polling
8
+ implementation.
9
+ """
10
+ from __future__ import annotations
11
+
12
+ import os
13
+ import threading
14
+ import time
15
+ from pathlib import Path
16
+ from typing import Any, Optional
17
+
18
+
19
+ def _emit_fs_change(project_root: Path, file_path: Path, event_kind: str) -> None:
20
+ """Append a fs_change event to the project's event log.
21
+
22
+ Uses the GCCRepository._append_event helper so the hash chain and
23
+ optional signing remain intact.
24
+ """
25
+ from devtorch_core import GCCRepository
26
+
27
+ repo = GCCRepository.at(project_root)
28
+ if not repo.is_initialized():
29
+ return
30
+
31
+ mtime: Optional[float] = None
32
+ try:
33
+ if file_path.exists():
34
+ mtime = file_path.stat().st_mtime
35
+ except Exception:
36
+ pass
37
+
38
+ payload = {
39
+ "path": str(file_path),
40
+ "event_kind": event_kind,
41
+ "mtime": mtime,
42
+ }
43
+
44
+ try:
45
+ repo._append_event("fs_change", payload)
46
+ except Exception:
47
+ # Last-resort fallback: write directly without hash chain.
48
+ # This should only happen if the repo backend is unavailable.
49
+ try:
50
+ import json
51
+
52
+ log_path = repo.gcc_dir / "events.log.jsonl"
53
+ entry = {
54
+ "timestamp": _now_iso(),
55
+ "actor": "devtorch-daemon",
56
+ "event_type": "fs_change",
57
+ "payload": payload,
58
+ }
59
+ with log_path.open("a", encoding="utf-8") as f:
60
+ f.write(json.dumps(entry) + "\n")
61
+ except Exception:
62
+ pass
63
+
64
+
65
+ def _now_iso() -> str:
66
+ import datetime as dt
67
+ return dt.datetime.now(tz=dt.timezone.utc).isoformat()
68
+
69
+
70
+ def _is_inside_gcc(path: Path, gcc_dir: Path) -> bool:
71
+ """Return True if path is inside or equal to the .GCC directory."""
72
+ try:
73
+ return str(path.resolve()).startswith(str(gcc_dir.resolve()))
74
+ except Exception:
75
+ return False
76
+
77
+
78
+ # ---------------------------------------------------------------------------
79
+ # watchdog-based implementation
80
+ # ---------------------------------------------------------------------------
81
+
82
+ try:
83
+ from watchdog.events import FileSystemEventHandler # type: ignore
84
+ from watchdog.observers import Observer # type: ignore
85
+
86
+ _HAS_WATCHDOG = True
87
+
88
+ class _WatchdogHandler(FileSystemEventHandler): # type: ignore[misc]
89
+ def __init__(self, watcher: "ProjectWatcher") -> None:
90
+ self._watcher = watcher
91
+
92
+ def on_created(self, event: Any) -> None:
93
+ self._watcher._emit(Path(event.src_path), "created") # noqa: SLF001
94
+
95
+ def on_modified(self, event: Any) -> None:
96
+ self._watcher._emit(Path(event.src_path), "modified") # noqa: SLF001
97
+
98
+ def on_deleted(self, event: Any) -> None:
99
+ self._watcher._emit(Path(event.src_path), "deleted") # noqa: SLF001
100
+
101
+ except Exception: # pragma: no cover
102
+ _HAS_WATCHDOG = False
103
+ Observer: Any = None # type: ignore[no-redef]
104
+ FileSystemEventHandler: Any = None # type: ignore[no-redef]
105
+
106
+
107
+ # ---------------------------------------------------------------------------
108
+ # polling-based implementation
109
+ # ---------------------------------------------------------------------------
110
+
111
+
112
+ class _PollingWatcher:
113
+ def __init__(self, project_root: Path, gcc_dir: Path, emit: Any, interval: float) -> None:
114
+ self.project_root = project_root
115
+ self.gcc_dir = gcc_dir
116
+ self.emit = emit
117
+ self.interval = interval
118
+ self._stop_event = threading.Event()
119
+ self._thread: Optional[threading.Thread] = None
120
+
121
+ def _build_snapshot(self) -> dict[str, float]:
122
+ snap: dict[str, float] = {}
123
+ for root, dirs, files in os.walk(self.project_root):
124
+ root_path = Path(root)
125
+ if _is_inside_gcc(root_path, self.gcc_dir):
126
+ dirs[:] = []
127
+ continue
128
+ for name in files:
129
+ p = root_path / name
130
+ if _is_inside_gcc(p, self.gcc_dir):
131
+ continue
132
+ try:
133
+ snap[str(p.resolve())] = p.stat().st_mtime
134
+ except Exception:
135
+ pass
136
+ return snap
137
+
138
+ def _detect_changes(self, old: dict[str, float], new: dict[str, float]) -> None:
139
+ for p, mtime in new.items():
140
+ if p not in old:
141
+ self.emit(Path(p), "created")
142
+ elif old[p] != mtime:
143
+ self.emit(Path(p), "modified")
144
+ for p in old:
145
+ if p not in new:
146
+ self.emit(Path(p), "deleted")
147
+
148
+ def _run(self) -> None:
149
+ snapshot = self._build_snapshot()
150
+ while not self._stop_event.is_set():
151
+ self._stop_event.wait(self.interval)
152
+ if self._stop_event.is_set():
153
+ break
154
+ new_snapshot = self._build_snapshot()
155
+ self._detect_changes(snapshot, new_snapshot)
156
+ snapshot = new_snapshot
157
+
158
+ def start(self) -> None:
159
+ self._stop_event.clear()
160
+ self._thread = threading.Thread(target=self._run, daemon=True)
161
+ self._thread.start()
162
+
163
+ def stop(self) -> None:
164
+ self._stop_event.set()
165
+ if self._thread is not None:
166
+ self._thread.join(timeout=2.0)
167
+ self._thread = None
168
+
169
+
170
+ # ---------------------------------------------------------------------------
171
+ # public watcher
172
+ # ---------------------------------------------------------------------------
173
+
174
+
175
+ class ProjectWatcher:
176
+ """Watch a project root for file changes and emit `fs_change` events."""
177
+
178
+ def __init__(self, project_root: Path, poll_interval: float = 1.0, use_watchdog: bool = True) -> None:
179
+ self.project_root = Path(project_root).resolve()
180
+ self.gcc_dir = self.project_root / ".GCC"
181
+ self.poll_interval = poll_interval
182
+ self.use_watchdog = use_watchdog
183
+ self._observer: Optional[Any] = None
184
+ self._polling: Optional[_PollingWatcher] = None
185
+
186
+ def _is_gcc_path(self, path: Path) -> bool:
187
+ return _is_inside_gcc(path, self.gcc_dir)
188
+
189
+ def _emit(self, path: Path, event_kind: str) -> None:
190
+ if self._is_gcc_path(path):
191
+ return
192
+ _emit_fs_change(self.project_root, path, event_kind)
193
+
194
+ def _start_watchdog(self) -> bool:
195
+ if not self.use_watchdog or not _HAS_WATCHDOG:
196
+ return False
197
+ observer = Observer()
198
+ handler = _WatchdogHandler(self)
199
+ observer.schedule(handler, str(self.project_root), recursive=True)
200
+ observer.start()
201
+ self._observer = observer
202
+ return True
203
+
204
+ def _start_polling(self) -> None:
205
+ polling = _PollingWatcher(
206
+ self.project_root,
207
+ self.gcc_dir,
208
+ self._emit,
209
+ self.poll_interval,
210
+ )
211
+ polling.start()
212
+ self._polling = polling
213
+
214
+ def start(self) -> None:
215
+ """Start watching the project root.
216
+
217
+ Tries to use watchdog if installed; otherwise falls back to polling.
218
+ """
219
+ if not self._start_watchdog():
220
+ self._start_polling()
221
+
222
+ def stop(self) -> None:
223
+ """Stop watching the project root."""
224
+ if self._observer is not None:
225
+ try:
226
+ self._observer.stop()
227
+ self._observer.join(timeout=2.0)
228
+ except Exception:
229
+ pass
230
+ self._observer = None
231
+ if self._polling is not None:
232
+ self._polling.stop()
233
+ self._polling = None
234
+
235
+ def is_alive(self) -> bool:
236
+ """Return True if the watcher is still running."""
237
+ if self._observer is not None:
238
+ try:
239
+ return self._observer.is_alive()
240
+ except Exception:
241
+ return False
242
+ if self._polling is not None:
243
+ return self._polling._thread is not None and self._polling._thread.is_alive()
244
+ return False