f211ece6bf
CI runs `pyright .` over the whole repo including tests; the earlier run only checked the source paths. The test helpers used `**over` dict-splat into typed constructors, which pyright strict rejects. - forge_state: build a typed ForgeState base and dataclasses.replace(**over) - provenance: explicit typed keyword params instead of a **over dict - resume: _launch_kwargs returns dict[str, Any] (copy call_args.kwargs) - forge_base: assert PermissionError in __mro__ (avoids always-true issubclass) - client: annotate _resp body param; type: ignore the mock __enter__ lambda pyright . now 0 errors; 47 tests still pass; pylint 9.97/10. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WL77TgFxKbs3cidGMG9dz7
95 lines
3.2 KiB
Python
95 lines
3.2 KiB
Python
"""Unit: provenance footer (PRD forge-native-integration)."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import unittest
|
|
|
|
from bot_bottle.contrib.gitea.provenance import build_provenance_footer
|
|
|
|
|
|
def _footer(
|
|
slug: str = "implementer-abc12",
|
|
*,
|
|
agent_name: str = "implementer",
|
|
bottle_names: tuple[str, ...] = ("claude",),
|
|
started_at: str = "2026-06-29T12:00:00-04:00",
|
|
finished_at: str = "2026-06-29T12:04:12-04:00",
|
|
exit_code: int = 0,
|
|
watchdog_fired: bool = False,
|
|
gitleaks_clean: bool | None = None,
|
|
egress_routes: list[str] | None = None,
|
|
) -> str:
|
|
return build_provenance_footer(
|
|
slug,
|
|
agent_name=agent_name,
|
|
bottle_names=bottle_names,
|
|
started_at=started_at,
|
|
finished_at=finished_at,
|
|
exit_code=exit_code,
|
|
watchdog_fired=watchdog_fired,
|
|
gitleaks_clean=gitleaks_clean,
|
|
egress_routes=egress_routes,
|
|
)
|
|
|
|
|
|
class ProvenanceTest(unittest.TestCase):
|
|
def test_required_fields_present(self):
|
|
out = _footer()
|
|
for token in ("Run provenance", "`implementer`", "`claude`",
|
|
"`implementer-abc12`", "| exit | 0 ✓ |"):
|
|
self.assertIn(token, out)
|
|
|
|
def test_collapsed_details_block(self):
|
|
out = _footer()
|
|
self.assertTrue(out.startswith("<details>"))
|
|
self.assertIn("</details>", out)
|
|
|
|
def test_duration_minutes_seconds(self):
|
|
self.assertIn("| duration | 4m 12s |", _footer())
|
|
|
|
def test_duration_under_a_minute(self):
|
|
out = _footer(finished_at="2026-06-29T12:00:30-04:00")
|
|
self.assertIn("| duration | 30s |", out)
|
|
|
|
def test_duration_unknown_on_bad_timestamp(self):
|
|
out = _footer(finished_at="not-a-time")
|
|
self.assertIn("| duration | unknown |", out)
|
|
|
|
def test_nonzero_exit_marked(self):
|
|
self.assertIn("| exit | 1 ✗ |", _footer(exit_code=1))
|
|
|
|
def test_watchdog_changes_done_signal_row(self):
|
|
normal = _footer()
|
|
self.assertIn("sidecar `signal_done`", normal)
|
|
fired = _footer(watchdog_fired=True)
|
|
self.assertIn("watchdog — agent did not signal", fired)
|
|
self.assertNotIn("sidecar `signal_done`", fired)
|
|
|
|
def test_gitleaks_states(self):
|
|
self.assertIn("not run", _footer())
|
|
self.assertIn("✓ no secrets detected", _footer(gitleaks_clean=True))
|
|
self.assertIn("✗ secrets detected", _footer(gitleaks_clean=False))
|
|
|
|
def test_egress_omitted_when_absent(self):
|
|
self.assertNotIn("**Egress**", _footer())
|
|
|
|
def test_egress_rendered_when_present(self):
|
|
out = _footer(egress_routes=[
|
|
"`api.anthropic.com` — Bearer auth",
|
|
"`pypi.org` — unauthenticated",
|
|
])
|
|
self.assertIn("**Egress** (deny-by-default; 2 routes allowed)", out)
|
|
self.assertIn("- `api.anthropic.com` — Bearer auth", out)
|
|
|
|
def test_egress_singular_route(self):
|
|
out = _footer(egress_routes=["`api.anthropic.com` — Bearer auth"])
|
|
self.assertIn("1 route allowed", out)
|
|
|
|
def test_multiple_bottles_listed(self):
|
|
out = _footer(bottle_names=("claude", "dev"))
|
|
self.assertIn("`claude`, `dev`", out)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|