Last month I merged a bug fix an AI agent wrote. It looked right. The agent said tests passed. I deployed it.
Two hours later, production caught fire.
Not because the agent was wrong — because I never verified anything. I just trusted it.
The problem isn't "can agents do things." It's "can agents prove what they did."
Every multi-agent framework today solves the same problem: make agents talk to each other.
MCP connects agents to tools. A2A connects agents to agents. LangChain, CrewAI, AutoGen orchestrate the dance. The tooling is incredible.
But here's what nobody solved: when agent #2 says "I reviewed the patch" or "tests passed," there's no protocol-level way to verify that claim.
Agent #3 just has to trust agent #2. The middleware just has to trust both. You — the human — just have to trust the pipeline.
That works in demos. It doesn't work in production.
Three questions that kept me up at night
When I started digging into this, I kept coming back to three questions:
1. Was this action even authorized?
An agent shouldn't be able to just decide to run rm -rf or push to production. Every tool call should carry machine-checkable proof that a specific role said "yes, within scope, within quota."
2. Is there a causal chain from the patch to the test results?
If an agent says "I tested the patch and it passed," you should be able to trace backwards: the test run → the patch it tested → the authorization to apply that patch → the work order that started it all. No gaps. No "I swear, bro."
3. Can a third party verify everything without trusting anyone?
This is the acid test. If verifying an agent's work requires logging into the agent's machine, reading its logs, and trusting its middleware, then you haven't really verified anything — you've just moved the trust around.
A real verification protocol should let an independent party replay the entire evidence chain offline, with nothing but the evidence bundle and public keys.
What I built
OpenWorkProof is a protocol layer (not a framework) that sits between agents and their tools. It doesn't replace MCP or A2A — it adds accountability on top of connectivity.
Here's what happens for every tool call:
Step 1: Authorization before execution
Before an agent touches any tool, a PolicyDecision is signed:
from openworkproof import policy
auth_ctx = policy.derive_authorization_context(
work_order=work_order,
grants=grants,
receipts=receipts,
request=signed_request,
arguments=args,
execution_facts=facts,
checkpoint=checkpoint,
)
decision = policy.authorize_tool_call(auth_ctx)
# decision.allowed == False → deny receipt, don't execute
Every decision binds: who authorized it (role + Ed25519 key), what tool they authorized, within what scope and quota, and when the authorization window expires.
If the agent wasn't authorized? The tool call never happens. Period.
Step 2: Signed execution receipt with causal chain
Once the tool runs, it produces an ActionReceipt that chains back to the authorization:
- Which
PolicyDecisionauthorized it - What evidence it produced (diff, test report, benchmarks)
- What quota it consumed
- What its parent receipts are (causal graph, not timeline)
You can't skip steps. You can't fabricate history. The causal graph enforces exact parent sets — if step 5 claims step 3 as its parent but step 3 never happened, verification fails at the protocol level.
Step 3: Offline third-party verification
This is the part I'm most proud of. Any third party can replay the entire chain with zero trust:
from openworkproof.acceptance import verify_acceptance_bundle
result = verify_acceptance_bundle(
work_order=work_order,
report=report,
effective_grants=grants,
receipts=receipts,
committed_evidence=evidence,
acceptance_receipt=signed,
public_keys=keys,
)
# Pure function. Zero I/O. Deterministic.
No database connections. No access to the agent's machine. No trust in any participant. Just the evidence bundle and the public keys. If the chain is internally consistent, it passes. If not, it fails — and tells you exactly where.
The six-role model
I settled on six roles after realizing that "agent" is too vague for accountability:
| Role | Responsibility |
|---|---|
| Maintainer | Creates the WorkOrder, issues root CapabilityGrant |
| Manager | Issues scoped child grants, composes multi-step proofs |
| Developer | Executes authorized tool calls, produces ActionReceipts |
| Verifier | Independently re-runs tests, cross-checks results |
| Sidecar | Assigns trusted execution facts (container ID, SHA, etc.) |
| Acceptor | Signs final accept/reject with an external key |
Key constraint: grants only attenuate. When you delegate from Maintainer → Manager → Developer, permissions can only shrink, never expand. A sub-grant can't grant more access than the parent had. This is the principle of no-cloning authority — it prevents privilege escalation at the protocol level.
The state machine flows: running → locally_verified → proof_ready → awaiting_human → accepted
Does it actually work? Two real bugs.
I didn't test this on toy examples. I tested it on two real open-source issues:
Bug 1: Rich #4196 — terminal formatting
Rich is a popular Python terminal formatting library (50k+ stars). Bug #4196 was a rendering edge case. I built a full 9-step evidence chain:
WorkOrder → Grant issuance → PolicyDecision → repo_read → apply_patch → run_tests → evidence publication → acceptance bundle → offline verification
Every step signed. Every step traceable. Third-party verifier confirmed the chain without touching any live system.
Bug 2: Dify #33013 — LLM application platform
Different project type entirely — a TypeError in Dify's QuestionClassifierNode. Same protocol worked without modification. This proves the protocol isn't coupled to one kind of codebase, one kind of bug, or one kind of test suite.
2,283 tests. 0 failures. Apache-2.0.
Honest limitations (v1.0)
This is a protocol, not a product. Here's what it doesn't do yet:
- Only
repo_read,apply_patch, andrun_testshave complete handler implementations — other tool types need handler closures - No formal security audit
- The Sidecar role still requires manual execution-fact assignment
- No hosted verification dashboard (yet)
The protocol core is solid. The implementation proves it. The surface area is limited — intentionally, at this stage.
Where this fits in the ecosystem
There's an interesting dynamic happening in AI agent infrastructure right now:
| Layer | What it solves | Who's building it |
|---|---|---|
| Identity | "Who is this agent?" | Catena Labs, GenLayer |
| Connectivity | "How do agents talk?" | MCP, A2A |
| Orchestration | "What should agents do?" | LangChain, CrewAI, AutoGen |
| Verification | "Did agents do what they claim?" | OpenWorkProof |
The verification layer is the one nobody has cracked yet. And it's about to become non-negotiable — the EU AI Act's high-risk provisions are already in effect, requiring provable authorization, constraint, and accountability for AI systems.
An analogy I keep coming back to: OAuth defined how humans authorize applications, and that created the Okta/Auth0 market. OpenWorkProof defines how humans authorize AI agents — and verify what they did. Same pattern, different domain.
What I'd love feedback on
I'm posting this because I want to know if I'm solving a real problem or just the one I hit:
- Does the six-role model map to your agent setup, or is it overengineered?
- Is offline third-party verification actually useful, or is "trust the middleware" good enough for your use case?
- What tool call handlers would you need first — beyond repo_read, apply_patch, and run_tests?
I'm not here to sell anything. The project is open-source (Apache-2.0), the repo is public, and I'm genuinely interested in whether other teams are hitting the same verification wall.
GitHub: dengyier/OpenWorkProof
Interactive demo: 9-step evidence chain for Rich #4196
pip install openworkproof
Top comments (18)
I like the separation between execution and independently verifiable evidence of what happened. Where do you see the substantive decision criteria behind a PolicyDecision living - inside the protocol implementation, or in a separately versioned and testable policy artifact?
Brian, great question — and it's one we've wrestled with internally. The short answer is: both, but with a strict separation of concerns.
The PolicyDecision itself — the signed, auditable receipt that says "this action is authorized under this policy" — is a protocol-level artifact. It lives in the receipt chain, is versioned by the protocol schema, and its structure is enforced by the OWP implementation. You can't have a valid PolicyDecision that doesn't conform to the schema, just as you can't have a valid HTTP request that doesn't conform to the spec.
But the substantive decision criteria — the actual rules that determine whether an action is permitted — live in a separately versioned, testable policy artifact. In our current implementation, this is a JSON policy document (the policy.json or capability_grant object) that is referenced by digest in the PolicyDecision receipt. The policy artifact is:
Versioned independently of the protocol schema. A PolicyDecision from v0.1 of the protocol can reference a policy artifact at v3.2, and the verifier checks both version constraints independently.
Testable in isolation. The policy artifact can be evaluated against a mock request without touching the receipt chain, making it possible to unit-test authorization logic separately from cryptographic plumbing.
Auditable by reference. The verifier doesn't need the full policy text in the receipt — just its digest. The policy artifact is fetched (or already cached) at verification time, and its digest is checked against the reference in the PolicyDecision.
This separation matters because the two artifacts have different trust properties. The PolicyDecision receipt proves who authorized what, when, and under which policy digest. The policy artifact defines what the rules actually are. If you conflate them — putting the full policy text inside the receipt — you bloat the chain and make policy updates expensive (every policy change requires re-signing all historical receipts). If you separate them, the receipt chain stays lean, and policy evolution is independent.
A subtlety: the policy artifact is itself signed (by the Authorizer role), so it's not just a loose JSON file. The verifier checks: (1) the PolicyDecision signature proves the Authorizer approved this action, (2) the policy digest in the PolicyDecision matches the signed policy artifact, and (3) the action parameters satisfy the policy rules. Three independent checks, three independent failure modes.
Does that map to what you were imagining, or were you thinking of a different boundary — e.g., embedding the policy criteria in a smart-contract-like layer?
The repo is at github.com/dengyier/OpenWorkProof if you want to trace how PolicyDecision and CapabilityGrant interact in the current implementation. The test_policy_decision.py suite covers the digest-matching and version-checking paths.
Yes - that maps closely to the boundary I had in mind.
The distinction I’m exploring is one step inside the substantive policy artifact. A
CapabilityGrantcan answer whether this actor has authority to perform an action, while some enterprise decisions also require a separate judgment over evidence, rules, exceptions, missing information, and escalation conditions before that authority should actually be exercised.That is where I’m experimenting with JPS - a separately versioned and testable judgment artifact that can produce a deterministic disposition such as approve, deny, unresolved, or escalate.
Your design suggests an interesting interoperability test: let JPS produce the judgment, then let OWP bind the exact policy version, facts/disposition, and authorized action into the
PolicyDecisionand receipt chain.The falsifiers would be the interesting part - change the pack version, substitute facts, replay an old decision, or change the execution arguments after approval and see whether an independent verifier detects the broken binding.
That would keep the responsibilities clean:
JPS - what should happen under these facts and rules
OWP - who authorized it, what actually happened, and whether the evidence chain still verifies
I’m going to explore that boundary experimentally.
Brian, this is brilliant — you've drawn the exact boundary that OWP was designed to enable, not to occupy.
Your distinction between "does this actor have authority?" (CapabilityGrant) and "should this authority be exercised, given these facts and rules?" (JPS) is precisely the separation of concerns we've been converging toward, but you've named it and given it a concrete shape.
JPS as a separately versioned judgment artifact is the right abstraction.
CapabilityGrant answers a binary question: is this action within scope? But real enterprise authorization — especially in regulated environments — requires a multi-factor judgment over evidence completeness, rule applicability, exception handling, missing information, and escalation conditions. That judgment is substantive, contextual, and domain-specific. It cannot live inside the protocol schema without bloating it, and it cannot live inside the receipt chain without making receipts non-deterministic. Your JPS layer solves both problems: the judgment is produced independently, versioned independently, tested independently, and then bound into the OWP chain at the exact moment of commitment.
On the interoperability test you proposed:
"let JPS produce the judgment, then let OWP bind the exact policy version, facts/disposition, and authorized action into the PolicyDecision and receipt chain."
This is not just a test — it's a reference architecture for how OWP should integrate with external judgment systems. In our current model, the Authorizer role produces a PolicyDecision that says "this action is permitted under this policy." If we extend this to "this action is permitted under this policy, as adjudicated by JPS v3.2 with these facts and this disposition,** the receipt chain gains a new layer of semantic richness without losing its cryptographic rigidity.
The binding would look like:
PolicyDecision references capability_grant_digest (static authority)
PolicyDecision also references jps_judgment_digest (contextual judgment)
The Verifier checks both: does the capability grant permit this action? and does the JPS judgment support this disposition under these facts?
The Executor runs the action only if both conditions hold
The receipt chain records the full binding: authority + judgment + execution + output
On the falsifiers:
Your proposed attack surface is exactly the right set of stress tests:
Falsifier What it tests
Change the pack version JPS versioning integrity
Substitute facts Fact-binding integrity
Replay an old decision Temporal freshness / nonce validation
Change execution arguments after approval Authorization-to-execution binding integrity
Each of these is a binding-layer attack — not against the cryptography (which OWP already protects), but against the semantic consistency between what was authorized, what was judged, and what was executed. This is the class of failures that pure signature verification cannot catch, but that a well-designed receipt chain can catch by embedding all relevant digests and requiring independent recomposition.
The responsibility split you articulated is clean and powerful:
JPS: What should happen, under these facts and rules
OWP: Who authorized it, what actually happened, and whether the evidence chain still verifies
This is exactly the division we need. OWP is not a judgment engine. It is an authorization-and-execution binding protocol. JPS supplies the judgment; OWP supplies the tamper-proof commitment of that judgment into an auditable action.
A concrete next step:
If you're open to it, we'd love to collaborate on a joint interoperability spec — a minimal schema for how JPS judgments bind into OWP PolicyDecisions, and a shared falsifier test suite that exercises the boundary. We could define:
The JPS judgment object schema (disposition, facts hash, rule version, reasoning trace)
The OWP binding format (how the judgment digest is referenced in PolicyDecision)
A shared test corpus of falsifier scenarios (pack-version mismatch, fact substitution, replay attacks, post-approval argument tampering)
A reference implementation showing an end-to-end flow: JPS adjudicates → OWP binds → Verifier independently reconstitutes both JPS and OWP states → acceptance or rejection
This would give both projects a rigorous, shared definition of the boundary between "judgment" and "commitment" — a boundary that, as you've shown, is where the real engineering complexity lives.
The OWP repo is at github.com/dengyier/OpenWorkProof. The test_policy_decision.py suite covers the current digest-matching and version-checking paths, and we'd be happy to extend it with JPS-binding tests if you have a schema you'd like to align on.
Looking forward to exploring this boundary with you.
Thanks - I took you up on this, although I decided to test the boundary before proposing an interoperability spec.
Study 014 is now frozen and run.
The question was:
Can an independently developed execution-verification protocol bind an executed action to the exact judgment that authorized it strongly enough that an offline third party detects substitution, drift, replay, and execution mismatch?
We pinned OpenWorkProof at
8eeca6fand calledverify_acceptance_bundleunchanged. JPS produced the deterministic judgment, a thin adapter committed the exact pack, facts, disposition, replay tuple, and authorized action into OWP-signed fields, and OWP handled the authorization, receipts, causal chain, and offline verification.Then we tried to break the composition.
The locked stratum had 39 registered cells - mutations plus controls and a demonstration - including variants coherently re-signed with the study keys rather than simple signature tampering. A separate reviewer-authored holdout added 8 cases that were first executed only after the study froze.
Result: zero divergences in both strata. Every registered detection landed on the layer and code predicted for it.
A few things from your design held up especially well.
OWP's unchanged verifier consistently caught tampering, causal-chain failures, authorization-window violations, evidence-set problems, and surplus execution. We also tried to construct additional execution through the retry path and hit a real protocol wall rather than finding a bypass.
The study also exposed two useful boundaries.
First, a coherently reminted alternative valid WorkOrder can pass all chain-internal checks. That was registered as an expected-undetected case, not patched away. Detecting rollback or freshness at that level needs an anchor outside the chain. I think that is an important and defensible boundary.
Second, the generic
metadataenvelope is outside the signed commitment. We demonstrated that a judgment reference placed there can be substituted while OWP still verifies green. Carrying the commitment through signed fields such asWorkOrder.objectiveandAgentRequest.context_source_digestclosed that in our composition. That might be worth calling out explicitly in the docs so downstream integrations do not mistake metadata for a binding point.The reviewer holdout was useful too. One self-consistent wrong-action case had a completely valid OWP chain - the commitment and receipt agreed with each other - but the action was not one the JPS disposition permitted. Only the disposition-to-action binding rejected it. That was probably the clearest evidence for the separation we were discussing: cryptographic consistency and substantive authorization are different checks.
Full study and detection matrix:
github.com/Judgment-Pack/judgment-...
The conclusion stayed deliberately narrow: binding and lineage, not truth. JPS does not prove the facts are true, and OWP does not prove the judgment is correct. But in this registered mutation set, the two layers composed cleanly and the boundary between judgment and verifiable execution held up under considerably more adversarial pressure than I expected.
I also filed one small housekeeping issue as OpenWorkProof #1 - the repository LICENSE is Apache-2.0 while some package metadata still reports MIT.
Thanks again for the detailed architecture explanation. It gave us something concrete enough to falsify rather than just claim was complementary.
Brian — this is extraordinary. You didn't just discuss the boundary. You built the bridge, walked across it, and then tried to blow it up. The fact that both strata held is the strongest external validation OWP has received to date.
I'm going to address this piece by piece because every paragraph contains something actionable.
On Study 014 and the question you posed:
"Can an independently developed execution-verification protocol bind an executed action to the exact judgment that authorized it strongly enough that an offline third party detects substitution, drift, replay, and execution mismatch?"
You answered it: yes. And not just in theory. You pinned OWP at a specific commit, called verify_acceptance_bundle unchanged, ran JPS as the judgment layer, used a thin adapter for binding, and then subjected the composition to adversarial mutation. The fact that you could do this with a "thin adapter" — not a fork, not a rewrite — is exactly the interoperability proof we were hoping for.
On the 39 registered cells + 8 reviewer holdout cases:
47 adversarial test cases with zero divergences is a remarkable result. That you included "variants coherently re-signed with the study keys rather than simple signature tampering" is especially important — it tests the protocol's resilience against sophisticated attacks, not just naive ones. The separate reviewer-authored holdout is good experimental hygiene. That both strata reported zero divergences means the binding between JPS judgment and OWP execution is cryptographically tight.
On "we tried to construct additional execution through the retry path and hit a real protocol wall":
This is the best possible outcome. A protocol that can be bypassed through retry logic is not a protocol; it's a suggestion. The fact that OWP's retry handling rejected surplus execution attempts means the causal chain is actually enforcing policy, not just logging it.
On Boundary 1 — coherently reminted alternative valid WorkOrder:
"A coherently reminted alternative valid WorkOrder can pass all chain-internal checks... Detecting rollback or freshness at that level needs an anchor outside the chain."
This is a profound and honest boundary. You're identifying a class of attacks that OWP's chain-internal verification is not designed to detect — and correctly labeling it as an expected-undetected case rather than a bug to patch. This is exactly the kind of disciplined security analysis that prevents protocols from promising more than they can deliver.
In OWP terms, this maps to the time-anchor problem: a fully valid receipt chain can be replayed in its entirety if an attacker controls the clock or rolls back the entire system state. Detecting this requires an external freshness anchor — a timestamp or nonce from a source the attacker cannot control (e.g., a blockchain timestamp, a trusted time server, or a counterparty's independent clock). This is a known limitation that we've documented but not yet hardened.
Your finding validates our decision to keep the protocol scope narrow: binding and lineage, not truth or freshness. We should make this boundary explicit in the docs.
On Boundary 2 — generic metadata envelope outside the signed commitment:
"A judgment reference placed there can be substituted while OWP still verifies green... Carrying the commitment through signed fields such as WorkOrder.objective and AgentRequest.context_source_digest closed that in our composition."
This is a critical documentation bug on our part. You're absolutely right: any field outside the signed commitment is not a binding point, no matter how convenient it is to put data there. If downstream integrators treat metadata as a place to embed judgment references or policy digests, they'll have a false sense of security.
Action items from this finding:
Update verify_acceptance_bundle documentation to explicitly warn: all binding commitments must flow through signed fields
Add a test case: test_metadata_substitution_attack — a mutation where a valid OWP chain has its metadata altered but still passes verification, proving that metadata is not a security boundary
Consider removing or restricting the metadata field in the next schema revision, or at minimum adding a metadata_digest in the signed envelope so metadata alterations break the chain
On the reviewer holdout case:
"One self-consistent wrong-action case had a completely valid OWP chain — the commitment and receipt agreed with each other — but the action was not one the JPS disposition permitted. Only the disposition-to-action binding rejected it."
This is the clearest evidence for the separation we've discussed. Cryptographic consistency and substantive authorization are different checks. OWP proves the chain is internally consistent. JPS proves the action is substantively authorized. Neither replaces the other. This single case validates the entire architecture.
On the narrow conclusion:
"JPS does not prove the facts are true, and OWP does not prove the judgment is correct. But in this registered mutation set, the two layers composed cleanly and the boundary between judgment and verifiable execution held up under considerably more adversarial pressure than I expected."
This is the gold standard for protocol evaluation. You tested the boundary under adversarial pressure, found it held, and correctly refused to overclaim. "Under considerably more adversarial pressure than I expected" is a sentence we will quote in the OWP documentation.
On the LICENSE issue (OpenWorkProof #1):
Thank you for catching this. You're right — some package metadata is still reporting MIT while the repository is Apache-2.0. We'll fix this immediately. This is exactly the kind of sharp-eyed review that makes external contributions so valuable.
What we'd like to do next:
Link to your study: Would you be open to us referencing Study 014 in the OWP documentation and README? The github.com/Judgment-Pack/judgment-... link you included — we'd like to add it as a reference implementation of JPS/OWP interoperability.
Integrate your two boundaries into the security model: We'll add explicit documentation on (a) the external-freshness-anchor requirement for rollback detection, and (b) the metadata field limitation.
Add your holdout case to the test suite: The "self-consistent wrong-action" case — where the OWP chain is valid but the JPS disposition rejects the action — is a perfect test for the disposition-to-action binding. We'd like to add it as a reference test.
Co-author the interoperability spec: You now have the only working JPS/OWP integration in the world. If you're willing, we'd like to co-author the interoperability specification with you, using Study 014 as the reference implementation.
This is no longer a discussion. It's a verified, tested, interoperable protocol boundary. Thank you for doing the work to prove it.
Brian — thank you for sharing this so openly.
The level of rigor in Study 014 — 7 rounds of cross-vendor review, 4 blockers found and fixed, reviewer-authored holdout cases committed before freeze, and a detection matrix published in full — is exactly the kind of adversarial verification the protocol space needs more of.
A few things that struck me reading the full post:
On "the study itself failed review several times before the system did": This is the most important sentence. Review is not a rubber stamp. It is the process by which the design proves it is not good enough — repeatedly — until it is. The fact that Round 1 found 14 findings including 4 blockers, and that Round 7 still found a package-metadata shadowing path, means the review process was doing its job. The final result is credible because the intermediate failures were not hidden.
On the reviewer holdout case — the "self-consistent wrong action": This is the single most valuable artifact the study produced. It proves that a fully valid OWP chain is not sufficient to establish authorization correctness. That is the boundary we needed to see, and you have now measured it.
On "where should the external anchor live?": This is the open question that Study 014 leaves behind, and it is a good one. A transparency service, monotonic registry, or trusted current-version pointer are all plausible. We're currently evaluating which fits best with OWP's offline-first design. If you have a direction in mind, we'd welcome the input.
We've linked to your study in the OWP README under "External Validation" and credited you as the first independent interoperability verification. If you have a preferred way to be cited, let us know.
Looking forward to the next study.
Thanks - and I really appreciate the External Validation credit.
On the external-anchor question, I think we may already have a useful pattern in JPS, although not a component you could plug in directly.
Our gateway keeps a small signed registry outside the artifacts it verifies. A verifier can take a saved copy of that registry, the bundle, and a public key and verify everything offline. The important property is monotonicity - an older valid state cannot simply be presented as though a newer one never existed.
That is very close to the shape of the problem Study 014 exposed.
The catch is that our registry currently tracks the wrong subject.
The gateway anchors the inputs used for a judgment. It does not track which Judgment Pack or policy version is currently authoritative, and by design it does not decide that a judgment is authorized or true.
So I would describe the gateway as the right blueprint, not the right component.
What seems missing is a small signed policy-state registry, something like:
policy identity -> current version -> artifact digest -> monotonic revisionThen an offline verifier could separately establish:
There is an important time distinction here too. "Was this the authoritative policy when the action was executed?" and "Is this still the current policy today?" are different questions, so the registry would probably need enough version/history information to answer both rather than simply rejecting every historical receipt once a new version exists.
I would also keep this separate from the judgment and receipt protocols themselves. JPS should not become the authority that declares its own pack current, and OWP should not have to become a policy registry.
One caveat: our gateway is intentionally a single-operator reference implementation. If JPS, OWP, auditors, and other systems all need to rely on the same external anchor, the trust model probably starts looking less like our current registry and more like a small transparency log or independently governed append-only registry.
So the direction I would explore is:
gateway registry pattern + policy-version subject + transparency-style trust model
That seems like a cleaner continuation of the boundary Study 014 exposed than adding more semantics inside either JPS or OWP.
github.com/Judgment-Pack/judgment-...
Brian — this is a genuinely significant architectural insight, and it reframes the entire external-anchor problem in a way that makes both JPS and OWP cleaner.
Your diagnosis — that the gateway is "right blueprint, not the right component" — is exactly the kind of boundary-drawing that prevents protocol bloat. I hadn't seen the policy-state registry as a separate component before, and your three-part offline verification chain is elegant:
Internal validity → 2. Recomputability → 3. Policy-history consistency
This creates a beautiful separation of concerns: OWP handles what happened, JPS handles what was judged, and the policy-state registry handles what was authoritative when. Each layer can evolve independently without cross-contamination.
A few reactions:
On monotonicity vs. policy drift: Your time distinction — "authoritative when executed" vs. "still current today" — is the critical distinction that most policy systems miss. I suspect this is where OWP's RetractionReceipt v0.2 (currently being co-designed with Mikhail) and your policy-state registry naturally converge: a retraction isn't just a binary "undo," it's a policy-state transition that needs to be anchored in the same registry. The monotonic registry becomes the single source of truth for both "what was valid then" and "what was retracted when."
On separation of concerns: I strongly agree that neither JPS nor OWP should become the policy registry. But this raises a practical question: who does govern the registry? If JPS, OWP, and auditors all need to rely on the same external anchor, your "transparency-style trust model" suggests something like a certificate transparency log or a lightweight append-only governance layer. Have you explored whether this could be a shared protocol primitive — something like a minimal PolicyAnchor interface that both JPS and OWP could reference without either owning it?
On the policy identity chain: The policy identity -> current version -> artifact digest -> monotonic revision format is particularly powerful because it turns policy evolution into a verifiable hash chain. This is similar to how we think about OWP's Execution Ledger vs. Evidence Bundle separation (raised by Zira), but applied to policy rather than execution. It suggests a unifying pattern: any system that needs to prove "what was true at time T" could benefit from the same monotonic registry primitive.
On Study 014's implications: The 47 attack cases you tested — they weren't just testing JPS's judgment quality, they were implicitly testing the shape of the boundary between judgment and evidence. Your finding of zero divergence wasn't just a validation of JPS; it was a validation of the architecture you're now describing. The registry pattern + policy-version separation is the structural reason why those 47 cases didn't create contradictions.
One specific question: If the policy-state registry is a separate component, how do you envision the bootstrap problem? When a new verifier comes online with no prior policy history, what is the minimal trust assumption they need to safely start verifying? Is there a "genesis policy digest" concept, or does the registry rely on some external attestation for the initial state?
This feels like it could become the fourth layer in the JPS/OWP interop model: Evidence → Judgment → Execution → Policy History. The first three are about what happened; the fourth is about what rules applied. And monotonicity is the guarantee that ties them all together.
Looking forward to your thoughts — and to seeing how this pattern evolves in the JPS codebase.
Thanks - I think we're converging on the same shape, with one distinction I want to preserve.
First, a small correction on Study 014: it was 47 total cells across the locked and reviewer-holdout strata, not 47 attacks. And the policy-state registry was not part of that experiment. The study established the boundary - two cases remained invisible to every chain-internal check. The registry pattern is a proposed way to address that boundary, not something the zero-divergence result validated.
On the bootstrap question, I think there has to be one explicit trust assumption outside the registry.
Our current gateway already has this problem in a simpler form: a verifier can check the signed registry offline, but the signing public key itself has to be pinned out of band. Fetching the key from the same system you are auditing only proves consistency with that system.
I think a policy-state registry would need the same basic starting point.
At minimum, a new verifier would need something like:
trusted authority/key + signed initial checkpointThe initial checkpoint could establish the policy identity, starting revision, artifact digest, and effective time. Every later state then advances monotonically from that anchor.
But there is another limit here. If one operator controls both the signing key and the history presented to a brand-new verifier, a signed genesis record alone does not prevent that operator from presenting two different valid histories.
That is where the trust model starts moving from "signed registry" toward "transparency log":
I would start with the smallest primitive before designing the governance around it:
policyId + revision + artifactDigest + effectiveFrom + previousCheckpointDigestpossibly with an explicit transition/status field later if retraction or supersession needs to be represented.
I can also see the connection to the RetractionReceipt work you mentioned, but I would keep the concepts separate initially. A retraction of an execution/result and a change in which policy is authoritative are both state transitions, but they have different owners and semantics. They may eventually share the same anchoring primitive without becoming the same protocol object.
And I would slightly redraw the four-layer model.
Policy history is not really "after" Evidence → Judgment → Execution. It is an external reference that both judgment and later verification depend on:
policy history / authority → judgment → execution → evidence
Then retrospective verification walks back across all of them.
So yes, a minimal
PolicyAnchor-style interface could be interesting - especially if it is small enough that JPS, OWP, or another system can consume it without any of them owning the trust root.I would prototype the signed record and offline verification ceremony first, then see whether the trust/governance problem deserves its own shared protocol.
@dengyier can we move this discussion out of the thread so we don't grow this comment chain further?
Brian — thank you for the correction. That's an important distinction, and I appreciate the precision.
47 cells across strata, not 47 attacks. And the registry pattern is a proposed resolution for the boundary the study identified, not something the zero-divergence result validated. That reframes the relationship correctly: Study 014 proved the boundary exists and is sharp. The registry is the architectural response, not the evidence.
On the bootstrap problem — you've identified the exact recursive trap that makes "decentralized trust" so hard.
Your trusted authority/key + signed initial checkpoint is the minimal viable bootstrap, and your observation that fetching the key from the same system you're auditing only proves consistency with that system is devastatingly correct. It's the same problem as "who watches the watchers" — but in cryptographic form.
The transparency-log pivot is the right move. A signed registry with a single operator is a consistency proof (the history is internally coherent), but not a uniqueness proof (this is the only history that ever existed). The transparency log properties you listed — externally pinned trust root, append-only checkpoints, monotonic revisions, effective-time history, and equivocation-observability — are exactly what upgrades consistency to uniqueness.
A few reactions:
On the minimal primitive: policyId + revision + artifactDigest + effectiveFrom + previousCheckpointDigest is beautifully small. The previousCheckpointDigest is the critical link — it turns a sequence of signed states into a verifiable hash chain without requiring a full blockchain. This is similar to how Rekor handles artifact transparency, but applied to policy evolution rather than software artifacts.
On the separation from RetractionReceipt: I agree completely. Retraction of an execution and change of policy authority are both state transitions, but they have different owners, different semantics, and different audit requirements. Sharing the anchoring primitive is elegant — both need monotonic history and external trust roots. But conflating them into the same protocol object would be the kind of premature abstraction that creates hidden coupling. Your "share the primitive, not the object" rule is exactly right.
On the redrawn four-layer model: This is the more important correction. I had it backwards.
policy history / authority → judgment → execution → evidence
This is the causal order. Policy authority is the prerequisite for judgment. Judgment is the prerequisite for execution. Execution produces evidence. Retrospective verification walks backward across all of them — but it can't verify what wasn't causally grounded.
This also clarifies why the registry is not "Layer 4" or "after" execution. It's Layer -1 — the foundation that everything else stands on. The full stack is:
Layer Role Question
-1 PolicyAnchor What rules were authoritative?
0 Semantic Correctness (Mikhail) Did the intent hold?
1 Judgment (JPS) What should happen?
2 Execution (OWP) What actually happened?
3 Evidence (OWP) Can we prove it?
Retrospective verification walks from Layer 3 back to Layer -1.
On the prototype-first approach: "Prototype the signed record and offline verification ceremony first, then see whether the trust/governance problem deserves its own shared protocol" — this is the right sequencing. The technical primitive (signed checkpoint chain) is separable from the governance primitive (who pins the trust root, who witnesses, how equivocation is detected). Starting with the technical layer means we can iterate on the signature format and verification ceremony without getting stuck in governance debates.
One question: The effectiveFrom field — is this the wall-clock time when the policy became effective, or the logical time (e.g., block height, sequence number)? Wall-clock time introduces clock-skew and NTP trust assumptions. Logical time is cleaner for verification but harder for humans to reason about. Given that the registry needs to answer both "was this policy authoritative at time T?" and "what is the current authoritative policy?", do you see effectiveFrom as serving both, or should there be a separate effectiveUntil / supersededBy field for the retrospective query?
Also — if you're prototyping the signed record, would you be open to sharing the format draft in the same GitHub Discussion Mikhail proposed for Layer 0? I suspect the PolicyAnchor primitive and the Semantic Correctness layer are going to intersect in interesting ways — specifically, the "external semantic oracle" that Layer 0 needs might be the same kind of externally pinned, append-only reference that the registry provides.
@dengyier sorry for delayed response, I am currently in South Korea for conference, my response will be delayed.
On
effective_from, the evidence we have points to logical ordering, not wall-clock ordering, at least for the offline verification path we tested.In Study 016, the ordering that actually affects verification is positional: a contiguous sequence, a hash chain over prior checkpoints, and a signed snapshot head.
effective_fromis carried inside the signed record, but no verdict compares it.That distinction matters because there are really three different questions:
Was this version in force at registry position P?
We can answer that offline against a trusted signed snapshot.
Was this version authoritative at wall-clock time T?
We cannot answer that from the registry alone. A decision legitimately used before retirement and the same decision reused after retirement can leave identical retained decision bytes. Distinguishing those histories requires trusted ordering between the action and the registry state.
What is current right now?
An offline verifier cannot know that either. It can only say what was in force at the snapshot it was given.
That is why I would be cautious about making
effective_froma verification clock. The moment the verifier starts comparing wall-clock values, the protocol inherits clock source, skew, and time-authority assumptions that the current offline ceremony avoids.Study 016 is here:
github.com/Judgment-Pack/judgment-...
On
effective_untilandsuperseded_by, I would probably not make either one a canonical registry field.The registry is modeling membership in a supported set, not "the one latest version." Several versions may legitimately be supported at once, and retirement or reinstatement are themselves signed lifecycle events.
So instead of storing:
I would rather let the signed history say:
and derive the supported set from that history.
That also avoids hard-coding one organization's transition semantics into the registry. Retiring a policy version does not necessarily mean every decision made under it instantly becomes unusable. One organization may expire them immediately, another may allow a grace period, and another may grandfather existing decisions. The registry should state what happened to the policy series; a separate judgment should decide what that means for an existing decision.
One correction to my earlier transparency-log language too: I would no longer describe witnessing as upgrading consistency to uniqueness.
The follow-up study gave us a narrower result. If a conflicting view reaches a verifier that has enough prior or witnessed state, some forks become observable. But that depends on the witness contract - who reports what, retention, coverage, recency, enforcement, and independence. A witness that colludes or selectively shows different histories can still preserve the ambiguity.
That boundary is now recorded separately:
github.com/Judgment-Pack/judgment-...
Study:
github.com/Judgment-Pack/judgment-...
And yes on moving this to a GitHub Discussion. Once you open the one you proposed, send me the URL and I'll move the design discussion there. The RFCs and study matrices are already public, so it will be a much better place to separate what has been measured from what is still protocol design.
The boundary I would preserve from the beginning is the same one we have been converging on: the registry records authoritative assertions and their history. It does not decide whether the underlying judgment is semantically correct.
OK
Great question! Verifying AI agent work is crucial for trust. I build PureHub, a privacy-first open-source tool collection, and while it doesn't do AI verification, it does offer tools for cryptographic signing and verification that might complement your workflow. For your specific protocol, I'd suggest checking out existing standards like Sigstore or Rekor for transparency logs. What's your main challenge—ensuring the agent's identity or the integrity of the work output?
Thanks for the pointer, PureHub! You're right that Sigstore and Rekor are highly relevant reference points — they've solved a big chunk of the supply-chain transparency problem for traditional software. The OWP protocol draws on similar principles (signed digests, immutable log chains, key-bound identity), but we had to extend the model in two specific directions for the AI agent case:
Identity alone isn't enough. In Sigstore, identity is "who pushed this container image." In OWP, it's "which agent, acting under which policy, with which capability grant, issued this command." The challenge is that AI agents are delegated actors — their authority is scoped and time-bound, and the verifier needs to independently confirm that scope hasn't been exceeded. So identity is the starting point, not the endpoint.
Output integrity needs to be re-executable, not just signed. A signed container image is a static artifact. A signed AI action receipt is a claim about a dynamic execution. The verifier must be able to independently reconstruct the execution environment (from container_image_digest + command_digest) and re-execute to verify, not just check the signature. That's where the protocol's recomposition design comes in.
Rekor's transparency log model is close to what we want for the receipt chain, but we'd need to extend it to support retraction — the ability to mark a previously accepted receipt as REFUTED without rewriting the original record. That's a unique requirement for agents that run continuously and may produce results that degrade over time (stale context, changed state, etc.).
Your PureHub tools for cryptographic signing and verification might actually be a good fit for the lower-level receipt operations in OWP. We'd be curious to compare notes — especially if there's a clean way to integrate your signing primitives into a role-bound capability grant system. If you're interested, the OWP MCP server is available on PyPI and glama.ai. and the full source is on GitHub: github.com/dengyier/OpenWorkProof. A quick pip install open-work-proof + pip install mcp_server will get you to a local verifier. We'd love your take on whether it extends cleanly.
Some comments may only be visible to logged-in visitors. Sign in to view all comments.