cohzen 0.2.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 (74) hide show
  1. cohzen-0.2.0.dist-info/METADATA +295 -0
  2. cohzen-0.2.0.dist-info/RECORD +74 -0
  3. cohzen-0.2.0.dist-info/WHEEL +4 -0
  4. cohzen-0.2.0.dist-info/entry_points.txt +3 -0
  5. cohzen-0.2.0.dist-info/licenses/LICENSE +21 -0
  6. cz/__init__.py +28 -0
  7. cz/audit/__init__.py +21 -0
  8. cz/audit/agentops/__init__.py +5 -0
  9. cz/audit/agentops/detector.py +34 -0
  10. cz/audit/arize_phoenix/__init__.py +5 -0
  11. cz/audit/arize_phoenix/detector.py +34 -0
  12. cz/audit/base.py +37 -0
  13. cz/audit/engine.py +65 -0
  14. cz/audit/langfuse/__init__.py +5 -0
  15. cz/audit/langfuse/detector.py +34 -0
  16. cz/audit/langsmith/__init__.py +5 -0
  17. cz/audit/langsmith/detector.py +34 -0
  18. cz/audit/opentelemetry/__init__.py +5 -0
  19. cz/audit/opentelemetry/detector.py +44 -0
  20. cz/audit/registry.py +192 -0
  21. cz/audit/traceloop/__init__.py +5 -0
  22. cz/audit/traceloop/detector.py +34 -0
  23. cz/audit/wandb/__init__.py +5 -0
  24. cz/audit/wandb/detector.py +34 -0
  25. cz/cli/__init__.py +5 -0
  26. cz/cli/main.py +757 -0
  27. cz/detectors/__init__.py +18 -0
  28. cz/detectors/base.py +70 -0
  29. cz/detectors/langgraph/__init__.py +5 -0
  30. cz/detectors/langgraph/scanner.py +345 -0
  31. cz/detectors/llm/__init__.py +6 -0
  32. cz/detectors/llm/anthropic/__init__.py +5 -0
  33. cz/detectors/llm/anthropic/detector.py +46 -0
  34. cz/detectors/llm/base.py +26 -0
  35. cz/detectors/llm/google/__init__.py +5 -0
  36. cz/detectors/llm/google/detector.py +47 -0
  37. cz/detectors/llm/grok/__init__.py +5 -0
  38. cz/detectors/llm/grok/detector.py +46 -0
  39. cz/detectors/llm/groq/__init__.py +5 -0
  40. cz/detectors/llm/groq/detector.py +47 -0
  41. cz/detectors/llm/langchain/__init__.py +5 -0
  42. cz/detectors/llm/langchain/detector.py +58 -0
  43. cz/detectors/llm/litellm/__init__.py +5 -0
  44. cz/detectors/llm/litellm/detector.py +46 -0
  45. cz/detectors/llm/openai/__init__.py +5 -0
  46. cz/detectors/llm/openai/detector.py +46 -0
  47. cz/detectors/llm/registry.py +50 -0
  48. cz/detectors/registry.py +29 -0
  49. cz/detectors/tools/__init__.py +5 -0
  50. cz/detectors/tools/detector.py +46 -0
  51. cz/execution/__init__.py +45 -0
  52. cz/execution/callbacks.py +466 -0
  53. cz/execution/context.py +260 -0
  54. cz/execution/debugger.py +520 -0
  55. cz/execution/instrumentation.py +456 -0
  56. cz/execution/manifest_matcher.py +87 -0
  57. cz/execution/models.py +67 -0
  58. cz/execution/processor.py +79 -0
  59. cz/execution/serializer.py +157 -0
  60. cz/execution/sqlite.py +422 -0
  61. cz/execution/store.py +67 -0
  62. cz/formatters/__init__.py +9 -0
  63. cz/formatters/console.py +616 -0
  64. cz/formatters/execution_fmt.py +452 -0
  65. cz/formatters/json_fmt.py +16 -0
  66. cz/formatters/mermaid.py +220 -0
  67. cz/formatters/viewer.py +741 -0
  68. cz/manifest/__init__.py +29 -0
  69. cz/manifest/schema.py +157 -0
  70. cz/scanner/__init__.py +40 -0
  71. cz/scanner/engine.py +214 -0
  72. cz/scanner/models.py +447 -0
  73. cz/scanner/utils.py +80 -0
  74. cz/scanner/visitor.py +352 -0
@@ -0,0 +1,295 @@
1
+ Metadata-Version: 2.5
2
+ Name: cohzen
3
+ Version: 0.2.0
4
+ Summary: Fast, static scanner for LangGraph architectures: detecting compiled graphs, agents, and routing edges.
5
+ Author-email: Cohzen <dev@cohzen.ai>
6
+ License-Expression: MIT
7
+ License-File: LICENSE
8
+ Keywords: agents,ast-scanner,cli,langchain,langgraph,static-analysis
9
+ Classifier: Development Status :: 4 - Beta
10
+ Classifier: Environment :: Console
11
+ Classifier: Intended Audience :: Developers
12
+ Classifier: License :: OSI Approved :: MIT License
13
+ Classifier: Programming Language :: Python :: 3
14
+ Classifier: Programming Language :: Python :: 3.10
15
+ Classifier: Programming Language :: Python :: 3.11
16
+ Classifier: Programming Language :: Python :: 3.12
17
+ Classifier: Topic :: Software Development :: Code Generators
18
+ Classifier: Topic :: Software Development :: Quality Assurance
19
+ Requires-Python: >=3.10
20
+ Requires-Dist: pydantic>=2.7.0
21
+ Requires-Dist: rich>=13.7.0
22
+ Requires-Dist: typer>=0.12.0
23
+ Provides-Extra: dev
24
+ Requires-Dist: pytest-cov>=4.1.0; extra == 'dev'
25
+ Requires-Dist: pytest>=8.0.0; extra == 'dev'
26
+ Description-Content-Type: text/markdown
27
+
28
+ # `cz` (Cohzen CLI)
29
+
30
+ **`cz`** statically reconstructs existing **LangGraph** applications' architecture and emits an immutable, machine-readable system manifest (**Cohzen Manifest v0.1**).
31
+
32
+ > **Core Philosophy**: *"Cohzen reconstructs what can be determined statically from the codebase with zero runtime execution."*
33
+
34
+ Everything in Cohzen flows through a single unified pipeline:
35
+
36
+ ```text
37
+ Repository ──► AST ──► Discovery ──► Resolution ──► CohzenManifest (v0.1)
38
+ │
39
+ ┌───────────────────┬─────────────────┴─────────────────┐
40
+ ▼ ▼ ▼
41
+ Terminal / Flow Mermaid Diagram Browser Visualizer
42
+ (`cz scan`) (`cz scan --mermaid`) (`cz view`)
43
+ ```
44
+
45
+ And **`cz audit`** consumes the exact same discovered AST facts to perform in-depth observability and telemetry health audits without redefining architecture.
46
+
47
+ ---
48
+
49
+ ## 🚀 Installation
50
+
51
+ ```bash
52
+ pip install cohzen
53
+ # or with uv:
54
+ uv add cohzen
55
+ ```
56
+
57
+ *Note: Once installed, both `cz` and `cohzen` commands are available.*
58
+
59
+ ---
60
+
61
+ ## 🏗️ Production-Grade Modular Architecture
62
+
63
+ The repository is organized into distinct, enterprise-grade domain packages:
64
+
65
+ ```
66
+ cohzen/
67
+ ├── .github/ # CI/CD workflows & issue templates
68
+ │ ├── workflows/ # GitHub Actions (tests.yml, release.yml)
69
+ │ ├── ISSUE_TEMPLATE/ # Bug report & feature request templates
70
+ │ └── pull_request_template.md # Pull request checklist & guide
71
+ │
72
+ ├── docs/ # Comprehensive technical documentation
73
+ │ ├── architecture.md # Static AST pipeline & engine architecture
74
+ │ ├── manifest.md # CohzenManifest v0.1 JSON specification
75
+ │ ├── supported-frameworks.md # Framework & LLM detector matrix
76
+ │ └── development.md # Contributor quickstart & testing guidelines
77
+ │
78
+ ├── examples/ # Runnable standalone LangGraph examples
79
+ │ ├── langgraph-basic/ # ProcessState pipeline with MemorySaver
80
+ │ ├── langgraph-tools/ # MessagesState agent with ToolNode & lambda routing
81
+ │ └── langgraph-routing/ # Supervisor team with conditional routing & interrupts
82
+ │
83
+ ├── src/cz/
84
+ │ ├── cli/ # Modern CLI application (`main.py`, Typer app)
85
+ │ ├── scanner/ # Core AST scanner engine, visitor, and models
86
+ │ │ ├── engine.py # Repository scan orchestrator
87
+ │ │ ├── visitor.py # Unified AST visitor & symbol resolver
88
+ │ │ ├── utils.py # AST string & expression extractors
89
+ │ │ └── models.py # Internal AST scan models & telemetry types
90
+ │ │
91
+ │ ├── manifest/ # Immutable Cohzen Manifest v0.1 Contract
92
+ │ │ ├── schema.py # CohzenManifest, GraphDef, NodeDef, ToolDef, ModelDef
93
+ │ │ └── builder.py # Deterministic Manifest compilation
94
+ │ │
95
+ │ ├── detectors/ # Static AST pattern detectors
96
+ │ │ ├── base.py # BaseFrameworkScanner & BaseLLMDetector protocols
97
+ │ │ ├── langgraph/ # LangGraph framework detector (StateGraph, nodes, edges)
98
+ │ │ ├── llm/ # Frozen v0.1 LLM provider detectors (OpenAI, Anthropic, Google, etc.)
99
+ │ │ └── tools/ # Tool detector (@tool decorators, line spans)
100
+ │ │
101
+ │ ├── audit/ # Observability & telemetry governance engine
102
+ │ │ ├── engine.py # Audit orchestrator
103
+ │ │ ├── registry.py # Observability detector registry
104
+ │ │ └── [providers]/ # LangSmith, Langfuse, Phoenix, Traceloop, AgentOps, etc.
105
+ │ │
106
+ │ └── formatters/ # Presentation & serialization
107
+ │ ├── console.py # Rich architecture & audit flow reports
108
+ │ ├── mermaid.py # LangGraph-compatible Mermaid flowchart
109
+ │ ├── json_fmt.py # Cohzen Manifest JSON serializer
110
+ │ └── viewer.py # Interactive dark-mode HTML browser visualizer
111
+ │
112
+ └── tests/
113
+ ├── fixtures/ # Real-world & sample test fixtures
114
+ │ ├── real_world/ # 10 production-pattern test projects
115
+ │ └── sample_graphs/ # Specialized graph variations
116
+ └── test_*.py # Automated test suites
117
+ ```
118
+
119
+ ---
120
+
121
+ ## 🔍 CLI Command Hierarchy
122
+
123
+ | Command | Domain | Description |
124
+ |---|---|---|
125
+ | **`cz scan [path]`** | **Architecture Discovery** | Reconstructs graphs, nodes, edges, models, tools, and checkpointer persistence. Emits terminal flow or **`CohzenManifest`** JSON. |
126
+ | **`cz audit [path]`** | **Observability Audit** | Audits telemetry packages, `.env` configurations, and node-by-node / tool-by-tool instrumentation attribution. |
127
+ | **`cz view [path]`** | **Visualization Shortcut** | Convenience alias for `cz scan --view` to launch the interactive browser visualizer. |
128
+ | **`cz version`** | **System Info** | Displays the installed `cz` release version. |
129
+
130
+ ### 1. Architecture Discovery (`cz scan`)
131
+
132
+ ```bash
133
+ # Clean high-signal terminal report
134
+ cz scan .
135
+
136
+ # Emit the official Cohzen Manifest v0.1 JSON
137
+ cz scan . --json
138
+
139
+ # Export to Mermaid Diagram
140
+ cz scan . --mermaid -o architecture.mmd
141
+
142
+ # Launch dark-mode interactive web visualizer
143
+ cz scan . --view
144
+ # or shortcut:
145
+ cz view .
146
+ ```
147
+
148
+ ### 2. Observability & Telemetry Audit (`cz audit`)
149
+
150
+ ```bash
151
+ # Terminal telemetry audit with active tool attribution
152
+ cz audit .
153
+
154
+ # Export audit findings and coverage as JSON for CI/CD gates
155
+ cz audit . --json
156
+ ```
157
+
158
+ ---
159
+
160
+ ## 📜 The Cohzen System Manifest (v0.1)
161
+
162
+ The manifest is the **immutable, machine-readable contract** produced by `cz scan --json`. Discovered entities use stable IDs, standardized `SourceLocation`, and explicit resolution tracking:
163
+
164
+ ```json
165
+ {
166
+ "version": "0.1.0",
167
+ "metadata": {
168
+ "target": ".",
169
+ "files_scanned": 14,
170
+ "files_skipped": 0,
171
+ "parse_errors": 0,
172
+ "unresolved_symbols": 0,
173
+ "dynamic_constructions": 0,
174
+ "scan_duration_ms": 2.14,
175
+ "created_at": "2026-09-19T12:00:00Z",
176
+ "warnings": []
177
+ },
178
+ "frameworks": ["langgraph"],
179
+ "graphs": [
180
+ {
181
+ "id": "graph.workflow",
182
+ "name": "workflow",
183
+ "framework": "langgraph",
184
+ "graph_class": "StateGraph",
185
+ "state_schema": "AgentState",
186
+ "source": { "file": "app.py", "line_start": 20, "line_end": 20 },
187
+ "node_ids": ["planner", "tools"],
188
+ "edges": [
189
+ { "source": "START", "target": "planner", "edge_type": "direct" },
190
+ { "source": "planner", "target": "tools", "edge_type": "conditional" }
191
+ ],
192
+ "compilation": {
193
+ "compiled_var": "app",
194
+ "checkpointer": "MemorySaver",
195
+ "source": { "file": "app.py", "line_start": 35, "line_end": 35 }
196
+ }
197
+ }
198
+ ],
199
+ "nodes": [
200
+ {
201
+ "id": "planner",
202
+ "name": "planner",
203
+ "kind": "node",
204
+ "handler": "planner_node",
205
+ "source": { "file": "app.py", "line_start": 10, "line_end": 18 },
206
+ "model_ids": ["model.openai.gpt-4o"],
207
+ "tool_ids": ["tool.search_web"],
208
+ "resolution": { "status": "resolved", "reason": null },
209
+ "classification": { "role": "agent", "confidence": "high", "evidence": ["llm_invocation", "tool_binding"] }
210
+ }
211
+ ],
212
+ "tools": [
213
+ {
214
+ "id": "tool.search_web",
215
+ "name": "search_web",
216
+ "source": { "file": "tools.py", "line_start": 5, "line_end": 8 },
217
+ "docstring": "Searches the web",
218
+ "resolution": { "status": "resolved", "reason": null }
219
+ }
220
+ ],
221
+ "models": [
222
+ {
223
+ "id": "model.openai.gpt-4o",
224
+ "provider": "openai",
225
+ "name": "gpt-4o",
226
+ "source": { "file": "app.py", "line_start": 12, "line_end": 12 }
227
+ }
228
+ ]
229
+ }
230
+ ```
231
+
232
+ ---
233
+
234
+ ## 🎯 Features Detected
235
+
236
+ | Domain | Provider / Tool | Capabilities Detected |
237
+ |---|---|---|
238
+ | **Frameworks** | **LangGraph** | `StateGraph`, `Graph`, `MessageGraph`, `.compile()` call sites, checkpointers (`MemorySaver`, `SqliteSaver`), human-in-the-loop interrupts (`interrupt_before`, `interrupt_after`), `store`, nodes, direct & conditional edges, `ToolNode` |
239
+ | **LLMs & Tool Bindings** | **OpenAI** | `chat.completions.create`, model identification, `tools=[...]`, `functions=[...]` |
240
+ | | **Anthropic** | `messages.create`, model identification, `tools=[...]` |
241
+ | | **Google** | `generate_content`, `generate_text`, model identification, `tools=[...]` |
242
+ | | **Groq** | Groq client chat completions, models, `tools=[...]` |
243
+ | | **Grok** | xAI Grok chat completions, models |
244
+ | | **LangChain** | `.invoke()`, `.ainvoke()`, `.stream()`, `model.bind_tools(tools)` |
245
+ | | **LiteLLM** | `completion()`, `acompletion()`, models, `tools=[...]` |
246
+ | **Observability (`cz audit`)** | **LangSmith** | Package manifests, `LANGCHAIN_TRACING_V2`, `@traceable` |
247
+ | | **Langfuse** | Package manifests, `LANGFUSE_*`, `@observe` |
248
+ | | **OpenTelemetry** | `opentelemetry-*`, `openinference-*`, `OTEL_*` |
249
+ | | **Arize Phoenix**| `arize-phoenix`, `phoenix`, `PHOENIX_*` |
250
+ | | **Traceloop** | `traceloop-sdk`, `TRACELOOP_*` |
251
+ | | **AgentOps** | `agentops`, `AGENTOPS_API_KEY`, `@track_agent` |
252
+ | | **W&B Weave** | `wandb`, `weave`, `@weave.op()` |
253
+
254
+ ---
255
+
256
+ ## 🔬 How `cz` Performs the Scan
257
+
258
+ 1. **Zero-Execution Static AST Parsing**: `cz` never executes target code or imports unverified packages. It parses Python source trees into Abstract Syntax Trees using Python's native `ast` standard library.
259
+ 2. **Registry-Driven Plugin Dispatch**: A unified AST visitor visits syntax nodes and dispatches them in parallel to modular registries:
260
+ - **Framework Scanners**: Trace graph instantiations (`StateGraph`), node registrations (`add_node`), edge links (`add_edge`, `add_conditional_edges`), and compilation points (`compile(checkpointer=...)`).
261
+ - **LLM Detectors**: Inspect function bodies for LLM client invocations, model parameters, and tool binding calls.
262
+ - **Observability Detectors**: Cross-reference decorator names, package manifests (`pyproject.toml`, `requirements.txt`, `Pipfile`), and environment variable configs (`.env`).
263
+ 3. **Multi-Scope Cross-Referencing**: Connects graph nodes to their corresponding agent implementations and tool executions, resolving same-file definitions before repository-wide fallbacks.
264
+ 4. **Multi-Format Synthesis**: Formats the unified `ScanResult` into:
265
+ - Rich interactive terminal dashboards with ASCII/Unicode flowcharts
266
+ - Native LangGraph Mermaid diagrams
267
+ - Interactive browser visualizer
268
+ - Automated JSON payloads for CI/CD gates
269
+
270
+ ---
271
+
272
+ ## 🧪 Testing
273
+
274
+ Run all 56 modular unit, integration, and real-world fixture tests:
275
+ ```bash
276
+ pytest tests/ -v
277
+ ```
278
+
279
+ Includes 10 real-world architectural fixture projects under `tests/real_world_fixtures/`:
280
+ - `01_single_file.py`: Monolithic graph definition
281
+ - `02_graph_split_across_modules/`: Nodes and state split across files
282
+ - `03_multiple_graphs/`: Separate supervisor and worker graphs
283
+ - `04_imported_nodes/`: Third-party and cross-package node handlers
284
+ - `05_imported_tools/`: Tools imported from external helper modules
285
+ - `06_factory_created_graph/`: Builder functions returning compiled StateGraphs
286
+ - `07_conditional_routing/`: Multi-branch conditional edges
287
+ - `08_toolnode_and_bind_tools/`: LangGraph `ToolNode` and LLM `bind_tools`
288
+ - `09_subgraphs/`: Parent graphs embedding child workflow nodes
289
+ - `10_dynamic_or_partially_unresolvable/`: Dynamic lambdas and unresolvable imports with graceful degradation
290
+
291
+ Run test coverage report (92%+ coverage):
292
+ ```bash
293
+ pytest --cov=cz --cov-report=term-missing tests/
294
+ ```
295
+
@@ -0,0 +1,74 @@
1
+ cz/__init__.py,sha256=jDOrEDWy7F6iJCyM9ut4znF_LhxUI69WGP1RGgxUNN0,550
2
+ cz/audit/__init__.py,sha256=HXNj7NRPRsK_tmTnSpA-OtzAgSxQ45HWA9LqqivaOs4,495
3
+ cz/audit/base.py,sha256=I-Pj2_BP3RfNnfPW3o9nUTyr1LfumIxlqJT3BL4QDXM,1192
4
+ cz/audit/engine.py,sha256=D4xjBYPbw4e5GCBYDzXacjLjPsWUHCswFx6W6z4c09g,2135
5
+ cz/audit/registry.py,sha256=n3qlXve8t6i2HsYpvxvmiLmIKgSeFjSHOY_PmlJ3itE,7400
6
+ cz/audit/agentops/__init__.py,sha256=k2AdjR4um4ROfSejJJwFEiDwt50oRNqlNkEktQnIUhw,128
7
+ cz/audit/agentops/detector.py,sha256=yWVLhSxT9UkmCcXrn5BiRcbxZNqaeeVd0GMd5MSJXPI,1190
8
+ cz/audit/arize_phoenix/__init__.py,sha256=7laKbDLjwN8t5WGan-b88ol2_sS51647IFh0ef5wmcQ,146
9
+ cz/audit/arize_phoenix/detector.py,sha256=SR34EYWr8jIDe1CFO8tirmucN85Pp9IVDJg6p8OvdYk,1254
10
+ cz/audit/langfuse/__init__.py,sha256=_OueDLVGYeW5VNyGT2dbHyqKwxFrr2OsF1n2cI1DU4I,128
11
+ cz/audit/langfuse/detector.py,sha256=Mj3V2eO6i-r_FtCCitsSNSRwJkRaPSL1-BYLAEN7Ymw,1216
12
+ cz/audit/langsmith/__init__.py,sha256=429LIXfFjMJB_KlOXTdCPfz3hpYcLjhTpaVTuPicmBQ,132
13
+ cz/audit/langsmith/detector.py,sha256=O-NVlus091zyjF2PLoy0EbqNUqnxwrSMXuXLL9FwCDw,1243
14
+ cz/audit/opentelemetry/__init__.py,sha256=7R4Wk18JzNgWi4Y8veQvh4uPcB11qW6LHzoVNDr0aOA,148
15
+ cz/audit/opentelemetry/detector.py,sha256=voQHNm1HMf_yuRxisSgOUjmx4MIApC4CBtDbgeU_X00,1700
16
+ cz/audit/traceloop/__init__.py,sha256=GJONreTVrtfYRRo783th5Gjbgw3XiV0nEmdo_w0Ws2M,132
17
+ cz/audit/traceloop/detector.py,sha256=sKn8D-qZLNRBuovYUsfajyz8wqTTWQY3olT8DaSmEHg,1231
18
+ cz/audit/wandb/__init__.py,sha256=X39UERAgYxnyULQeMlUVVm01RW0XzepvRDarfFAkOiY,120
19
+ cz/audit/wandb/detector.py,sha256=u4y190D1-CFmAqlo57_0Dm06GLt8xjFRAwT7M6UfIwU,1191
20
+ cz/cli/__init__.py,sha256=WIM1Rh7ttu-2L4eP86KxurTOXMvp0SQ1JWHhq3dOjEw,88
21
+ cz/cli/main.py,sha256=wpkQdJ-okt7Bva-5CG27SeieMpwoQxI6QOi2XAPIKm4,27069
22
+ cz/detectors/__init__.py,sha256=a2N87Hh3vouJ7IAqMKCwk3jQRZd3weDOleYL751ZhjY,581
23
+ cz/detectors/base.py,sha256=ymbfks0c7NhUyVYNF0OR6-BCbtSH15Pr9ChnXPp_pGI,2253
24
+ cz/detectors/registry.py,sha256=1odfqL53xVo0_TE1b5NZSa7PztNKxMXNjSHWZTDev8c,816
25
+ cz/detectors/langgraph/__init__.py,sha256=e5QXIbFXiv75899Wkn2bLdTl9l4bHKFWqznov9hFx9Q,130
26
+ cz/detectors/langgraph/scanner.py,sha256=4wKa66S6mGeYjiyNg7C7btzv79g9v2fYHfKWgXANdbg,13234
27
+ cz/detectors/llm/__init__.py,sha256=tG8UhHKvD8XCuid_iVRLgdp-zBIbI8_zgyQzfdwoANI,170
28
+ cz/detectors/llm/base.py,sha256=XkPed9pdAF3HzDt_qMExTsMDUjrL3j1ixitmu61ZXco,962
29
+ cz/detectors/llm/registry.py,sha256=fO_5vGzaXDOPuHfbUAk0FrQYZTVg7hpsj1igDi1KvzQ,1739
30
+ cz/detectors/llm/anthropic/__init__.py,sha256=-HCdtcZ3uORCjbVFy2PksXFHehsrfqzeowyFLKyB-WA,139
31
+ cz/detectors/llm/anthropic/detector.py,sha256=x7c5aWXN0bNmByKE4GNoo16NX_WSDfd1Tr4Zym2NFvE,1620
32
+ cz/detectors/llm/google/__init__.py,sha256=OFzF5BZ38owV79Ae4WY4h2mvV9MYEMQcNo2cnIxgWY4,127
33
+ cz/detectors/llm/google/detector.py,sha256=BVAfPlP8-6K7CeUS05rnhQOCS6ze2gbSEB7qbaU-whU,1744
34
+ cz/detectors/llm/grok/__init__.py,sha256=C53QJD0O26lWZZgWh3aph-XB59VanYBmzP2MvanicMs,123
35
+ cz/detectors/llm/grok/detector.py,sha256=cnrlqmd8Q1b-Zu3sF5vsluSBPvFkg8lcSB4DfNyyirI,1613
36
+ cz/detectors/llm/groq/__init__.py,sha256=_GUKV_BRUOPpVcodBZok4oCnd6hQTbQmradopBRksLQ,119
37
+ cz/detectors/llm/groq/detector.py,sha256=VJn3DVyeiOMdy2jqCaH-pDu-xWw5TXLIkLj5RCrF-JM,1688
38
+ cz/detectors/llm/langchain/__init__.py,sha256=p7g3rhWBT9Y53Fxis6VcyH7BT1FRoWgRj3Bbyj_IoYc,145
39
+ cz/detectors/llm/langchain/detector.py,sha256=xkcOg0mjhNXQkGDUd0QXvSJ_SwMWnnv-NU7-fW21xR8,2426
40
+ cz/detectors/llm/litellm/__init__.py,sha256=bsRgv6lmhNPjN_5UKU6fE82TfJa_ct3TdIEQMud_8Uw,127
41
+ cz/detectors/llm/litellm/detector.py,sha256=CAo3bOk4EuWQf0RYFC5Nkjguiw7nGMJ-H5EDd1VQ4DA,1649
42
+ cz/detectors/llm/openai/__init__.py,sha256=8iNeXeM0aN_dHyHk6teQv4bU33_hmuwKL7yRzGcTCMA,127
43
+ cz/detectors/llm/openai/detector.py,sha256=kiMLjxuSEwfQWjVbDxzrGh3b-KyhxETjiefgBkdKyfw,1614
44
+ cz/detectors/tools/__init__.py,sha256=kKf7jy3iyNXdE3rkCTzWtju0X9HgVatnGY5aR962a3Q,115
45
+ cz/detectors/tools/detector.py,sha256=6pTBnHJbIIuyNpdLDtw-dJEVn52lCMO2GG7nnAnyATA,1667
46
+ cz/execution/__init__.py,sha256=MJ7qq69ghA5upO9z7L9bVL7PQ8JO-_37Jxzz9ZZYHOE,1183
47
+ cz/execution/callbacks.py,sha256=bET9wL0qINMh3aylHodaqea2bKtURjOpK7eF7btSAf8,16641
48
+ cz/execution/context.py,sha256=m9LbnTNf--93Po1lUVluIMFuLLyZhJjIBV49uBa8_ho,8897
49
+ cz/execution/debugger.py,sha256=e12uyRyBZRaAmJGobFaP5Vb_3CPWeNHvrGisBTAVcV4,20115
50
+ cz/execution/instrumentation.py,sha256=f33bleCWN1zmbIrbO0ItI_2m2ua7lGQ5fkvXnLJbG7k,18401
51
+ cz/execution/manifest_matcher.py,sha256=g4CEkBLxYuIYSRxRPNt5OV7Ih9LH0mWNcvK8NRuPMd8,3342
52
+ cz/execution/models.py,sha256=nanJ60WjSwcTiAwfeBfB0WaRH6MAQgUmC0WSMsSvoeU,4252
53
+ cz/execution/processor.py,sha256=uzRGS8oT7mNcYpp09HoK0b8qXZOggRe51xKnEeJPK3s,2383
54
+ cz/execution/serializer.py,sha256=XKu_Rbc4Onbzy5eLnfbWgrobDSDUBIcx4pvT1bJugrw,6111
55
+ cz/execution/sqlite.py,sha256=R8NHdJ7ZcyJH97xNPQWe2IS_-b3IOtbKD5DHH6XY6w4,16111
56
+ cz/execution/store.py,sha256=byV6l2jHBf_DllPxwPtbBFHr1Qu4KUA-O4fskbfP2sM,2082
57
+ cz/formatters/__init__.py,sha256=URJGeqeocGVNVm0W8Wn6u2KOlVKd1uYNUDLgvHP2lyA,365
58
+ cz/formatters/console.py,sha256=JT9eWne-Uzwhh88P8lTRn17a-y6dsRe2C8iBtgDKrtE,29702
59
+ cz/formatters/execution_fmt.py,sha256=pOzEEJwNNmGdbpkMBvEaqhjJ5edsuT-EqubjzDzjcuY,17797
60
+ cz/formatters/json_fmt.py,sha256=N1aQ5YMHflMziDRklntSMfTz3fZ1JhVydNPKtc7eg44,562
61
+ cz/formatters/mermaid.py,sha256=Vx9XOr5dq4NqQJfliMBCpZDNCOVDJPbeX0lQumzbi6s,10651
62
+ cz/formatters/viewer.py,sha256=LoWucZbTqLVqZlKd83lGv_sv4fX1g7IM6tTo-4hIakc,23157
63
+ cz/manifest/__init__.py,sha256=KkOXAEqS2dsqAB_a8aWaYmaBpUXdqJ6EqHO05q7q9xU,488
64
+ cz/manifest/schema.py,sha256=0z2gFa1BynEgkzT07fp2RsMslwVDmQttk1QLTuURkgo,9271
65
+ cz/scanner/__init__.py,sha256=eGKeTyLuC2ZfvkGEVMoKEMPp6T-D0jMxIIWQ4jEn-8M,830
66
+ cz/scanner/engine.py,sha256=MVQk9oJ84kr_uoeQyK_5UXMY4sdFw2kxGGWdkn6-ipU,8013
67
+ cz/scanner/models.py,sha256=WIvBd3PpoP1-v_1XgPguwhFso5Z3Lv77n4zUB1fSeIQ,23702
68
+ cz/scanner/utils.py,sha256=S6r8eAYLh0g8BW0PZjCbxDVOf9Qo6ecMcK1v-f1zGEI,2980
69
+ cz/scanner/visitor.py,sha256=DO2NFTDSYvbFsWdTJxm5WafJQn_3IWU2FruHmHzbmfQ,13940
70
+ cohzen-0.2.0.dist-info/METADATA,sha256=DuPgFU_WzukxeZ-U1yVldB-nSy1Qqd529neBKAJkDF8,13203
71
+ cohzen-0.2.0.dist-info/WHEEL,sha256=W3fkpkm7-wf9vBI5Z-7s0eWkeM-spu78I8Neb98DeEg,87
72
+ cohzen-0.2.0.dist-info/entry_points.txt,sha256=VnJoJszmDaJ5zBZQAzI7VufvD7xObK78f3947682sQ4,64
73
+ cohzen-0.2.0.dist-info/licenses/LICENSE,sha256=1Rdm6nomRg4OoJxxYWStrIHWjpDagvfdx28FCj0puCg,1063
74
+ cohzen-0.2.0.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: hatchling 1.32.4
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
@@ -0,0 +1,3 @@
1
+ [console_scripts]
2
+ cohzen = cz.cli.main:app
3
+ cz = cz.cli.main:app
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 Cohzen
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
cz/__init__.py ADDED
@@ -0,0 +1,28 @@
1
+ """cz - Cohzen CLI & Runtime Observability Engine."""
2
+
3
+ from cz.execution import execution_scope, observe, record_reason, span_scope, track
4
+ from cz.execution.debugger import run_isolated_node
5
+
6
+ __version__ = "0.2.0"
7
+
8
+ # Auto-activate tracking when cz is imported
9
+ try:
10
+ track()
11
+ except Exception:
12
+ pass
13
+
14
+ # Aliases
15
+ reason = record_reason
16
+ debug_node = run_isolated_node
17
+
18
+ __all__ = [
19
+ "__version__",
20
+ "observe",
21
+ "track",
22
+ "execution_scope",
23
+ "span_scope",
24
+ "record_reason",
25
+ "reason",
26
+ "debug_node",
27
+ "run_isolated_node",
28
+ ]
cz/audit/__init__.py ADDED
@@ -0,0 +1,21 @@
1
+ """Observability and governance audit subpackage."""
2
+
3
+ from cz.audit.base import BaseObservabilityDetector
4
+ from cz.audit.engine import (
5
+ AuditEngine,
6
+ audit_observability,
7
+ audit_repository,
8
+ scan_env_files,
9
+ scan_manifest_files,
10
+ )
11
+ from cz.audit.registry import ObservabilityRegistry
12
+
13
+ __all__ = [
14
+ "AuditEngine",
15
+ "BaseObservabilityDetector",
16
+ "ObservabilityRegistry",
17
+ "audit_observability",
18
+ "audit_repository",
19
+ "scan_env_files",
20
+ "scan_manifest_files",
21
+ ]
@@ -0,0 +1,5 @@
1
+ """AgentOps observability detector."""
2
+
3
+ from cz.audit.agentops.detector import AgentOpsDetector
4
+
5
+ __all__ = ["AgentOpsDetector"]
@@ -0,0 +1,34 @@
1
+ """AgentOps observability provider detector."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import re
6
+ from typing import List, Optional
7
+ from cz.scanner.models import ObservabilityPackage
8
+
9
+
10
+ class AgentOpsDetector:
11
+ def __init__(self) -> None:
12
+ self.provider_id = "agentops"
13
+ self.display_name = "AgentOps"
14
+ self.category = "Agent Monitoring & Replay"
15
+
16
+ def check_manifest(self, manifest_content: str, filename: str) -> Optional[ObservabilityPackage]:
17
+ pattern = r"(?i)(?:^|[\"'\s,])(agentops)(?:\[[^\]]*\])?([><=~!].*)?(?:$|[\"'\s,\n])"
18
+ match = re.search(pattern, manifest_content, re.MULTILINE)
19
+ if match:
20
+ version_spec = match.group(2).strip() if match.group(2) else None
21
+ return ObservabilityPackage(
22
+ name=self.display_name,
23
+ provider_id=self.provider_id,
24
+ category=self.category,
25
+ source_file=filename,
26
+ version_spec=version_spec,
27
+ )
28
+ return None
29
+
30
+ def get_known_env_vars(self) -> List[str]:
31
+ return ["AGENTOPS_API_KEY"]
32
+
33
+ def get_known_decorators(self) -> List[str]:
34
+ return ["record_action", "track_agent"]
@@ -0,0 +1,5 @@
1
+ """Arize Phoenix observability detector."""
2
+
3
+ from cz.audit.arize_phoenix.detector import ArizePhoenixDetector
4
+
5
+ __all__ = ["ArizePhoenixDetector"]
@@ -0,0 +1,34 @@
1
+ """Arize Phoenix observability provider detector."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import re
6
+ from typing import List, Optional
7
+ from cz.scanner.models import ObservabilityPackage
8
+
9
+
10
+ class ArizePhoenixDetector:
11
+ def __init__(self) -> None:
12
+ self.provider_id = "arize_phoenix"
13
+ self.display_name = "Arize Phoenix"
14
+ self.category = "LLM Observability & Tracing"
15
+
16
+ def check_manifest(self, manifest_content: str, filename: str) -> Optional[ObservabilityPackage]:
17
+ pattern = r"(?i)(?:^|[\"'\s,])(arize-phoenix|phoenix)(?:\[[^\]]*\])?([><=~!].*)?(?:$|[\"'\s,\n])"
18
+ match = re.search(pattern, manifest_content, re.MULTILINE)
19
+ if match:
20
+ version_spec = match.group(2).strip() if match.group(2) else None
21
+ return ObservabilityPackage(
22
+ name=self.display_name,
23
+ provider_id=self.provider_id,
24
+ category=self.category,
25
+ source_file=filename,
26
+ version_spec=version_spec,
27
+ )
28
+ return None
29
+
30
+ def get_known_env_vars(self) -> List[str]:
31
+ return ["PHOENIX_API_KEY", "PHOENIX_COLLECTOR_ENDPOINT", "PHOENIX_PROJECT_NAME"]
32
+
33
+ def get_known_decorators(self) -> List[str]:
34
+ return ["trace"]
cz/audit/base.py ADDED
@@ -0,0 +1,37 @@
1
+ """Base protocol for observability and telemetry tool plugins."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from typing import List, Optional, Protocol
6
+ from cz.scanner.models import ObservabilityPackage
7
+
8
+
9
+ class BaseObservabilityDetector(Protocol):
10
+ """Protocol for an observability tool detector."""
11
+
12
+ @property
13
+ def provider_id(self) -> str:
14
+ """Internal provider identifier (e.g. 'langsmith', 'langfuse')."""
15
+ ...
16
+
17
+ @property
18
+ def display_name(self) -> str:
19
+ """Human-readable display name (e.g. 'LangSmith', 'Langfuse')."""
20
+ ...
21
+
22
+ @property
23
+ def category(self) -> str:
24
+ """Category (e.g. 'LLM Tracing & Evaluation', 'Distributed Tracing')."""
25
+ ...
26
+
27
+ def check_manifest(self, manifest_content: str, filename: str) -> Optional[ObservabilityPackage]:
28
+ """Check if this tool's package is listed in a dependency manifest."""
29
+ ...
30
+
31
+ def get_known_env_vars(self) -> List[str]:
32
+ """List of environment variable keys associated with this tool."""
33
+ ...
34
+
35
+ def get_known_decorators(self) -> List[str]:
36
+ """List of AST decorator names indicating tracing (e.g. 'traceable', 'observe')."""
37
+ ...
cz/audit/engine.py ADDED
@@ -0,0 +1,65 @@
1
+ """Audit engine evaluating repository observability and governance posture."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from pathlib import Path
6
+ from typing import List, Tuple
7
+ from cz.scanner.models import (
8
+ AgentDef,
9
+ ObservabilityAudit,
10
+ ObservabilityPackage,
11
+ ToolDef,
12
+ )
13
+ from cz.audit.registry import ObservabilityRegistry
14
+
15
+
16
+ class AuditEngine:
17
+ """Engine executing observability audits against repositories and discovered components."""
18
+
19
+ def __init__(self, registry: ObservabilityRegistry | None = None) -> None:
20
+ self.registry = registry or ObservabilityRegistry()
21
+
22
+ def scan_manifests(self, repo_path: Path) -> List[ObservabilityPackage]:
23
+ """Scan dependency manifests for known observability tools."""
24
+ return self.registry.scan_manifests(repo_path)
25
+
26
+ def scan_env_files(self, repo_path: Path) -> List[str]:
27
+ """Scan environment files for known telemetry variables."""
28
+ return self.registry.scan_env_files(repo_path)
29
+
30
+ def audit(
31
+ self, repo_path: Path, agents: List[AgentDef], tools: List[ToolDef]
32
+ ) -> ObservabilityAudit:
33
+ """Perform comprehensive observability audit across manifests, env, and code."""
34
+ return self.registry.audit(repo_path, agents, tools)
35
+
36
+
37
+ _default_audit_engine = AuditEngine()
38
+
39
+
40
+ def audit_repository(
41
+ repo_path: Path, agents: List[AgentDef], tools: List[ToolDef]
42
+ ) -> ObservabilityAudit:
43
+ """Convenience function auditing a repository against detected agents and tools."""
44
+ return _default_audit_engine.audit(repo_path, agents, tools)
45
+
46
+
47
+ def scan_manifest_files(repo_path: Path) -> List[ObservabilityPackage]:
48
+ """Convenience helper scanning manifests for observability dependencies."""
49
+ return _default_audit_engine.scan_manifests(repo_path)
50
+
51
+
52
+ def scan_env_files(repo_path: Path) -> List[str]:
53
+ """Convenience helper scanning env files for observability variables."""
54
+ return _default_audit_engine.scan_env_files(repo_path)
55
+
56
+
57
+ audit_observability = audit_repository
58
+
59
+ __all__ = [
60
+ "AuditEngine",
61
+ "audit_observability",
62
+ "audit_repository",
63
+ "scan_env_files",
64
+ "scan_manifest_files",
65
+ ]
@@ -0,0 +1,5 @@
1
+ """Langfuse observability detector."""
2
+
3
+ from cz.audit.langfuse.detector import LangfuseDetector
4
+
5
+ __all__ = ["LangfuseDetector"]