Files
ietf-draft-analyzer/workspace/packages/act/tests/test_dag.py
Christian Nennemann 3a139dfc7e feat: ACT/ECT strategy, package restructure, draft -01/-02 prep
Strategic work for IETF submission of draft-nennemann-act-01 and
draft-nennemann-wimse-ect-02:

Package restructure:
- move ACT and ECT refimpls to workspace/packages/{act,ect}/
- ietf-act and ietf-ect distribution names (sibling packages)
- cross-spec interop test plan (INTEROP-TEST-PLAN.md)

ACT draft -01 revisions:
- rename 'par' claim to 'pred' (align with ECT)
- rename 'Agent Compact Token' to 'Agent Context Token' (semantic
  alignment with ECT family)
- add Applicability section (MCP, OpenAI, LangGraph, A2A, CrewAI)
- add DAG vs Linear Delegation Chains section (differentiator vs
  txn-tokens-for-agents actchain, Agentic JWT, AIP/IBCTs)
- add Related Work: AIP, SentinelAgent, Agentic JWT, txn-tokens-for-agents,
  HDP, SCITT-AI-agent-execution
- pin SCITT arch to -22, note AUTH48 status

Outreach drafts:
- Emirdag liaison email (SCITT-AI coordination)
- OAuth ML response on txn-tokens-for-agents-06

Strategy document:
- STRATEGY.md with phased action plan, risk register, timeline

Submodule:
- update workspace/drafts/ietf-wimse-ect pointer to -02 commit
2026-04-12 07:33:08 +02:00

104 lines
3.5 KiB
Python

"""Tests for act.dag module."""
import time
import pytest
from act.dag import validate_dag
from act.errors import ACTCapabilityError, ACTDAGError
from act.ledger import ACTLedger
from act.token import ACTRecord, Capability, TaskClaim
def make_record(jti, pred=None, exec_act="do.thing", exec_ts=None, cap=None):
"""Helper to create a minimal ACTRecord."""
return ACTRecord(
alg="EdDSA", kid="k", iss="a", sub="b", aud="b",
iat=1772064000, exp=1772064900,
jti=jti,
task=TaskClaim(purpose="t"),
cap=cap or [Capability(action="do.thing")],
exec_act=exec_act,
pred=pred or [],
exec_ts=exec_ts or 1772064100,
status="completed",
)
class TestDAGValidation:
def test_root_task(self):
ledger = ACTLedger()
r = make_record("root-1")
validate_dag(r, ledger)
def test_child_with_parent(self):
ledger = ACTLedger()
parent = make_record("parent-1", exec_ts=1772064050)
ledger.append(parent)
child = make_record("child-1", pred=["parent-1"], exec_ts=1772064100)
validate_dag(child, ledger)
def test_fan_in(self):
ledger = ACTLedger()
p1 = make_record("p1", exec_ts=1772064050)
p2 = make_record("p2", exec_ts=1772064060)
ledger.append(p1)
ledger.append(p2)
child = make_record("child", pred=["p1", "p2"], exec_ts=1772064100)
validate_dag(child, ledger)
def test_duplicate_jti(self):
ledger = ACTLedger()
r = make_record("dup-1")
ledger.append(r)
r2 = make_record("dup-1")
with pytest.raises(ACTDAGError, match="Duplicate"):
validate_dag(r2, ledger)
def test_missing_parent(self):
ledger = ACTLedger()
r = make_record("orphan", pred=["nonexistent"])
with pytest.raises(ACTDAGError, match="not found"):
validate_dag(r, ledger)
def test_self_cycle(self):
ledger = ACTLedger()
r = make_record("cycle", pred=["cycle"])
with pytest.raises(ACTDAGError, match="cycle"):
validate_dag(r, ledger)
def test_indirect_cycle(self):
ledger = ACTLedger()
# a -> b -> a would be a cycle
a = make_record("a", pred=["b"], exec_ts=1772064100)
b = make_record("b", pred=["a"], exec_ts=1772064100)
ledger.append(b)
# When validating a, following pred leads to b,
# which has pred=["a"] — cycle!
with pytest.raises(ACTDAGError, match="cycle"):
validate_dag(a, ledger)
def test_temporal_ordering_violation(self):
ledger = ACTLedger()
parent = make_record("parent", exec_ts=1772064200)
ledger.append(parent)
# Child's exec_ts is way before parent
child = make_record("child", pred=["parent"], exec_ts=1772064100)
with pytest.raises(ACTDAGError, match="Temporal"):
validate_dag(child, ledger)
def test_temporal_within_tolerance(self):
ledger = ACTLedger()
parent = make_record("parent", exec_ts=1772064120)
ledger.append(parent)
# Child exec_ts is slightly before parent but within 30s tolerance
child = make_record("child", pred=["parent"], exec_ts=1772064100)
validate_dag(child, ledger)
def test_bad_exec_act(self):
ledger = ACTLedger()
r = make_record("bad", exec_act="not.authorized",
cap=[Capability(action="do.thing")])
with pytest.raises(ACTCapabilityError):
validate_dag(r, ledger)