| Internet-Draft | UPIP | September 2026 |
| van de Meent & AI | Expires 28 March 2027 | [Page] |
This document defines UPIP (Universal Process Integrity Protocol), a five-layer protocol for capturing, verifying, and reproducing computational processes across machines, actors, and trust domains. UPIP defines a cryptographic hash chain over five layers: STATE (input), DEPS (dependencies), PROCESS (execution), RESULT (output), and VERIFY (cross- machine proof). The stack hash chains these layers, ensuring that modification of any component is detectable.¶
This document also defines continuation artifacts: Task Capsules, Work Corridors, and Fork Tokens. A task capsule carries a bounded process blueprint and evidence context. A work corridor names a bounded continuation window. A fork token freezes the UPIP stack at a specific point and transfers it to another actor with cryptographic chain of custody. The receiving actor can verify what was handed off, validate capabilities, and continue the process with full provenance.¶
UPIP integrates with TIBET [TIBET] for provenance tokens, JIS [JIS] for actor identity, AINS [AINS] for discovery, and RVP [RVP] for presence evidence. UPIP is transport-agnostic with JSON as the baseline serialization.¶
This Internet-Draft is submitted in full conformance with the provisions of BCP 78 and BCP 79.¶
Internet-Drafts are working documents of the Internet Engineering Task Force (IETF). Note that other groups may also distribute working documents as Internet-Drafts. The list of current Internet-Drafts is at https://datatracker.ietf.org/drafts/current/.¶
Internet-Drafts are draft documents valid for a maximum of six months and may be updated, replaced, or obsoleted by other documents at any time. It is inappropriate to use Internet-Drafts as reference material or to cite them other than as "work in progress."¶
This Internet-Draft will expire on 28 March 2027.¶
Copyright (c) 2026 IETF Trust and the persons identified as the document authors. All rights reserved.¶
This document is subject to BCP 78 and the IETF Trust's Legal Provisions Relating to IETF Documents (https://trustee.ietf.org/license-info) in effect on the date of publication of this document. Please review these documents carefully, as they describe your rights and restrictions with respect to this document. Code Components extracted from this document must include Revised BSD License text as described in Section 4.e of the Trust Legal Provisions and are provided without warranty as described in the Revised BSD License.¶
Distributed computing increasingly involves heterogeneous actors: human operators, AI agents, automated pipelines, edge devices, and cloud services. When a process moves between actors -- from one machine to another, from an AI to a human for review, from a drone to a command station -- the integrity of the process state must be verifiable at every handoff point.¶
UPIP fills this gap with four complementary mechanisms:¶
The UPIP Stack: a five-layer bundle capturing everything needed to reproduce a process, with a single stack hash that invalidates if any layer is modified.¶
Fork Tokens: a continuation mechanism that freezes the stack state and transfers it to another actor with cryptographic proof of what was handed off, who handed it off, why, and what capabilities are required to continue.¶
Task Capsules: bounded process blueprints that can travel as files, messages, or sealed carriers without becoming runtime authority.¶
Work Corridors: bounded continuation windows in which session references and groove markers bind process steps into a causal walk.¶
Existing solutions address parts of process integrity:¶
Version control (git) tracks code state but not execution¶
Container images (OCI) capture environment but not intent¶
CI/CD pipelines orchestrate execution but provide no cross-machine reproducibility proof¶
Package managers record dependencies but not their usage context¶
None provide a unified, self-verifying bundle that captures the complete execution context with cryptographic chain of custody across actor boundaries.¶
EVIDENCE OVER ENFORCEMENT: UPIP proves what happened and reports validation outcomes. It does not itself execute or admit a transition. A consuming application or target may refuse according to local policy; the evidence remains independently inspectable.¶
HASH CHAIN INTEGRITY: Every layer is independently hashed. The stack hash chains them. Fork hashes chain into the fork chain. Tampering with any component invalidates the chain.¶
ACTOR AGNOSTICISM: Actors may be human operators, AI agents, automated scripts, services, or identity-bearing endpoints for IoT peripherals. A keyless peripheral is not thereby an autonomous actor; its accountable endpoint carries identity. The protocol otherwise makes no assumption about actor type.¶
TRANSPORT AGNOSTICISM: UPIP bundles are JSON documents. They can be transferred via file copy, HTTP API, message queue, I-Poll, or physical media.¶
CONTINUITY IS NOT AUTHORITY: A process may continue, resume, fork, or be carried without being admitted for a concrete action. UPIP evidence may inform admission; it does not replace admission.¶
CEREMONY IS NOT AUTHORITY: A human-facing ceremony runner can walk an operator through a UPIP-shaped process. The ceremony runner does not decide whether the resulting transition may execute.¶
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in BCP 14 [RFC2119] [RFC8174] when, and only when, they appear in all capitals, as shown here.¶
UPIP operates in two modes:¶
Single-Actor Mode (Capture-Run-Verify):¶
Multi-Actor Mode (Fork-Resume):¶
+----------+ +---------+ +---------+ +---------+
| L1 STATE |---->| L2 DEPS |---->| L3 PROC |---->| L4 RSLT |
+----------+ +---------+ +---------+ +---------+
| | | |
v v v v
state_hash deps_hash (intent) result_hash
| | | |
+-------+--------+-------+-------+
|
v
stack_hash = SHA-256(L1 || L2 || L3 || L4)
|
v
+------------+
| Fork Token |---> Actor B ---> New UPIP Stack
+------------+
|
v
fork_chain: [{fork_id, parent_hash, ...}]
A UPIP stack MUST be a [RFC8259] JSON object with the following top-level fields:¶
{
"protocol": "UPIP",
"version": "1.1",
"title": "<human-readable description>",
"created_by": "<actor identity (JIS format)>",
"created_at": "<ISO-8601 timestamp>",
"stack_hash": "upip:sha256:<hex>",
"state": { },
"deps": { },
"process": { },
"result": { },
"verify": [ ],
"fork_chain": [ ],
"source_files": { }
}
¶
L1 captures the complete input state before execution. The state_type field determines the capture method:¶
{
"state_type": "git | files | image | empty",
"state_hash": "<type>:<hash>",
"captured_at": "<ISO-8601 timestamp>"
}
¶
State Types:¶
For "git" type, additional fields:¶
For "files" type, additional fields:¶
L2 captures the exact dependency set at execution time.¶
{
"python_version": "<major.minor.patch>",
"packages": { "<name>": "<version>" },
"system_packages": [ "<name>=<version>" ],
"deps_hash": "deps:sha256:<hex>",
"captured_at": "<ISO-8601 timestamp>"
}
¶
The deps_hash MUST be computed as SHA-256 of the sorted, deterministic serialization of all package name:version pairs.¶
While this specification uses Python as the reference implementation, L2 is language-agnostic. Other implementations MAY substitute appropriate dependency metadata for their runtime environment (e.g., Cargo.lock for Rust, go.sum for Go, package-lock.json for Node.js).¶
L3 defines what was executed and why. The "intent" field maps to TIBET ERACHTER [TIBET] and the "actor" field uses JIS identifier format [JIS].¶
{
"command": [ "<arg0>", "<arg1>" ],
"intent": "<human-readable purpose>",
"actor": "<actor identity (JIS format)>",
"env_vars": { "<key>": "<value>" },
"working_dir": "<path>"
}
¶
The command field MUST be an array of strings, not a shell command string. This prevents injection attacks and ensures deterministic execution.¶
The intent field MUST be a human-readable string describing WHY this process is being run. This serves as the ERACHTER (intent) component for TIBET integration.¶
The actor field MUST identify the entity that initiated the process using JIS identifier format. This may be a human operator, AI agent (IDD), or system service.¶
L4 captures the execution result.¶
{
"success": true,
"exit_code": 0,
"stdout": "<captured stdout>",
"stderr": "<captured stderr>",
"result_hash": "sha256:<hex>",
"files_changed": 3,
"diff": "<unified diff of file changes>",
"captured_at": "<ISO-8601 timestamp>"
}
¶
The result_hash MUST be computed as SHA-256 of the concatenation of: exit_code (as string) + stdout + stderr.¶
If execution occurs in an airlock, the diff field SHOULD contain the unified diff of all file changes detected.¶
L5 records verification attempts when the UPIP stack is reproduced on another machine.¶
{
"machine": "<hostname or identifier>",
"verified_at": "<ISO-8601 timestamp>",
"match": true,
"environment": { "os": "linux", "arch": "x86_64" },
"original_hash": "upip:sha256:<hex>",
"reproduced_hash": "upip:sha256:<hex>"
}
¶
The match field MUST be true only if reproduced_hash equals original_hash.¶
L5 is an array, allowing multiple verification records from different machines. Each verification is independent.¶
The stack hash MUST be computed as follows:¶
Result: "upip:sha256:4f2e8a..."¶
The canonical_json() function is defined in Section 4.7.¶
Before hashing, JSON objects MUST be serialized to canonical form:¶
This ensures deterministic hashing across implementations. The same canonical serialization is used in TIBET [TIBET] Section 5.1.¶
A fork token MUST be a [RFC8259] JSON object with the following fields. Actor fields use JIS identifier format [JIS]:¶
{
"fork_id": "fork-<uuid>",
"parent_hash": "sha256:<hex>",
"parent_stack_hash": "upip:sha256:<hex>",
"continuation_point": "L<n>:<position>",
"intent_snapshot": "<human-readable purpose>",
"active_memory_hash": "sha256:<hex>",
"memory_ref": "<path or URL to memory blob>",
"fork_type": "script|ai_to_ai|human_to_ai|fragment",
"actor_from": "<JIS actor identifier>",
"actor_to": "<JIS actor identifier or *>",
"actor_handoff": "<from> -> <to>",
"capability_required": { },
"forked_at": "<ISO-8601 timestamp>",
"expires_at": "<ISO-8601 timestamp or empty>",
"fork_hash": "fork:sha256:<hex>",
"partial_layers": { },
"metadata": { }
}
¶
The actor_to field MAY be empty, indicating the fork is available to any capable actor. In this case, actor_handoff MUST use "*" as the target: "ActorA -> *".¶
The fork hash MUST be computed as follows:¶
Result: "fork:sha256:7d3f..."¶
This ensures that modifying ANY field invalidates the fork.¶
The active_memory_hash captures cognitive or computational state at fork time.¶
This field is EVIDENCE, not a reproducibility guarantee. Exact reproduction of AI state is generally not achievable. The hash proves what the state WAS at fork time, enabling audit and comparison.¶
Implementations MUST NOT require exact memory reproduction for fork validation.¶
The capability_required field specifies what the resuming actor needs:¶
{
"capability_required": {
"deps": ["package>=version"],
"gpu": true,
"min_memory_gb": 16,
"platform": "linux/amd64",
"custom": { }
}
}
¶
On resume, the receiving actor SHOULD verify these requirements and record the result in the verification record. UPIP reports missing capabilities as evidence and does not itself execute or admit the transition. The consuming application or target MAY refuse according to local policy.¶
The fork_chain field in the UPIP stack is an ordered array of fork token references:¶
{
"fork_chain": [
{
"fork_id": "fork-abc123",
"fork_hash": "fork:sha256:...",
"actor_handoff": "A -> B",
"forked_at": "2026-03-29T14:00:00Z"
}
]
}
¶
When a process is resumed, the new UPIP stack MUST include the fork token in its fork_chain. This creates a complete audit trail of all handoffs.¶
Input: command, source_dir, intent, actor¶
Output: UPIP stack with L1-L4 populated¶
Input: Fork Token (.fork.json), command, actor¶
Output: New UPIP stack, verification record¶
Input: UPIP stack, N fragments, actor list¶
Output: N Fork Tokens of type "fragment"¶
Fragment tokens MUST include metadata fields:¶
A work corridor is a bounded continuation window for a task, install, recovery, maintenance operation, or multi-actor process. A corridor is named by a session_ref or equivalent work_chain_ref.¶
The session_ref answers:¶
Which walk or corridor is this?¶
A groove answers:¶
Do these marks belong to the same walk?¶
A groove MUST be fresh per corridor and MUST be derived or advanced causally from prior corridor material. A groove MUST NOT be treated as identity, mandate, standing, admission, or authority. A valid groove proves only continuity of marks within the named corridor.¶
A corridor step MAY contain:¶
{
"session_ref": "mss-2026-09-18-a",
"task_ref": "install.example.v1",
"previous_groove": "sha256:...",
"next_groove_commitment": "sha256:...",
"snapshot_ref": "sha256:...",
"actor": "jasper-admin.aint",
"on_behalf_of": "jasper.aint",
"receipt_refs": []
}¶
Consumers SHOULD distinguish at least the following groove outcomes:¶
groove_match:
The expected mark was presented for this corridor.
groove_missing:
The next step failed to present the expected mark.
groove_mismatch:
A mark was presented but does not match this corridor's
expected mark.
groove_from_wrong_session:
A mark appears valid in form but belongs to another
session_ref.
groove_expired:
The mark was valid for an earlier window but not for the
current corridor.¶
These outcomes are evidence for process continuity. They do not decide whether the target may execute the requested transition.¶
At the end of a corridor, a clock-out or equivalent close step MAY seal a portable session capsule. Such a capsule SHOULD include before/after snapshot refs, changed refs where known, task refs, session refs, groove-chain summary, actor, on_behalf_of, receipt refs, and open ends.¶
A runtime/incarnation reference is context inside the capsule, not the custody endpoint. A runtime may disappear. The evidence must not. Deployments SHOULD bind long-term custody to the accountable principal, organization, or archive lane rather than to a volatile runtime.¶
A UPIP task capsule may be rendered to a human or operator by a ceremony runner such as actiond. The ceremony runner mediates intent into canonical local verbs and records the steps taken. It does not become the authority for execution.¶
A typical installation or maintenance flow is:¶
rolodex / blueprint reference
-> UPIP task capsule
-> actiond ceremony
-> presence / consent / choice where required
-> canonical local verb
-> admission or refusal
-> receipt¶
The following boundaries MUST be preserved:¶
Fetching a blueprint is not execution. Rendering a ceremony is not admission. Human presence is not mandate. Capability to carry is not permission to act. The UI does not certify its own consequence.¶
If a transition cannot consume presence evidence because it is already out of state, resolved, refused, or not in scope, the ceremony MUST NOT request presence for that transition. The result SHOULD be recorded with fields equivalent to:¶
{
"presence": "not_asked",
"presence_why": "transition cannot consume presence"
}¶
This prevents human evidence from being spent on a question nobody posed.¶
Where a ceremony requests presence, the lifecycle and the carrier window are separate protocol roles. The lifecycle owns the typed question and its result; a fingerprint reader, an NFC exchange, or an Ed25519 LAN channel merely carries that question and answer.¶
A conforming continuation MUST preserve these boundaries:¶
presence.request identifies one actor, operation, target, lane, window, and challenge. presence.response records the carrier outcome for that exact question. A matching response is evidence; it is not a bind. presence.bind records that a named consumer verified and consumed that evidence for the same question. admission remains a separate target- or policy-side decision for the concrete transition.¶
Implementations MUST NOT reuse a response across a different lane, window, challenge, actor, operation, or target. A historical match MUST NOT become fresh presence for a later transition. A bind may accompany either admission or refusal and grants no reusable authority.¶
A UPIP stack is valid if and only if:¶
Validation MUST be performed when loading a .upip.json file and SHOULD be performed before reproduction.¶
When resuming a fork token, the following checks MUST be performed:¶
All four checks MUST be recorded in the L5 VERIFY record.¶
This section specifies what happens when validation fails.¶
Hash mismatch (stack_hash or fork_hash): - MUST be recorded as tamper evidence - SHOULD trigger enhanced logging for subsequent actions - The UPIP layer reports evidence and does not execute or admit the transition itself - The consuming application or target decides whether to proceed and MAY refuse according to local policy¶
Capability mismatch: - MUST be recorded in L5 VERIFY - Missing GPU when GPU required: record as "degraded" - Missing dependency: record as "incomplete_deps" - Each mismatch is classified:¶
FATAL: Execution cannot proceed (e.g., wrong OS)
DEGRADED: Execution possible but results may differ
MINOR: Cosmetic difference (e.g., locale)¶
FATAL mismatches SHOULD trigger a warning to the operator. UPIP records the mismatch; the operator, consuming application, or target decides whether the concrete transition is admissible.¶
Expiration: - Expired forks SHOULD generate a warning - MUST be recorded in L5 VERIFY - MUST NOT be represented as current continuation evidence - The consumer or target MAY refuse the transition¶
If fork_hash validation fails:¶
{
"fork_hash_match": false,
"expected_hash": "fork:sha256:<original>",
"computed_hash": "fork:sha256:<recomputed>",
"tamper_evidence": true,
"fields_checked": ["fork_id", "parent_hash", "..."]
}
¶
This creates an evidence record that tampering occurred. The decision to act on tamper evidence is a local policy decision.¶
UPIP consumers MUST NOT collapse deployment or runtime changes into a single "updated" state. The following are distinct:¶
file_copied:
Bytes were copied to a location.
package_carried:
A package or capsule was transported or made available.
process_restarted:
A running process was restarted.
behavior_changed:
The observed behavior changed.
consumer_observed:
A named consumer read or acted on the new material.
fleet_converged:
All intended consumers in a fleet were observed at the
intended version or state.¶
Implementations SHOULD record which of these transitions was observed. File copy, package carriage, process restart, behavior change, and fleet convergence are different facts.¶
UPIP stacks use the ".upip.json" extension. Fork tokens use the ".fork.json" extension. Task capsules MAY use ".upip.json", ".task.upip.json", or a sealed carrier format such as ".tza" when carried with custody and envelope metadata.¶
Content-Type for HTTP: application/upip+json (stacks), application/upip-fork+json (fork tokens).¶
A .tza/TBZ carrier may physically carry multiple logical
roles. Implementations MUST distinguish those roles:¶
UPIP task capsule:
Process blueprint or continuation evidence.
Rolodex info disk:
Vocabulary, index, or meaning hints.
Carrier envelope:
Custody and transport wrapper.
Admission receipt:
Decision or effect evidence.¶
The same carrier may contain several roles, but finding one role MUST NOT imply another. In particular, finding a task capsule or rolodex reference MUST NOT execute the task.¶
Fork tokens MAY be delivered via I-Poll TASK messages. I-Poll is OPTIONAL; UPIP does not depend on I-Poll.¶
Fork tokens are delivered via I-Poll TASK messages:¶
{
"from_agent": "<source agent>",
"to_agent": "<target agent>",
"content": "<human-readable fork summary>",
"poll_type": "TASK",
"metadata": {
"upip_fork": true,
"fork_id": "<fork_id>",
"fork_hash": "fork:sha256:<hex>",
"fork_type": "<type>",
"continuation_point": "<point>",
"actor_handoff": "<from> -> <to>",
"fork_data": { }
}
}
¶
The "upip_fork" metadata flag MUST be true to identify this message as a fork delivery.¶
The "fork_data" field MUST contain the complete fork token as defined in Section 5.1. This allows the receiving agent to reconstruct the fork token without needing the .fork.json file.¶
After processing a fork token, the receiving actor SHOULD send an ACK message:¶
{
"from_agent": "<resuming agent>",
"to_agent": "<original agent>",
"content": "FORK RESUMED_OK -- <fork_id>",
"poll_type": "ACK",
"metadata": {
"upip_fork": true,
"fork_id": "<fork_id>",
"fork_status": "RESUMED_OK",
"resume_hash": "upip:sha256:<hex>",
"resumed_by": "<agent identity>"
}
}
¶
The resume_hash is the stack_hash of the new UPIP stack created during resume.¶
The fork_status field MUST be one of "RESUMED_OK" or "RESUMED_FAIL".¶
L3 PROCESS may contain sensitive command arguments. L4 RESULT may contain sensitive output. Implementations MUST support encryption at rest for stored UPIP stacks. Implementations SHOULD support per-layer encryption.¶
For ai_to_ai forks, the memory blob (.blob file) may contain the AI's full context window, which could include sensitive user data. Memory blobs MUST be encrypted at rest. Implementations SHOULD encrypt memory blobs in transit.¶
UPIP uses SHA-256 for all hash computations. Implementations MUST use SHA-256 as defined in [FIPS180-4]. The hash prefix ("sha256:", "upip:", "fork:") provides algorithm agility for future migration. Future versions MAY support SHA-3 or other hash functions via an algorithm identifier prefix.¶
The hash chain structure ensures that modifying any component at any layer propagates to the stack hash, providing tamper evidence for the entire bundle.¶
UPIP is deliberately designed as an evidence protocol, not an enforcement protocol. Fork validation failures do not block execution; they are recorded as evidence. This design choice reflects the reality that:¶
Applications that require enforcement SHOULD implement additional policy layers on top of UPIP evidence. UPIP evidence chains are designed to satisfy audit and traceability requirements in regulatory frameworks such as the EU AI Act [EU-AI-ACT] and the NIST AI Risk Management Framework [NIST-AI-RMF].¶
When fork_type is "ai_to_ai", the active_memory_hash represents the SHA-256 of the serialized AI context window. This raises unique considerations:¶
The active_memory_hash is evidence of state at fork time, not a reproducibility guarantee. This is explicitly informational. Implementations MUST NOT treat memory hash verification as a pass/fail gate.¶
Implementations SHOULD encrypt memory blobs at rest. Implementations MUST NOT require exact memory reproduction for fork validation. The memory hash serves as evidence of state at fork time, not as a reproducibility guarantee.¶
Capability requirements in fork tokens are self-reported by the forking actor. The receiving actor SHOULD independently verify capabilities rather than trusting the requirement specification alone.¶
Package version verification SHOULD use installed package metadata. GPU availability SHOULD be verified via hardware detection, not configuration claims.¶
Fork tokens include fork_id and forked_at fields to mitigate replay attacks. Implementations SHOULD track consumed fork_ids and reject duplicate fork_ids within a configurable time window.¶
The expires_at field provides time-based expiration. Agents SHOULD set expires_at for forks that are time-sensitive.¶
Attack: An adversary obtains a fork token intended for another actor.¶
Impact: The adversary can execute the continuation, possibly with malicious modifications.¶
Mitigation: Fork tokens with actor_to set to a specific actor restrict intended recipients. The fork hash includes actor_handoff, so changing the recipient invalidates the hash. For open forks (actor_to = "*"), the first valid resume creates an evidence chain that subsequent attempts can be compared against.¶
Deployment: Use specific actor_to values for sensitive processes. Set short expires_at for time-sensitive forks. Monitor for duplicate fork_id resume attempts.¶
Attack: An actor claims to meet capability requirements (e.g., claims GPU when none exists).¶
Impact: Process executes in degraded environment, producing potentially unreliable results.¶
Mitigation: Capability verification SHOULD use hardware detection, not configuration claims. The L5 VERIFY record captures actual environment details. Mismatches between claimed and detected capabilities are recorded as evidence.¶
Deployment: Use hardware detection APIs (e.g., CUDA device query for GPU). Do not trust self-reported capabilities.¶
Attack: A receiver treats continuity evidence, carrier availability, or a valid groove as proof that an action is authorized.¶
Impact: A process continuation, task capsule, or work corridor is allowed to act beyond its mandate. A copied capsule or replayed corridor mark may be mistaken for a fresh admission.¶
Mitigation: UPIP artifacts MUST be interpreted as evidence of process shape, continuation, or custody only. Admission of a concrete transition remains outside UPIP and MUST be evaluated by the target or local policy layer. Implementations SHOULD record explicit fields for "not_admitted", "not_evaluated", "not_asked", and "not_consumed" instead of collapsing them into failure.¶
Deployment: Gate high-impact transitions through fresh admission and record the receipt. Do not allow a valid task capsule, can-carry result, or groove match to bypass admission.¶
Each UPIP operation MAY produce TIBET [TIBET] tokens:¶
The L3 PROCESS "intent" field maps to TIBET ERACHTER. Fork tokens reference TIBET chains in their provenance.¶
Actor identifiers in UPIP use JIS format (Section 3.4 of [JIS]). Fork token actor_from and actor_to use JIS identifiers, enabling signature verification through JIS key resolution.¶
AINS [AINS] provides discovery of actors for fork delivery. An actor_to value can be resolved through AINS to determine the delivery endpoint.¶
RVP [RVP] may provide fresh presence or verification evidence for a UPIP-shaped transition. RVP evidence is consumed only when the concrete transition requires it. Presence evidence does not prove mandate, authority, or admission.¶
A ceremony runner such as actiond may render a UPIP task capsule to a human and route chosen intent to canonical local verbs. The runner records what was shown, chosen, refused, or completed. It does not certify its own consequence.¶
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"required": ["protocol", "version", "stack_hash",
"state", "deps", "process", "result"],
"properties": {
"protocol": {"const": "UPIP"},
"version": {"type": "string"},
"title": {"type": "string"},
"created_by": {"type": "string"},
"created_at": {"type": "string", "format": "date-time"},
"stack_hash": {
"type": "string",
"pattern": "^upip:sha256:[a-f0-9]{64}$"
},
"state": {
"type": "object",
"required": ["state_type", "state_hash"],
"properties": {
"state_type": {
"enum": ["git", "files", "image", "empty"]
},
"state_hash": {"type": "string"}
}
},
"deps": {
"type": "object",
"required": ["deps_hash"],
"properties": {
"python_version": {"type": "string"},
"packages": {"type": "object"},
"deps_hash": {"type": "string"}
}
},
"process": {
"type": "object",
"required": ["command", "intent", "actor"],
"properties": {
"command": {"type": "array", "items": {"type": "string"}},
"intent": {"type": "string"},
"actor": {"type": "string"}
}
},
"result": {
"type": "object",
"required": ["success", "exit_code", "result_hash"],
"properties": {
"success": {"type": "boolean"},
"exit_code": {"type": "integer"},
"result_hash": {"type": "string"}
}
},
"fork_chain": {
"type": "array",
"items": {"type": "object"}
}
}
}
¶
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"required": ["fork_id", "fork_type", "fork_hash",
"active_memory_hash", "forked_at"],
"properties": {
"fork_id": {"type": "string", "pattern": "^fork-"},
"parent_hash": {"type": "string"},
"parent_stack_hash": {
"type": "string",
"pattern": "^upip:sha256:"
},
"continuation_point": {"type": "string"},
"intent_snapshot": {"type": "string"},
"active_memory_hash": {
"type": "string",
"pattern": "^sha256:"
},
"memory_ref": {"type": "string"},
"fork_type": {
"enum": ["script", "ai_to_ai", "human_to_ai", "fragment"]
},
"actor_from": {"type": "string"},
"actor_to": {"type": "string"},
"actor_handoff": {"type": "string"},
"capability_required": {"type": "object"},
"forked_at": {"type": "string", "format": "date-time"},
"expires_at": {"type": "string"},
"fork_hash": {
"type": "string",
"pattern": "^fork:sha256:[a-f0-9]{64}$"
},
"partial_layers": {"type": "object"},
"metadata": {"type": "object"}
}
}
¶
An AI orchestrator (Agent A) analyzes a dataset, creates a UPIP bundle, forks it to a specialist AI (Agent B) for deep analysis, and receives the result with cryptographic proof.¶
Agent A: capture_and_run(["python", "scan.py"], intent="Initial scan") fork_upip(actor_from="A", actor_to="B", intent="Deep analysis") deliver_fork(fork, to_agent="B") Agent B: pull_forks() resume_upip(fork, command=["python", "deep_analyze.py"]) ack_fork(fork, resume_hash=stack.hash, success=True)¶
Result: Both agents have UPIP stacks linked by fork_chain. Any auditor can verify the complete chain.¶
A command station dispatches N reconnaissance tasks to N drones. Each drone receives a fragment fork token, executes its assigned sector scan, and returns the result.¶
Command Station:
base_stack = capture_and_run(["mission_plan.py"])
for i in range(N):
fork = fork_upip(base_stack,
actor_from="command",
actor_to=f"drone-{i}",
fork_type="fragment",
metadata={"sector": sectors[i]})
deliver_fork(fork, to_agent=f"drone-{i}")
Each Drone:
fork_msg = pull_forks()
stack = resume_upip(fork, command=["scan_sector.py"])
ack_fork(fork, resume_hash=stack.hash)
Command Station:
# Verify all N results, reconstruct combined map
for ack in collect_acks():
verify(ack.resume_hash)
¶
Lab A publishes an experiment as a UPIP bundle. Lab B reproduces it independently and gets cryptographic proof that results match (or don't).¶
Lab A:
stack = capture_and_run(
["python", "train_model.py"],
source_dir="./experiment",
intent="Train model v3 on dataset-2026Q1"
)
save_upip(stack, "experiment-2026Q1.upip.json")
# Publish to journal / data repository
Lab B:
stack = load_upip("experiment-2026Q1.upip.json")
verify = reproduce_upip(stack)
# verify.match == True: exact reproduction
# verify.match == False: divergence (investigate)
¶
Expanded the draft from Fork Tokens alone to Task Capsules, Work Corridors, and Fork Tokens.¶
Added terminology for task capsule, work corridor, session_ref, groove, scar/mark, and actiond.¶
Added the continuity invariant: session_ref names the corridor, groove binds marks inside the corridor, and groove grants no authority.¶
Added actiond and installation ceremony language. A ceremony runner may render and mediate a UPIP-shaped process, but the box/admission layer decides whether a transition may execute.¶
Added the not_asked / not_consumed presence pattern for transitions that cannot consume human evidence.¶
Added process change ladder states: file_copied, package_carried, process_restarted, behavior_changed, consumer_observed, and fleet_converged.¶
Added .tza/TBZ carrier boundary language distinguishing
task capsules, rolodex info disks, carrier envelopes, and
admission receipts.¶
Added principal-bound retention guidance: runtime refs are context inside the capsule, not the long-term custody endpoint.¶
Added Continuity and Carrier Laundering security considerations.¶
Added RVP and actiond/human ceremony companion integration sections.¶
Split presence response, evidence consumption, and admission. A carrier response binds only after a named consumer verifies the same question, and the target still admits or refuses the concrete transition.¶
Clarified failure behavior: UPIP reports evidence and does not itself execute or admit a transition; local consumers may refuse on hash, capability, or expiry policy.¶
Added RFC 8174 alongside RFC 2119.¶
Changed intended status from Standards Track to Informational.¶
Added version field "1.1" to UPIP stack.¶
Added canonical serialization section (4.7), consistent with TIBET [TIBET] Section 5.1.¶
Added failure behavior specification (Section 7.3): what happens on hash mismatch, capability mismatch, and expiration. Each failure type classified as FATAL, DEGRADED, or MINOR.¶
Added Security Considerations for stolen fork tokens (10.6), unauthorized resume (10.7), and partial capability spoofing (10.8).¶
Added Privacy Considerations section (Section 9).¶
Clarified active_memory_hash as evidence-only, not reproducibility guarantee (emphasized in 5.4 and 10.3).¶
Made I-Poll transport explicitly optional (Section 8.2). UPIP does not depend on I-Poll.¶
Removed X-UPIP-* HTTP header registration from IANA.¶
Normalized companion protocol references to [TIBET], [JIS], [RVP], [AINS].¶
Actor identifiers now use JIS format throughout.¶
Added Integration section (Section 11) describing specific touchpoints with TIBET, JIS, and AINS.¶
The UPIP protocol was developed as part of HumoticaOS, an AI governance framework built on human-AI symbiosis. UPIP builds on concepts from the TIBET evidence trail protocol and extends them into the domain of process integrity and multi-actor continuation.¶
The Fork Token mechanism was inspired by the need for cryptographic chain of custody in multi-agent AI systems, where processes move between heterogeneous actors across trust boundaries.¶
The authors thank Codex (codex.aint) for the suite-wide cleanup analysis that informed this revision.¶