hapax-agentgov 0.2.0__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.
Files changed (31) hide show
  1. hapax_agentgov-0.2.0/.gitignore +76 -0
  2. hapax_agentgov-0.2.0/LICENSE +21 -0
  3. hapax_agentgov-0.2.0/PKG-INFO +166 -0
  4. hapax_agentgov-0.2.0/README.md +135 -0
  5. hapax_agentgov-0.2.0/pyproject.toml +62 -0
  6. hapax_agentgov-0.2.0/src/agentgov/__init__.py +104 -0
  7. hapax_agentgov-0.2.0/src/agentgov/agent_governor.py +129 -0
  8. hapax_agentgov-0.2.0/src/agentgov/carrier.py +138 -0
  9. hapax_agentgov-0.2.0/src/agentgov/consent.py +316 -0
  10. hapax_agentgov-0.2.0/src/agentgov/consent_label.py +56 -0
  11. hapax_agentgov-0.2.0/src/agentgov/governor.py +142 -0
  12. hapax_agentgov-0.2.0/src/agentgov/hooks.py +227 -0
  13. hapax_agentgov-0.2.0/src/agentgov/labeled.py +81 -0
  14. hapax_agentgov-0.2.0/src/agentgov/primitives.py +150 -0
  15. hapax_agentgov-0.2.0/src/agentgov/principal.py +69 -0
  16. hapax_agentgov-0.2.0/src/agentgov/provenance.py +135 -0
  17. hapax_agentgov-0.2.0/src/agentgov/py.typed +0 -0
  18. hapax_agentgov-0.2.0/src/agentgov/revocation.py +95 -0
  19. hapax_agentgov-0.2.0/src/agentgov/says.py +85 -0
  20. hapax_agentgov-0.2.0/tests/__init__.py +0 -0
  21. hapax_agentgov-0.2.0/tests/strategies.py +64 -0
  22. hapax_agentgov-0.2.0/tests/test_carrier.py +71 -0
  23. hapax_agentgov-0.2.0/tests/test_consent_label.py +88 -0
  24. hapax_agentgov-0.2.0/tests/test_governor.py +80 -0
  25. hapax_agentgov-0.2.0/tests/test_hooks.py +87 -0
  26. hapax_agentgov-0.2.0/tests/test_primitives.py +73 -0
  27. hapax_agentgov-0.2.0/tests/test_principal.py +103 -0
  28. hapax_agentgov-0.2.0/tests/test_provenance.py +116 -0
  29. hapax_agentgov-0.2.0/tests/test_revocation.py +68 -0
  30. hapax_agentgov-0.2.0/tests/test_says.py +86 -0
  31. hapax_agentgov-0.2.0/uv.lock +213 -0
@@ -0,0 +1,76 @@
1
+ # Python-generated files
2
+ __pycache__/
3
+ *.py[oc]
4
+ build/
5
+ dist/
6
+ wheels/
7
+ *.egg-info
8
+
9
+ # Virtual environments
10
+ .venv
11
+
12
+ # Secrets
13
+ .env
14
+ .envrc
15
+
16
+ # Profile outputs (generated, may contain personal data)
17
+ # Use ** to match subdirectories (engine-audit/, deliberations/, etc.)
18
+ profiles/**/*.json
19
+ profiles/**/*.md
20
+ profiles/**/*.jsonl
21
+ profiles/**/*.yaml
22
+ !profiles/presenter-style.yaml
23
+ !profiles/component-registry.yaml
24
+ !profiles/demo-audiences.yaml
25
+ !profiles/workflow-registry.yaml
26
+ profiles/**/*.bak
27
+ profiles/**/*.db
28
+ profiles/.quarantine/*
29
+ !profiles/.quarantine/.gitkeep
30
+
31
+ # SQLite WAL/SHM files
32
+ *.db-wal
33
+ *.db-shm
34
+
35
+ # Playwright MCP cache
36
+ .playwright-mcp/
37
+ .claude/settings.local.json
38
+ .claude/hookify*.local.md
39
+ .claude/worktrees/
40
+ --Frag*
41
+
42
+ # Demo outputs (generated)
43
+ output/demos/
44
+ .worktrees/
45
+ .venv-ingest/
46
+
47
+ # Wake word training data (large, generated)
48
+ data/wake-word-training/
49
+ .hypothesis/
50
+ plugins/gst-temporalfx/target/
51
+
52
+ # Model weights (large binaries, download on demand)
53
+ *.pt
54
+ *.task
55
+
56
+ # Screenshots / snapshots (generated)
57
+ *.jpeg
58
+ /hapax-visual/
59
+
60
+ # Temp profiles
61
+ profiles/tmp*
62
+
63
+ # Voice experiment session data (contains operator interactions)
64
+ agents/hapax_daimonion/proofs/**/data/
65
+
66
+ # Screenshots (smoke tests, stress tests, explorations)
67
+ *.png
68
+ # Committed test golden images (cairo render regression pins)
69
+ !tests/studio_compositor/golden_images/*.png
70
+ .claude/settings.json
71
+ /plugins/gst-crossfade/target/
72
+ /plugins/gst-smooth-delay/target/
73
+ docs/superpowers/plans/2026-03-29-hapax-obsidian-v2-plan-full.md
74
+ .superpowers/
75
+ gst-plugin-glfeedback/target/
76
+ .compositor-inspect/
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Ryan Lee
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,166 @@
1
+ Metadata-Version: 2.4
2
+ Name: hapax-agentgov
3
+ Version: 0.2.0
4
+ Summary: Computational constitutional governance for AI agent systems
5
+ Project-URL: Homepage, https://github.com/hapax-systems/agentgov
6
+ Project-URL: Documentation, https://github.com/hapax-systems/agentgov#readme
7
+ Project-URL: Repository, https://github.com/hapax-systems/agentgov
8
+ Project-URL: Issues, https://github.com/hapax-systems/agentgov/issues
9
+ Author-email: Ryan Lee <rylklee@gmail.com>
10
+ License-Expression: MIT
11
+ License-File: LICENSE
12
+ Keywords: access-control,agents,consent,governance,information-flow,multi-agent
13
+ Classifier: Development Status :: 4 - Beta
14
+ Classifier: Intended Audience :: Developers
15
+ Classifier: Intended Audience :: Science/Research
16
+ Classifier: License :: OSI Approved :: MIT License
17
+ Classifier: Programming Language :: Python :: 3
18
+ Classifier: Programming Language :: Python :: 3.12
19
+ Classifier: Programming Language :: Python :: 3.13
20
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
21
+ Classifier: Topic :: Security
22
+ Classifier: Typing :: Typed
23
+ Requires-Python: >=3.12
24
+ Requires-Dist: pyyaml>=6.0
25
+ Provides-Extra: dev
26
+ Requires-Dist: hypothesis>=6.0; extra == 'dev'
27
+ Requires-Dist: pyright>=1.1; extra == 'dev'
28
+ Requires-Dist: pytest>=8.0; extra == 'dev'
29
+ Requires-Dist: ruff>=0.4; extra == 'dev'
30
+ Description-Content-Type: text/markdown
31
+
32
+ # agentgov
33
+
34
+ [![PyPI](https://img.shields.io/pypi/v/hapax-agentgov)](https://pypi.org/project/hapax-agentgov/)
35
+ [![License: MIT](https://img.shields.io/badge/license-MIT-blue)](LICENSE)
36
+
37
+ Computational constitutional governance for AI agent systems.
38
+
39
+ agentgov provides algebraically-verified primitives for governing multi-agent systems: consent contracts, information flow control, principal delegation, provenance tracking, and compositional policy enforcement. Zero dependencies beyond PyYAML. Extracted from [hapax-council](https://github.com/hapax-systems/hapax-council), where it governs 200+ AI agents in production.
40
+
41
+ ## Install
42
+
43
+ ```bash
44
+ pip install hapax-agentgov
45
+ ```
46
+
47
+ ## Core Concepts
48
+
49
+ ### Principals
50
+
51
+ Actors in the system. Sovereign principals (humans) originate consent; bound principals (agents) operate under delegated authority with non-amplification guarantees.
52
+
53
+ ```python
54
+ from agentgov import Principal, PrincipalKind
55
+
56
+ operator = Principal(id="operator", kind=PrincipalKind.SOVEREIGN)
57
+ agent = operator.delegate("sync-agent", frozenset({"email", "calendar"}))
58
+ sub = agent.delegate("sub-agent", frozenset({"email"})) # narrows authority
59
+ ```
60
+
61
+ ### Consent Labels (DLM Join-Semilattice)
62
+
63
+ Information flow labels track who may read data. Labels combine via join — combining data with different consent requirements produces the most restrictive combination.
64
+
65
+ ```python
66
+ from agentgov import ConsentLabel
67
+
68
+ public = ConsentLabel.bottom() # no restrictions
69
+ restricted = ConsentLabel(frozenset({("alice", frozenset({"bob"}))}))
70
+ combined = public.join(restricted) # most restrictive wins
71
+ assert public.can_flow_to(combined) # less restrictive flows to more
72
+ ```
73
+
74
+ ### Labeled Values (LIO-Style)
75
+
76
+ Wrap any value with its consent label and why-provenance.
77
+
78
+ ```python
79
+ from agentgov import Labeled, ConsentLabel
80
+
81
+ data = Labeled(value="secret", label=restricted, provenance=frozenset({"contract-1"}))
82
+ transformed = data.map(str.upper) # label preserved through transformations
83
+ ```
84
+
85
+ ### Provenance Semirings
86
+
87
+ Track WHY data exists using algebraic provenance (Green et al., PODS 2007). Supports tensor (both required) and plus (either sufficient) composition.
88
+
89
+ ```python
90
+ from agentgov import ProvenanceExpr
91
+
92
+ combined = ProvenanceExpr.leaf("c1").tensor(ProvenanceExpr.leaf("c2"))
93
+ assert combined.evaluate(frozenset({"c1", "c2"})) # both active: survives
94
+ assert not combined.evaluate(frozenset({"c1"})) # one revoked: purged
95
+ ```
96
+
97
+ ### Governor (Per-Agent Policy Enforcement)
98
+
99
+ Each agent gets a governance wrapper that validates inputs/outputs at boundaries. Pure validation layer — allows or denies, never modifies.
100
+
101
+ ```python
102
+ from agentgov import GovernorWrapper, GovernorPolicy, Labeled, ConsentLabel
103
+
104
+ gov = GovernorWrapper("my-agent")
105
+ gov.add_input_policy(GovernorPolicy(
106
+ name="require-consent",
107
+ check=lambda agent_id, data: data.label != ConsentLabel.bottom(),
108
+ axiom_id="consent",
109
+ ))
110
+ result = gov.check_input(Labeled(value="data", label=ConsentLabel.bottom()))
111
+ assert not result.allowed
112
+ ```
113
+
114
+ ### VetoChain (Deny-Wins Composition)
115
+
116
+ Order-independent constraint composition. Any denial blocks the action.
117
+
118
+ ```python
119
+ from agentgov import VetoChain, Veto
120
+
121
+ chain = VetoChain([
122
+ Veto("budget", lambda ctx: ctx["budget"] > 0),
123
+ Veto("auth", lambda ctx: ctx["authenticated"]),
124
+ ])
125
+ result = chain.evaluate({"budget": 100, "authenticated": False})
126
+ assert not result.allowed
127
+ assert "auth" in result.denied_by
128
+ ```
129
+
130
+ ### Says Monad (DCC Attribution)
131
+
132
+ Principal-annotated assertions following Abadi's DCC formalism. Threads authority through data transformations.
133
+
134
+ ```python
135
+ from agentgov import Says, Principal, PrincipalKind
136
+
137
+ operator = Principal(id="op", kind=PrincipalKind.SOVEREIGN)
138
+ assertion = Says.unit(operator, "approved")
139
+ delegated = assertion.handoff(operator.delegate("agent", frozenset({"approve"})))
140
+ ```
141
+
142
+ ### Revocation Cascade
143
+
144
+ When a consent contract is revoked, all data whose provenance includes that contract is automatically purged across registered subsystems.
145
+
146
+ ```python
147
+ from agentgov import ConsentRegistry, RevocationPropagator, CarrierRegistry
148
+
149
+ registry = ConsentRegistry()
150
+ propagator = RevocationPropagator(registry)
151
+ propagator.register_carrier_registry(carrier_reg)
152
+ report = propagator.revoke("alice") # cascading purge
153
+ ```
154
+
155
+ ## Algebraic Properties (Hypothesis-Verified)
156
+
157
+ - **ConsentLabel**: join-semilattice (associative, commutative, idempotent, bottom identity)
158
+ - **Labeled[T]**: functor laws (identity, composition)
159
+ - **Principal**: non-amplification (bound authority <= delegator authority)
160
+ - **ProvenanceExpr**: PosBool(X) semiring (plus/tensor commutativity, associativity, distributivity, annihilation)
161
+ - **VetoChain**: monotonic (adding vetoes only restricts, never permits)
162
+ - **Governor**: consistent with can_flow_to
163
+
164
+ ## License
165
+
166
+ MIT
@@ -0,0 +1,135 @@
1
+ # agentgov
2
+
3
+ [![PyPI](https://img.shields.io/pypi/v/hapax-agentgov)](https://pypi.org/project/hapax-agentgov/)
4
+ [![License: MIT](https://img.shields.io/badge/license-MIT-blue)](LICENSE)
5
+
6
+ Computational constitutional governance for AI agent systems.
7
+
8
+ agentgov provides algebraically-verified primitives for governing multi-agent systems: consent contracts, information flow control, principal delegation, provenance tracking, and compositional policy enforcement. Zero dependencies beyond PyYAML. Extracted from [hapax-council](https://github.com/hapax-systems/hapax-council), where it governs 200+ AI agents in production.
9
+
10
+ ## Install
11
+
12
+ ```bash
13
+ pip install hapax-agentgov
14
+ ```
15
+
16
+ ## Core Concepts
17
+
18
+ ### Principals
19
+
20
+ Actors in the system. Sovereign principals (humans) originate consent; bound principals (agents) operate under delegated authority with non-amplification guarantees.
21
+
22
+ ```python
23
+ from agentgov import Principal, PrincipalKind
24
+
25
+ operator = Principal(id="operator", kind=PrincipalKind.SOVEREIGN)
26
+ agent = operator.delegate("sync-agent", frozenset({"email", "calendar"}))
27
+ sub = agent.delegate("sub-agent", frozenset({"email"})) # narrows authority
28
+ ```
29
+
30
+ ### Consent Labels (DLM Join-Semilattice)
31
+
32
+ Information flow labels track who may read data. Labels combine via join — combining data with different consent requirements produces the most restrictive combination.
33
+
34
+ ```python
35
+ from agentgov import ConsentLabel
36
+
37
+ public = ConsentLabel.bottom() # no restrictions
38
+ restricted = ConsentLabel(frozenset({("alice", frozenset({"bob"}))}))
39
+ combined = public.join(restricted) # most restrictive wins
40
+ assert public.can_flow_to(combined) # less restrictive flows to more
41
+ ```
42
+
43
+ ### Labeled Values (LIO-Style)
44
+
45
+ Wrap any value with its consent label and why-provenance.
46
+
47
+ ```python
48
+ from agentgov import Labeled, ConsentLabel
49
+
50
+ data = Labeled(value="secret", label=restricted, provenance=frozenset({"contract-1"}))
51
+ transformed = data.map(str.upper) # label preserved through transformations
52
+ ```
53
+
54
+ ### Provenance Semirings
55
+
56
+ Track WHY data exists using algebraic provenance (Green et al., PODS 2007). Supports tensor (both required) and plus (either sufficient) composition.
57
+
58
+ ```python
59
+ from agentgov import ProvenanceExpr
60
+
61
+ combined = ProvenanceExpr.leaf("c1").tensor(ProvenanceExpr.leaf("c2"))
62
+ assert combined.evaluate(frozenset({"c1", "c2"})) # both active: survives
63
+ assert not combined.evaluate(frozenset({"c1"})) # one revoked: purged
64
+ ```
65
+
66
+ ### Governor (Per-Agent Policy Enforcement)
67
+
68
+ Each agent gets a governance wrapper that validates inputs/outputs at boundaries. Pure validation layer — allows or denies, never modifies.
69
+
70
+ ```python
71
+ from agentgov import GovernorWrapper, GovernorPolicy, Labeled, ConsentLabel
72
+
73
+ gov = GovernorWrapper("my-agent")
74
+ gov.add_input_policy(GovernorPolicy(
75
+ name="require-consent",
76
+ check=lambda agent_id, data: data.label != ConsentLabel.bottom(),
77
+ axiom_id="consent",
78
+ ))
79
+ result = gov.check_input(Labeled(value="data", label=ConsentLabel.bottom()))
80
+ assert not result.allowed
81
+ ```
82
+
83
+ ### VetoChain (Deny-Wins Composition)
84
+
85
+ Order-independent constraint composition. Any denial blocks the action.
86
+
87
+ ```python
88
+ from agentgov import VetoChain, Veto
89
+
90
+ chain = VetoChain([
91
+ Veto("budget", lambda ctx: ctx["budget"] > 0),
92
+ Veto("auth", lambda ctx: ctx["authenticated"]),
93
+ ])
94
+ result = chain.evaluate({"budget": 100, "authenticated": False})
95
+ assert not result.allowed
96
+ assert "auth" in result.denied_by
97
+ ```
98
+
99
+ ### Says Monad (DCC Attribution)
100
+
101
+ Principal-annotated assertions following Abadi's DCC formalism. Threads authority through data transformations.
102
+
103
+ ```python
104
+ from agentgov import Says, Principal, PrincipalKind
105
+
106
+ operator = Principal(id="op", kind=PrincipalKind.SOVEREIGN)
107
+ assertion = Says.unit(operator, "approved")
108
+ delegated = assertion.handoff(operator.delegate("agent", frozenset({"approve"})))
109
+ ```
110
+
111
+ ### Revocation Cascade
112
+
113
+ When a consent contract is revoked, all data whose provenance includes that contract is automatically purged across registered subsystems.
114
+
115
+ ```python
116
+ from agentgov import ConsentRegistry, RevocationPropagator, CarrierRegistry
117
+
118
+ registry = ConsentRegistry()
119
+ propagator = RevocationPropagator(registry)
120
+ propagator.register_carrier_registry(carrier_reg)
121
+ report = propagator.revoke("alice") # cascading purge
122
+ ```
123
+
124
+ ## Algebraic Properties (Hypothesis-Verified)
125
+
126
+ - **ConsentLabel**: join-semilattice (associative, commutative, idempotent, bottom identity)
127
+ - **Labeled[T]**: functor laws (identity, composition)
128
+ - **Principal**: non-amplification (bound authority <= delegator authority)
129
+ - **ProvenanceExpr**: PosBool(X) semiring (plus/tensor commutativity, associativity, distributivity, annihilation)
130
+ - **VetoChain**: monotonic (adding vetoes only restricts, never permits)
131
+ - **Governor**: consistent with can_flow_to
132
+
133
+ ## License
134
+
135
+ MIT
@@ -0,0 +1,62 @@
1
+ [build-system]
2
+ requires = ["hatchling"]
3
+ build-backend = "hatchling.build"
4
+
5
+ [project]
6
+ name = "hapax-agentgov"
7
+ version = "0.2.0"
8
+ description = "Computational constitutional governance for AI agent systems"
9
+ readme = "README.md"
10
+ license = "MIT"
11
+ requires-python = ">=3.12"
12
+ authors = [{ name = "Ryan Lee", email = "rylklee@gmail.com" }]
13
+ keywords = [
14
+ "governance",
15
+ "consent",
16
+ "agents",
17
+ "multi-agent",
18
+ "information-flow",
19
+ "access-control",
20
+ ]
21
+ classifiers = [
22
+ "Development Status :: 4 - Beta",
23
+ "Intended Audience :: Developers",
24
+ "Intended Audience :: Science/Research",
25
+ "License :: OSI Approved :: MIT License",
26
+ "Programming Language :: Python :: 3",
27
+ "Programming Language :: Python :: 3.12",
28
+ "Programming Language :: Python :: 3.13",
29
+ "Topic :: Scientific/Engineering :: Artificial Intelligence",
30
+ "Topic :: Security",
31
+ "Typing :: Typed",
32
+ ]
33
+ dependencies = ["pyyaml>=6.0"]
34
+
35
+ [project.optional-dependencies]
36
+ dev = ["pytest>=8.0", "hypothesis>=6.0", "ruff>=0.4", "pyright>=1.1"]
37
+
38
+ [project.urls]
39
+ Homepage = "https://github.com/hapax-systems/agentgov"
40
+ Documentation = "https://github.com/hapax-systems/agentgov#readme"
41
+ Repository = "https://github.com/hapax-systems/agentgov"
42
+ Issues = "https://github.com/hapax-systems/agentgov/issues"
43
+
44
+ [tool.hatch.build.targets.wheel]
45
+ packages = ["src/agentgov"]
46
+
47
+ [tool.ruff]
48
+ line-length = 100
49
+ target-version = "py312"
50
+
51
+ [tool.ruff.lint]
52
+ select = ["E", "F", "I", "UP", "B", "SIM"]
53
+
54
+ [tool.ruff.format]
55
+ quote-style = "double"
56
+
57
+ [tool.pyright]
58
+ pythonVersion = "3.12"
59
+ typeCheckingMode = "standard"
60
+
61
+ [tool.pytest.ini_options]
62
+ testpaths = ["tests"]
@@ -0,0 +1,104 @@
1
+ """agentgov — Computational constitutional governance for AI agent systems.
2
+
3
+ Pure governance logic with algebraic guarantees:
4
+ - ConsentLabel: join-semilattice (associative, commutative, idempotent)
5
+ - Labeled[T]: functor (identity, composition)
6
+ - Principal: non-amplification (bound <= delegator authority)
7
+ - Governor: consistent with can_flow_to
8
+ - ProvenanceExpr: PosBool(X) semiring
9
+ - VetoChain: deny-wins composition
10
+ - Says: DCC-style principal attribution monad
11
+ """
12
+
13
+ from agentgov.agent_governor import create_agent_governor
14
+ from agentgov.carrier import CarrierFact, CarrierRegistry, DisplacementResult
15
+ from agentgov.consent import ConsentContract, ConsentRegistry, load_contracts
16
+ from agentgov.consent_label import ConsentLabel
17
+ from agentgov.governor import (
18
+ GovernorDenial,
19
+ GovernorPolicy,
20
+ GovernorResult,
21
+ GovernorWrapper,
22
+ consent_input_policy,
23
+ consent_output_policy,
24
+ )
25
+ from agentgov.hooks import (
26
+ HookResult,
27
+ scan_attribution_entities,
28
+ scan_management_boundary,
29
+ scan_pii,
30
+ scan_provenance_references,
31
+ scan_single_user_violations,
32
+ validate_all,
33
+ )
34
+ from agentgov.labeled import Labeled
35
+ from agentgov.primitives import (
36
+ Candidate,
37
+ FallbackChain,
38
+ GatedResult,
39
+ Selected,
40
+ Veto,
41
+ VetoChain,
42
+ VetoResult,
43
+ )
44
+ from agentgov.principal import Principal, PrincipalKind
45
+ from agentgov.provenance import ProvenanceExpr
46
+ from agentgov.revocation import (
47
+ PurgeResult,
48
+ RevocationPropagator,
49
+ RevocationReport,
50
+ check_provenance,
51
+ )
52
+ from agentgov.says import Says
53
+
54
+ __version__ = "0.2.0"
55
+
56
+ __all__ = [
57
+ # Principal model
58
+ "Principal",
59
+ "PrincipalKind",
60
+ # Consent
61
+ "ConsentContract",
62
+ "ConsentRegistry",
63
+ "ConsentLabel",
64
+ "load_contracts",
65
+ # Labeled data
66
+ "Labeled",
67
+ # Provenance
68
+ "ProvenanceExpr",
69
+ # Carrier dynamics
70
+ "CarrierFact",
71
+ "CarrierRegistry",
72
+ "DisplacementResult",
73
+ # Governor
74
+ "GovernorWrapper",
75
+ "GovernorPolicy",
76
+ "GovernorResult",
77
+ "GovernorDenial",
78
+ "consent_input_policy",
79
+ "consent_output_policy",
80
+ "create_agent_governor",
81
+ # Revocation cascade
82
+ "RevocationPropagator",
83
+ "RevocationReport",
84
+ "PurgeResult",
85
+ "check_provenance",
86
+ # Compositional primitives
87
+ "Candidate",
88
+ "FallbackChain",
89
+ "GatedResult",
90
+ "Selected",
91
+ "Veto",
92
+ "VetoChain",
93
+ "VetoResult",
94
+ # Says monad
95
+ "Says",
96
+ # Governance hooks
97
+ "HookResult",
98
+ "scan_pii",
99
+ "scan_single_user_violations",
100
+ "scan_attribution_entities",
101
+ "scan_provenance_references",
102
+ "scan_management_boundary",
103
+ "validate_all",
104
+ ]
@@ -0,0 +1,129 @@
1
+ """Agent governor factory: builds GovernorWrapper from axiom bindings.
2
+
3
+ Translates declarative axiom bindings in agent manifests into runtime
4
+ governance policies. Each agent gets a GovernorWrapper configured with
5
+ input/output policies derived from its axiom relationships.
6
+ """
7
+
8
+ from __future__ import annotations
9
+
10
+ import logging
11
+ from collections.abc import Callable
12
+ from typing import Any
13
+
14
+ from agentgov.consent_label import ConsentLabel
15
+ from agentgov.governor import (
16
+ GovernorPolicy,
17
+ GovernorWrapper,
18
+ consent_input_policy,
19
+ consent_output_policy,
20
+ )
21
+ from agentgov.labeled import Labeled
22
+
23
+ _log = logging.getLogger(__name__)
24
+
25
+ PolicyBuilder = Callable[[str], tuple[list[GovernorPolicy], list[GovernorPolicy]]]
26
+
27
+
28
+ def interpersonal_transparency_policies(
29
+ role: str,
30
+ ) -> tuple[list[GovernorPolicy], list[GovernorPolicy]]:
31
+ """Build policies for the interpersonal_transparency axiom."""
32
+ input_policies: list[GovernorPolicy] = []
33
+ output_policies: list[GovernorPolicy] = []
34
+
35
+ if role in ("subject", "enforcer"):
36
+ input_policies.append(consent_input_policy(ConsentLabel.bottom()))
37
+ output_policies.append(consent_output_policy(ConsentLabel.bottom()))
38
+
39
+ return input_policies, output_policies
40
+
41
+
42
+ def corporate_boundary_policies(
43
+ role: str,
44
+ ) -> tuple[list[GovernorPolicy], list[GovernorPolicy]]:
45
+ """Build policies for the corporate_boundary axiom."""
46
+ input_policies: list[GovernorPolicy] = []
47
+ output_policies: list[GovernorPolicy] = []
48
+
49
+ if role in ("subject", "enforcer"):
50
+
51
+ def _no_work_data(_agent_id: str, data: Labeled[Any]) -> bool:
52
+ if not (hasattr(data, "metadata") and isinstance(data.metadata, dict)):
53
+ _log.warning("corporate_boundary: denying data with no metadata dict (fail-closed)")
54
+ return False
55
+ category = data.metadata.get("data_category")
56
+ if category is None:
57
+ _log.warning(
58
+ "corporate_boundary: denying data with no data_category key (fail-closed)"
59
+ )
60
+ return False
61
+ return category != "work"
62
+
63
+ output_policies.append(
64
+ GovernorPolicy(
65
+ name="corporate_boundary_output",
66
+ check=_no_work_data,
67
+ axiom_id="corporate_boundary",
68
+ description="Block work data from persisting to home system",
69
+ )
70
+ )
71
+
72
+ return input_policies, output_policies
73
+
74
+
75
+ DEFAULT_AXIOM_BUILDERS: dict[str, PolicyBuilder] = {
76
+ "interpersonal_transparency": interpersonal_transparency_policies,
77
+ "corporate_boundary": corporate_boundary_policies,
78
+ }
79
+
80
+
81
+ def create_agent_governor(
82
+ agent_id: str,
83
+ axiom_bindings: list[dict[str, Any]] | None = None,
84
+ *,
85
+ axiom_builders: dict[str, PolicyBuilder] | None = None,
86
+ binding_loader: Callable[[str], list[Any]] | None = None,
87
+ ) -> GovernorWrapper:
88
+ """Build a GovernorWrapper from agent manifest axiom bindings.
89
+
90
+ Args:
91
+ agent_id: Agent identifier.
92
+ axiom_bindings: List of binding dicts with keys 'axiom_id', 'role'.
93
+ axiom_builders: Custom axiom-to-policy mapping. Defaults to
94
+ built-in interpersonal_transparency and corporate_boundary.
95
+ binding_loader: Optional callable to load bindings from an
96
+ external registry when axiom_bindings is None.
97
+ """
98
+ gov = GovernorWrapper(agent_id)
99
+ builders = axiom_builders or DEFAULT_AXIOM_BUILDERS
100
+
101
+ bindings = axiom_bindings
102
+ if bindings is None and binding_loader is not None:
103
+ bindings = binding_loader(agent_id)
104
+ if bindings is None:
105
+ bindings = []
106
+
107
+ for binding in bindings:
108
+ axiom_id = binding.get("axiom_id", "") if isinstance(binding, dict) else binding.axiom_id
109
+ role = binding.get("role", "subject") if isinstance(binding, dict) else binding.role
110
+
111
+ builder = builders.get(axiom_id)
112
+ if builder is None:
113
+ continue
114
+
115
+ input_policies, output_policies = builder(role)
116
+ for p in input_policies:
117
+ gov.add_input_policy(p)
118
+ for p in output_policies:
119
+ gov.add_output_policy(p)
120
+
121
+ _log.debug(
122
+ "Governor %s: added %d input + %d output policies for %s",
123
+ agent_id,
124
+ len(input_policies),
125
+ len(output_policies),
126
+ axiom_id,
127
+ )
128
+
129
+ return gov