> ## Documentation Index
> Fetch the complete documentation index at: https://docs.parmanasystems.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Write it down before you do it

A refund agent asks for ₹7,800 back for a customer whose order never arrived. The policy approves, the store manager
has signed an approval, and Parmana releases the refund to the payment service. Ten seconds pass. The call times out.

Did the customer get ₹7,800?

You do not know. The request may never have reached the payment provider. It may have reached it, been processed,
and the answer got lost on the way back. A system that reports this as "failed" invites the obvious next step: try
again. If the first refund went through, the customer now has ₹15,600.

This is not hypothetical for me. A repeat test run of Parmana recorded exactly this: a real timeout from a slow
payment staging call, after ten seconds.

## Two problems, one idea

The first problem is the record. Parmana's signed Execution Trust Record contains the result of the action, so it
can only be built after the action is released. If building or storing it fails, an action has run and nothing signed
describes it. Before 21 September that was possible in Parmana. The context needed to rebuild the record existed only
in the memory of the request that failed.

The second problem is language. "Failed" and "we don't know" are different facts, and they call for opposite
actions.

The idea for both is old and simple: write down what you are about to do, before you do it. If you cannot write it
down, do not do it. And when you do not know the outcome, say so.

## How Parmana does it

**An Execution Intent is signed and stored before release.** After the policy approves, the authorization is signed
and a signing readiness check passes, the runtime signs an intent and writes it to the database. Only then is the
action released to the connector. If the intent cannot be signed or stored, the caller gets a 503 and nothing is
released. This is enforced everywhere except test and development, there is no switch to turn it off in
production, and the readiness endpoint reports a missing intents table before the first real request hits it.

The intent holds only what exists before release: the ids, the policy reference, the hashes of the policy content,
the facts and the executable content copied from the signed authorization, the action and target, the caller, and
when it was created. It never holds the result and never the raw parameters; the content hash binds it to them. It
is signed with the same key as the Trust Record, so anyone with the public key can verify it, through an API route
that needs no credential or offline from a clone of the repository. The Python SDK has an offline verifier, and the
TypeScript SDK has one from version 1.3.0.

**Each intent has a state.** It is kept next to the intent, and it is not signed:

* **Prepared**: signed and stored; the action may or may not have been released.
* **Released**: the connector answered and the execution context was saved; no Trust Record yet.
* **Finalized**: a signed Trust Record exists. The normal outcome.
* **Errored**: the release stage raised an error. The action may still have run.
* **Resolved**: a verified human checked the target system and closed it.

**A missing record can be rebuilt.** For a released intent, a person with a verified human credential can run
finalize. It rebuilds the Trust Record from the saved context, verifies it, issues the receipt, and never calls the
connector. Running it twice, or twice at once, produces one record.

**An unknown outcome is called unknown.** Since 25 September, when the release fails after the request was sent, the
caller gets a 502 with the outcome marked unknown, not "failed". Execution has four statuses: executed, not
executed, failed (the target system said it failed), and unknown (the call failed, so nobody knows). The guidance is
explicit: do not resubmit under a new transaction id; check the target system first. After an operator checks, they
close the intent as executed or not executed, with a required note. The ₹7,800 refund that timed out becomes an
errored intent, not a silent failure.

**What was verified.** On 21 September, against the production Docker image, a real Postgres and the real AWS KMS
signing key, 23 of 23 checks passed: a normal request, a released action whose Trust Record could not be stored and
was then rebuilt with the connector called exactly once in total, and an intent that could not be stored, which
released nothing. With closing by hand added, the run passed 37 of 37. Since 1 October the normal path has also run
in production.

## What it does not do

* **An intent does not prove the action ran**, or what happened. It proves what was about to be released. A crash
  between storing the intent and releasing leaves an intent for an action that never ran.
* **Not every released action gets a signed Trust Record.** If the context save after release also failed, finalize
  refuses with a 409, and the outcome has to be established at the target system by hand.
* **Closing an intent by hand is not signed.** It is an attributed, timestamped statement by a person. It is not
  tamper evident and does not create a Trust Record. If an operator closes one as executed, the signed evidence is
  still only the intent.
* **Not verified on Vercel**: the failure paths (finalize, resolve) and a real Paytm refund. The extra signing cost
  (about 35 ms) was measured once from a developer machine, not from production.
* **An action refused at release stays errored** until a person closes it; there is no "not released" state yet.
* **Approved requests are slow today.** One took 24 to 32 seconds in production, so clients are told to use a 120
  second timeout and to read the record before sending anything again.
* **Transactions from before 21 September have no intent.**

## Takeaway

When an agent can move money, "I don't know if it happened" is a real answer, and the most dangerous thing a system
can do is round it to "failed". Write down what you are about to do before you do it, refuse to act if you cannot,
and give the unknown its own name so nobody retries their way into a double refund.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.