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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cuff-cli
3
- Version: 0.2.0
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.0
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-01/dist
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-01/e2e
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-01/e2e \
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.0
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-01/dist
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-01/e2e
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-01/e2e \
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.
@@ -1,4 +1,4 @@
1
1
  """Cuff's host-neutral claim and evidence gate."""
2
2
 
3
3
  __all__ = ["__version__"]
4
- __version__ = "0.2.0"
4
+ __version__ = "0.2.2"
@@ -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(root, args.work_item, base=args.base, head=args.head)
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
- return {
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.0
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.0
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-01/dist
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-01/e2e
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-01/e2e \
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.
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "cuff-cli"
7
- version = "0.2.0"
7
+ version = "0.2.2"
8
8
  description = "Cuff subject-bound claim, evidence, and verification gate."
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.11"
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes