FireResult
Type Alias: FireResult
FireResult = {
effectStatus:EffectStatus;executed?:false;materialized?:false;ok:true;settlement:"settled"|"awaiting-state";transition:TransitionRecord;version:number;whenSettled:Promise<FireSettlement>; } | {available:string[];ok:false;reason:"UNKNOWN_AFFORDANCE"; } | {ok:false;reason:"STALE_CURSOR";version:number; } | {node:string;ok:false;reason:"NOT_ON_NODE"; } | {evidence:FilterCondition[];ok:false;reason:"GUARD_FAILED"; } | {issues:string;ok:false;reason:"PAYLOAD_INVALID"; } | {ok:false;overlay:string;reason:"BLOCKED_BY_OVERLAY"; } | {node:string;ok:false;reason:"NODE_NOT_VISIBLE"; } | {node:string;ok:false;reason:"STILL_MOUNTING"; } | {instances:string[];ok:false;reason:"INSTANCE_REQUIRED"; } | {instances:string[];ok:false;reason:"INSTANCE_UNKNOWN"; } | {affordanceId:string;evidence?:FilterCondition[];ok:false;reason:"TOOL_DISABLED"; } | {affordanceId:string;gesture?:Binding;ok:false;reason:"NOT_MATERIALIZED"; } | {affordanceId:string;askId?:string;ok:false;reason:"APPROVAL_REQUIRED"; } | {affordanceId:string;askId:string;ok:false;reason:"APPROVAL_SPENT"; } | {affordanceId:string;askId:string;differs:"action"|"input"|"instance"|"both"|"cannot-judge";ok:false;reason:"APPROVAL_MISMATCH"; } | {affordanceId:string;askId:string;ok:false;reason:"APPROVAL_STALE"; } | {affordanceId:string;askId:string;ok:false;reason:"APPROVAL_DECLINED"; } | {affordanceId:string;askId:string;ok:false;reason:"APPROVAL_REVOKED"; } | {affordanceId:string;ok:false;reason:"OFFER_REQUIRED"; } | {affordanceId:string;offeredFor?:string;offerId:string;ok:false;reason:"OFFER_NOT_ON_RECORD";why:"unknown"|"evicted"|"other-action"; } | {affordanceId:string;moved:FreshnessMovement[];offerId:string;ok:false;reason:"WORLD_MOVED"; } | {acknowledgementId?:string;affordanceId:string;moved:FreshnessMovement[];offerId:string;ok:false;reason:"ACKNOWLEDGEMENT_REQUIRED";why?:"evicted"; } | {acknowledgementId:string;affordanceId:string;moved:FreshnessMovement[];offerId:string;ok:false;reason:"ACKNOWLEDGEMENT_STALE"; } | {affordanceId:string;howToSettle:string;ok:false;pendingTransitionId:string;reason:"PRIOR_FIRE_PENDING";scope:"action"|"instance"|"payload"; } | {affordanceId:string;attempted:Principal;ok:false;reason:"PRINCIPAL_NOT_ALLOWED";required:ActorKind[]; } | {affordanceId:string;needs:"observability"|"postcondition";observability?:Observability;ok:false;reason:"EFFECT_NOT_VERIFIABLE"; }
Defined in: src/atom/types.ts:2003
What became of one fire — the success arm, or one typed refusal.
The REFUSAL SET GROWS, and a consumer should be written for that. 0.6.0 added
NOT_MATERIALIZED; this release adds the five APPROVAL_* words, because the
library can now refuse a high-effect fire no human approved. What never
happens is a reason CHANGING meaning: every value keeps exactly what it had,
and a new one is always a new fact, never an old one relabelled. So read the
reasons you know (if (!fired.ok && fired.reason === 'GUARD_FAILED') …) and
let the rest fall through as "refused, and here is the word" — an exhaustive
never check over today's set is the one consumer shape a future reason will
stop compiling, and adding the case is the whole fix.
Union Members
Type Literal
{ effectStatus: EffectStatus; executed?: false; materialized?: false; ok: true; settlement: "settled" | "awaiting-state"; transition: TransitionRecord; version: number; whenSettled: Promise<FireSettlement>; }
effectStatus
effectStatus:
EffectStatus
Whether the app's side has run — the truth AT RETURN TIME. The handler
is always deferred, so this can never be 'performed' here: a fire with
something bound to run returns 'pending', and whenSettled carries the
answer. settlement answers a different question (does a commit bundle
exist yet?) — reading it as "the app did it" was the reported bug.
executed?
optionalexecuted?:false
Present (false) only on an allowed unmaterialized agent fire: nothing ran.
materialized?
optionalmaterialized?:false
Present (false) only on an allowed unmaterialized agent fire: nothing is bound.
ok
ok:
true
settlement
settlement:
"settled"|"awaiting-state"
transition
transition:
TransitionRecord
version
version:
number
whenSettled
whenSettled:
Promise<FireSettlement>
Resolves ONCE with what actually happened. NEVER rejects: a refusal
arrives as data (effectStatus: 'refused'), because most callers drop
this result unread and an orphaned rejecting promise would be noise
they never opted into.
Type Literal
{ available: string[]; ok: false; reason: "UNKNOWN_AFFORDANCE"; }
Type Literal
{ ok: false; reason: "STALE_CURSOR"; version: number; }
Type Literal
{ node: string; ok: false; reason: "NOT_ON_NODE"; }
Type Literal
{ evidence: FilterCondition[]; ok: false; reason: "GUARD_FAILED"; }
Type Literal
{ issues: string; ok: false; reason: "PAYLOAD_INVALID"; }
Type Literal
{ ok: false; overlay: string; reason: "BLOCKED_BY_OVERLAY"; }
A shown blocking modal masks this tool's node. Close the modal first.
Type Literal
{ node: string; ok: false; reason: "NODE_NOT_VISIBLE"; }
The tool's node carries an explicit not-visible signal (hidden tab, closed modal).
Type Literal
{ node: string; ok: false; reason: "STILL_MOUNTING"; }
RETRIABLE: the node's mounts have not arrived yet (mid-navigation / deep link).
Type Literal
{ instances: string[]; ok: false; reason: "INSTANCE_REQUIRED"; }
Type Literal
{ instances: string[]; ok: false; reason: "INSTANCE_UNKNOWN"; }
Type Literal
{ affordanceId: string; evidence?: FilterCondition[]; ok: false; reason: "TOOL_DISABLED"; }
RETRIABLE: the control is registered but currently greyed out (disabled).
affordanceId
affordanceId:
string
evidence?
optionalevidence?:FilterCondition[]
The enabledWhen conjuncts that did NOT hold — the machine proof of this
refusal, in the shape GUARD_FAILED serves. It exists so a reader can
name the FIELD instead of relaying a conclusion it cannot explain.
Present only where the app DECLARED a condition. An imperative
setEnabled(false) names no conditions, so this stays absent rather than
inventing one — and it is never a promise: meeting the condition may
still leave the control off through a wire that declares no reason.
ok
ok:
false
reason
reason:
"TOOL_DISABLED"
Type Literal
{ affordanceId: string; gesture?: Binding; ok: false; reason: "NOT_MATERIALIZED"; }
Declared but nothing is bound: an agent fire would execute NOTHING (register a tool group, or opt the session into read-only touring via allowUnmaterializedFires). The app-self-report tier (source 'user'/'system' or invoke:false) is never gated — that motion really happened.
affordanceId
affordanceId:
string
gesture?
optionalgesture?:Binding
The DECLARED gesture nothing is wired to perform — so the refusal says "this is a click on the checkout button", not "nothing is bound". Absent when the edge declared no binding (there the old words were already the whole truth).
ok
ok:
false
reason
reason:
"NOT_MATERIALIZED"
Type Literal
{ affordanceId: string; askId?: string; ok: false; reason: "APPROVAL_REQUIRED"; }
No recorded human approval authorizes this high-effect fire. askId echoes
the pointer that was presented, when one was and it named nothing usable.
Type Literal
{ affordanceId: string; askId: string; ok: false; reason: "APPROVAL_SPENT"; }
That approval was already spent by an earlier fire. One yes, one action.
Type Literal
{ affordanceId: string; askId: string; differs: "action" | "input" | "instance" | "both" | "cannot-judge"; ok: false; reason: "APPROVAL_MISMATCH"; }
The human approved something else — differs names which join failed.
Type Literal
{ affordanceId: string; askId: string; ok: false; reason: "APPROVAL_STALE"; }
The yes is older than this session's rules allow, or predates a state change.
Type Literal
{ affordanceId: string; askId: string; ok: false; reason: "APPROVAL_DECLINED"; }
The human said no to this ask. Terminal for that askId, for the session's life.
Type Literal
{ affordanceId: string; askId: string; ok: false; reason: "APPROVAL_REVOKED"; }
The human gave a yes and took it back before it was spent (Session.revokeAsk). The withdrawn pointer authorizes nothing; a fresh ask mints a new card.
Type Literal
{ affordanceId: string; ok: false; reason: "OFFER_REQUIRED"; }
A freshness axis enforces, and this fire cited no offer. Look again
(available() / whats_here) and cite the row you plan against — there is
nothing to compare a fire to otherwise.
Type Literal
{ affordanceId: string; offeredFor?: string; offerId: string; ok: false; reason: "OFFER_NOT_ON_RECORD"; why: "unknown" | "evicted" | "other-action"; }
The cited offer is not one this session can answer THIS fire with, and
why says which of the three things happened. 'unknown' — no such id was
ever minted here; 'evicted' — it was, and the bounded ledger has since
dropped it; 'other-action' — the id IS on this session's record and it
names a DIFFERENT control, so it answers that row and not this one. Three
words rather than one because the fixes differ and because collapsing them
would let the library report its own bound, or its own row, as a caller's
forged citation.
affordanceId
affordanceId:
string
offeredFor?
optionalofferedFor?:string
The control that offer WAS minted for — present only under
'other-action', where this session really does hold the row. An
authored action id, never app data.
offerId
offerId:
string
ok
ok:
false
reason
reason:
"OFFER_NOT_ON_RECORD"
why
why:
"unknown"|"evicted"|"other-action"
Type Literal
{ affordanceId: string; moved: FreshnessMovement[]; offerId: string; ok: false; reason: "WORLD_MOVED"; }
Something the row was offered under has moved, and this control's policy
says refuse. moved names the axes and the KEYS — never a value, never a
conclusion. Fix by looking again and citing the fresh offer.
Type Literal
{ acknowledgementId?: string; affordanceId: string; moved: FreshnessMovement[]; offerId: string; ok: false; reason: "ACKNOWLEDGEMENT_REQUIRED"; why?: "evicted"; }
Something moved and this control's policy says the caller must acknowledge
it first. acknowledgementId echoes the pointer that was presented, when
one was and it named nothing usable — exactly as APPROVAL_REQUIRED echoes
askId. Acknowledge with session.acknowledgeStale(actionId, keys, { offerId })
and cite what it hands back.
acknowledgementId?
optionalacknowledgementId?:string
affordanceId
affordanceId:
string
moved
moved:
FreshnessMovement[]
offerId
offerId:
string
ok
ok:
false
reason
reason:
"ACKNOWLEDGEMENT_REQUIRED"
why?
optionalwhy?:"evicted"
'evicted' — and only ever that. The receipt cited here IS one this
session wrote, and this session's own cap
(SessionOptions.maxAcknowledgements) dropped it. Present only on
that one case, because it is the only one that is not the caller's
mistake: the fix is a bigger cap, or acknowledge again. Absent covers
every other unusable pointer, deliberately without a taxonomy of how.
Type Literal
{ acknowledgementId: string; affordanceId: string; moved: FreshnessMovement[]; offerId: string; ok: false; reason: "ACKNOWLEDGEMENT_STALE"; }
That acknowledgement was made in a world that has since moved on. A step performed against different facts is not a step performed against these.
Type Literal
{ affordanceId: string; howToSettle: string; ok: false; pendingTransitionId: string; reason: "PRIOR_FIRE_PENDING"; scope: "action" | "instance" | "payload"; }
A prior occurrence of this control has not come to rest, and the action
declares concurrency: { mode: 'single-flight' }. It clears on SETTLEMENT
and nothing else — no timeout, no read, and not the caller reporting it
done. howToSettle names the doors that can.
affordanceId
affordanceId:
string
howToSettle
howToSettle:
string
The authored sentence naming every door that can settle it.
ok
ok:
false
pendingTransitionId
pendingTransitionId:
string
The fire that is still out there — ask session.settlementOf(id) about it.
reason
reason:
"PRIOR_FIRE_PENDING"
scope
scope:
"action"|"instance"|"payload"
Which scope matched: the action, this card, or this exact input.
Type Literal
{ affordanceId: string; attempted: Principal; ok: false; reason: "PRINCIPAL_NOT_ALLOWED"; required: ActorKind[]; }
This principal may not perform this action — the app declared who may, and
this is not one of them. required NAMES the kinds, because an agent told
only "no" tries again while an agent told "a human must do this" asks the
person. Never a retry: nothing about the world changes this one.
affordanceId
affordanceId:
string
attempted
attempted:
Principal
The principal that tried, echoed so one row answers the whole question.
ok
ok:
false
reason
reason:
"PRINCIPAL_NOT_ALLOWED"
required
required:
ActorKind[]
Type Literal
{ affordanceId: string; needs: "observability" | "postcondition"; observability?: Observability; ok: false; reason: "EFFECT_NOT_VERIFIABLE"; }
This session requires a high-effect action to say how its effect can be
checked, and this one cannot. needs says which half is missing:
'observability' — nothing was declared; 'postcondition' — what was
declared is not a check (key presence is not value correctness). Fixed by
the APP, at the keyboard, not by the caller at run time.
affordanceId
affordanceId:
string
needs
needs:
"observability"|"postcondition"
observability?
optionalobservability?:Observability
What the app did declare, when it declared something.
ok
ok:
false
reason
reason:
"EFFECT_NOT_VERIFIABLE"