Skip to main content

InteractionStore

@forge/monorepo


@forge/monorepo / backend/src / InteractionStore

Interface: InteractionStore

Defined in: backend/src/persistence/index.ts:348

Durable human-in-the-loop interactions (docs/04 → Questions & Approvals). Pending questions and approvals survive restart/deploy. answer/decide are idempotent — the first call resolves the interaction and reports alreadyResolved: false; a duplicate reports true and changes nothing, so a continuation is queued exactly once.

Methods

answerQuestion()

answerQuestion(input): Promise<{ alreadyResolved: boolean; question: PendingQuestion; }>

Defined in: backend/src/persistence/index.ts:358

Record answers.

A value may be a string or an array of strings (#155): a multi-select question has several answers, and QuestionSpec.multiple exists to say so. Widened rather than encoded — comma-joining would make an answer containing a comma indistinguishable from two answers.

Parameters

input

TenantScope & object

Returns

Promise<{ alreadyResolved: boolean; question: PendingQuestion; }>


claimApproval()

claimApproval(input): Promise<{ approval: PendingApproval; claimed: boolean; }>

Defined in: backend/src/persistence/index.ts:401

Claim the single execution a decided approval authorizes — the mechanism behind allow-once.

A compare-and-set, not a read-then-write: two workers racing a resumed run must see exactly one claimed: true, because the loser executing anyway is a duplicate publish. claimed is false for an approval that is already claimed and for one nobody has decided, so an undecided interaction can never be turned into permission.

Parameters

input

TenantScope & object

Returns

Promise<{ approval: PendingApproval; claimed: boolean; }>


createApproval()

createApproval(input): Promise<void>

Defined in: backend/src/persistence/index.ts:379

Parameters

input

TenantScope & object

Returns

Promise<void>


createQuestion()

createQuestion(input): Promise<void>

Defined in: backend/src/persistence/index.ts:349

Parameters

input

TenantScope & object

Returns

Promise<void>


decideApproval()

decideApproval(input): Promise<{ alreadyResolved: boolean; approval: PendingApproval; }>

Defined in: backend/src/persistence/index.ts:381

Parameters

input

TenantScope & object

Returns

Promise<{ alreadyResolved: boolean; approval: PendingApproval; }>


findAnsweredQuestion()

findAnsweredQuestion(input): Promise<PendingQuestion | null>

Defined in: backend/src/persistence/index.ts:377

The run's answered question — what a resumed run must tell the model — #163.

The approval side has had findDecidedApproval from the start; questions had nothing, so a resumed run could not learn that its question had been answered. The observable result was a loop: the person picked an option, the run resumed, the model had no idea and asked the same question again.

No claim, unlike an approval. A claim exists to make an external write happen exactly once; this produces a line of history, which is idempotent — and scoping to the run already bounds it, since the next turn is a different run. Adding a claim would mean a recovered run rebuilt its history without the answer, which is the bug again.

Parameters

input

TenantScope & object

Returns

Promise<PendingQuestion | null>


findApproval()

findApproval(input): Promise<PendingApproval | null>

Defined in: backend/src/persistence/index.ts:386

One approval by id — how a one-time authorization is verified against what was stored.

Parameters

input

TenantScope & object

Returns

Promise<PendingApproval | null>


findDecidedApproval()

findDecidedApproval(input): Promise<PendingApproval | null>

Defined in: backend/src/persistence/index.ts:392

The run's decided-but-unclaimed approval: what a resumed run must execute. Decided and claimed are separate states because the decision is the human's and the claim is the runtime's — without the second, nothing distinguishes "approved, waiting to run" from "approved, already run".

Parameters

input

TenantScope & object

Returns

Promise<PendingApproval | null>


findPendingApproval()

findPendingApproval(input): Promise<PendingApproval | null>

Defined in: backend/src/persistence/index.ts:380

Parameters

input

TenantScope & object

Returns

Promise<PendingApproval | null>


findPendingQuestion()

findPendingQuestion(input): Promise<PendingQuestion | null>

Defined in: backend/src/persistence/index.ts:350

Parameters

input

TenantScope & object

Returns

Promise<PendingQuestion | null>