cuff-cli 0.2.0__tar.gz → 0.2.2__tar.gz
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.
- {cuff_cli-0.2.0/core/cuff_cli.egg-info → cuff_cli-0.2.2}/PKG-INFO +24 -5
- {cuff_cli-0.2.0 → cuff_cli-0.2.2}/README.md +23 -4
- {cuff_cli-0.2.0 → cuff_cli-0.2.2}/core/cuff/__init__.py +1 -1
- {cuff_cli-0.2.0 → cuff_cli-0.2.2}/core/cuff/cli.py +12 -2
- {cuff_cli-0.2.0 → cuff_cli-0.2.2}/core/cuff/gate.py +29 -3
- {cuff_cli-0.2.0 → cuff_cli-0.2.2/core/cuff_cli.egg-info}/PKG-INFO +24 -5
- {cuff_cli-0.2.0 → cuff_cli-0.2.2}/pyproject.toml +1 -1
- {cuff_cli-0.2.0 → cuff_cli-0.2.2}/LICENSE +0 -0
- {cuff_cli-0.2.0 → cuff_cli-0.2.2}/core/cuff/__main__.py +0 -0
- {cuff_cli-0.2.0 → cuff_cli-0.2.2}/core/cuff/errors.py +0 -0
- {cuff_cli-0.2.0 → cuff_cli-0.2.2}/core/cuff/git.py +0 -0
- {cuff_cli-0.2.0 → cuff_cli-0.2.2}/core/cuff/ledger.py +0 -0
- {cuff_cli-0.2.0 → cuff_cli-0.2.2}/core/cuff/subject.py +0 -0
- {cuff_cli-0.2.0 → cuff_cli-0.2.2}/core/cuff/workspace.py +0 -0
- {cuff_cli-0.2.0 → cuff_cli-0.2.2}/core/cuff_cli.egg-info/SOURCES.txt +0 -0
- {cuff_cli-0.2.0 → cuff_cli-0.2.2}/core/cuff_cli.egg-info/dependency_links.txt +0 -0
- {cuff_cli-0.2.0 → cuff_cli-0.2.2}/core/cuff_cli.egg-info/entry_points.txt +0 -0
- {cuff_cli-0.2.0 → cuff_cli-0.2.2}/core/cuff_cli.egg-info/top_level.txt +0 -0
- {cuff_cli-0.2.0 → cuff_cli-0.2.2}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: cuff-cli
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.2
|
|
4
4
|
Summary: Cuff subject-bound claim, evidence, and verification gate.
|
|
5
5
|
Author: Fab7
|
|
6
6
|
License-Expression: Apache-2.0
|
|
@@ -38,7 +38,7 @@ worktree, or stages, commits, fetches, pushes, releases, or deploys anything.
|
|
|
38
38
|
Install a released version as a standard uv-managed tool:
|
|
39
39
|
|
|
40
40
|
```bash
|
|
41
|
-
uv tool install cuff-cli==0.2.
|
|
41
|
+
uv tool install cuff-cli==0.2.2
|
|
42
42
|
cuff --version
|
|
43
43
|
```
|
|
44
44
|
|
|
@@ -77,6 +77,15 @@ cuff seal \
|
|
|
77
77
|
cuff check --work-item task-1 --json
|
|
78
78
|
```
|
|
79
79
|
|
|
80
|
+
Recovery controllers that need the latest linked observation, including a
|
|
81
|
+
recorded verifier failure, may opt into the closed seven-field projection:
|
|
82
|
+
|
|
83
|
+
```bash
|
|
84
|
+
cuff check --work-item task-1 --json --include-latest-record
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
Without that flag, `check --json` retains its exact six-field response.
|
|
88
|
+
|
|
80
89
|
The split path is available when the claim must exist before verification:
|
|
81
90
|
|
|
82
91
|
```bash
|
|
@@ -142,19 +151,29 @@ Validate the built candidate and both host payloads without touching the
|
|
|
142
151
|
normal host configuration:
|
|
143
152
|
|
|
144
153
|
```bash
|
|
145
|
-
uv build --out-dir ../sandbox/cuff-
|
|
154
|
+
uv build --out-dir ../sandbox/cuff-02/dist
|
|
146
155
|
uv run python tools/local_release_check.py --host all
|
|
147
156
|
uv run python tools/local_release_check.py --host all --prepare-auth \
|
|
148
157
|
--candidate-commit COMMIT \
|
|
149
|
-
--evidence-dir ../sandbox/cuff-
|
|
158
|
+
--evidence-dir ../sandbox/cuff-02/e2e
|
|
150
159
|
# Log each CLI in using the isolated home paths printed by the prepare phase.
|
|
151
160
|
uv run python tools/local_release_check.py --host all --live --reuse-prepared \
|
|
152
161
|
--candidate-commit COMMIT \
|
|
153
|
-
--evidence-dir ../sandbox/cuff-
|
|
162
|
+
--evidence-dir ../sandbox/cuff-02/e2e \
|
|
163
|
+
--qualification-manifest ../sandbox/cuff-02/control/qualification.json \
|
|
164
|
+
--preflight-evidence ../sandbox/cuff-02/control/preflight.json \
|
|
154
165
|
--codex-model MODEL \
|
|
155
166
|
--claude-model MODEL
|
|
156
167
|
```
|
|
157
168
|
|
|
169
|
+
Before `--live`, freeze the exact candidate, host order, `current` and `stale`
|
|
170
|
+
cases, three-valid-sample rule, prompts, tool policies, and containment policies
|
|
171
|
+
in the qualification manifest. A trusted non-LLM runner must then record a
|
|
172
|
+
passing containment preflight for the same qualification and policy digests.
|
|
173
|
+
The checker rejects missing or mismatched controls and runs six fresh
|
|
174
|
+
workspaces and host sessions per host. Follow the root `LLM_VERIFICATION.md`;
|
|
175
|
+
unsupported isolation is `INCONCLUSIVE`, not a release pass.
|
|
176
|
+
|
|
158
177
|
See [RUNBOOK.md](RUNBOOK.md) for operations, [the architecture overview](docs/architecture/overview.md)
|
|
159
178
|
for ownership, and [the ledger contract](docs/architecture/ledger.md) for the
|
|
160
179
|
record and gate invariants.
|
|
@@ -27,7 +27,7 @@ worktree, or stages, commits, fetches, pushes, releases, or deploys anything.
|
|
|
27
27
|
Install a released version as a standard uv-managed tool:
|
|
28
28
|
|
|
29
29
|
```bash
|
|
30
|
-
uv tool install cuff-cli==0.2.
|
|
30
|
+
uv tool install cuff-cli==0.2.2
|
|
31
31
|
cuff --version
|
|
32
32
|
```
|
|
33
33
|
|
|
@@ -66,6 +66,15 @@ cuff seal \
|
|
|
66
66
|
cuff check --work-item task-1 --json
|
|
67
67
|
```
|
|
68
68
|
|
|
69
|
+
Recovery controllers that need the latest linked observation, including a
|
|
70
|
+
recorded verifier failure, may opt into the closed seven-field projection:
|
|
71
|
+
|
|
72
|
+
```bash
|
|
73
|
+
cuff check --work-item task-1 --json --include-latest-record
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
Without that flag, `check --json` retains its exact six-field response.
|
|
77
|
+
|
|
69
78
|
The split path is available when the claim must exist before verification:
|
|
70
79
|
|
|
71
80
|
```bash
|
|
@@ -131,19 +140,29 @@ Validate the built candidate and both host payloads without touching the
|
|
|
131
140
|
normal host configuration:
|
|
132
141
|
|
|
133
142
|
```bash
|
|
134
|
-
uv build --out-dir ../sandbox/cuff-
|
|
143
|
+
uv build --out-dir ../sandbox/cuff-02/dist
|
|
135
144
|
uv run python tools/local_release_check.py --host all
|
|
136
145
|
uv run python tools/local_release_check.py --host all --prepare-auth \
|
|
137
146
|
--candidate-commit COMMIT \
|
|
138
|
-
--evidence-dir ../sandbox/cuff-
|
|
147
|
+
--evidence-dir ../sandbox/cuff-02/e2e
|
|
139
148
|
# Log each CLI in using the isolated home paths printed by the prepare phase.
|
|
140
149
|
uv run python tools/local_release_check.py --host all --live --reuse-prepared \
|
|
141
150
|
--candidate-commit COMMIT \
|
|
142
|
-
--evidence-dir ../sandbox/cuff-
|
|
151
|
+
--evidence-dir ../sandbox/cuff-02/e2e \
|
|
152
|
+
--qualification-manifest ../sandbox/cuff-02/control/qualification.json \
|
|
153
|
+
--preflight-evidence ../sandbox/cuff-02/control/preflight.json \
|
|
143
154
|
--codex-model MODEL \
|
|
144
155
|
--claude-model MODEL
|
|
145
156
|
```
|
|
146
157
|
|
|
158
|
+
Before `--live`, freeze the exact candidate, host order, `current` and `stale`
|
|
159
|
+
cases, three-valid-sample rule, prompts, tool policies, and containment policies
|
|
160
|
+
in the qualification manifest. A trusted non-LLM runner must then record a
|
|
161
|
+
passing containment preflight for the same qualification and policy digests.
|
|
162
|
+
The checker rejects missing or mismatched controls and runs six fresh
|
|
163
|
+
workspaces and host sessions per host. Follow the root `LLM_VERIFICATION.md`;
|
|
164
|
+
unsupported isolation is `INCONCLUSIVE`, not a release pass.
|
|
165
|
+
|
|
147
166
|
See [RUNBOOK.md](RUNBOOK.md) for operations, [the architecture overview](docs/architecture/overview.md)
|
|
148
167
|
for ownership, and [the ledger contract](docs/architecture/ledger.md) for the
|
|
149
168
|
record and gate invariants.
|
|
@@ -57,6 +57,7 @@ def build_parser() -> argparse.ArgumentParser:
|
|
|
57
57
|
readiness.add_argument("--work-item", required=True)
|
|
58
58
|
readiness.add_argument("--base")
|
|
59
59
|
readiness.add_argument("--head")
|
|
60
|
+
readiness.add_argument("--include-latest-record", action="store_true")
|
|
60
61
|
readiness.add_argument("--json", action="store_true")
|
|
61
62
|
return parser
|
|
62
63
|
|
|
@@ -129,7 +130,13 @@ def main(argv: list[str] | None = None) -> int:
|
|
|
129
130
|
f"exit {sealed.evidence['exit_code']}",
|
|
130
131
|
)
|
|
131
132
|
if args.command == "check":
|
|
132
|
-
data = check(
|
|
133
|
+
data = check(
|
|
134
|
+
root,
|
|
135
|
+
args.work_item,
|
|
136
|
+
base=args.base,
|
|
137
|
+
head=args.head,
|
|
138
|
+
include_latest_record=args.include_latest_record,
|
|
139
|
+
)
|
|
133
140
|
return _finish_result(args, data, "Cuff readiness")
|
|
134
141
|
parser.error("unknown command")
|
|
135
142
|
except CuffError as exc:
|
|
@@ -231,7 +238,7 @@ def _check_error(args: argparse.Namespace, error: dict[str, Any]) -> dict[str, A
|
|
|
231
238
|
work_item = normalize_work_item(work_item)
|
|
232
239
|
except CuffError:
|
|
233
240
|
pass
|
|
234
|
-
|
|
241
|
+
result = {
|
|
235
242
|
"ok": False,
|
|
236
243
|
"errors": [error],
|
|
237
244
|
"work_item": work_item,
|
|
@@ -239,6 +246,9 @@ def _check_error(args: argparse.Namespace, error: dict[str, Any]) -> dict[str, A
|
|
|
239
246
|
"selected_evidence": None,
|
|
240
247
|
"record_count": 0,
|
|
241
248
|
}
|
|
249
|
+
if getattr(args, "include_latest_record", False):
|
|
250
|
+
result["latest_record"] = None
|
|
251
|
+
return result
|
|
242
252
|
|
|
243
253
|
|
|
244
254
|
def _replay(content: bytes, stream: Any) -> None:
|
|
@@ -6,7 +6,7 @@ from pathlib import Path
|
|
|
6
6
|
from typing import Any
|
|
7
7
|
|
|
8
8
|
from .errors import CuffError
|
|
9
|
-
from .ledger import RECORDS_DIR, normalize_work_item, read, read_all
|
|
9
|
+
from .ledger import RECORDS_DIR, normalize_work_item, read, read_all, record_path
|
|
10
10
|
from .subject import current_subject
|
|
11
11
|
|
|
12
12
|
|
|
@@ -16,6 +16,7 @@ def check(
|
|
|
16
16
|
*,
|
|
17
17
|
base: str | None = None,
|
|
18
18
|
head: str | None = None,
|
|
19
|
+
include_latest_record: bool = False,
|
|
19
20
|
) -> dict[str, Any]:
|
|
20
21
|
normalized = normalize_work_item(work_item)
|
|
21
22
|
result: dict[str, Any] = {
|
|
@@ -26,6 +27,8 @@ def check(
|
|
|
26
27
|
"selected_evidence": None,
|
|
27
28
|
"record_count": 0,
|
|
28
29
|
}
|
|
30
|
+
if include_latest_record:
|
|
31
|
+
result["latest_record"] = None
|
|
29
32
|
try:
|
|
30
33
|
read_all(root)
|
|
31
34
|
records = read(root, normalized)
|
|
@@ -37,6 +40,17 @@ def check(
|
|
|
37
40
|
claims = [record for record in records if record["type"] == "claim"]
|
|
38
41
|
claim = claims[-1] if claims else None
|
|
39
42
|
result["latest_claim"] = claim
|
|
43
|
+
if claim is not None and include_latest_record:
|
|
44
|
+
linked = [
|
|
45
|
+
record
|
|
46
|
+
for record in records
|
|
47
|
+
if record["type"] == "evidence" and record["claim"] == claim["id"]
|
|
48
|
+
]
|
|
49
|
+
result["latest_record"] = {
|
|
50
|
+
"path": _relative_record_path(root, normalized),
|
|
51
|
+
"claim": claim,
|
|
52
|
+
"evidence": linked[-1] if linked else None,
|
|
53
|
+
}
|
|
40
54
|
|
|
41
55
|
git_context = _check_git_workspace(root, base, head, result["errors"])
|
|
42
56
|
if claim is None:
|
|
@@ -46,8 +60,7 @@ def check(
|
|
|
46
60
|
linked = [
|
|
47
61
|
record
|
|
48
62
|
for record in records
|
|
49
|
-
if record["type"] == "evidence"
|
|
50
|
-
and record["claim"] == claim["id"]
|
|
63
|
+
if record["type"] == "evidence" and record["claim"] == claim["id"]
|
|
51
64
|
]
|
|
52
65
|
if not linked:
|
|
53
66
|
_fail(
|
|
@@ -97,6 +110,19 @@ def check(
|
|
|
97
110
|
return result
|
|
98
111
|
|
|
99
112
|
|
|
113
|
+
def _relative_record_path(root: Path, work_item: str) -> str:
|
|
114
|
+
workspace = root.resolve()
|
|
115
|
+
path = record_path(workspace, work_item).resolve()
|
|
116
|
+
try:
|
|
117
|
+
return path.relative_to(workspace).as_posix()
|
|
118
|
+
except ValueError as exc:
|
|
119
|
+
raise CuffError(
|
|
120
|
+
"CUFF_PATH_INVALID",
|
|
121
|
+
"Cuff ledger path escapes the workspace",
|
|
122
|
+
{"path": str(path), "workspace": str(workspace)},
|
|
123
|
+
) from exc
|
|
124
|
+
|
|
125
|
+
|
|
100
126
|
def _subject_fresh(root: Path, claim: dict[str, Any]) -> bool:
|
|
101
127
|
try:
|
|
102
128
|
return current_subject(root, claim["subject"]) == claim["subject"]
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: cuff-cli
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.2
|
|
4
4
|
Summary: Cuff subject-bound claim, evidence, and verification gate.
|
|
5
5
|
Author: Fab7
|
|
6
6
|
License-Expression: Apache-2.0
|
|
@@ -38,7 +38,7 @@ worktree, or stages, commits, fetches, pushes, releases, or deploys anything.
|
|
|
38
38
|
Install a released version as a standard uv-managed tool:
|
|
39
39
|
|
|
40
40
|
```bash
|
|
41
|
-
uv tool install cuff-cli==0.2.
|
|
41
|
+
uv tool install cuff-cli==0.2.2
|
|
42
42
|
cuff --version
|
|
43
43
|
```
|
|
44
44
|
|
|
@@ -77,6 +77,15 @@ cuff seal \
|
|
|
77
77
|
cuff check --work-item task-1 --json
|
|
78
78
|
```
|
|
79
79
|
|
|
80
|
+
Recovery controllers that need the latest linked observation, including a
|
|
81
|
+
recorded verifier failure, may opt into the closed seven-field projection:
|
|
82
|
+
|
|
83
|
+
```bash
|
|
84
|
+
cuff check --work-item task-1 --json --include-latest-record
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
Without that flag, `check --json` retains its exact six-field response.
|
|
88
|
+
|
|
80
89
|
The split path is available when the claim must exist before verification:
|
|
81
90
|
|
|
82
91
|
```bash
|
|
@@ -142,19 +151,29 @@ Validate the built candidate and both host payloads without touching the
|
|
|
142
151
|
normal host configuration:
|
|
143
152
|
|
|
144
153
|
```bash
|
|
145
|
-
uv build --out-dir ../sandbox/cuff-
|
|
154
|
+
uv build --out-dir ../sandbox/cuff-02/dist
|
|
146
155
|
uv run python tools/local_release_check.py --host all
|
|
147
156
|
uv run python tools/local_release_check.py --host all --prepare-auth \
|
|
148
157
|
--candidate-commit COMMIT \
|
|
149
|
-
--evidence-dir ../sandbox/cuff-
|
|
158
|
+
--evidence-dir ../sandbox/cuff-02/e2e
|
|
150
159
|
# Log each CLI in using the isolated home paths printed by the prepare phase.
|
|
151
160
|
uv run python tools/local_release_check.py --host all --live --reuse-prepared \
|
|
152
161
|
--candidate-commit COMMIT \
|
|
153
|
-
--evidence-dir ../sandbox/cuff-
|
|
162
|
+
--evidence-dir ../sandbox/cuff-02/e2e \
|
|
163
|
+
--qualification-manifest ../sandbox/cuff-02/control/qualification.json \
|
|
164
|
+
--preflight-evidence ../sandbox/cuff-02/control/preflight.json \
|
|
154
165
|
--codex-model MODEL \
|
|
155
166
|
--claude-model MODEL
|
|
156
167
|
```
|
|
157
168
|
|
|
169
|
+
Before `--live`, freeze the exact candidate, host order, `current` and `stale`
|
|
170
|
+
cases, three-valid-sample rule, prompts, tool policies, and containment policies
|
|
171
|
+
in the qualification manifest. A trusted non-LLM runner must then record a
|
|
172
|
+
passing containment preflight for the same qualification and policy digests.
|
|
173
|
+
The checker rejects missing or mismatched controls and runs six fresh
|
|
174
|
+
workspaces and host sessions per host. Follow the root `LLM_VERIFICATION.md`;
|
|
175
|
+
unsupported isolation is `INCONCLUSIVE`, not a release pass.
|
|
176
|
+
|
|
158
177
|
See [RUNBOOK.md](RUNBOOK.md) for operations, [the architecture overview](docs/architecture/overview.md)
|
|
159
178
|
for ownership, and [the ledger contract](docs/architecture/ledger.md) for the
|
|
160
179
|
record and gate invariants.
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|