sequential-hooks 0.1.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.
- plugins/agy/_sequential_hooks/__init__.py +1 -0
- plugins/agy/_sequential_hooks/_adapter.py +566 -0
- plugins/agy/_sequential_hooks/_doctor.py +413 -0
- plugins/claude/_sequential_hooks/__init__.py +1 -0
- plugins/claude/_sequential_hooks/_adapter.py +560 -0
- plugins/claude/_sequential_hooks/_doctor.py +455 -0
- plugins/codex/_sequential_hooks/__init__.py +1 -0
- plugins/codex/_sequential_hooks/_adapter.py +466 -0
- plugins/codex/_sequential_hooks/_doctor.py +563 -0
- sequential_hooks/__init__.py +3 -0
- sequential_hooks/__main__.py +5 -0
- sequential_hooks/_arguments.py +222 -0
- sequential_hooks/_cleanup.py +88 -0
- sequential_hooks/_cli.py +440 -0
- sequential_hooks/_containment/__init__.py +410 -0
- sequential_hooks/_containment/_posix.py +236 -0
- sequential_hooks/_containment/_uncontained.py +239 -0
- sequential_hooks/_containment/_windows.py +853 -0
- sequential_hooks/_containment/_windows_api.py +570 -0
- sequential_hooks/_containment/_windows_launcher.py +189 -0
- sequential_hooks/_diagnostics.py +265 -0
- sequential_hooks/_doctor/__init__.py +342 -0
- sequential_hooks/_doctor/_command.py +469 -0
- sequential_hooks/_doctor/_common.py +448 -0
- sequential_hooks/_doctor/_types.py +94 -0
- sequential_hooks/_downstream.py +181 -0
- sequential_hooks/_executable.py +187 -0
- sequential_hooks/_executor.py +825 -0
- sequential_hooks/_registry.py +103 -0
- sequential_hooks/_runner.py +48 -0
- sequential_hooks/_types.py +125 -0
- sequential_hooks/hosts/__init__.py +130 -0
- sequential_hooks/hosts/_contract.py +434 -0
- sequential_hooks/hosts/_inspection.py +78 -0
- sequential_hooks/hosts/_json.py +150 -0
- sequential_hooks/hosts/_records.py +273 -0
- sequential_hooks/hosts/_skeleton.py +1326 -0
- sequential_hooks/py.typed +0 -0
- sequential_hooks-0.1.0.dist-info/METADATA +90 -0
- sequential_hooks-0.1.0.dist-info/RECORD +43 -0
- sequential_hooks-0.1.0.dist-info/WHEEL +4 -0
- sequential_hooks-0.1.0.dist-info/entry_points.txt +7 -0
- sequential_hooks-0.1.0.dist-info/licenses/LICENSE +21 -0
|
@@ -0,0 +1,273 @@
|
|
|
1
|
+
"""Define the doctor record types a host loader produces and reads."""
|
|
2
|
+
|
|
3
|
+
from collections.abc import Sequence
|
|
4
|
+
from dataclasses import dataclass
|
|
5
|
+
from enum import StrEnum
|
|
6
|
+
from pathlib import Path
|
|
7
|
+
from typing import Protocol
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class ContractError(StrEnum):
|
|
11
|
+
"""Classify a statically recognized wrapper contract failure.
|
|
12
|
+
|
|
13
|
+
Attributes:
|
|
14
|
+
EVENT_FORBIDDEN: The wrapper supplies an event to a host that does not
|
|
15
|
+
accept the option.
|
|
16
|
+
EVENT_MISSING: The wrapper omits the event required by its host.
|
|
17
|
+
HOST_MISSING: The wrapper omits its required host.
|
|
18
|
+
WRONG_EVENT: The wrapper event is unsupported or differs from the
|
|
19
|
+
registered event.
|
|
20
|
+
WRONG_HOST: The wrapper host is unsupported or differs from the
|
|
21
|
+
configuration host.
|
|
22
|
+
"""
|
|
23
|
+
|
|
24
|
+
EVENT_FORBIDDEN = 'event_forbidden'
|
|
25
|
+
EVENT_MISSING = 'event_missing'
|
|
26
|
+
HOST_MISSING = 'host_missing'
|
|
27
|
+
WRONG_EVENT = 'wrong_event'
|
|
28
|
+
WRONG_HOST = 'wrong_host'
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
class FindingSeverity(StrEnum):
|
|
32
|
+
"""Classify a doctor finding's effect on the process status.
|
|
33
|
+
|
|
34
|
+
Attributes:
|
|
35
|
+
ERROR: An actionable error that makes the doctor status nonzero.
|
|
36
|
+
WARNING: An actionable warning that makes the doctor status nonzero.
|
|
37
|
+
INFO: Informational context that does not make the status nonzero.
|
|
38
|
+
"""
|
|
39
|
+
|
|
40
|
+
ERROR = 'error'
|
|
41
|
+
WARNING = 'warning'
|
|
42
|
+
INFO = 'info'
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
@dataclass(frozen=True)
|
|
46
|
+
class Finding:
|
|
47
|
+
"""Describe one immutable doctor finding.
|
|
48
|
+
|
|
49
|
+
Args:
|
|
50
|
+
severity: Effect of the finding on the doctor status.
|
|
51
|
+
code: Machine-readable finding category.
|
|
52
|
+
message: User-facing diagnostic detail.
|
|
53
|
+
correction: Exact corrective guidance, when available.
|
|
54
|
+
|
|
55
|
+
Attributes:
|
|
56
|
+
severity: Effect of the finding on the doctor status.
|
|
57
|
+
code: Machine-readable finding category.
|
|
58
|
+
message: User-facing diagnostic detail.
|
|
59
|
+
correction: Exact corrective guidance, when available.
|
|
60
|
+
"""
|
|
61
|
+
|
|
62
|
+
severity: FindingSeverity
|
|
63
|
+
code: str
|
|
64
|
+
message: str
|
|
65
|
+
correction: str | None = None
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
class WrapperStep(Protocol):
|
|
69
|
+
"""Describe one child command parsed from a registered wrapper command."""
|
|
70
|
+
|
|
71
|
+
@property
|
|
72
|
+
def argv(self) -> tuple[str, ...]:
|
|
73
|
+
"""Return the literal executable token and arguments.
|
|
74
|
+
|
|
75
|
+
Returns:
|
|
76
|
+
Argument vector exactly as registered.
|
|
77
|
+
"""
|
|
78
|
+
...
|
|
79
|
+
|
|
80
|
+
@property
|
|
81
|
+
def index(self) -> int:
|
|
82
|
+
"""Return the one-based chain position.
|
|
83
|
+
|
|
84
|
+
Returns:
|
|
85
|
+
Position starting at 1.
|
|
86
|
+
"""
|
|
87
|
+
...
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
class WrapperInvocation(Protocol):
|
|
91
|
+
"""Describe one statically parsed wrapper command from a registration."""
|
|
92
|
+
|
|
93
|
+
@property
|
|
94
|
+
def allow_on_failure(self) -> bool:
|
|
95
|
+
"""Return whether the registration passes `--allow-on-failure`.
|
|
96
|
+
|
|
97
|
+
Returns:
|
|
98
|
+
`True` when the failure override is configured.
|
|
99
|
+
"""
|
|
100
|
+
...
|
|
101
|
+
|
|
102
|
+
@property
|
|
103
|
+
def event(self) -> str | None:
|
|
104
|
+
"""Return the explicit `--event` value, if any.
|
|
105
|
+
|
|
106
|
+
Returns:
|
|
107
|
+
Event name, or `None` when the command passes no event.
|
|
108
|
+
"""
|
|
109
|
+
...
|
|
110
|
+
|
|
111
|
+
@property
|
|
112
|
+
def host(self) -> str:
|
|
113
|
+
"""Return the `--agent` value.
|
|
114
|
+
|
|
115
|
+
Returns:
|
|
116
|
+
Host name exactly as registered.
|
|
117
|
+
"""
|
|
118
|
+
...
|
|
119
|
+
|
|
120
|
+
@property
|
|
121
|
+
def step_timeout(self) -> float | None:
|
|
122
|
+
"""Return the `--step-timeout` value, if any.
|
|
123
|
+
|
|
124
|
+
Returns:
|
|
125
|
+
Positive finite seconds, or `None`.
|
|
126
|
+
"""
|
|
127
|
+
...
|
|
128
|
+
|
|
129
|
+
@property
|
|
130
|
+
def steps(self) -> Sequence[WrapperStep]:
|
|
131
|
+
"""Return the child commands in execution order.
|
|
132
|
+
|
|
133
|
+
Returns:
|
|
134
|
+
One to three steps.
|
|
135
|
+
"""
|
|
136
|
+
...
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
@dataclass(frozen=True)
|
|
140
|
+
class InspectedCommand:
|
|
141
|
+
"""Carry one immutable, non-executing command inspection.
|
|
142
|
+
|
|
143
|
+
Args:
|
|
144
|
+
argv: Statically decoded argument vector, when available.
|
|
145
|
+
invocation: Parsed wrapper invocation, when the command invokes the
|
|
146
|
+
wrapper and satisfies its grammar.
|
|
147
|
+
dynamic: Whether shell syntax prevents static inspection.
|
|
148
|
+
error: Bounded reason static inspection did not yield a usable command,
|
|
149
|
+
when applicable.
|
|
150
|
+
contract_error: Safely recognized wrapper contract failure, when
|
|
151
|
+
applicable.
|
|
152
|
+
|
|
153
|
+
Attributes:
|
|
154
|
+
argv: Statically decoded argument vector, when available.
|
|
155
|
+
invocation: Parsed wrapper invocation, when available.
|
|
156
|
+
dynamic: Whether shell syntax prevents static inspection.
|
|
157
|
+
error: Bounded static-inspection failure detail, when applicable.
|
|
158
|
+
contract_error: Safely recognized wrapper contract failure, when
|
|
159
|
+
applicable.
|
|
160
|
+
"""
|
|
161
|
+
|
|
162
|
+
argv: tuple[str, ...] | None
|
|
163
|
+
invocation: WrapperInvocation | None
|
|
164
|
+
dynamic: bool
|
|
165
|
+
error: str | None
|
|
166
|
+
contract_error: ContractError | None = None
|
|
167
|
+
|
|
168
|
+
|
|
169
|
+
class LaunchSemantics(StrEnum):
|
|
170
|
+
"""Classify how a host launches a registration command.
|
|
171
|
+
|
|
172
|
+
Attributes:
|
|
173
|
+
DIRECT_ARGV: The host launches a command with an explicit argument
|
|
174
|
+
vector.
|
|
175
|
+
POSIX_SHELL: A POSIX shell interprets the command text.
|
|
176
|
+
WINDOWS_SHELL: A Windows shell interprets the command text.
|
|
177
|
+
HOST_TOKENIZER: The host owns platform-specific command tokenization.
|
|
178
|
+
UNKNOWN: No supported launch behavior is known.
|
|
179
|
+
"""
|
|
180
|
+
|
|
181
|
+
DIRECT_ARGV = 'direct_argv'
|
|
182
|
+
POSIX_SHELL = 'posix_shell'
|
|
183
|
+
WINDOWS_SHELL = 'windows_shell'
|
|
184
|
+
HOST_TOKENIZER = 'host_tokenizer'
|
|
185
|
+
UNKNOWN = 'unknown'
|
|
186
|
+
|
|
187
|
+
|
|
188
|
+
class SourceKind(StrEnum):
|
|
189
|
+
"""Classify the ownership scope of a configuration source.
|
|
190
|
+
|
|
191
|
+
Attributes:
|
|
192
|
+
USER: User-scoped configuration.
|
|
193
|
+
PROJECT: Project-scoped configuration inherited by the working
|
|
194
|
+
directory.
|
|
195
|
+
SYSTEM: System-wide configuration.
|
|
196
|
+
MANAGED: Organization-managed configuration.
|
|
197
|
+
LOCAL: Project-local override configuration.
|
|
198
|
+
"""
|
|
199
|
+
|
|
200
|
+
USER = 'user'
|
|
201
|
+
PROJECT = 'project'
|
|
202
|
+
SYSTEM = 'system'
|
|
203
|
+
MANAGED = 'managed'
|
|
204
|
+
LOCAL = 'local'
|
|
205
|
+
|
|
206
|
+
|
|
207
|
+
@dataclass(frozen=True)
|
|
208
|
+
class ConfigSource:
|
|
209
|
+
"""Describe one immutable candidate configuration source.
|
|
210
|
+
|
|
211
|
+
Args:
|
|
212
|
+
path: Candidate configuration path.
|
|
213
|
+
kind: Ownership scope assigned by the host loader.
|
|
214
|
+
exists: Whether the candidate existed during discovery.
|
|
215
|
+
|
|
216
|
+
Attributes:
|
|
217
|
+
path: Candidate configuration path.
|
|
218
|
+
kind: Ownership scope assigned by the host loader.
|
|
219
|
+
exists: Whether the candidate existed during discovery.
|
|
220
|
+
"""
|
|
221
|
+
|
|
222
|
+
path: Path
|
|
223
|
+
kind: SourceKind
|
|
224
|
+
exists: bool
|
|
225
|
+
|
|
226
|
+
|
|
227
|
+
@dataclass(frozen=True)
|
|
228
|
+
class Registration:
|
|
229
|
+
"""Describe one immutable host registration accepted by a loader.
|
|
230
|
+
|
|
231
|
+
Args:
|
|
232
|
+
source: Configuration source that owns the registration.
|
|
233
|
+
event: Native host event containing the registration.
|
|
234
|
+
matcher: Native host matcher, when configured.
|
|
235
|
+
command: Primary command text or executable token.
|
|
236
|
+
args: Explicit argument vector tail, when the host provides one.
|
|
237
|
+
launch_semantics: Launch behavior for the primary command.
|
|
238
|
+
command_windows: Windows-specific command text, when configured.
|
|
239
|
+
windows_launch_semantics: Windows launch behavior, when documented.
|
|
240
|
+
timeout: Outer host timeout, when valid and configured.
|
|
241
|
+
enabled: Statically known activation state, when available.
|
|
242
|
+
type: Native handler type, when available.
|
|
243
|
+
configuration_findings: Notes from accepting this hook, in loader
|
|
244
|
+
order.
|
|
245
|
+
|
|
246
|
+
Attributes:
|
|
247
|
+
source: Configuration source that owns the registration.
|
|
248
|
+
event: Native host event containing the registration.
|
|
249
|
+
matcher: Native host matcher, when configured.
|
|
250
|
+
command: Primary command text or executable token.
|
|
251
|
+
args: Explicit argument vector tail, when the host provides one.
|
|
252
|
+
launch_semantics: Launch behavior for the primary command.
|
|
253
|
+
command_windows: Windows-specific command text, when configured.
|
|
254
|
+
windows_launch_semantics: Windows launch behavior, when documented.
|
|
255
|
+
timeout: Outer host timeout, when valid and configured.
|
|
256
|
+
enabled: Statically known activation state, when available.
|
|
257
|
+
type: Native handler type, when available.
|
|
258
|
+
configuration_findings: Notes from accepting this hook, in loader
|
|
259
|
+
order.
|
|
260
|
+
"""
|
|
261
|
+
|
|
262
|
+
source: ConfigSource
|
|
263
|
+
event: str
|
|
264
|
+
matcher: str | None
|
|
265
|
+
command: str
|
|
266
|
+
args: tuple[str, ...] | None
|
|
267
|
+
launch_semantics: LaunchSemantics
|
|
268
|
+
command_windows: str | None
|
|
269
|
+
windows_launch_semantics: LaunchSemantics | None
|
|
270
|
+
timeout: float | None
|
|
271
|
+
enabled: bool | None
|
|
272
|
+
type: str | None
|
|
273
|
+
configuration_findings: tuple[Finding, ...] = ()
|