Skip to main content

Audit logs and action gates for safer AI agents.

Project description

Problem Frame Gate

Problem Frame Gate is a Python library and CLI for finite, proof-carrying audit checks around AI decision frames and external action gates. It implements the audit-calculus concepts in:

Takahashi, K. (2026). Problemogenesis Theory: A Finite Proof-Carrying Audit Calculus for Problem-Frame Activation. Zenodo. https://doi.org/10.5281/zenodo.20913669

The package is strict by default. A log is not considered safe unless a finite manifest declares writer authority, protected action constructors, capacities, certificate families, risk modes, and gate bundle policy.

Install

uv sync --all-extras
uv run pytest

From PyPI:

pip install problem-frame-gate
pfg init-manifest > horizon.json

Safe Quickstart

Create a strict manifest:

pfg init-manifest > horizon.json

Validate and fold a log. The repository contains complete copy-paste JSON fixtures in docs/examples/:

pfg validate-schema horizon docs/examples/horizon.json
pfg validate-schema log docs/examples/log.json
pfg verify-log --horizon docs/examples/horizon.json docs/examples/log.json
pfg fold --horizon docs/examples/horizon.json docs/examples/log.json

Check an action gate and emit the atomic bundle:

pfg validate-schema gate-request docs/examples/gate-request.json
pfg check-gate --horizon docs/examples/horizon.json --bundle docs/examples/gate-request.json docs/examples/log.json

The generated bundle contains exactly five protected rows:

  1. GateCheck
  2. OutboxClaim
  3. UseCap
  4. ConsumeResource
  5. RiskClose

Each row must be written by the executor writer and committed in one atomic group. A standalone OutboxClaim is rejected.

For a new project, copy the three JSON files from docs/examples/, then change the writer ids, certificate issuers, frame id, action name, risk id, and resource ids to match your deployment.

Python Example

from problem_frame_gate import (
    Envelope,
    EnvelopeClass,
    ExecutorGate,
    GateRequest,
    Horizon,
    RiskClaimRecord,
    RiskRouteWitness,
    digest_json,
)

horizon = Horizon.strict_default(agent_writers=("agent",))

def env(eid: str, commit: int, kind: str, **payload: object) -> Envelope:
    return Envelope(eid, eid, "0", commit, "agent", "agent", 1, EnvelopeClass.NORMAL, {"kind": kind, **payload})

family_check = {
    "accepted": True,
    "checker": "example-certificate-family-v1",
    "transcript_digest": digest_json({"checker": "example-certificate-family-v1", "accepted": True}),
    "dependency_digest": digest_json({"dependencies": [], "source_ids": []}),
    "revocation_frontier": [],
    "checked_at": 2,
    "assumption": "CertificateFamilyChecker",
}

log = [
    env("e0", 0, "Frame", frame_id="p1", scope="lab", goal="test anomaly",
        evidence_ids=["u1"], actions=["run-check"], acceptance=["review"], risk_ids=["r1"]),
    env("e1", 1, "Evidence", evidence_id="u1", digest="sha256:source"),
    env("e2", 2, "Issue", cert_id="c-risk", family="risk", issuer="agent",
        expires_at=99, family_check=family_check),
    env("e3", 3, "Activated", frame_id="p1"),
    env("e4", 4, "RiskReg", hypothesis_id="h1", family="fixed"),
    env("e5", 5, "RiskReserve", risk_id="r1", hypothesis_id="h1", frame_id="p1", eta="1/100"),
    env("e6", 6, "RiskSpend", risk_id="r1", hypothesis_id="h1", frame_id="p1",
        eta="1/100", mode="fixed", cert_id="c-risk"),
    env("e7", 7, "ReserveResource", lease_id="lease1", token_id="tool", frame_id="p1"),
    env("e8", 8, "MintCap", capability_id="cap1", frame_id="p1", action="run-check"),
    env("e9", 9, "AuthorizeOutbox", outbox_id="out1", frame_id="p1", action="run-check"),
]

risk_claim = RiskClaimRecord(
    claim_id="q1",
    risk_id="r1",
    hypothesis_id="h1",
    mode="fixed",
    cert_id="c-risk",
    eta="1/100",
    event_id="F1",
    standardized_event_id="F1",
    route_witness=RiskRouteWitness(
        accepted=True,
        checker="example-risk-route-v1",
        transcript_digest=digest_json({"checker": "example-risk-route-v1", "mode": "fixed"}),
        route="fixed",
    ),
)

request = GateRequest(
    gate_id="gate1", bundle_id="bundle1", frame_id="p1", action="run-check",
    outbox_id="out1", capability_id="cap1", lease_id="lease1",
    risk_id="r1", hypothesis_id="h1", risk_mode="fixed", risk_cert_id="c-risk",
    source_time=9, commit_time=10, risk_claim=risk_claim.to_json(), risk_alpha="1/50",
)

gate = ExecutorGate()
assert gate.check(horizon, log, request).ok
bundle = gate.create_bundle(horizon, log, request)
assert bundle.verify(horizon, log).ok

Security Boundary

The library proves finite audit consistency. It does not prove external truth, cryptographic collision resistance, statistical model validity, or physical effect. Those are explicit assumptions in checker results.

Strict certificates require a finite family-check record with a checker name, transcript digest, dependency digest, revocation frontier, and check time. Boolean certificate flags are treated as legacy assumptions and fail strict v1.0.0 checks.

There are two verification routes:

  • JSON-only use relies on manifest-declared environment assumptions such as CertificateFamilyChecker and StatisticalModel.
  • Python deployments can register callable CertificateFamily and RiskMode checkers. The verifier reuses those registries when replaying embedded GateCheck transcripts.

See docs/quickstart.md, docs/schema.md, docs/theory-mapping.md, and docs/issue-codes.md for operational use.

Release

The canonical repository is https://github.com/kadubon/problem-frame-gate. Versioned releases are published by GitHub Actions through PyPI Trusted Publishing from .github/workflows/workflow.yml; no long-lived PyPI token is required.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

problem_frame_gate-1.0.0.tar.gz (80.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

problem_frame_gate-1.0.0-py3-none-any.whl (59.9 kB view details)

Uploaded Python 3

File details

Details for the file problem_frame_gate-1.0.0.tar.gz.

File metadata

  • Download URL: problem_frame_gate-1.0.0.tar.gz
  • Upload date:
  • Size: 80.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for problem_frame_gate-1.0.0.tar.gz
Algorithm Hash digest
SHA256 8cb20e9e7fe90393cd95c757f458646dbad9940ed74f551620f29f2635a7756c
MD5 48eccd4bd9c04a7db0f0592f00bb8068
BLAKE2b-256 c9e40105ee4ab1ca7763f5b8e26d274cd33a3240202ac20ecbcb3a8c53a68de9

See more details on using hashes here.

Provenance

The following attestation bundles were made for problem_frame_gate-1.0.0.tar.gz:

Publisher: workflow.yml on kadubon/problem-frame-gate

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file problem_frame_gate-1.0.0-py3-none-any.whl.

File metadata

File hashes

Hashes for problem_frame_gate-1.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 87b202f1cb8caba24137389375445dc026226970010ca107c74eaddcd17f5e48
MD5 24a76247422adb521b333c4a212dc6e8
BLAKE2b-256 fc7a3786c9b49cac171fe67f0fe09ce04fbfc0d707454024788cda23b746a5ee

See more details on using hashes here.

Provenance

The following attestation bundles were made for problem_frame_gate-1.0.0-py3-none-any.whl:

Publisher: workflow.yml on kadubon/problem-frame-gate

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page