adapter.py
python
sha256:4671b7f787ddbe63ced31c895b688c77ab495653b65a730b423329f26b3c1439
feat: K1-P1 complete — agent provenance, build-verification…
Sonnet 4.6
patch
53 days ago
| 1 | """Git-only VCS adapter backend (§4).""" |
| 2 | |
| 3 | from __future__ import annotations |
| 4 | |
| 5 | from adapters.base import BaseAdapter |
| 6 | from adapters.errors import ReadError, WriteError |
| 7 | from adapters.runner import CommandResult |
| 8 | from adapters.types import ( |
| 9 | AnchorResult, |
| 10 | CommitResult, |
| 11 | HeadResult, |
| 12 | MirrorResult, |
| 13 | RealignResult, |
| 14 | StatusResult, |
| 15 | ) |
| 16 | |
| 17 | |
| 18 | class GitOnlyAdapter(BaseAdapter): |
| 19 | """Single-history Git backend for external developers.""" |
| 20 | |
| 21 | def status(self) -> StatusResult | ReadError: |
| 22 | branch_result = self._git("rev-parse", "--abbrev-ref", "HEAD") |
| 23 | if isinstance(branch_result, ReadError): |
| 24 | return branch_result |
| 25 | dirty_result = self._git("status", "--porcelain") |
| 26 | if isinstance(dirty_result, ReadError): |
| 27 | return dirty_result |
| 28 | return StatusResult( |
| 29 | regime=self.regime, |
| 30 | dirty=bool(dirty_result.stdout.strip()), |
| 31 | branch=branch_result.stdout, |
| 32 | notes=["canonical=git", "single-history"], |
| 33 | ) |
| 34 | |
| 35 | def read_head(self, ref: str) -> HeadResult | ReadError: |
| 36 | if ref.startswith("muse:"): |
| 37 | return ReadError( |
| 38 | "read_head", |
| 39 | "muse refs forbidden in git-only regime", |
| 40 | ) |
| 41 | result = self._git("rev-parse", ref) |
| 42 | if isinstance(result, ReadError): |
| 43 | return result |
| 44 | sha = result.stdout.splitlines()[-1].strip() |
| 45 | if not sha: |
| 46 | return ReadError(f"git rev-parse {ref}", "empty sha") |
| 47 | return HeadResult(sha=sha, kind="git") |
| 48 | |
| 49 | def read_canonical_anchor(self) -> AnchorResult | ReadError: |
| 50 | remote = self.config.vcs.git.remote |
| 51 | main = self.config.vcs.git.main_branch |
| 52 | ref = f"{remote}/{main}" |
| 53 | head = self.read_head(ref) |
| 54 | if isinstance(head, ReadError): |
| 55 | return head |
| 56 | return AnchorResult(anchor_sha=head.sha, source=ref) |
| 57 | |
| 58 | def realign(self, *, dry_run: bool, max_commits: int) -> RealignResult: |
| 59 | return RealignResult( |
| 60 | would_import=0, |
| 61 | applied=False, |
| 62 | from_ref=None, |
| 63 | to_ref=None, |
| 64 | reason="single-history", |
| 65 | ) |
| 66 | |
| 67 | def commit_feature( |
| 68 | self, |
| 69 | *, |
| 70 | branch: str, |
| 71 | message: str, |
| 72 | paths: list[str], |
| 73 | ) -> CommitResult | ReadError | WriteError: |
| 74 | unsafe = self._validate_paths(paths) |
| 75 | if unsafe: |
| 76 | return unsafe |
| 77 | if self._is_protected_branch(branch): |
| 78 | return WriteError( |
| 79 | "commit_feature", |
| 80 | f"refused protected branch {branch!r}", |
| 81 | ) |
| 82 | |
| 83 | checkout = self._git("checkout", branch) |
| 84 | if isinstance(checkout, ReadError): |
| 85 | return checkout |
| 86 | |
| 87 | if paths: |
| 88 | add = self._git("add", "--", *paths) |
| 89 | if isinstance(add, ReadError): |
| 90 | return add |
| 91 | |
| 92 | commit = self._git("commit", "-m", message) |
| 93 | if isinstance(commit, ReadError): |
| 94 | return commit |
| 95 | |
| 96 | head = self._git("rev-parse", "HEAD") |
| 97 | if isinstance(head, ReadError): |
| 98 | return head |
| 99 | return CommitResult(committed=True, sha=head.stdout.strip()) |
| 100 | |
| 101 | def mirror(self, *, dry_run: bool) -> MirrorResult: |
| 102 | return MirrorResult( |
| 103 | diff_summary="", |
| 104 | pushed=False, |
| 105 | reason="single-history", |
| 106 | ) |
File History
1 commit
sha256:4671b7f787ddbe63ced31c895b688c77ab495653b65a730b423329f26b3c1439
feat: K1-P1 complete — agent provenance, build-verification…
Sonnet 4.6
patch
53 days ago