@arbiterforge/ca-pi 0.16.5 → 0.17.0

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.
Files changed (46) hide show
  1. package/README.md +1 -1
  2. package/package.json +1 -1
  3. package/plugins/ca-pi/CHANGELOG.md +46 -0
  4. package/plugins/ca-pi/agents/map-deps.md +26 -26
  5. package/plugins/ca-pi/agents/map-structure.md +27 -28
  6. package/plugins/ca-pi/agents/tribunal-lens-reviewer.md +70 -39
  7. package/plugins/ca-pi/generated/roles.json +2 -5
  8. package/plugins/ca-pi/helpers/artifacts/release.json +18 -18
  9. package/plugins/ca-pi/hooks/_artifactauthoritylib.py +16 -10
  10. package/plugins/ca-pi/hooks/_artifactlib.py +29 -2
  11. package/plugins/ca-pi/hooks/_contextmergelib.py +160 -0
  12. package/plugins/ca-pi/hooks/_githooks.py +2 -0
  13. package/plugins/ca-pi/hooks/_host.py +1 -1
  14. package/plugins/ca-pi/hooks/_tribunalinventorylib.py +653 -0
  15. package/plugins/ca-pi/hooks/_tribunalrunlib.py +652 -0
  16. package/plugins/ca-pi/hooks/hostapi.py +1 -1
  17. package/plugins/ca-pi/hooks/resolve-context-conflict.py +8 -0
  18. package/plugins/ca-pi/hooks/tribunal.py +113 -0
  19. package/plugins/ca-pi/package.json +1 -1
  20. package/plugins/ca-pi/routines/finishing-a-development-branch/SKILL.md +29 -0
  21. package/plugins/ca-pi/routines/tribunal/SKILL.md +192 -99
  22. package/plugins/ca-pi/routines/tribunal/references/ai-markers.md +6 -27
  23. package/plugins/ca-pi/routines/tribunal/references/cost-and-models.md +73 -52
  24. package/plugins/ca-pi/routines/tribunal/references/finding-record.md +69 -13
  25. package/plugins/ca-pi/routines/tribunal/references/issue-filing.md +63 -45
  26. package/plugins/ca-pi/routines/tribunal/references/lenses/appsec.md +55 -12
  27. package/plugins/ca-pi/routines/tribunal/references/lenses/architecture.md +51 -13
  28. package/plugins/ca-pi/routines/tribunal/references/lenses/change-closure.md +65 -0
  29. package/plugins/ca-pi/routines/tribunal/references/lenses/coverage.md +51 -10
  30. package/plugins/ca-pi/routines/tribunal/references/lenses/infra.md +53 -13
  31. package/plugins/ca-pi/routines/tribunal/references/lenses/migration.md +52 -12
  32. package/plugins/ca-pi/routines/tribunal/references/lenses/observability.md +52 -11
  33. package/plugins/ca-pi/routines/tribunal/references/lenses/performance.md +52 -12
  34. package/plugins/ca-pi/routines/tribunal/references/lenses/reliability.md +53 -13
  35. package/plugins/ca-pi/routines/tribunal/references/lenses/secrets-supply.md +55 -12
  36. package/plugins/ca-pi/routines/tribunal/references/lenses/semantic-contract.md +62 -0
  37. package/plugins/ca-pi/routines/tribunal/references/lenses/test-fidelity.md +48 -13
  38. package/plugins/ca-pi/routines/tribunal/references/lenses/typesafety.md +52 -11
  39. package/plugins/ca-pi/routines/tribunal/references/report.md +34 -12
  40. package/plugins/ca-pi/routines/tribunal/references/review-risk.md +78 -0
  41. package/plugins/ca-pi/routines/tribunal/references/schemas.md +171 -38
  42. package/plugins/ca-pi/routines/tribunal/references/telemetry.md +52 -17
  43. package/plugins/ca-pi/routines/tribunal/references/triage.md +95 -47
  44. package/plugins/ca-pi/routines/tribunal/references/verification-quality.md +61 -0
  45. package/plugins/ca-pi/skills/ca-pr/SKILL.md +29 -0
  46. package/plugins/ca-pi/skills/ca-tribunal/SKILL.md +192 -99
@@ -0,0 +1,160 @@
1
+ #!/usr/bin/env python3
2
+ # codeArbiter — restore the committed current side of a legacy code-map conflict.
3
+ #
4
+ # Fixed target and source only. Inspection binds the real merge, all index bytes,
5
+ # conflict rendering and legacy provenance. Application rechecks that identity,
6
+ # retains all three index stages, and never adopts or edits native-owned context.
7
+ # Ordinary H-22 writes remain blocked. No import-time I/O or caller content.
8
+ #
9
+ # Public API:
10
+ # inspect(root) -> dict read-only recovery binding
11
+ # restore_head(root, expected) -> dict restore exact HEAD blob, never stage
12
+ # main(argv=None) -> int bounded JSON CLI
13
+
14
+ import argparse
15
+ import hashlib
16
+ import json
17
+ import os
18
+ from pathlib import Path
19
+ import re
20
+ import stat
21
+ import subprocess
22
+ import sys
23
+
24
+ from _appendonlyconflictlib import ResolutionError, _validate_conflicted_worktree, _write_bytes_atomic
25
+ from _artifactlib import ArtifactError, _decode, _open_pinned_regular, _trusted_directory
26
+ from _gitexec import git_executable, root_bound_git_env
27
+ from _protectedstatelib import _committed_context_journal
28
+ from _provenancelib import valid_provenance_record
29
+
30
+
31
+ TARGET = ".codearbiter/code-map.md"
32
+ PROVENANCE = ".codearbiter/.provenance/code-map.json"
33
+ MAX_BYTES = 8 << 20
34
+ OID = r"[0-9a-f]{40}(?:[0-9a-f]{24})?"
35
+
36
+
37
+ def _require(condition, reason):
38
+ if not condition:
39
+ raise ResolutionError(reason)
40
+
41
+
42
+ def _hash(raw):
43
+ return hashlib.sha256(raw).hexdigest()
44
+
45
+
46
+ def _git(root, *args):
47
+ env = root_bound_git_env()
48
+ env.update(GIT_OPTIONAL_LOCKS="0", GIT_TERMINAL_PROMPT="0", GIT_NO_REPLACE_OBJECTS="1")
49
+ result = subprocess.run(
50
+ [git_executable(), "--no-pager", "--no-lazy-fetch", "-c", "core.fsmonitor=false",
51
+ "-c", "core.untrackedCache=false", *args],
52
+ cwd=root, env=env, capture_output=True, shell=False, timeout=30)
53
+ _require(result.returncode == 0 and len(result.stdout) <= MAX_BYTES, "Git conflict evidence unavailable")
54
+ return result.stdout
55
+
56
+
57
+ def _read(path):
58
+ _trusted_directory(path.parent, "UNSAFE_CONTEXT_PATH")
59
+ descriptor = _open_pinned_regular(path)
60
+ try:
61
+ info = os.fstat(descriptor)
62
+ _require(stat.S_ISREG(info.st_mode) and not getattr(info, "st_file_attributes", 0) & 0x400
63
+ and info.st_size <= MAX_BYTES, "context evidence must be a bounded regular file")
64
+ with os.fdopen(descriptor, "rb", closefd=False) as handle:
65
+ raw = handle.read(MAX_BYTES + 1)
66
+ _require(len(raw) <= MAX_BYTES, "context evidence is oversized")
67
+ return raw
68
+ finally:
69
+ os.close(descriptor)
70
+
71
+
72
+ def _legacy(raw):
73
+ record = _decode(raw)
74
+ _require(valid_provenance_record(record) and record["schema"] == 1
75
+ and record["doc"] == "code-map", "legacy code-map provenance required; native ownership is not recoverable here")
76
+
77
+
78
+ def _snapshot(requested_root):
79
+ root = _trusted_directory(requested_root, "UNSAFE_CONTEXT_ROOT")
80
+ actual = Path(_git(root, "rev-parse", "--show-toplevel").decode().strip()).resolve(strict=True)
81
+ _require(actual == root, "explicit repository root required")
82
+ git_dir = _trusted_directory(
83
+ _git(root, "rev-parse", "--absolute-git-dir").decode().strip(), "UNSAFE_GIT_DIRECTORY")
84
+ index = Path(_git(root, "rev-parse", "--path-format=absolute", "--git-path", "index").decode().strip())
85
+ head = _git(root, "rev-parse", "--verify", "HEAD^{commit}").decode().strip()
86
+ incoming = _read(git_dir / "MERGE_HEAD").decode().strip()
87
+ _require(re.fullmatch(OID, head) and re.fullmatch(OID, incoming), "one current merge head required")
88
+ records = _git(root, "ls-files", "--unmerged", "-z", "--", TARGET).split(b"\0")
89
+ stages = []
90
+ for raw in records:
91
+ if raw:
92
+ matched = re.fullmatch(r"100644 (" + OID + r") ([123])\t" + re.escape(TARGET), raw.decode())
93
+ _require(matched is not None, "regular code-map conflict stages required")
94
+ stages.append((matched[2], matched[1]))
95
+ _require([stage for stage, _oid in stages] == ["1", "2", "3"], "complete three-stage code-map conflict required")
96
+ base = _git(root, "merge-base", "--all", head, incoming).decode().strip()
97
+ _require(re.fullmatch(OID, base), "one unambiguous merge base required")
98
+ for revision, (_stage, oid) in zip((base, head, incoming), stages):
99
+ _require(_git(root, "rev-parse", revision + ":" + TARGET).decode().strip() == oid,
100
+ "index conflict no longer matches the current merge")
101
+ current = _read(root / TARGET)
102
+ ours = _git(root, "cat-file", "blob", stages[1][1])
103
+ theirs = _git(root, "cat-file", "blob", stages[2][1])
104
+ # Reuse the existing single-conflict renderer check. Unsupported renderings
105
+ # (including a non-empty diff3 base) refuse rather than discarding human text.
106
+ _validate_conflicted_worktree(current, b"", ours, theirs)
107
+ provenance = _read(root / PROVENANCE)
108
+ _legacy(provenance)
109
+ for revision in (base, head, incoming):
110
+ _legacy(_git(root, "cat-file", "blob", revision + ":" + PROVENANCE))
111
+ for relative in (".codearbiter/.artifacts", ".codearbiter/.artifacts/transactions"):
112
+ if os.path.lexists(root / relative):
113
+ _trusted_directory(root / relative, "UNSAFE_CONTEXT_JOURNAL")
114
+ _require(_committed_context_journal(root, "code-map", TARGET) is False,
115
+ "native or uncertain context ownership requires its writer")
116
+ binding = {"root": str(root), "git_dir": str(git_dir), "head": head, "merge_head": incoming,
117
+ "stages": stages, "index_sha256": _hash(_read(index)),
118
+ "worktree_sha256": _hash(current), "provenance_sha256": _hash(provenance)}
119
+ digest = _hash(json.dumps(binding, sort_keys=True, separators=(",", ":")).encode())
120
+ return root, index, current, ours, {"target": TARGET, "head": head, "merge_head": incoming,
121
+ "head_sha256": _hash(ours), "binding": digest}
122
+
123
+
124
+ def inspect(root):
125
+ return _snapshot(root)[-1]
126
+
127
+
128
+ def restore_head(root, expected):
129
+ _require(isinstance(expected, str) and re.fullmatch(r"[0-9a-f]{64}", expected), "exact inspection binding required")
130
+ root, index, _before, _ours, initial = _snapshot(root)
131
+ _require(initial["binding"] == expected, "stale context conflict binding; inspect again")
132
+ # Git's own lock blocks cooperative index writers during replacement. It is
133
+ # removed on exit; the index itself and all unmerged stages stay byte-identical.
134
+ lock_path = Path(str(index) + ".lock")
135
+ descriptor = os.open(lock_path, os.O_WRONLY | os.O_CREAT | os.O_EXCL, 0o600)
136
+ try:
137
+ root, _index, before, ours, fresh = _snapshot(root)
138
+ _require(fresh["binding"] == expected, "stale context conflict binding; inspect again")
139
+ _write_bytes_atomic(root / TARGET, ours, expected=before)
140
+ finally:
141
+ os.close(descriptor)
142
+ lock_path.unlink()
143
+ return {**fresh, "status": "restored", "staged": False}
144
+
145
+
146
+ def main(argv=None):
147
+ parser = argparse.ArgumentParser(description="Recover only the exact HEAD-side legacy code-map in a current Git conflict.")
148
+ parser.add_argument("--root", required=True)
149
+ operations = parser.add_subparsers(dest="operation", required=True)
150
+ operations.add_parser("inspect")
151
+ restore = operations.add_parser("restore-head")
152
+ restore.add_argument("--expected", required=True)
153
+ args = parser.parse_args(argv)
154
+ try:
155
+ result = inspect(args.root) if args.operation == "inspect" else restore_head(args.root, args.expected)
156
+ except (OSError, ValueError, RuntimeError, ArtifactError, subprocess.SubprocessError):
157
+ print("context conflict recovery refused: absent, changed, unsafe or unsupported conflict evidence", file=sys.stderr)
158
+ return 1
159
+ print(json.dumps(result, sort_keys=True))
160
+ return 0
@@ -801,6 +801,8 @@ def _shim(dropin_dir, phase):
801
801
  f"{_FRESHNESS_PY}"
802
802
  "CODEARBITER_556_FRESHNESS\n"
803
803
  ")\n"
804
+ # Match each line from the probe, including native Windows CRLF output.
805
+ "SKIP=$(printf '%s' \"$SKIP\" | tr '\\r\\n' ' ')\n"
804
806
  "SEEN=0\n"
805
807
  'for c in "$D"/*.path; do\n'
806
808
  ' [ -f "$c" ] || continue\n'
@@ -11,7 +11,7 @@ import hostapi # noqa: E402
11
11
  class PiHost(hostapi.Host):
12
12
  name = "pi"
13
13
  adapter_name = "@arbiterforge/ca-pi"
14
- adapter_version = "0.16.5"
14
+ adapter_version = "0.17.0"
15
15
  update_target = "ca-pi"
16
16
  update_tag_prefix = "ca-pi-v"
17
17
  update_command = "pi update npm:@arbiterforge/ca-pi"