Skip to content

Commit f42f436

Browse files
docs(lib): tighten provenance code comments
1 parent 22dc5b5 commit f42f436

1 file changed

Lines changed: 8 additions & 55 deletions

File tree

src/agentex/lib/utils/build_provenance.py

Lines changed: 8 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,4 @@
1-
"""Client-attested build provenance capture (AGX1-418).
2-
3-
The single producer of source identity for agent builds: git coordinates plus a
4-
deterministic content hash of the build context. Every build path (CLI, sgpctl,
5-
CI) imports this so capture logic and the ``working_tree_hash`` definition live
6-
in exactly one place. Capture is best-effort — a missing/odd git state degrades
7-
to nulls and never raises into a build.
8-
"""
1+
"""Capture client-attested source identity without failing agent builds."""
92

103
from __future__ import annotations
114

@@ -28,14 +21,7 @@
2821

2922
@dataclass(frozen=True)
3023
class BuildProvenance:
31-
"""Source identity for one build; every field degrades to ``None``.
32-
33-
``working_tree_hash`` is the deterministic content hash of the build context
34-
and is always computed — it identifies the exact bytes that shipped,
35-
independent of git state. ``commit`` (+ ``ref`` / ``repo``) anchor those bytes
36-
to source, and ``dirty`` records whether the work tree had uncommitted changes
37-
at build time (``None`` outside a git work tree).
38-
"""
24+
"""Source identity for one build; unavailable fields degrade to ``None``."""
3925

4026
repo: Optional[str] = None
4127
commit: Optional[str] = None
@@ -60,13 +46,7 @@ def source_fields(self) -> dict[str, object]:
6046
return {key: value for key, value in fields.items() if value is not None}
6147

6248
def build_info(self) -> dict[str, object]:
63-
"""The ``build-info.json`` payload (runtime ``registration_metadata``).
64-
65-
Overlapping keys match the server's ``DeploymentHistory`` type
66-
(``commit_hash`` / ``branch_name`` / ``author_*`` / ``build_timestamp``),
67-
which is populated from ``registration_metadata``; the rest are the
68-
provenance-specific coordinates.
69-
"""
49+
"""Return provenance using the runtime registration metadata field names."""
7050
info = {
7151
"repo": self.repo,
7252
"commit_hash": self.commit,
@@ -99,12 +79,7 @@ def _git(repo_root: Path, *args: str) -> Optional[str]:
9979

10080

10181
def normalize_remote(url: Optional[str]) -> Optional[str]:
102-
"""Canonicalize a git remote to ``host/path`` — credentials and scheme stripped.
103-
104-
``git@github.com:org/repo.git`` and ``https://x:tok@github.com/org/repo.git``
105-
both normalize to ``github.com/org/repo``. Host is lowercased; path casing is
106-
preserved (repo paths can be case-significant).
107-
"""
82+
"""Strip credentials and scheme from a remote, returning ``host/path``."""
10883
if not url:
10984
return None
11085
candidate = url.strip()
@@ -133,25 +108,15 @@ def _sha256_file(path: Path) -> str:
133108

134109

135110
def iter_context_files(root: Path) -> list[Path]:
136-
"""Files (and symlinks) under ``root``, sorted by POSIX relpath.
137-
138-
The canonical, order-stable enumeration shared by the content hash and the
139-
archive packer so the two can never drift on which files they cover.
140-
"""
111+
"""Return files and symlinks under ``root``, sorted by POSIX relative path."""
141112
return sorted(
142113
(path for path in root.rglob("*") if path.is_symlink() or path.is_file()),
143114
key=lambda path: path.relative_to(root).as_posix(),
144115
)
145116

146117

147118
def working_tree_hash(root: Path) -> str:
148-
"""Deterministic content hash of the build context at ``root``.
149-
150-
sha256 over the sorted ``(relpath, normalized mode, content digest)`` of every
151-
file — the build *inputs*, not the tarball (tar/gzip framing is
152-
non-deterministic and would defeat dedupe). Mode is normalized to the
153-
executable bit; symlinks hash their target string, not the resolved content.
154-
"""
119+
"""Hash sorted build inputs, normalized modes, and symlink target strings."""
155120
lines: list[str] = []
156121
for path in iter_context_files(root):
157122
relpath = path.relative_to(root).as_posix()
@@ -167,11 +132,7 @@ def working_tree_hash(root: Path) -> str:
167132

168133

169134
def _safe_working_tree_hash(root: Path) -> Optional[str]:
170-
"""``working_tree_hash`` that degrades to None — capture must never fail a build.
171-
172-
A permission error or filesystem race during the walk/stat/read would otherwise
173-
raise out of capture and abort the build before the archive is even created.
174-
"""
135+
"""Compute the context hash without allowing capture to fail a build."""
175136
try:
176137
return working_tree_hash(root)
177138
except Exception:
@@ -182,15 +143,7 @@ def _safe_working_tree_hash(root: Path) -> Optional[str]:
182143
def capture_build_provenance(
183144
repo_path: Path, context_root: Path, content_root: Optional[Path] = None
184145
) -> BuildProvenance:
185-
"""Capture source identity for a build of ``context_root``.
186-
187-
``repo_path`` is where git is interrogated and ``subpath`` is ``context_root``
188-
relative to the repo root (which agent, in a monorepo). ``content_root`` is
189-
the directory hashed — the *staged*, post-``.dockerignore`` tree that actually
190-
ships; it defaults to ``context_root`` when there is no separate staging dir.
191-
``working_tree_hash`` is always computed; git coordinates anchor it to source
192-
when available.
193-
"""
146+
"""Capture git coordinates and the staged build-context hash."""
194147
timestamp = datetime.now(timezone.utc).isoformat()
195148
hash_root = content_root if content_root is not None else context_root
196149
tree_hash = _safe_working_tree_hash(hash_root)

0 commit comments

Comments
 (0)