cuff-cli 0.2.1__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.1
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.1
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
@@ -1,14 +1,3 @@
1
- Metadata-Version: 2.4
2
- Name: cuff-cli
3
- Version: 0.2.1
4
- Summary: Cuff subject-bound claim, evidence, and verification gate.
5
- Author: Fab7
6
- License-Expression: Apache-2.0
7
- Requires-Python: >=3.11
8
- Description-Content-Type: text/markdown
9
- License-File: LICENSE
10
- Dynamic: license-file
11
-
12
1
  <p align="center">
13
2
  <img src="docs/assets/banner.svg" alt="Cuff check flow: bind the subject, observe the verifier, require fresh evidence" width="100%" />
14
3
  </p>
@@ -38,7 +27,7 @@ worktree, or stages, commits, fetches, pushes, releases, or deploys anything.
38
27
  Install a released version as a standard uv-managed tool:
39
28
 
40
29
  ```bash
41
- uv tool install cuff-cli==0.2.1
30
+ uv tool install cuff-cli==0.2.2
42
31
  cuff --version
43
32
  ```
44
33
 
@@ -77,6 +66,15 @@ cuff seal \
77
66
  cuff check --work-item task-1 --json
78
67
  ```
79
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
+
80
78
  The split path is available when the claim must exist before verification:
81
79
 
82
80
  ```bash
@@ -1,4 +1,4 @@
1
1
  """Cuff's host-neutral claim and evidence gate."""
2
2
 
3
3
  __all__ = ["__version__"]
4
- __version__ = "0.2.1"
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,3 +1,14 @@
1
+ Metadata-Version: 2.4
2
+ Name: cuff-cli
3
+ Version: 0.2.2
4
+ Summary: Cuff subject-bound claim, evidence, and verification gate.
5
+ Author: Fab7
6
+ License-Expression: Apache-2.0
7
+ Requires-Python: >=3.11
8
+ Description-Content-Type: text/markdown
9
+ License-File: LICENSE
10
+ Dynamic: license-file
11
+
1
12
  <p align="center">
2
13
  <img src="docs/assets/banner.svg" alt="Cuff check flow: bind the subject, observe the verifier, require fresh evidence" width="100%" />
3
14
  </p>
@@ -27,7 +38,7 @@ worktree, or stages, commits, fetches, pushes, releases, or deploys anything.
27
38
  Install a released version as a standard uv-managed tool:
28
39
 
29
40
  ```bash
30
- uv tool install cuff-cli==0.2.1
41
+ uv tool install cuff-cli==0.2.2
31
42
  cuff --version
32
43
  ```
33
44
 
@@ -66,6 +77,15 @@ cuff seal \
66
77
  cuff check --work-item task-1 --json
67
78
  ```
68
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
+
69
89
  The split path is available when the claim must exist before verification:
70
90
 
71
91
  ```bash
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "cuff-cli"
7
- version = "0.2.1"
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