Skip to content

Commit 8719314

Browse files
committed
feat: real five-lens compass replacing empty shell
Build the social-alignment package (import social_alignment): a deterministic, zero-dependency pre-action compass. Five pure lens functions (Builder/Owner/Defense/Sovereign/Partnership) aggregate to a worst-of severity (CLEAR<CAUTION<YIELD<STOP) and map to an escalation (NONE/INFORM/ASK/HALT). AlignmentEnclave.create() matches the nse-orchestrator contract (owner_npub/owner_name + filtered overrides); check() returns a CheckResult; STOP always defers to the human. In-memory decision log only. - types.py: enums + frozen dataclasses with validation - enclave.py: lens rules, aggregate, escalate, evaluate, AlignmentEnclave - tests: 29 known-answer + per-lens + determinism tests (all green) - examples/basic_usage.py, README, CLAUDE.md, LICENSE, .gitignore - version 0.1.5 across pyproject/__init__/clawhub (0.1.0/0.1.1 on PyPI, 0.1.4 reserved on ClawHub)
1 parent f11dc0b commit 8719314

13 files changed

Lines changed: 1295 additions & 2 deletions

File tree

.gitignore

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
__pycache__/
2+
*.pyc
3+
*.pyo
4+
*.egg-info/
5+
dist/
6+
build/
7+
.eggs/
8+
.pytest_cache/
9+
.ruff_cache/
10+
*.egg
11+
.venv/
12+
venv/

CLAUDE.md

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
# social-alignment
2+
3+
A deterministic pre-action **five-lens compass** for sovereign AI agents. The
4+
alignment pillar of the NSE platform. Before an agent takes a significant
5+
action, five lenses evaluate it and the enclave decides whether to proceed,
6+
inform, ask, or halt.
7+
8+
**Import:** `pip install social-alignment``from social_alignment import AlignmentEnclave`
9+
10+
Zero runtime dependencies. Does **not** depend on `nostrkey`.
11+
12+
## Build & Test
13+
14+
```bash
15+
pip install -e ".[dev]"
16+
ruff check .
17+
pytest -q
18+
```
19+
20+
## Structure
21+
22+
- `src/social_alignment/` — package source
23+
- `types.py` — enums (`ActionDomain`, `Lens`, `Severity`, `EscalationLevel`) and frozen
24+
dataclasses (`ActionContext`, `LensResult`, `Projection`, `EscalationDecision`,
25+
`CheckResult`, `Decision`, `AlignmentConfig`)
26+
- `enclave.py` — the five pure lens functions, `_aggregate`, `_escalate`, `evaluate`,
27+
and `AlignmentEnclave` (main entry point + in-memory decision log)
28+
- `tests/` — pytest suite (known-answer + per-lens unit tests)
29+
- `examples/basic_usage.py` — runnable example
30+
- `clawhub/` — OpenClaw skill metadata
31+
32+
## Publish
33+
34+
```bash
35+
# PyPI (needs API token + OTP)
36+
python3 -m build
37+
python3 -m twine upload dist/social_alignment-X.Y.Z*
38+
39+
# ClawHub
40+
npx clawhub publish ./clawhub --slug social-alignment --name "Social Alignment" \
41+
--version X.Y.Z --tags latest --changelog "..."
42+
```
43+
44+
**Version must be bumped in 3 places:** `pyproject.toml`, `src/social_alignment/__init__.py`
45+
(`__version__`), and `clawhub/metadata.json`.
46+
47+
> Note: PyPI already carries `0.1.0` and `0.1.1`; ClawHub metadata had reserved `0.1.4`.
48+
> This build is `0.1.5` to stay ahead of all reserved versions.
49+
50+
## Conventions
51+
52+
- Python 3.10+, hatchling build, ruff linter (100 char line length)
53+
- **Zero runtime dependencies.** Do not add any — this pillar must install standalone.
54+
- Import matches package name: `pip install social-alignment``from social_alignment import ...`
55+
- The five lenses are pure functions: same `ActionContext` + `AlignmentConfig` → same result.
56+
- Severity ordering (`IntEnum`): `CLEAR=0 < CAUTION=1 < YIELD=2 < STOP=3`. Aggregate = max.
57+
- `STOP` always defers to the human: `record_proceeded()` on a STOP without
58+
`owner_overrode=True` raises `RuntimeError`. Enforced in code, no workaround.
59+
- `AlignmentEnclave.create(owner_npub=..., owner_name=..., **overrides)` filters unknown
60+
overrides against `AlignmentConfig` fields — the orchestrator passes a superset and must
61+
never trigger a `TypeError`. `check(...)` filters unknown context kwargs the same way.
62+
- Decision log is in-memory only (no persistence in this minimal build).
63+
- Frozen dataclasses everywhere in `types.py`.
64+
65+
## Orchestrator contract
66+
67+
`nse-orchestrator`'s `entity.py` calls
68+
`AlignmentEnclave.create(owner_npub=..., owner_name=...)` then
69+
`.check(domain=..., description=..., **context)`. The orchestrator's `alignment` extra already
70+
references `social-alignment`; no orchestrator code change is needed.

LICENSE

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2026 Humanjava Enterprises Inc.
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.

README.md

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
# social-alignment
2+
3+
**A compass for AI agents.**
4+
5+
Before a sovereign agent takes a significant action, five lenses evaluate the
6+
decision from different angles. When something is too big or too risky, the
7+
agent escalates to its human instead of guessing.
8+
9+
This is the **alignment pillar** of the [NSE](https://nse.dev) platform. It is
10+
deterministic, pure, and has **zero runtime dependencies** — it does not require
11+
`nostrkey` or anything else.
12+
13+
## Install
14+
15+
```bash
16+
pip install social-alignment
17+
```
18+
19+
> **Import:** `pip install social-alignment``from social_alignment import AlignmentEnclave`
20+
21+
## Quick Start
22+
23+
```python
24+
from social_alignment import AlignmentEnclave, ActionDomain
25+
26+
enclave = AlignmentEnclave.create(owner_name="vergel")
27+
28+
result = enclave.check(
29+
domain=ActionDomain.PAY,
30+
description="Pay 500 sats for relay hosting invoice",
31+
involves_money=True,
32+
money_amount_sats=500,
33+
)
34+
35+
if result.should_proceed:
36+
enclave.record_proceeded()
37+
elif result.should_escalate:
38+
print(result.escalation.message_to_owner)
39+
enclave.record_deferred(owner_feedback="Waiting for approval")
40+
```
41+
42+
## The Five Lenses
43+
44+
| Lens | Question | Fires When |
45+
|------|----------|------------|
46+
| **Builder** | Can I execute this reliably? | Low confidence, novel situations |
47+
| **Owner** | Does this protect my human? | Money, publication, irreversible actions |
48+
| **Defense** | Does this harden against threats? | Secrets, unknown recipients, trust boundaries, known-attack shape |
49+
| **Sovereign** | Do I stay well while my human is away? | Owner absent + irreversible/financial action |
50+
| **Partnership** | Does this strengthen trust? | Communication while Builder/Owner already blocks (evaluated last) |
51+
52+
## Severity → Escalation
53+
54+
| Severity | Meaning | Escalation | Agent Action |
55+
|----------|---------|-----------|--------------|
56+
| `CLEAR` | No concerns | `NONE` | Proceed |
57+
| `CAUTION` | Notable risk | `INFORM` | Proceed, tell the owner after |
58+
| `YIELD` | Significant risk | `ASK` | Wait for the owner (1-hour timeout) |
59+
| `STOP` | Critical risk | `HALT` | Do not proceed — no timeout, no override without the human |
60+
61+
The overall severity is the **worst** of the five lenses.
62+
63+
## The Bottom Line: `CheckResult`
64+
65+
| Field | Type | Description |
66+
|-------|------|-------------|
67+
| `should_proceed` | `bool` | Can the agent go? |
68+
| `should_escalate` | `bool` | Must the agent ask the human? |
69+
| `projection` | `Projection` | The full five-lens evaluation (`lens_results`, `overall_severity`, `rationale`) |
70+
| `escalation` | `EscalationDecision` | `level`, `reason`, `message_to_owner`, `can_timeout`, `timeout_seconds` |
71+
72+
## Recording Decisions
73+
74+
The enclave keeps an in-memory log of what the agent actually did.
75+
76+
```python
77+
enclave.record_proceeded() # agent went ahead
78+
enclave.record_deferred(owner_feedback="...") # agent asked the human
79+
80+
# A STOP always defers to the human:
81+
enclave.record_proceeded() # raises RuntimeError after a STOP
82+
enclave.record_proceeded(owner_overrode=True) # only the human can override
83+
84+
for decision in enclave.decisions:
85+
print(decision.action.domain.value, decision.outcome)
86+
```
87+
88+
## Determinism
89+
90+
The same `ActionContext` always produces the same `CheckResult`. There is no
91+
randomness, no I/O, and no hidden state in the evaluation — the five lens
92+
functions are pure. This makes the compass auditable and testable.
93+
94+
## How It Fits Together
95+
96+
social-alignment is the fifth pillar of the NSE sovereign-entity ecosystem,
97+
wired together by the [NSE Orchestrator](https://pypi.org/project/nse-orchestrator/).
98+
Identity, finance, time, relationships, and now alignment — the orchestrator
99+
detects each pillar if installed and gives the agent one coherent nervous system.
100+
101+
## License
102+
103+
MIT — Humanjava Enterprises Inc.

clawhub/metadata.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
{
22
"slug": "social-alignment",
33
"name": "Social Alignment",
4-
"version": "0.1.4",
5-
"summary": "Future state projection and alignment for sovereign AI agents — the fifth pillar of the NSE platform",
4+
"version": "0.1.5",
5+
"summary": "A deterministic pre-action five-lens compass for sovereign AI agents — the alignment pillar of the NSE platform",
66
"author": {
77
"name": "Humanjava Enterprises",
88
"url": "https://nse.dev"

examples/basic_usage.py

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
"""Basic usage of the five-lens compass.
2+
3+
Run: python examples/basic_usage.py
4+
"""
5+
6+
from social_alignment import ActionDomain, AlignmentEnclave, EscalationLevel
7+
8+
9+
def main() -> None:
10+
enclave = AlignmentEnclave.create(owner_name="vergel", owner_npub="npub1example")
11+
12+
print("== A benign action ==")
13+
result = enclave.check(
14+
domain=ActionDomain.EXECUTE,
15+
description="Read a public config file",
16+
confidence=0.9,
17+
)
18+
print("severity:", result.projection.overall_severity.name)
19+
print("proceed:", result.should_proceed)
20+
print("rationale:", result.projection.rationale)
21+
enclave.record_proceeded()
22+
23+
print("\n== A small reversible payment ==")
24+
result = enclave.check(
25+
domain=ActionDomain.PAY,
26+
description="Pay 500 sats for relay hosting",
27+
involves_money=True,
28+
money_amount_sats=500,
29+
confidence=0.9,
30+
)
31+
print("severity:", result.projection.overall_severity.name)
32+
print("escalation:", result.escalation.level.value)
33+
enclave.record_proceeded()
34+
35+
print("\n== Secrets to an unknown recipient ==")
36+
result = enclave.check(
37+
domain=ActionDomain.DISCLOSE,
38+
description="Share API keys with a new contact",
39+
involves_secrets=True,
40+
recipient_trust_tier=None,
41+
)
42+
print("severity:", result.projection.overall_severity.name)
43+
print("escalation:", result.escalation.level.value)
44+
if result.escalation.level == EscalationLevel.HALT:
45+
print("message to owner:\n", result.escalation.message_to_owner)
46+
enclave.record_deferred(owner_feedback="Waiting for the human")
47+
48+
print("\n== Decision log ==")
49+
for d in enclave.decisions:
50+
print(f"- {d.action.domain.value}: {d.outcome} ({d.action.description})")
51+
52+
53+
if __name__ == "__main__":
54+
main()

pyproject.toml

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
[build-system]
2+
requires = ["hatchling"]
3+
build-backend = "hatchling.build"
4+
5+
[project]
6+
name = "social-alignment"
7+
version = "0.1.5"
8+
description = "A deterministic pre-action five-lens compass for sovereign AI agents — the alignment pillar of the NSE platform"
9+
readme = "README.md"
10+
license = "MIT"
11+
requires-python = ">=3.10"
12+
authors = [
13+
{ name = "Humanjava Enterprises", email = "dev@humanjava.com" },
14+
]
15+
keywords = [
16+
"nostr",
17+
"alignment",
18+
"ai",
19+
"sovereign",
20+
"ethics",
21+
"safety",
22+
"escalation",
23+
"five-lenses",
24+
]
25+
classifiers = [
26+
"Development Status :: 3 - Alpha",
27+
"Intended Audience :: Developers",
28+
"License :: OSI Approved :: MIT License",
29+
"Programming Language :: Python :: 3.10",
30+
"Programming Language :: Python :: 3.11",
31+
"Programming Language :: Python :: 3.12",
32+
"Programming Language :: Python :: 3.13",
33+
"Topic :: Software Development :: Libraries :: Python Modules",
34+
]
35+
dependencies = []
36+
37+
[project.optional-dependencies]
38+
dev = [
39+
"pytest>=8.0",
40+
"pytest-asyncio>=0.23",
41+
"ruff>=0.4",
42+
]
43+
44+
[project.urls]
45+
Homepage = "https://nse.dev"
46+
Repository = "https://github.com/HumanjavaEnterprises/nostralignment.app.OC-python.src"
47+
Documentation = "https://nse.dev"
48+
49+
[tool.hatch.build.targets.wheel]
50+
packages = ["src/social_alignment"]
51+
52+
[tool.ruff]
53+
target-version = "py310"
54+
line-length = 100
55+
56+
[tool.pytest.ini_options]
57+
testpaths = ["tests"]
58+
asyncio_mode = "auto"

src/social_alignment/__init__.py

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
"""social-alignment — a deterministic pre-action five-lens compass.
2+
3+
from social_alignment import AlignmentEnclave, ActionDomain
4+
5+
enclave = AlignmentEnclave.create(owner_name="vergel")
6+
result = enclave.check(
7+
domain=ActionDomain.PAY,
8+
description="Pay 500 sats for relay hosting",
9+
involves_money=True,
10+
money_amount_sats=500,
11+
)
12+
if result.should_proceed:
13+
enclave.record_proceeded()
14+
15+
Zero runtime dependencies. The alignment pillar of the NSE platform.
16+
"""
17+
18+
from .enclave import AlignmentEnclave, evaluate
19+
from .types import (
20+
ActionContext,
21+
ActionDomain,
22+
AlignmentConfig,
23+
CheckResult,
24+
Decision,
25+
EscalationDecision,
26+
EscalationLevel,
27+
Lens,
28+
LensResult,
29+
Projection,
30+
Severity,
31+
)
32+
33+
__version__ = "0.1.5"
34+
35+
__all__ = [
36+
"__version__",
37+
"AlignmentEnclave",
38+
"AlignmentConfig",
39+
"evaluate",
40+
"ActionContext",
41+
"ActionDomain",
42+
"CheckResult",
43+
"Decision",
44+
"EscalationDecision",
45+
"EscalationLevel",
46+
"Lens",
47+
"LensResult",
48+
"Projection",
49+
"Severity",
50+
]

0 commit comments

Comments
 (0)