watchlight-agent-sdk 0.5.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.
@@ -0,0 +1,221 @@
1
+ Metadata-Version: 2.4
2
+ Name: watchlight-agent-sdk
3
+ Version: 0.5.0
4
+ Summary: Watchlight Agent SDK — build governed AI-agent plugins for any framework
5
+ Author-email: Watchlight AI <team@watchlight.ai>
6
+ License: Apache-2.0
7
+ Project-URL: Homepage, https://www.watchlight.ai
8
+ Project-URL: Documentation, https://docs.watchlight.ai
9
+ Project-URL: Repository, https://github.com/watchlight-ai-beacon/watchlight
10
+ Project-URL: Plugin SDK Guide, https://github.com/watchlight-ai-beacon/watchlight/tree/main/plugins
11
+ Keywords: watchlight,ai-governance,agent-runtime,ai-agents,agent-sdk,policy-decision-point,cedar-policy
12
+ Classifier: Development Status :: 4 - Beta
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: License :: OSI Approved :: Apache Software License
15
+ Classifier: Operating System :: OS Independent
16
+ Classifier: Programming Language :: Python :: 3
17
+ Classifier: Programming Language :: Python :: 3.10
18
+ Classifier: Programming Language :: Python :: 3.11
19
+ Classifier: Programming Language :: Python :: 3.12
20
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
21
+ Classifier: Topic :: System :: Monitoring
22
+ Classifier: Topic :: Security
23
+ Classifier: Typing :: Typed
24
+ Requires-Python: >=3.10
25
+ Description-Content-Type: text/markdown
26
+ Requires-Dist: httpx>=0.27
27
+ Requires-Dist: pydantic>=2.0
28
+ Requires-Dist: typing-extensions>=4.5; python_version < "3.12"
29
+ Provides-Extra: dev
30
+ Requires-Dist: pytest>=7; extra == "dev"
31
+ Requires-Dist: pytest-asyncio>=0.21; extra == "dev"
32
+ Requires-Dist: mypy>=1.8; extra == "dev"
33
+ Requires-Dist: cryptography>=42; extra == "dev"
34
+ Requires-Dist: requests>=2.32; extra == "dev"
35
+ Provides-Extra: otlp
36
+ Requires-Dist: opentelemetry-api>=1.20; extra == "otlp"
37
+ Requires-Dist: opentelemetry-sdk>=1.20; extra == "otlp"
38
+ Requires-Dist: opentelemetry-exporter-otlp-proto-http>=1.20; extra == "otlp"
39
+
40
+ # watchlight-core
41
+
42
+ Shared HTTP client and governance primitives used by every Watchlight
43
+ AI framework plugin (`watchlight-adk`, `watchlight-langgraph`,
44
+ `watchlight-bedrock`, …).
45
+
46
+ ## Why this exists
47
+
48
+ Until #312, the same APDP HTTP client lived as three near-identical
49
+ copies under each framework plugin. As the contract stabilised across
50
+ ADK / LangGraph / Bedrock, three copies became the right trigger for
51
+ extraction. This package is the single source of truth for:
52
+
53
+ - The HTTP wire format with WL-APDP (`ApdpClient`)
54
+ - Plan-validation / preflight result wrappers (`PlanResult`,
55
+ `PreflightResult`)
56
+ - The plan-normalisation contract (`normalize_plan`)
57
+ - The framework-agnostic `GovernanceState` shape consumed by the
58
+ Beacon Dashboard / Streamlit governance card
59
+ - The base run-handle lifecycle (`BaseRunHandle`)
60
+ - Shared error types and the `governance_mode` env reader
61
+ - Plugin telemetry contract (`GovernanceTelemetry`)
62
+
63
+ ## What's intentionally NOT here
64
+
65
+ Framework-specific behaviour stays in the plugin packages:
66
+
67
+ - ADK lifecycle callbacks + `PlanReActPlanner` parser + `BaseToolset`
68
+ — `watchlight-adk`
69
+ - LangGraph plan-and-execute primitives — `watchlight-langgraph`
70
+ - AWS Bedrock event parsing + Lambda action-group decorator +
71
+ `bedrock_session_attributes()` helper — `watchlight-bedrock`
72
+
73
+ ## Install
74
+
75
+ ```bash
76
+ # Minimal — APDP client + governance primitives only
77
+ pip install watchlight-core
78
+
79
+ # With OpenTelemetry export support (adds ~50MB of OTel SDK deps)
80
+ pip install 'watchlight-core[otlp]'
81
+
82
+ # Or in this monorepo:
83
+ pip install -e plugins/watchlight-core
84
+ pip install -e 'plugins/watchlight-core[otlp]'
85
+ ```
86
+
87
+ Plugins depend on it explicitly via their `pyproject.toml`; the core
88
+ package depends only on `httpx` and (on Python 3.10) `typing-extensions`.
89
+ The `[otlp]` extra pulls in `opentelemetry-api`, `opentelemetry-sdk`, and
90
+ `opentelemetry-exporter-otlp-proto-http` — optional so cold-start-
91
+ sensitive environments (Lambda, Cloudflare Workers) don't pay the install
92
+ weight when they're not exporting to OTel.
93
+
94
+ ## Public API
95
+
96
+ ```python
97
+ from watchlight_core import (
98
+ # HTTP client
99
+ ApdpClient,
100
+
101
+ # Errors
102
+ WatchlightError,
103
+ AgentNotRegistered,
104
+ GovernanceUnavailable,
105
+
106
+ # Result wrappers
107
+ PlanResult,
108
+ PreflightResult,
109
+
110
+ # Plan / state
111
+ normalize_plan,
112
+ GovernanceState,
113
+ GovernanceTelemetry,
114
+ state_from_attrs,
115
+
116
+ # Lifecycle
117
+ BaseRunHandle,
118
+ GovernedPlugin,
119
+
120
+ # Custom-agent SDK (EN.6)
121
+ watchlight,
122
+
123
+ # OpenTelemetry export (EN.6) — requires [otlp] extra at construction
124
+ OtlpConfig,
125
+ OtlpProfile,
126
+ WatchlightOtlpExporter,
127
+
128
+ # Env
129
+ governance_mode,
130
+ )
131
+ ```
132
+
133
+ ### Custom-agent SDK (`@watchlight`)
134
+
135
+ For agents NOT built on a framework with a Watchlight plugin (LangGraph,
136
+ ADK, Bedrock), the `@watchlight` decorator emits the canonical lineage
137
+ events for any Python function:
138
+
139
+ ```python
140
+ from watchlight_core import ApdpClient, watchlight
141
+
142
+ client = ApdpClient(base_url="http://localhost:8081")
143
+
144
+ @watchlight(agent_id="custom-research", apdp_client=client)
145
+ async def run_research(query: str) -> str:
146
+ # Your agent logic — emits execution_started / completed / failed
147
+ return result
148
+ ```
149
+
150
+ ### OpenTelemetry export
151
+
152
+ Opt-in customer observability — sends a deliberate **subset** of the
153
+ lineage stream to your OTel collector. Default is `profile=off`; the
154
+ exporter is a no-op until you turn it on.
155
+
156
+ ```python
157
+ from watchlight_core import OtlpConfig, WatchlightOtlpExporter
158
+
159
+ # Profile ladder: off ⊂ metrics ⊂ standard ⊂ governance
160
+ otlp = WatchlightOtlpExporter(OtlpConfig.from_env())
161
+ # WL_OTLP_PROFILE=standard
162
+ # WL_OTLP_ENDPOINT=http://otel-collector:4318
163
+ ```
164
+
165
+ Tool arguments, LLM prompts, ABR raw scores, drift baselines, and
166
+ security-internal anomalies never leave Watchlight. The exported subset
167
+ is documented in `dev-docs/architecture/otlp-export.md`.
168
+
169
+ The package exposes a `py.typed` marker so type checkers (mypy, pyright)
170
+ pick up the inline annotations directly.
171
+
172
+ ## Contract stability
173
+
174
+ Anything in `watchlight_core/__init__.py`'s `__all__` is a **stable
175
+ public API** under SemVer minor-version compatibility. Anything else
176
+ is internal and may move between minor versions.
177
+
178
+ When changing the wire format with WL-APDP (e.g. adding a route or
179
+ field), update `ApdpClient` here — the plugins inherit it for free.
180
+
181
+ ## Building a new plugin
182
+
183
+ Implement the framework integration surface (lifecycle hooks, native
184
+ plan format, etc.) in your plugin package and use this package for
185
+ everything else:
186
+
187
+ 1. Inherit `GovernanceTelemetry` to satisfy the `last_*` contract.
188
+ 2. For frameworks with explicit primitives (LangGraph, Bedrock):
189
+ subclass `BaseRunHandle` and add framework-specific helpers; expose
190
+ `start_run(slug)` returning your subclass.
191
+ 3. For frameworks with lifecycle callbacks (ADK): use `ApdpClient`
192
+ directly and populate the `last_*` attributes from your callbacks.
193
+ 4. Provide a one-line `state_from_<framework>_plugin` state helper
194
+ using `state_from_attrs(plugin, framework="<name>")`.
195
+
196
+ The `GovernanceState` shape parity test in your plugin's test suite
197
+ guarantees the dashboard renders consistently across frameworks.
198
+
199
+ ## Cross-references
200
+
201
+ - Multi-framework contract: `dev-docs/architecture/proxy-plugin-interop.md` §6
202
+ - Threat model: `dev-docs/security/HARDENING.md` (entries #301, #312, plus this PR's entry)
203
+
204
+ ## Open-source by design — the plugin is glue
205
+
206
+ This package (and the framework plugins built on it) ships as readable,
207
+ Apache-2.0 source. That's safe because **all authorization decisions, scope
208
+ strict-subset attenuation, lineage/audit signing, and drift/anomaly scoring are
209
+ server-side** — in the compiled Rust core (`wl-apdp`) and the governed platform.
210
+ The plugin registers hooks, shapes a request, round-trips it to the PDP, and
211
+ projects the answer.
212
+
213
+ There is **no differentiating IP to strip** for a community build: the
214
+ difference between Developer Edition and Enterprise is the *backend* the plugin
215
+ talks to (the in-process DE engine vs. the full governed plane), never the
216
+ plugin code. And because any decision made client-side is *bypassable*, keeping
217
+ enforcement server-side is a security rule, not just an IP one.
218
+
219
+ This boundary is documented in [`plugins/CONTRIBUTING.md`](../CONTRIBUTING.md)
220
+ and enforced in CI by the plugin IP-boundary gate
221
+ (`scripts/ci/check_plugin_ip_boundary.py`).
@@ -0,0 +1,31 @@
1
+ watchlight_core/__init__.py,sha256=eQ13zudOF7ke3wzdzagyYEUCvlsh6nXe41o0HOVv1FQ,10364
2
+ watchlight_core/__main__.py,sha256=lmWetuNAdAjx-hRhPB-OLEG44yj-qZ-aOYuPmf398uA,397
3
+ watchlight_core/apdp_client.py,sha256=m5BIlWSfIDzIe75ertnbGh521ADyq8GRVPjNSapQFpo,40039
4
+ watchlight_core/conformance.py,sha256=jsPa5BE1_EkgcwMeBYy4mGLXybRUwmBY9UBJ1bj2-zM,94460
5
+ watchlight_core/connect_proxy.py,sha256=T0kvze0OAeb27kAwJBRog3WkCRdt4h21rxmRdOY8NlA,26246
6
+ watchlight_core/credentials.py,sha256=qYDpcEye2uHDv_ooNJvAz0XZFYerqiYFn6x1ccIxYzQ,25452
7
+ watchlight_core/decision.py,sha256=fWJQNNrKB3VCYqTLpwvKkL6-Juw91a3FSknB48rWj5I,49198
8
+ watchlight_core/declare_intent.py,sha256=qXlvuHfToYM0M8o3l74lv7qkkf4vQFhqs1aZx0Vwfdw,14043
9
+ watchlight_core/decorator.py,sha256=hKNBKCKx7pWw2xmRR833QPy5NMnHWgyGHkfj4StHz9I,15332
10
+ watchlight_core/env.py,sha256=ff-jDECh0-NhW8c52EzHek7NY8IZZovYPtipyXWEuk4,832
11
+ watchlight_core/errors.py,sha256=Txfox_uwoXC3pm0vxmigvpqZ7D_yJ6WrbsMzLio4_68,11458
12
+ watchlight_core/events_schema.py,sha256=JLppEas6jdJ3gMA83TtNagOgvo8l3C3t39OuyrhbajI,30209
13
+ watchlight_core/in_process_client.py,sha256=x58KGszayu0iqFqNz9BsM1INTCPlHy95v6sQg1H6QqM,11812
14
+ watchlight_core/kill_signal.py,sha256=1p9ytEm_CaMmjHeZDPbDQn-anOzn09AVIE4hEW0bQOw,19474
15
+ watchlight_core/otlp.py,sha256=1dWvn8bAo4qkZhNoiHILZMChMHUPwZU8N8wf9LJIC14,36485
16
+ watchlight_core/plan.py,sha256=yZL3DxZTp0uXxxLdn0bNz7dw9xCsC2ssmVVHgZPyiAQ,3437
17
+ watchlight_core/plan_event.py,sha256=Nm7xzqMLRr9_78VT-tQW6CcTZBRg-EHOCrs1pmmtUFc,6353
18
+ watchlight_core/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
19
+ watchlight_core/results.py,sha256=Gb2x8BomDXL7TC3opiY2hwyrYXK83vttkSS0SakKz-A,8491
20
+ watchlight_core/run_handle.py,sha256=wgVe-CeTTksyo1DbQy5Q56oHBHnWdzgPaN0XuIWrz3s,179209
21
+ watchlight_core/scope.py,sha256=AwAp-12Kv21a_T_m08e3hRNm83JiEUCuIL9RKewUNHc,19007
22
+ watchlight_core/sidecar.py,sha256=QU4ST4CQyz3o-EnJeqREkWjrRZSxv74VMuQe5O_BNnU,9476
23
+ watchlight_core/state.py,sha256=CNWdklncaNB0z2Kw9E5rOnb1Nzsji8xGlUg8p9Mq4Dw,4380
24
+ watchlight_core/subagent_registry.py,sha256=jdUo72zkeBPd8XCpsttbccWneo2Sz8XXONX0DBwrbBI,19613
25
+ watchlight_core/telemetry.py,sha256=5oC9LgLisMZco3H4yXZweD0WBH8mJXRVjzBEeRMxl58,3162
26
+ watchlight_core/testing.py,sha256=czSvy5xfYl5uWICbc6RzQJ8ihlS-Me4jfm1FqNffZPg,31639
27
+ watchlight_agent_sdk-0.5.0.dist-info/METADATA,sha256=jH-Abcl07GjCJdM0H7ob7heBC_Dm1yT6zU5vCK9TjBw,8159
28
+ watchlight_agent_sdk-0.5.0.dist-info/WHEEL,sha256=YVMoNqKzERt-wjUZwJ33xBGAwnFl-4cqbYkTtWa4itE,91
29
+ watchlight_agent_sdk-0.5.0.dist-info/entry_points.txt,sha256=ZQf77xM52PLaOlyLLIJ9S2hC6uURm3zCzxHI6_ez1ts,77
30
+ watchlight_agent_sdk-0.5.0.dist-info/top_level.txt,sha256=rdAml4jKiOja7d6WmXx57XXRLO1lIbPmtlmjOu0mw-k,16
31
+ watchlight_agent_sdk-0.5.0.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (84.0.0)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ watchlight-conformance = watchlight_core.conformance:_main
@@ -0,0 +1 @@
1
+ watchlight_core
@@ -0,0 +1,355 @@
1
+ """Watchlight AI shared governance primitives — used by every framework plugin.
2
+
3
+ This package is the single source of truth for:
4
+
5
+ - The HTTP wire format with WL-APDP (``ApdpClient``)
6
+ - The plan-validation / preflight result wrappers
7
+ - The plan-normalisation contract
8
+ - The framework-agnostic ``GovernanceState`` shape rendered by the
9
+ Streamlit / Beacon Dashboard governance card
10
+ - The base run-handle lifecycle (resolve → session → manifest → close)
11
+ - Shared error types and the ``governance_mode`` env reader
12
+
13
+ Framework-specific behaviour stays in the plugin packages
14
+ (``watchlight-adk``, ``watchlight-langgraph``, ``watchlight-bedrock``,
15
+ …). When you bring up a new plugin, you only own the framework
16
+ integration surface; everything in this module is reused.
17
+
18
+ Public API is intentionally narrow. Anything not re-exported here is
19
+ considered internal to a future minor release.
20
+ """
21
+
22
+ from .apdp_client import ApdpClient
23
+ from .in_process_client import GovernanceBackend, InProcessClient
24
+ from .connect_proxy import (
25
+ install_connect_proxy,
26
+ is_connect_proxy_installed,
27
+ uninstall_connect_proxy,
28
+ )
29
+ from .sidecar import (
30
+ install_sidecar,
31
+ is_sidecar_installed,
32
+ uninstall_sidecar,
33
+ )
34
+ from .credentials import (
35
+ Credential,
36
+ CredentialKind,
37
+ CredentialNotFound,
38
+ InvalidCredential,
39
+ PluginCredential,
40
+ ServiceCredential,
41
+ )
42
+ from .declare_intent import (
43
+ BROWNFIELD,
44
+ DECLARE_INTENT_RESPONSE_STATUS,
45
+ DECLARE_INTENT_TOOL_DESCRIPTION,
46
+ DECLARE_INTENT_TOOL_NAME,
47
+ GREENFIELD,
48
+ INTENT_ENFORCEMENT_MODE_ENV_VAR,
49
+ WATCHLIGHT_DECLARE_INTENT_TOOL,
50
+ handle_declare_intent_call,
51
+ is_declare_intent_tool_call,
52
+ is_declare_intent_tool_name,
53
+ resolve_intent_enforcement_mode,
54
+ should_inject_synthetic_tool,
55
+ truncate_intent_objective,
56
+ )
57
+ from .decision import (
58
+ AgentQuarantinedError,
59
+ AgentRevokedError,
60
+ AllowDecision,
61
+ Attenuation,
62
+ AuthorizationDecision,
63
+ DenyDecision,
64
+ Escalation,
65
+ ExecutionTerminatedError,
66
+ NeedsApprovalDecision,
67
+ Observation,
68
+ QuarantineDecision,
69
+ RevokeDecision,
70
+ RunHandleState,
71
+ SeverSubtreeDecision,
72
+ SubtreeSeveredError,
73
+ TerminateDecision,
74
+ parse_authorization_decision,
75
+ )
76
+ from .decorator import watchlight
77
+ from .errors import (
78
+ AgentNotRegistered,
79
+ CredentialProbeFailed,
80
+ GovernanceUnavailable,
81
+ InsecureChannelError,
82
+ RunHandleInvalidated,
83
+ ScopeAttenuationDenied,
84
+ ScopeViolationDimension,
85
+ WatchlightContractError,
86
+ WatchlightError,
87
+ )
88
+ from .env import governance_mode
89
+ from .events_schema import (
90
+ EVENT_ID_PATTERN,
91
+ EVENT_ID_RE,
92
+ ERROR_MESSAGE_MAX_CHARS,
93
+ INPUT_SUMMARY_MAX_CHARS,
94
+ INTENT_OBJECTIVE_MAX_BYTES,
95
+ LIFT_REASON_MAX_BYTES,
96
+ MAX_CONTRIBUTING_FEATURES,
97
+ REASON_MAX_BYTES,
98
+ ActionRef,
99
+ CredentialRef,
100
+ EventEnvelope,
101
+ EventType,
102
+ ExecutionEvent,
103
+ ExecutionQuarantinedPayload,
104
+ ExecutionResumedPayload,
105
+ FeatureContribution,
106
+ IntentProvenance,
107
+ PrincipalRef,
108
+ ResourceRef,
109
+ summarize_arg_keys,
110
+ truncate_error_message,
111
+ truncate_summary,
112
+ )
113
+ from .kill_signal import (
114
+ DISPOSITION_GRACEFUL,
115
+ DISPOSITION_PROXY_HARD_KILL,
116
+ InterceptorKillRegistry,
117
+ KILL_SIGNAL_GRACEFUL_WINDOW_MS,
118
+ KillSignalResult,
119
+ LLM_CALL_INTERRUPTED_REASON_HARD_TIMEOUT,
120
+ LLM_CALL_INTERRUPTED_REASON_MANUAL_TERMINATE,
121
+ LLM_CALL_INTERRUPTED_REASON_POLICY_TERMINATE,
122
+ LLM_CALL_INTERRUPTED_REASON_QUARANTINE,
123
+ LLM_CALL_INTERRUPTED_REASON_REVOKE,
124
+ LLM_CALL_INTERRUPTED_REASON_SCOPE_VIOLATION,
125
+ LLM_CALL_INTERRUPTED_REASON_SEVER_SUBTREE,
126
+ LlmCallInterruptedPayload,
127
+ LlmCallInterruptedValidationError,
128
+ RegisterRequestOptions,
129
+ httpx_hard_kill_escalator,
130
+ )
131
+ from .otlp import (
132
+ OtlpConfig,
133
+ OtlpProfile,
134
+ WatchlightOtlpExporter,
135
+ )
136
+ from .plan import normalize_plan
137
+ from .plan_event import (
138
+ PLAN_INTENDED_TOOLS_MAX,
139
+ PLAN_RATIONALE_MAX_BYTES,
140
+ PLAN_TOOL_NAME_PATTERN,
141
+ PLAN_TOOL_NAME_RE,
142
+ PlanKind,
143
+ PlanValidationError,
144
+ build_plan_payload,
145
+ filter_valid_tool_names,
146
+ is_valid_tool_name,
147
+ truncate_rationale,
148
+ )
149
+ from .results import AuthorizeResult, PlanResult, PreflightResult
150
+ from .run_handle import (
151
+ BaseRunHandle,
152
+ GovernedPlugin,
153
+ HandleLineage,
154
+ current_handle_lineage,
155
+ current_subagent_handle,
156
+ )
157
+ from .scope import (
158
+ GrantedScope,
159
+ ParentSignature,
160
+ RequestedScope,
161
+ ResourceMatcher,
162
+ SpawnSubagentRequest,
163
+ SpawnSubagentResponse,
164
+ granted_scope_from_dict,
165
+ granted_scope_to_dict,
166
+ parent_signature_from_dict,
167
+ parent_signature_to_dict,
168
+ requested_scope_from_dict,
169
+ requested_scope_to_dict,
170
+ resource_matcher_from_dict,
171
+ resource_matcher_to_dict,
172
+ spawn_subagent_request_from_dict,
173
+ spawn_subagent_request_to_dict,
174
+ spawn_subagent_response_from_dict,
175
+ spawn_subagent_response_to_dict,
176
+ )
177
+ from .state import GovernanceState, state_from_attrs
178
+ from .subagent_registry import (
179
+ DEFAULT_SUBAGENT_SCOPE_ENV_VAR,
180
+ SubagentRegistry,
181
+ default_subagent_scope_from_env,
182
+ )
183
+ from .telemetry import GovernanceTelemetry
184
+
185
+ __all__ = [
186
+ # Client
187
+ "ApdpClient",
188
+ "InProcessClient",
189
+ "GovernanceBackend",
190
+ # CONNECT local sidecar proxy (M37-B3)
191
+ "install_connect_proxy",
192
+ "is_connect_proxy_installed",
193
+ "uninstall_connect_proxy",
194
+ "install_sidecar",
195
+ "is_sidecar_installed",
196
+ "uninstall_sidecar",
197
+ # Credentials
198
+ "Credential",
199
+ "CredentialKind",
200
+ "CredentialNotFound",
201
+ "InvalidCredential",
202
+ "PluginCredential",
203
+ "ServiceCredential",
204
+ # Decorator (custom-agent SDK)
205
+ "watchlight",
206
+ # Errors
207
+ "WatchlightError",
208
+ "WatchlightContractError",
209
+ "AgentNotRegistered",
210
+ "CredentialProbeFailed",
211
+ "GovernanceUnavailable",
212
+ "InsecureChannelError",
213
+ # M43-E — sub-agent scope attenuation typed errors
214
+ "RunHandleInvalidated",
215
+ "ScopeAttenuationDenied",
216
+ "ScopeViolationDimension",
217
+ # OTLP export (EN.6)
218
+ "OtlpConfig",
219
+ "OtlpProfile",
220
+ "WatchlightOtlpExporter",
221
+ # Result wrappers
222
+ "AuthorizeResult",
223
+ "PlanResult",
224
+ "PreflightResult",
225
+ # Plan
226
+ "normalize_plan",
227
+ # PlanObserved event helpers (MCP.1)
228
+ "PLAN_INTENDED_TOOLS_MAX",
229
+ "PLAN_RATIONALE_MAX_BYTES",
230
+ "PLAN_TOOL_NAME_PATTERN",
231
+ "PLAN_TOOL_NAME_RE",
232
+ "PlanKind",
233
+ "PlanValidationError",
234
+ "build_plan_payload",
235
+ "filter_valid_tool_names",
236
+ "is_valid_tool_name",
237
+ "truncate_rationale",
238
+ # State + telemetry
239
+ "GovernanceState",
240
+ "GovernanceTelemetry",
241
+ "state_from_attrs",
242
+ # Lifecycle base
243
+ "BaseRunHandle",
244
+ "GovernedPlugin",
245
+ # M43-E — sub-agent contextvar accessor
246
+ "current_subagent_handle",
247
+ # #889 — lineage propagation contextvar (CONNECT sidecar reads this
248
+ # to inject ``X-Wl-Execution-Id`` headers on outbound CONNECTs so
249
+ # wl-proxy emits per-tunnel events with the orchestrator's
250
+ # execution_id instead of phantom fallbacks).
251
+ "HandleLineage",
252
+ "current_handle_lineage",
253
+ # Env
254
+ "governance_mode",
255
+ # Events schema (SDK 0.4.0 — pydantic mirror of wl-lineage::events)
256
+ "ActionRef",
257
+ "CredentialRef",
258
+ "EventEnvelope",
259
+ "EventType",
260
+ "ExecutionEvent",
261
+ "PrincipalRef",
262
+ "ResourceRef",
263
+ "EVENT_ID_PATTERN",
264
+ "EVENT_ID_RE",
265
+ "INPUT_SUMMARY_MAX_CHARS",
266
+ "ERROR_MESSAGE_MAX_CHARS",
267
+ "summarize_arg_keys",
268
+ "truncate_error_message",
269
+ "truncate_summary",
270
+ # M46-B — intent provenance enum + byte cap (mirror of
271
+ # wl-lineage::events::IntentProvenance + INTENT_OBJECTIVE_MAX_BYTES)
272
+ "INTENT_OBJECTIVE_MAX_BYTES",
273
+ "IntentProvenance",
274
+ # M45-E — quarantine event payload mirrors + size constants
275
+ "ExecutionQuarantinedPayload",
276
+ "ExecutionResumedPayload",
277
+ "FeatureContribution",
278
+ "LIFT_REASON_MAX_BYTES",
279
+ "MAX_CONTRIBUTING_FEATURES",
280
+ "REASON_MAX_BYTES",
281
+ # M45-F — typed authorization decision + handle state machine
282
+ "AgentQuarantinedError",
283
+ "AgentRevokedError",
284
+ "AllowDecision",
285
+ "Attenuation",
286
+ "AuthorizationDecision",
287
+ "DenyDecision",
288
+ "Escalation",
289
+ "ExecutionTerminatedError",
290
+ "NeedsApprovalDecision",
291
+ "Observation",
292
+ "QuarantineDecision",
293
+ "RevokeDecision",
294
+ "RunHandleState",
295
+ "SeverSubtreeDecision",
296
+ "SubtreeSeveredError",
297
+ "TerminateDecision",
298
+ "parse_authorization_decision",
299
+ # M45-I — kill-signal protocol for HTTP interceptors
300
+ "InterceptorKillRegistry",
301
+ "KILL_SIGNAL_GRACEFUL_WINDOW_MS",
302
+ "DISPOSITION_GRACEFUL",
303
+ "DISPOSITION_PROXY_HARD_KILL",
304
+ "LLM_CALL_INTERRUPTED_REASON_QUARANTINE",
305
+ "LLM_CALL_INTERRUPTED_REASON_SCOPE_VIOLATION",
306
+ "LLM_CALL_INTERRUPTED_REASON_MANUAL_TERMINATE",
307
+ "LLM_CALL_INTERRUPTED_REASON_HARD_TIMEOUT",
308
+ "LLM_CALL_INTERRUPTED_REASON_POLICY_TERMINATE",
309
+ "LLM_CALL_INTERRUPTED_REASON_SEVER_SUBTREE",
310
+ "LLM_CALL_INTERRUPTED_REASON_REVOKE",
311
+ "LlmCallInterruptedPayload",
312
+ "LlmCallInterruptedValidationError",
313
+ "KillSignalResult",
314
+ "RegisterRequestOptions",
315
+ "httpx_hard_kill_escalator",
316
+ # M46-K — synthetic ``watchlight.declare_intent`` tool contract.
317
+ "BROWNFIELD",
318
+ "DECLARE_INTENT_RESPONSE_STATUS",
319
+ "DECLARE_INTENT_TOOL_DESCRIPTION",
320
+ "DECLARE_INTENT_TOOL_NAME",
321
+ "GREENFIELD",
322
+ "INTENT_ENFORCEMENT_MODE_ENV_VAR",
323
+ "WATCHLIGHT_DECLARE_INTENT_TOOL",
324
+ "handle_declare_intent_call",
325
+ "is_declare_intent_tool_call",
326
+ "is_declare_intent_tool_name",
327
+ "resolve_intent_enforcement_mode",
328
+ "should_inject_synthetic_tool",
329
+ "truncate_intent_objective",
330
+ # M43-B — sub-agent scope attenuation wire shapes.
331
+ "GrantedScope",
332
+ "ParentSignature",
333
+ "RequestedScope",
334
+ "ResourceMatcher",
335
+ "SpawnSubagentRequest",
336
+ "SpawnSubagentResponse",
337
+ "granted_scope_from_dict",
338
+ "granted_scope_to_dict",
339
+ "parent_signature_from_dict",
340
+ "parent_signature_to_dict",
341
+ "requested_scope_from_dict",
342
+ "requested_scope_to_dict",
343
+ "resource_matcher_from_dict",
344
+ "resource_matcher_to_dict",
345
+ "spawn_subagent_request_from_dict",
346
+ "spawn_subagent_request_to_dict",
347
+ "spawn_subagent_response_from_dict",
348
+ "spawn_subagent_response_to_dict",
349
+ # Uniform governed-spawn routing primitive.
350
+ "SubagentRegistry",
351
+ "DEFAULT_SUBAGENT_SCOPE_ENV_VAR",
352
+ "default_subagent_scope_from_env",
353
+ ]
354
+
355
+ __version__ = "0.5.0"
@@ -0,0 +1,18 @@
1
+ """Module-level CLI dispatch for ``python -m watchlight_core``.
2
+
3
+ Currently dispatches to the conformance runner; future commands
4
+ (scaffold new plugin, validate event schema, etc.) plug in here.
5
+
6
+ Usage:
7
+
8
+ python -m watchlight_core.conformance my_plugin_package
9
+ """
10
+
11
+ from __future__ import annotations
12
+
13
+ import sys
14
+
15
+ from .conformance import _main
16
+
17
+ if __name__ == "__main__":
18
+ sys.exit(_main())