context-guard-cli 2.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.
Files changed (32) hide show
  1. context_guard/__init__.py +1 -0
  2. context_guard/_data/hosts/antigravity/hooks.snippet.json +16 -0
  3. context_guard/_data/hosts/antigravity/rules/context-guard.md +15 -0
  4. context_guard/_data/hosts/claude-code/commands/cg-continue.md +13 -0
  5. context_guard/_data/hosts/claude-code/commands/cg-new.md +11 -0
  6. context_guard/_data/hosts/claude-code/mcp.snippet.json +7 -0
  7. context_guard/_data/hosts/claude-code/settings.snippet.json +12 -0
  8. context_guard/_data/hosts/opencode/agent.snippet.json +7 -0
  9. context_guard/_data/hosts/opencode/commands/cg-continue.md +16 -0
  10. context_guard/_data/hosts/opencode/commands/cg-new.md +12 -0
  11. context_guard/_data/hosts/opencode/mcp.snippet.json +9 -0
  12. context_guard/_data/hosts/opencode/permissions.snippet.json +12 -0
  13. context_guard/_data/phases/execute.md +99 -0
  14. context_guard/_data/phases/plan.md +136 -0
  15. context_guard/_data/phases/verify.md +129 -0
  16. context_guard/guard/__init__.py +1 -0
  17. context_guard/guard/assets.py +94 -0
  18. context_guard/guard/cli.py +307 -0
  19. context_guard/guard/commands.py +811 -0
  20. context_guard/guard/errors.py +71 -0
  21. context_guard/guard/locking.py +181 -0
  22. context_guard/guard/manifest.py +69 -0
  23. context_guard/guard/migrate.py +288 -0
  24. context_guard/guard/paths.py +199 -0
  25. context_guard/guard/setup.py +476 -0
  26. context_guard/guard/transaction.py +403 -0
  27. context_guard/mcp_server.py +280 -0
  28. context_guard_cli-2.1.0.dist-info/METADATA +296 -0
  29. context_guard_cli-2.1.0.dist-info/RECORD +32 -0
  30. context_guard_cli-2.1.0.dist-info/WHEEL +4 -0
  31. context_guard_cli-2.1.0.dist-info/entry_points.txt +4 -0
  32. context_guard_cli-2.1.0.dist-info/licenses/LICENSE +21 -0
@@ -0,0 +1,296 @@
1
+ Metadata-Version: 2.4
2
+ Name: context-guard-cli
3
+ Version: 2.1.0
4
+ Summary: The transactional memory layer for AI coding agents — your context survives crashes, compaction, and session loss
5
+ License-Expression: MIT
6
+ License-File: LICENSE
7
+ Requires-Python: >=3.10
8
+ Requires-Dist: mcp<2.0.0,>=1.0.0
9
+ Provides-Extra: dev
10
+ Requires-Dist: build>=1.0; extra == 'dev'
11
+ Requires-Dist: hatchling; extra == 'dev'
12
+ Description-Content-Type: text/markdown
13
+
14
+ # Context Guard
15
+
16
+ [![CI](https://github.com/fdomerlo/context-guard/actions/workflows/ci.yml/badge.svg)](https://github.com/fdomerlo/context-guard/actions/workflows/ci.yml)
17
+ [![PyPI](https://img.shields.io/pypi/v/context-guard-cli)](https://pypi.org/project/context-guard-cli/)
18
+
19
+ **The transactional memory layer for AI coding agents — your context survives crashes, compaction, and session loss.**
20
+
21
+ *[Leer en español](README.es.md)*
22
+
23
+ *[Aqui un tutorial (también en español) para usuarios no técnicos y novatos](TUTORIAL.es.md)*
24
+
25
+ ---
26
+
27
+ ## The problem
28
+
29
+ Long-running agent sessions degrade. Context drift, "lost in the middle,"
30
+ completion hallucination (the agent believes it finished before it verified
31
+ anything), and — the one that actually loses work — a crash or a compaction
32
+ mid-task that leaves the repository half-edited with no way back.
33
+
34
+ context-guard is not another agent framework and it does not write code. It
35
+ is a small, deterministic state machine that sits between an agent and a
36
+ project: a manifest on disk that survives the agent's process ending, a
37
+ strict `PLAN → EXECUTE → VERIFY → ARCHIVE` pipeline the agent cannot skip
38
+ phases in, and a transaction log that can be rolled back. If the session
39
+ dies, the manifest is what the next session reads to pick up exactly where
40
+ the last one left off — that persistence, not the pipeline shape, is the
41
+ point.
42
+
43
+ ## Quickstart
44
+
45
+ Five commands: plan a change, get a human to sign off on it, advance into
46
+ execution, claim a task, and check where things stand.
47
+
48
+ <!-- quickstart:start -->
49
+ ```bash
50
+ # (1) start a change — this begins PLAN and scaffolds the artifacts
51
+ cg new redis-cache
52
+
53
+ # fill in the plan — an agent writes this, not you
54
+ cat > .context-guard/changes/redis-cache/objective.md <<'EOF'
55
+ # Objective: Add Redis caching
56
+ Cache the top-N query results behind a 60s TTL.
57
+ EOF
58
+ cat > .context-guard/changes/redis-cache/tasks.md <<'EOF'
59
+ - [ ] 1.1 Add the redis client dependency
60
+ - [ ] 1.2 Wrap the query path with a cache lookup
61
+ EOF
62
+
63
+ # (2) a human reviews objective.md and tasks.md, then approves
64
+ cg approve
65
+
66
+ # (3) the recorded approval unlocks EXECUTE
67
+ cg commit --next-phase EXECUTE
68
+
69
+ # (4) claim the next task atomically — safe with several agents at once
70
+ cg next-task
71
+
72
+ # (5) one-shot rehydration after a crash, a compaction, or a new session
73
+ cg status
74
+ ```
75
+ <!-- quickstart:end -->
76
+
77
+ Every line above runs as written against a fresh directory; nothing here is
78
+ illustrative shorthand.
79
+
80
+ ## Install
81
+
82
+ Two lines, once per machine:
83
+
84
+ ```bash
85
+ pip install context-guard-cli
86
+ cg setup
87
+ ```
88
+
89
+ `cg setup` detects Claude Code, OpenCode and Antigravity, installs the slash
90
+ commands, and puts `cg approve` behind each one's permission prompt — see
91
+ [Adapters](#adapters-and-permission-configuration). It prints every file it
92
+ touched, and running it again changes nothing.
93
+
94
+ Per project there is no install step: `cg new` writes the phase documents
95
+ into `.context-guard/phases/` the first time you start a change.
96
+
97
+ **Optional — the MCP server**, for hosts with no shell (Claude Desktop is the
98
+ case it exists for): `cg setup --with-mcp` registers it. Every adapter works
99
+ completely without it; MCP is an alternative transport, not a requirement.
100
+
101
+ **Contributing** ([development](#development) has the rest):
102
+
103
+ ```bash
104
+ git clone https://github.com/fdomerlo/context-guard.git
105
+ cd context-guard && uv venv && uv pip install -e ".[dev]"
106
+ git config core.hooksPath .githooks # activates the pre-commit gate below
107
+ ```
108
+
109
+ ## How it works
110
+
111
+ ```
112
+ PLAN → EXECUTE → VERIFY → ARCHIVE
113
+ ```
114
+
115
+ Each change (`.context-guard/changes/<name>/`) moves through this pipeline
116
+ one phase at a time, enforced by code, not by convention:
117
+
118
+ - **`begin`** refuses to start a phase that is not the manifest's
119
+ `lock_phase` — the DAG is checked before work starts, not only when it is
120
+ claimed done.
121
+ - **`commit`** validates the phase's artifacts (`objective.md` + `tasks.md`
122
+ for PLAN, `review-report.md` + `verify-report.md` for VERIFY) contain no
123
+ leftover `[PENDING]` marker before advancing `lock_phase`.
124
+ - **`begin` on a fresh PLAN** auto-scaffolds five markdown files —
125
+ `objective.md`, `snapshot.md`, `tasks.md`, `review-report.md`,
126
+ `verify-report.md` — each starting as `[PENDING]`, so the agent edits
127
+ templates instead of inventing a shape from scratch.
128
+ - **`rollback`** restores the exact manifest snapshot taken when the phase
129
+ began.
130
+ - **Session and write locks** are OS-level (`O_CREAT|O_EXCL`), with
131
+ liveness-checked stale detection, so two agents on the same change do not
132
+ silently race each other.
133
+ - **Task claims** carry a lease (`claim-task` / `next-task` / `doctor
134
+ --fix`), so several agents can work one change concurrently without two of
135
+ them picking the same task.
136
+ - **`--change <name>`** scopes every command to one change. Several changes
137
+ active and no `--change` given is an error naming them — never a silent
138
+ guess at "the first one."
139
+
140
+ ## Threat Model
141
+
142
+ Read this before you rely on context-guard for anything you actually care
143
+ about.
144
+
145
+ The pipeline enforcement (`begin`/`commit` validating the DAG and the
146
+ artifacts) is real code, not a system prompt suggestion — an agent using the
147
+ `cg` tool cannot accidentally skip a phase or advance past `[PENDING]`
148
+ artifacts. But that enforcement is **cooperative**: it only binds an agent
149
+ that calls `cg` in the first place. An agent with a shell can write directly
150
+ to `manifest.json`, or simply not use the tool at all, and nothing in the
151
+ process stops it.
152
+
153
+ The one command that is explicitly **human-only** is `cg approve`. It
154
+ records the sign-off `commit --next-phase EXECUTE` requires. The name it
155
+ records (`--by`, defaulting to the OS user) is **audit metadata, not
156
+ authentication**: it says who to ask about this approval later, and an agent
157
+ could pass any string it liked. The command itself is just as cooperative as
158
+ the rest: an agent with a shell can
159
+ run `cg approve` itself, and nothing in `cg` prevents that. The actual hard
160
+ control does not live in `cg` at all — it is your harness's permission
161
+ prompt on the `cg approve` command, configured per host in
162
+ `docs/adapters/*/PERMISSIONS.md`. That prompt runs outside the agent's process,
163
+ which is the only place a control that does not depend on the agent's
164
+ cooperation can live. `approve` is deliberately not exposed as an MCP tool,
165
+ for the same reason: an MCP tool is a channel the permission prompt does not
166
+ see.
167
+
168
+ The pre-commit hook is the one layer that runs entirely outside the agent's
169
+ process — git invokes it regardless of what the agent chose to do — but it
170
+ is a perimeter check on file count, not a guarantee about correctness, and it
171
+ ships with an audited bypass (`CONTEXT_GUARD_BYPASS=1`) by design: an
172
+ unconditional block just gets `--no-verify`d, which leaves no trace at all.
173
+
174
+ ## CLI reference
175
+
176
+ | Command | Purpose |
177
+ |---|---|
178
+ | `cg new <name> --context <path>` | Create a change and begin PLAN |
179
+ | `cg list --context <path>` | List active changes and their phase |
180
+ | `cg begin --phase <PHASE> --context <path>` | Start a transaction for the given phase |
181
+ | `cg approve [--by <who>] [--hotfix --reason "<text>"]` | Human-only: record the sign-off `commit` into EXECUTE requires |
182
+ | `cg commit --next-phase <PHASE> --context <path>` | Validate the current phase's artifacts and advance the DAG |
183
+ | `cg rollback --context <path>` | Restore the manifest snapshot taken at `begin` |
184
+ | `cg checkpoint --summary "<text>" --context <path>` | Persist a session summary for warm-boot resume |
185
+ | `cg claim --context <path>` | Acquire the session lock, taking over a stale one if needed |
186
+ | `cg release --context <path> --agent-id <id>` | Release the session lock (ownership-checked) |
187
+ | `cg claim-task --task-id <id> --context <path>` | Claim one task with a lease |
188
+ | `cg release-task --task-id <id> --agent-id <id> --context <path>` | Release a claimed task |
189
+ | `cg next-task --context <path>` | Claim and return the next unclaimed pending task |
190
+ | `cg check-completion --context <path>` | Deterministic count of checked-off tasks |
191
+ | `cg validate --context <path>` | Lint session artifacts: existence, size cap, language |
192
+ | `cg status --context <path>` | One-shot summary for rehydration after context loss |
193
+ | `cg doctor --context <path> [--fix]` | Diagnose (or repair) stale claims and locks |
194
+ | `cg archive --context <path>` | Move a completed change to `changes/archive/` |
195
+ | `cg migrate --context <path>` | Convert a legacy state-guard or context-guard 1.x layout in place |
196
+
197
+ Every command accepts `--format json`. `cg` and `context-guard` are the same
198
+ binary under two entry points.
199
+
200
+ ## MCP server
201
+
202
+ `context-guard-mcp` exposes eight tools over stdio — the four transactional
203
+ ones plus four read-only ones for hosts with no shell (Claude Desktop is the
204
+ case these exist for):
205
+
206
+ `begin_transaction`, `commit_transaction`, `rollback_transaction`,
207
+ `save_checkpoint`, `get_status`, `check_completion`, `validate`, `next_task`.
208
+
209
+ `cg approve` is not an MCP tool. See Threat Model above.
210
+
211
+ ## Multi-change
212
+
213
+ State lives under `.context-guard/changes/<name>/`, one manifest and lock
214
+ set per change, so several changes can be planned and executed
215
+ independently in the same project. `cg new <name>` creates one; `cg list`
216
+ shows what is active; `cg archive` moves a finished one to
217
+ `changes/archive/`. `cg migrate` converts both legacy layouts — state-guard's
218
+ `state.ini` and context-guard 1.x's flat `.context-guard/` — in place and
219
+ idempotently, preserving any recorded human approval it finds.
220
+
221
+ ## Pre-commit hook
222
+
223
+ `.githooks/pre-commit` rejects commits touching more than a threshold number
224
+ of files when no change shows the protocol was engaged (a completed phase or
225
+ an open transaction). Activate it once per clone with
226
+ `git config core.hooksPath .githooks`.
227
+
228
+ - **Threshold**: `hook.file_threshold` in a change's manifest, or the
229
+ `CONTEXT_GUARD_FILE_THRESHOLD` environment variable, which wins over the
230
+ manifest. Across several active changes, the strictest configured value
231
+ applies.
232
+ - **`files_in_scope`**: staged files outside an executing change's declared
233
+ scope produce a warning, never a block.
234
+ - **Bypass**: `CONTEXT_GUARD_BYPASS=1 CONTEXT_GUARD_BYPASS_REASON='...' git
235
+ commit ...`. Every bypass is appended to `.context-guard/bypass.log` with
236
+ a timestamp and the file list — the door stays open, but nobody walks
237
+ through it unrecorded.
238
+
239
+ ## Exit codes
240
+
241
+ | Code | Name | Meaning |
242
+ |---|---|---|
243
+ | `[0]` | `EXIT_OK` | Success. |
244
+ | `[1]` | `EXIT_GENERIC` | Corrupt manifest, or no session at this context/change. |
245
+ | `[2]` | `EXIT_LOCK_HELD` | Another agent holds the lock or claim. Retryable with backoff. |
246
+ | `[3]` | `EXIT_LOCK_CONTENDED` | Lost the takeover race for a stale lock. Retryable. |
247
+ | `[4]` | `EXIT_VALIDATION` | Missing artifact, leftover `[PENDING]`, oversized artifact, or non-English text. |
248
+ | `[5]` | `EXIT_BAD_TRANSITION` | The phase requested is not the DAG's current `lock_phase`. Do not retry. |
249
+ | `[6]` | `EXIT_APPROVAL_REQUIRED` | `commit` into EXECUTE with no recorded `cg approve`. Only a human resolves it. |
250
+
251
+ ## Adapters and permission configuration
252
+
253
+ Thin, per-harness wrappers ship inside the package under
254
+ `context_guard/_data/hosts/{claude-code,opencode,antigravity}/` — each points
255
+ at `phases/{plan,execute,verify}.md` rather than duplicating them. How to put
256
+ `cg approve` behind each harness's permission prompt is documented in
257
+ [docs/adapters/](docs/adapters/), one `PERMISSIONS.md` per host, alongside the
258
+ manual smoke-test checklist in [docs/adapters/VERIFY.md](docs/adapters/VERIFY.md).
259
+ `cg setup` installs the right one for each detected host. The OpenCode and Antigravity
260
+ adapters are ported from state-guard and covered by static tests only — they
261
+ have not been run against a live host of either.
262
+
263
+ ## How this compares
264
+
265
+ context-guard is not a spec-writing tool, and it is not trying to be one.
266
+
267
+ | | context-guard | spec-kit | Kiro | bare `AGENTS.md` |
268
+ |---|---|---|---|---|
269
+ | Generates specs/plans from a prompt | No | Yes | Yes | No |
270
+ | IDE-native experience | No (CLI + MCP) | Depends on host | Yes | No |
271
+ | Enforces phase order in code, not prose | **Yes** | No | Partial | No |
272
+ | Atomic manifest, survives a crash mid-phase | **Yes** | No | No | No |
273
+ | OS-level locking for concurrent agents | **Yes** | No | No | No |
274
+ | Human-approval gate before execution | **Yes** | No | No | No |
275
+
276
+ What we do that they do not: runtime enforcement of a state machine that
277
+ outlives the agent's process. What they do that we do not: everything about
278
+ turning a prompt into a good spec in the first place. Use context-guard
279
+ together with whichever of them already generates your `objective.md` — it
280
+ was designed to consume one, not to write one.
281
+
282
+ ## Development
283
+
284
+ ```bash
285
+ git clone https://github.com/fdomerlo/context-guard.git
286
+ cd context-guard && uv venv && uv pip install -e .
287
+ python -m unittest discover -s tests
288
+ ```
289
+
290
+ Framework: `unittest`. Every fix ships with an adversarial test that
291
+ reproduces the bypass it closes; see `tests/test_adversarial_*.py` for the
292
+ pattern. No fixtures on disk outside `tempfile.mkdtemp()`.
293
+
294
+ ## License
295
+
296
+ MIT — see [LICENSE](LICENSE).
@@ -0,0 +1,32 @@
1
+ context_guard/__init__.py,sha256=H72uwUdIexHxAJjD5PnYBkrlVbYGa5UfOq2Ip2IJxbs,29
2
+ context_guard/mcp_server.py,sha256=XSZa-FcToAQuYM99IZSrJdonDvZbOX-oj9s86r-ayik,11576
3
+ context_guard/_data/hosts/antigravity/hooks.snippet.json,sha256=4Q-IPllMmHojp_HAZYncSVvyTQd0USw7RNt5vZSba70,325
4
+ context_guard/_data/hosts/antigravity/rules/context-guard.md,sha256=VzxWOyk0H-Wq6D_xNbtu0r71YKdrrqdKTl0YOYLB7iY,928
5
+ context_guard/_data/hosts/claude-code/mcp.snippet.json,sha256=awepjaQwV7DBlctPYgtHOX87Aupcv2MWIvseUQ1Cu0A,92
6
+ context_guard/_data/hosts/claude-code/settings.snippet.json,sha256=g9O5t3ZowK3lADDPbqVkYdJd0NYP93d5r8DfINVBjs8,345
7
+ context_guard/_data/hosts/claude-code/commands/cg-continue.md,sha256=n4wKaY0xNdzW445nGv9GAuIZVdZXOJoBc-i-AUkqyHU,485
8
+ context_guard/_data/hosts/claude-code/commands/cg-new.md,sha256=5dbF_dEXry363UA9BurIlhbnLJpAMLoUx0w12HAVtDI,382
9
+ context_guard/_data/hosts/opencode/agent.snippet.json,sha256=WM0LRPX8QlPBr9O7Q08Q3lgIm6tvPt8W6qVNMpVGq-4,510
10
+ context_guard/_data/hosts/opencode/mcp.snippet.json,sha256=f8KX2rco5SwLNlsDFFTg0W1geiNQq8bo0yfYNCdDnik,133
11
+ context_guard/_data/hosts/opencode/permissions.snippet.json,sha256=F41dGpQ-ucL4WhJVr7PYbX-ZCL4Fa4iEibSZlWY_tXM,229
12
+ context_guard/_data/hosts/opencode/commands/cg-continue.md,sha256=j2oPCd-bBuOpHYPZArfrmKi7n2EeDQH9uU4tsYbvtA0,569
13
+ context_guard/_data/hosts/opencode/commands/cg-new.md,sha256=NAl0DNGDZWWFnpo6-H54V_kSFGStUg1IDRmTKLp7KrY,403
14
+ context_guard/_data/phases/execute.md,sha256=ADcDdhfjAWmLdDU_1Sm1-u6Llcsq-1ZRLwCOsb-yATU,3143
15
+ context_guard/_data/phases/plan.md,sha256=p6SSbBqx7rWj9Gl1woaG9w3Cp9myvBi3vi0ICDWyVFY,4341
16
+ context_guard/_data/phases/verify.md,sha256=uyIMTxXJ-gWDBnAmslThZBZPPClMVbXnE_A-_UdBdYo,3912
17
+ context_guard/guard/__init__.py,sha256=3SnNGZIYKJa-7XUy310WITknYOfT4ppksSXwP985wII,35
18
+ context_guard/guard/assets.py,sha256=FYEOYM9x-45LdT8FSeW84tHAX4PTN0D6WhZue659nJk,3703
19
+ context_guard/guard/cli.py,sha256=kKJAatVKEpngj564aFAMYHIfi7e9_R355FuoqyAm5uk,11878
20
+ context_guard/guard/commands.py,sha256=ikAyEw0UQSL7uPXKUyOvxEzZA6yo_RCMa2sy0iKL-TA,29798
21
+ context_guard/guard/errors.py,sha256=gE37Z3-3V6tNDEoz2oGDy5GHS-zQ3VHMiF8sFZCFqR8,2812
22
+ context_guard/guard/locking.py,sha256=CO82IWLbFfXVZxgsc-_dR_mpfTH_d3XpJAvodC-2DOo,6502
23
+ context_guard/guard/manifest.py,sha256=dTMdJDn1UjRG7KxODICmCFriXHnxuU3LGvu4ohZGod0,1965
24
+ context_guard/guard/migrate.py,sha256=pK-10Dbw7fIg00pPckFE8KLlL6BmrCC_WUKGCqXgu-k,10598
25
+ context_guard/guard/paths.py,sha256=lCINd-BvMqlZMDElxzkfpw-kdfk9WVgCkxv1Lhbeq_s,6838
26
+ context_guard/guard/setup.py,sha256=X0ISWUasmyRuzKxhGTcBRwnacHeHgrpvmG8aL7sgXLI,18240
27
+ context_guard/guard/transaction.py,sha256=wgdo9qaflHV5j92rsVTpy8hXFOF7peSaY90c-4iXuXE,16008
28
+ context_guard_cli-2.1.0.dist-info/METADATA,sha256=jIPMt-3J8iCIizYx3BYiZs1EptojS5y2_FbWQr87Pg8,13556
29
+ context_guard_cli-2.1.0.dist-info/WHEEL,sha256=lCkmxWfQsSc9CfIClYeavTdQeEX2toPqufh9gI35EQA,87
30
+ context_guard_cli-2.1.0.dist-info/entry_points.txt,sha256=SpGuOnXXj_0uw7BD1B6Ap7hhJJrbH33n9F7NoiphWUQ,147
31
+ context_guard_cli-2.1.0.dist-info/licenses/LICENSE,sha256=hReNFwlnYKKvbkKeQpzX8V5WmE0fsHaNDQb8q4iPLRY,1071
32
+ context_guard_cli-2.1.0.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: hatchling 1.31.0
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
@@ -0,0 +1,4 @@
1
+ [console_scripts]
2
+ cg = context_guard.guard.cli:main
3
+ context-guard = context_guard.guard.cli:main
4
+ context-guard-mcp = context_guard.mcp_server:main
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Fernando Merlo
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.