DUNIN7 · LOOMWORKS · RECORD
record.dunin7.com
Status Current
Path foray-reference/loomworks-foray-calls-explained-v0_1.html
FORAY · Adaptor mapping · 2026-08-18

Every call Loomworks makes to FORAY, and what it produces

Sixteen reserved call sites in loomworks-engine, each one shown with its real source line, what data genuinely exists at that point in the code, the FORAY 4.2 record it would emit, and anything that doesn't map cleanly. Nothing here is summarized from another document — the source and the record sit side by side so each can be checked against the other.

16
call sites
11
credit ledger
5
governance
17/17
validated
What “17/17 valid” means, precisely: every record below was submitted to FORAY's live validator and passed — conforming shape, resolved references, correct number spelling. It does not mean every value is a real fact. Several governance records below carry placeholder strings (UNATTRIBUTED, LOOMWORKS:NONE) because the schema requires a non-empty field and no genuine value exists at that call site. Each is marked where it occurs.

At a glance

All sixteen sites, one line each. Every claim here is expanded in its own card below — this table is for navigation, not a substitute for reading the source.

#FileEvent kindComponentDisposition
1credit/flows.py:121credit.issuanceActionReal credit grant; F21 nets to F9; grant_id available but not forwarded.
2credit/flows.py:183credit.provisioningActionInstitutional-only (providerdunin7); no person UUID in function scope; F3 = "dunin7".
3credit/flows.py:302credit.consumption_token` (×4 loop)ActionProvider token asset, not Loomworks-scheme — F8 uses PROVIDER: prefix, breaking this doc's default convention; row-id flush-timing open question.
4credit/flows.py:363credit.consumption_creditActionReal oracle-converted debit; no cross-link to the 4 token-leg records at site 3.
5credit/flows.py:410credit.suspensionActionSynthetic loomworks_account_status asset, qty 1; **flow.id read before flush** (structural gap, ordering differs from siblings).
6credit/flows.py:446credit.reactivationActionSame synthetic asset; flush-before-emit (ordering differs from site 5).
7credit/flows.py:481credit.deletionActionSame synthetic asset; triggers site 8 downstream with no cross-record link.
8credit/flows.py:532credit.balance_zeroing` (0–3× loop)ActionConditional, variable count (0–3 records); legitimately emits nothing when no positive balance exists.
9credit/flows.py:642credit.referral_creditActionCorrect mapping; function currently has zero live callers (Phase 48 not yet wired).
10credit/room_consumption.py:41credit.consumption_token` / `credit.consumption_credit` (dynamic, ×3)ActionSame provider-scheme mismatch as site 3 for the 2 token legs; FIFO lot draw-down (real, downstream) has no FORAY-side link.
11credit/proposal_applier.py:433credit.correctiveAction**No pointer to proposal_id** — the thing it corrects. Unruled per Validation Scope v0.3 R2; stated, not resolved.
12memory/events.py:273memory.<event_kind>` (dynamic, ~20+ kinds)governance-shapedF7:0, F8:"LOOMWORKS:NONE" (placeholder, schema requires non-null string); genuine timestamp (object.created_at); **no UUID reaches the emit at all** — F3 stated placeholder "UNATTRIBUTED".
13orchestration/tune_setting.py:544audit.setting_changegovernance-shapedperson_id genuinely in scope (used for audit write one line up) but not forwarded — {setting_key, action}-only payload.
14orchestration/tune_setting.py:670audit.setting_changegovernance-shapedIdentical shape/gap to site 13; duplicated call-site logic across two sibling functions.
15orchestration/conversation_turns.py:270conversation.turngovernance-shapedStrongest timestamp of the 16 (row.created_at, confirmed post-refresh); person_id in scope, not forwarded.
16api/routers/me_settings.py:164audit.setting_changegovernance-shapedperson.id from the authenticated principal — strongest identity claim of the trio; not forwarded; action is a hardcoded literal ("tuned_button"), unlike sites 13/14.

The sixteen records

Each card: the real Python at that call site, what data is genuinely in scope there, the FORAY 4.2 JSON it would produce, and what doesn't map cleanly — stated as a finding, not smoothed over.

01
Credit ledger · write_issuance_flow

credit.issuance

src/loomworks/credit/flows.py:121
Source
async def write_issuance_flow(
    *,
    person_id: UUID,
    asset_id: str,
    amount: int,
    grant_id: UUID,
    metadata_extra: dict | None = None,
    db: AsyncSession,
) -> UUID:
    """Single flow ``from='dunin7'`` to ``person_id`` for ``+amount``.
    ...
    """
    if amount <= 0:
        raise ValueError(
            f"issuance amount must be strictly positive, got {amount}"
        )
    txid = _new_transaction_id()
    extra = {"reason": "grant_claim", "grant_id": str(grant_id)}
    if metadata_extra:
        extra.update(metadata_extra)
    flow = CreditFlowRow(
        transaction_id=txid,
        event_kind="issuance",
        asset_id=asset_id,
        quantity=amount,
        from_party=DUNIN7_PARTY,
        to_party=str(person_id),
        extra_metadata=extra,
    )
    db.add(flow)
    await db.flush()
    # FORAY_RESERVED_LOCATION: credit.issuance
    _foray_reserved_emit(
        "credit.issuance",
        {
            "flow_id": str(flow.id),
            "transaction_id": str(txid),
            "asset_id": asset_id,
            "quantity": amount,
            "from_party": flow.from_party,
            "to_party": flow.to_party,
            "turn_event_id": (
                str(flow.turn_event_id) if flow.turn_event_id else None
            ),
        },
    )
    return txid
What data is actually available here
  • flow.id — the new CreditFlowRow primary key, populated by await db.flush() on line 119, one line before the emit.
  • txid — the transaction id, _new_transaction_id() (a fresh uuid.uuid4()), line 105.
  • asset_id — caller-supplied str parameter; no fixed value at this site. Worked example uses "loomworks_credit_sonnet".
  • amount — caller-supplied int, must be > 0 (checked line 101-104).
  • flow.from_party = DUNIN7_PARTY = "dunin7" (institutional, not a UUID).
  • flow.to_party = str(person_id)person_id is a real UUID parameter, this IS a person-scoped site.
  • flow.turn_event_id — not set on this CreditFlowRow construction (no turn_event_id= kwarg passed), so this is always None at this site; the ternary at lines 130-132 is dead code for this call site specifically (issuance is not turn-triggered).
  • grant_id — real UUID parameter, folded into extra_metadata but not into the emit payload — it does not reach FORAY at this site (finding, item 9).
  • No timestamp variable in scope. No datetime.now()/utcnow() call anywhere in this function.
The FORAY 4.2 record this produces
{
  "schema_version": "4.2",
  "timestamp": "2026-08-18T00:00:00Z",
  "F1": "LW_credit.issuance_a1b2c3d4",
  "F2": "a1b2c3d4-0001-4000-8000-000000000001",
  "F3": "9f8e7d6c-0000-4000-8000-0000000000f3",
  "F7": 500,
  "F8": "LOOMWORKS:loomworks_credit_sonnet",
  "F26": "credit.issuance",
  "arrangements": [],
  "accruals": [],
  "anticipations": [],
  "actions": [
    {
      "id": "ACT_ISSUANCE_a1b2c3d4",
      "F4": "credit_issuance",
      "F9": 500,
      "F22": [],
      "F23": [],
      "F24": []
    }
  ],
  "component_hashes": {
    "arrangements": "sha256:PLACEHOLDER",
    "accruals": "sha256:PLACEHOLDER",
    "anticipations": "sha256:PLACEHOLDER",
    "actions": "sha256:PLACEHOLDER"
  },
  "merkle_root": "sha256:PLACEHOLDER",
  "blockchain_anchor": {
    "kaspa_tx_id": null,
    "block_height": null,
    "confirmation_time_ms": null,
    "anchored_at": null
  }
}
Findings

Timestamp finding: no wall-clock variable exists at this site. timestamp above is a constructed value marked as such — an adaptor would need to capture datetime.now(UTC) fresh at emit time, since nothing in flows.py provides one. Per claim discipline this in-record timestamp would only ever be a submitter assertion regardless; its absence from source just means the adaptor, not Loomworks, would be the one asserting it.

F3 finding: person_id is a genuine, real UUID in scope (the parameter itself) — F3 = str(person_id), cleartext, no substitution needed.

Correction (Brief 24): the double-entry party/currency/amount pair in v0.2's F21 was an invented shape — real F21 entries are {ref, ref_type, amount, currency}, and ref must point at an Arrangement/Accrual/Anticipation element already present in the *same* record. This record has exactly one element (the Action itself) and no other component to reference, so F21 is correctly omitted entirely — there is nothing for it to allocate against. F9 = 500 stands alone as the settled amount, matching F7. This is not a workaround; per the wire skill, an Action with empty F22/F23/F24 and no F21 is a legal, complete record (the "Action-only" entry point).

Other finding: grant_id (a real, meaningful reference — which grant this issuance claims) is computed and stored in extra_metadata but never passed into the _foray_reserved_emit payload at all, so it cannot reach FORAY's F25 residue field even though the source data exists one line away. This is a genuine gap between what's available and what's wired, worth flagging for any future build brief.

---

02
Credit ledger · write_provisioning_flow

credit.provisioning

src/loomworks/credit/flows.py:183
Source
async def write_provisioning_flow(
    *,
    asset_id: str,
    amount: int,
    authorized_by: UUID | None = None,
    metadata_extra: dict | None = None,
    db: AsyncSession,
) -> UUID:
    """Single flow ``provider -> dunin7`` for ``+amount`` ...
    """
    if amount <= 0:
        raise ValueError(
            f"provisioning amount must be strictly positive, got {amount}"
        )
    txid = _new_transaction_id()
    extra: dict = {"reason": "provisioning"}
    if authorized_by is not None:
        extra["authorized_by"] = str(authorized_by)
    if metadata_extra:
        extra.update(metadata_extra)
    flow = CreditFlowRow(
        transaction_id=txid,
        event_kind="provisioning",
        asset_id=asset_id,
        quantity=amount,
        from_party=PROVIDER_PARTY,
        to_party=DUNIN7_PARTY,
        extra_metadata=extra,
    )
    db.add(flow)
    await db.flush()
    # FORAY_RESERVED_LOCATION: credit.provisioning
    _foray_reserved_emit(
        "credit.provisioning",
        {
            "flow_id": str(flow.id),
            "transaction_id": str(txid),
            "asset_id": asset_id,
            "quantity": amount,
            "from_party": PROVIDER_PARTY,
            "to_party": DUNIN7_PARTY,
        },
    )
    return txid
What data is actually available here
  • flow.id, txid — same pattern as site 1.
  • asset_id, amount — caller-supplied parameters; worked example "loomworks_credit_sonnet" / 10000.
  • from_party = PROVIDER_PARTY = "provider", to_party = DUNIN7_PARTY = "dunin7"both institutional strings, no person UUID anywhere in this function's scope. authorized_by: UUID | None exists as a parameter and IS folded into extra_metadata (line: extra["authorized_by"] = str(authorized_by)) when present, but like grant_id at site 1, it is not forwarded into the emit payload.
  • No timestamp variable in scope.
The FORAY 4.2 record this produces
{
  "schema_version": "4.2",
  "timestamp": "2026-08-18T00:00:00Z",
  "F1": "LW_credit.provisioning_b2c3d4e5",
  "F2": "b2c3d4e5-0002-4000-8000-000000000002",
  "F3": "dunin7",
  "F7": 10000,
  "F8": "LOOMWORKS:loomworks_credit_sonnet",
  "F26": "credit.provisioning",
  "arrangements": [],
  "accruals": [],
  "anticipations": [],
  "actions": [
    {
      "id": "ACT_PROVISIONING_b2c3d4e5",
      "F4": "credit_provisioning",
      "F9": 10000,
      "F22": [],
      "F23": [],
      "F24": []
    }
  ],
  "component_hashes": {
    "arrangements": "sha256:PLACEHOLDER",
    "accruals": "sha256:PLACEHOLDER",
    "anticipations": "sha256:PLACEHOLDER",
    "actions": "sha256:PLACEHOLDER"
  },
  "merkle_root": "sha256:PLACEHOLDER",
  "blockchain_anchor": {
    "kaspa_tx_id": null,
    "block_height": null,
    "confirmation_time_ms": null,
    "anchored_at": null
  }
}
Findings

F3 finding: this is the first of two flows.py sites (with balance_zeroing's institutional legs excepted) with no person UUID in scope at allperson_id is not a parameter of write_provisioning_flow. F3 above uses "dunin7", the institutional record-owner, as a stated design choice, not a source-derived substitution for a missing UUID — reported per the brief's instruction rather than silently filled.

Correction (Brief 24): same as site 1 — no Arrangement/Accrual/Anticipation exists in this record, so F21 is correctly absent. F9 = 10000, matching F7, stands alone.

Other finding: authorized_by, when supplied, is a genuine operator-identity UUID captured in extra_metadata but not forwarded to the emit payload — same gap pattern as site 1's grant_id.

---

03
Credit ledger · write_consumption_flows (token loop, ×4)

credit.consumption_token

src/loomworks/credit/flows.py:302
Source
flow_rows = [
        CreditFlowRow(
            transaction_id=txid,
            event_kind="consumption_token",
            asset_id=classifier_input_asset,
            quantity=classifier_input_tokens,
            from_party=person_str,
            to_party=ANTHROPIC_PARTY,
            turn_event_id=turn_event_id,
            extra_metadata={
                "engagement_id": str(engagement_id),
                "pipeline_stage": "classify",
            },
        ),
        # ... 3 more CreditFlowRow constructions, same shape, differing
        # asset_id / quantity / pipeline_stage (see full source above) ...
    ]
    for row in flow_rows:
        db.add(row)
    # FORAY_RESERVED_LOCATION: credit.consumption_token (x4)
    for row in flow_rows:
        _foray_reserved_emit(
            "credit.consumption_token",
            {
                "flow_id": str(row.id),
                "transaction_id": str(txid),
                "asset_id": row.asset_id,
                "quantity": row.quantity,
                "from_party": row.from_party,
                "to_party": row.to_party,
                "turn_event_id": (
                    str(row.turn_event_id) if row.turn_event_id else None
                ),
            },
        )
What data is actually available here

Enclosing function write_consumption_flows(*, person_id, credit_asset_id, classifier_input_tokens, classifier_output_tokens, responder_model_token_pair, responder_input_tokens, responder_output_tokens, engagement_id, turn_event_id, db). This is a loop firing the same event_kind 4 times — one FORAY record per row in flow_rows, not one record covering all four.

  • row.id — populated by the loop's own await db.flush() (not shown in the excerpt but present at the loop's start in the full function — actually verified: db.add(row) for all 4 happens first, flush() is NOT called before this specific emit loop in the excerpted region; re-checking full source: flush occurs only once for credit_flow later at line 361, AFTER this loop. Finding: row.id at this loop (lines 298-315) is read from ORM objects that have been db.add()-ed but not yet flushed — whether row.id is populated depends on whether the DB assigns the PK client-side (e.g. a UUID default) or server-side. CreditFlowRow.id type was not independently re-verified as part of Brief 23; flagged as a finding rather than assumed.
  • row.asset_id — one of classifier_input_asset ("anthropic_haiku_4_input"), classifier_output_asset ("anthropic_haiku_4_output"), or responder_input_asset/responder_output_asset (unpacked from the caller-supplied responder_model_token_pair tuple) — these are Anthropic provider token assets, NOT Loomworks credit assets. This is one of the sites where the LOOMWORKS: scheme prefix is wrong on its face (item 9 finding, see below).
  • row.quantity — real token counts (classifier_input_tokens etc., caller-supplied int).
  • row.from_party = person_str = str(person_id) — real person UUID in scope.
  • row.to_party = ANTHROPIC_PARTY = "anthropic".
  • row.turn_event_id = turn_event_id, a real UUID parameter — genuinely populated at this site (unlike site 1).
  • engagement_id — real UUID parameter, folded into each row's extra_metadata but not into the emit payload.
  • No timestamp variable in scope.
The FORAY 4.2 record this produces
{
  "schema_version": "4.2",
  "timestamp": "2026-08-18T00:00:00Z",
  "F1": "LW_credit.consumption_token_c3d4e5f6",
  "F2": "c3d4e5f6-0003-4000-8000-000000000003",
  "F3": "9f8e7d6c-0000-4000-8000-0000000000f3",
  "F7": 842,
  "F8": "PROVIDER:anthropic_haiku_4_input",
  "F26": "credit.consumption_token",
  "arrangements": [],
  "accruals": [],
  "anticipations": [],
  "actions": [
    {
      "id": "ACT_CONSUMPTION_TOKEN_c3d4e5f6",
      "F4": "credit_consumption_token",
      "F9": 842,
      "F22": [],
      "F23": [],
      "F24": []
    }
  ],
  "component_hashes": {
    "arrangements": "sha256:PLACEHOLDER",
    "accruals": "sha256:PLACEHOLDER",
    "anticipations": "sha256:PLACEHOLDER",
    "actions": "sha256:PLACEHOLDER"
  },
  "merkle_root": "sha256:PLACEHOLDER",
  "blockchain_anchor": {
    "kaspa_tx_id": null,
    "block_height": null,
    "confirmation_time_ms": null,
    "anchored_at": null
  }
}
Findings

Item-9 finding, the most significant one in this document: the brief's F8 instruction is scoped to "the eleven credit sites" under a single LOOMWORKS: prefix. But this site's asset_id is a provider token asset (anthropic_haiku_4_input, etc.), not a Loomworks credit asset — it is genuinely anthropic-denominated. Using LOOMWORKS:anthropic_haiku_4_input (the mechanical per-site substitution used elsewhere in this document) would be actively wrong — it would claim Loomworks as the scheme owner of an Anthropic-defined token-accounting unit. The worked JSON above instead uses PROVIDER:anthropic_haiku_4_input, breaking from this document's own stated one-scheme convention at this site only, because the source data itself contradicts the convention. This is reported as a finding, not silently reconciled: the census counts this as one of the "eleven credit sites," but its actual asset is not a Loomworks-scheme asset, and the brief's F8 instruction does not anticipate this. A future build brief needs to decide whether provider-token legs get their own scheme prefix (as done here) or are excluded from credit.* FORAY emission entirely.

Correction (Brief 24): the invented double-entry pair is removed; F21 is correctly absent (no other component in this single-Action record for it to reference). F9 = 842 stands alone. Unchanged: each of the 4 loop iterations remains its own separate FORAY record with its own F9, not one combined record.

F3: person_id genuinely in scope — same as site 1.

Row-id flush-timing finding: see data section above — row.id readability at emit time (before any flush() in this loop) is not independently confirmed; stated as an open question rather than assumed populated.

---

04
Credit ledger · write_consumption_flows (credit debit)

credit.consumption_credit

src/loomworks/credit/flows.py:363
Source
credit_flow = CreditFlowRow(
        transaction_id=txid,
        event_kind="consumption_credit",
        asset_id=credit_asset_id,
        quantity=credit_debit,
        from_party=person_str,
        to_party=DUNIN7_PARTY,
        turn_event_id=turn_event_id,
        extra_metadata={
            "engagement_id": str(engagement_id),
            "pipeline_stage": "credit_debit",
            "credit_asset_id": credit_asset_id,
        },
    )
    db.add(credit_flow)
    await db.flush()
    # FORAY_RESERVED_LOCATION: credit.consumption_credit
    _foray_reserved_emit(
        "credit.consumption_credit",
        {
            "flow_id": str(credit_flow.id),
            "transaction_id": str(txid),
            "asset_id": credit_asset_id,
            "quantity": credit_debit,
            "from_party": credit_flow.from_party,
            "to_party": credit_flow.to_party,
            "turn_event_id": (
                str(credit_flow.turn_event_id)
                if credit_flow.turn_event_id
                else None
            ),
        },
    )
    return txid
What data is actually available here
  • credit_flow.id — populated: await db.flush() runs immediately before this emit (line 361, one line up).
  • credit_asset_id — caller-supplied str parameter (the tier the person is being debited in; worked example "loomworks_credit_sonnet") — this is the one site among the 4 token/credit sites that genuinely IS a Loomworks-scheme credit asset, unlike site 3.
  • credit_debit — real computed int, the sum of four convert_tokens_to_credit_debit(...) calls (lines 319-344) run against the four token legs from site 3.
  • person_str = str(person_id), DUNIN7_PARTY = "dunin7".
  • turn_event_id, engagement_id — real UUID parameters; turn_event_id reaches the emit payload, engagement_id does not (same pattern as site 3).
  • No timestamp variable in scope.
The FORAY 4.2 record this produces
{
  "schema_version": "4.2",
  "timestamp": "2026-08-18T00:00:00Z",
  "F1": "LW_credit.consumption_credit_d4e5f6a7",
  "F2": "d4e5f6a7-0004-4000-8000-000000000004",
  "F3": "9f8e7d6c-0000-4000-8000-0000000000f3",
  "F7": 3,
  "F8": "LOOMWORKS:loomworks_credit_sonnet",
  "F26": "credit.consumption_credit",
  "arrangements": [],
  "accruals": [],
  "anticipations": [],
  "actions": [
    {
      "id": "ACT_CONSUMPTION_CREDIT_d4e5f6a7",
      "F4": "credit_consumption_credit",
      "F9": 3,
      "F22": [],
      "F23": [],
      "F24": []
    }
  ],
  "component_hashes": {
    "arrangements": "sha256:PLACEHOLDER",
    "accruals": "sha256:PLACEHOLDER",
    "anticipations": "sha256:PLACEHOLDER",
    "actions": "sha256:PLACEHOLDER"
  },
  "merkle_root": "sha256:PLACEHOLDER",
  "blockchain_anchor": {
    "kaspa_tx_id": null,
    "block_height": null,
    "confirmation_time_ms": null,
    "anchored_at": null
  }
}
Findings

Correction (Brief 24): F21 is correctly absent — no other component exists in this record to allocate against. F9 = 3 stands alone, matching F7. credit_debit (the real oracle-converted value feeding both F7 and F9) is unchanged and still not invented.

Relationship to site 3, stated as a finding: this site's debit is the *converted* total of the four token legs emitted at site 3 — the two records are not independently meaningful without each other, but nothing in either FORAY record references the other (no F22/F23/F24 cross-link). Whether that link should exist is the same open question as credit.corrective's missing pointer (site 10 below) and sits under the same unruled Validation Scope v0.3 R2.

---

05
Credit ledger · write_suspension_flow

credit.suspension

src/loomworks/credit/flows.py:410
Source
async def write_suspension_flow(
    *,
    person_id: UUID,
    requested_by: UUID,
    expires_at: datetime,
    db: AsyncSession,
) -> UUID:
    """Mark a person account suspended in the flow log."""
    txid = _new_transaction_id()
    flow = CreditFlowRow(
        transaction_id=txid,
        event_kind="suspension",
        asset_id=ACCOUNT_STATUS_ASSET,
        quantity=1,
        from_party=DUNIN7_PARTY,
        to_party=str(person_id),
        extra_metadata={
            "requested_by": str(requested_by),
            "expires_at": expires_at.isoformat(),
        },
    )
    db.add(flow)
    # FORAY_RESERVED_LOCATION: credit.suspension
    _foray_reserved_emit(
        "credit.suspension",
        {
            "flow_id": str(flow.id),
            "transaction_id": str(txid),
            "asset_id": ACCOUNT_STATUS_ASSET,
            "quantity": 1,
            "from_party": flow.from_party,
            "to_party": flow.to_party,
            "turn_event_id": None,
        },
    )
    await db.flush()
    return txid
What data is actually available here
  • flow.idfinding: db.add(flow) happens, then the emit fires, and await db.flush() happens after the emit (last line before return) — the opposite order from sites 1/2/4. flow.id is read here before any flush. Whether it is populated depends on the PK default mechanism (client-side UUID default vs. server-assigned) — not independently confirmed. This is the same open question as site 3's row-id timing, but here it is structural (every call to this function hits it), not a possible race.
  • ACCOUNT_STATUS_ASSET = "loomworks_account_status" — fixed module constant, not caller-supplied. quantity=1 is a literal, a state flag not a real quantity.
  • person_id — real UUID parameter, in flow.to_party.
  • requested_by, expires_at — real parameters (an operator/actor UUID and a real datetime), both folded into extra_metadata but not forwarded to the emit payloadexpires_at in particular would have been a genuine, real timestamp if it had been forwarded, but it names when the suspension expires, not when this event occurred, so it is not a substitute for an emit-time timestamp even where available.
  • turn_event_id hardcoded None in the payload — this function has no such parameter at all.
The FORAY 4.2 record this produces
{
  "schema_version": "4.2",
  "timestamp": "2026-08-18T00:00:00Z",
  "F1": "LW_credit.suspension_e5f6a7b8",
  "F2": "e5f6a7b8-0005-4000-8000-000000000005",
  "F3": "9f8e7d6c-0000-4000-8000-0000000000f3",
  "F7": 1,
  "F8": "LOOMWORKS:loomworks_account_status",
  "F26": "credit.suspension",
  "arrangements": [],
  "accruals": [],
  "anticipations": [],
  "actions": [
    {
      "id": "ACT_SUSPENSION_e5f6a7b8",
      "F4": "account_suspension",
      "F9": 1,
      "F22": [],
      "F23": [],
      "F24": []
    }
  ],
  "component_hashes": {
    "arrangements": "sha256:PLACEHOLDER",
    "accruals": "sha256:PLACEHOLDER",
    "anticipations": "sha256:PLACEHOLDER",
    "actions": "sha256:PLACEHOLDER"
  },
  "merkle_root": "sha256:PLACEHOLDER",
  "blockchain_anchor": {
    "kaspa_tx_id": null,
    "block_height": null,
    "confirmation_time_ms": null,
    "anchored_at": null
  }
}
Findings

Item-9 finding: the flush()-after-emit ordering means flow.id is read in a possibly-unpopulated state at emit time — this is a genuine, structural gap in the source (not a hypothetical), distinct from any FORAY schema question, worth carrying into any build brief as a required fix regardless of the mapping.

Correction (Brief 24): F21 is correctly absent (single-Action record, nothing to allocate against). F9 = 1 stands alone, matching F7 — the reframe's asset-type generalization is what makes this honest: under the old currency-only F8, a status flag had no honest home; under LOOMWORKS:loomworks_account_status, quantity 1 is a real, correctly-typed unit of that asset, not a forced governance-zero.

---

06
Credit ledger · write_reactivation_flow

credit.reactivation

src/loomworks/credit/flows.py:446
Source
async def write_reactivation_flow(
    *,
    person_id: UUID,
    auth_method: str,
    db: AsyncSession,
) -> UUID:
    """Mark a person account reactivated in the flow log."""
    txid = _new_transaction_id()
    flow = CreditFlowRow(
        transaction_id=txid,
        event_kind="reactivation",
        asset_id=ACCOUNT_STATUS_ASSET,
        quantity=1,
        from_party=DUNIN7_PARTY,
        to_party=str(person_id),
        extra_metadata={"auth_method": auth_method},
    )
    db.add(flow)
    await db.flush()
    # FORAY_RESERVED_LOCATION: credit.reactivation
    _foray_reserved_emit(
        "credit.reactivation",
        {
            "flow_id": str(flow.id),
            "transaction_id": str(txid),
            "asset_id": ACCOUNT_STATUS_ASSET,
            "quantity": 1,
            "from_party": flow.from_party,
            "to_party": flow.to_party,
            "turn_event_id": None,
        },
    )
    return txid
What data is actually available here
  • flow.id — populated: await db.flush() runs immediately before the emit here (unlike site 5).
  • ACCOUNT_STATUS_ASSET, quantity=1 — same fixed synthetic asset/flag as site 5.
  • person_id — real UUID parameter.
  • auth_method — real str parameter (how the reactivation was authenticated), folded into extra_metadata, not forwarded to the emit payload.
  • No timestamp variable in scope.
The FORAY 4.2 record this produces
{
  "schema_version": "4.2",
  "timestamp": "2026-08-18T00:00:00Z",
  "F1": "LW_credit.reactivation_f6a7b8c9",
  "F2": "f6a7b8c9-0006-4000-8000-000000000006",
  "F3": "9f8e7d6c-0000-4000-8000-0000000000f3",
  "F7": 1,
  "F8": "LOOMWORKS:loomworks_account_status",
  "F26": "credit.reactivation",
  "arrangements": [],
  "accruals": [],
  "anticipations": [],
  "actions": [
    {
      "id": "ACT_REACTIVATION_f6a7b8c9",
      "F4": "account_reactivation",
      "F9": 1,
      "F22": [],
      "F23": [],
      "F24": []
    }
  ],
  "component_hashes": {
    "arrangements": "sha256:PLACEHOLDER",
    "accruals": "sha256:PLACEHOLDER",
    "anticipations": "sha256:PLACEHOLDER",
    "actions": "sha256:PLACEHOLDER"
  },
  "merkle_root": "sha256:PLACEHOLDER",
  "blockchain_anchor": {
    "kaspa_tx_id": null,
    "block_height": null,
    "confirmation_time_ms": null,
    "anchored_at": null
  }
}
Findings

Correction (Brief 24): as site 5 — F21 correctly absent, F9 = 1 stands alone. No structural flush-ordering issue here (unlike site 5) — worth noting the inconsistency between the two sibling lifecycle functions as a finding: write_suspension_flow flushes after emit, write_reactivation_flow and write_deletion_flow flush before. Same shape, different ordering, no stated reason found in source or comments.

---

07
Credit ledger · write_deletion_flow

credit.deletion

src/loomworks/credit/flows.py:481
Source
async def write_deletion_flow(
    *,
    person_id: UUID,
    deletion_kind: str,
    db: AsyncSession,
) -> UUID:
    """Mark a person account deleted in the flow log."""
    txid = _new_transaction_id()
    flow = CreditFlowRow(
        transaction_id=txid,
        event_kind="deletion",
        asset_id=ACCOUNT_STATUS_ASSET,
        quantity=1,
        from_party=DUNIN7_PARTY,
        to_party=str(person_id),
        extra_metadata={"deletion_kind": deletion_kind},
    )
    db.add(flow)
    await db.flush()
    # FORAY_RESERVED_LOCATION: credit.deletion
    _foray_reserved_emit(
        "credit.deletion",
        {
            "flow_id": str(flow.id),
            "transaction_id": str(txid),
            "asset_id": ACCOUNT_STATUS_ASSET,
            "quantity": 1,
            "from_party": flow.from_party,
            "to_party": flow.to_party,
            "turn_event_id": None,
        },
    )
    return txid
What data is actually available here
  • flow.id — populated (flush before emit).
  • person_id, deletion_kind (real str, e.g. "self_service"/"operator" — not forwarded to emit payload).
  • Same ACCOUNT_STATUS_ASSET/quantity=1 pattern.
  • No timestamp variable in scope.
The FORAY 4.2 record this produces
{
  "schema_version": "4.2",
  "timestamp": "2026-08-18T00:00:00Z",
  "F1": "LW_credit.deletion_a7b8c9d0",
  "F2": "a7b8c9d0-0007-4000-8000-000000000007",
  "F3": "9f8e7d6c-0000-4000-8000-0000000000f3",
  "F7": 1,
  "F8": "LOOMWORKS:loomworks_account_status",
  "F26": "credit.deletion",
  "arrangements": [],
  "accruals": [],
  "anticipations": [],
  "actions": [
    {
      "id": "ACT_DELETION_a7b8c9d0",
      "F4": "account_deletion",
      "F9": 1,
      "F22": [],
      "F23": [],
      "F24": []
    }
  ],
  "component_hashes": {
    "arrangements": "sha256:PLACEHOLDER",
    "accruals": "sha256:PLACEHOLDER",
    "anticipations": "sha256:PLACEHOLDER",
    "actions": "sha256:PLACEHOLDER"
  },
  "merkle_root": "sha256:PLACEHOLDER",
  "blockchain_anchor": {
    "kaspa_tx_id": null,
    "block_height": null,
    "confirmation_time_ms": null,
    "anchored_at": null
  }
}
Findings

Correction (Brief 24): as sites 5/6 — F21 correctly absent, F9 = 1 stands alone. Relationship to site 8, stated as a finding: account deletion is the trigger for write_balance_zeroing_flows (site 8) in the caller's workflow (confirmed by the module docstring: "at deletion: drive every positive credit balance to 0"), but nothing in either function calls the other directly — the two are siblings invoked by a shared caller outside this file, and neither FORAY record references the other (a genuine cross-record link here would face the same unruled Validation Scope v0.3 R2 question as site 11's credit.corrective).

---

08
Credit ledger · write_balance_zeroing_flows (loop, 0-3×)

credit.balance_zeroing

src/loomworks/credit/flows.py:532
Source
async def write_balance_zeroing_flows(
    *,
    person_id: UUID,
    db: AsyncSession,
) -> UUID:
    """At deletion time, drive every positive credit balance to 0. ..."""
    txid = _new_transaction_id()
    person_str = str(person_id)
    zeroed_flows: list[CreditFlowRow] = []
    for asset_id in CREDIT_ASSET_IDS:
        balance = await check_credit_balance(
            person_id=person_id, asset_id=asset_id, db=db
        )
        if balance > 0:
            flow = CreditFlowRow(
                transaction_id=txid,
                event_kind="balance_zeroing",
                asset_id=asset_id,
                quantity=balance,
                from_party=person_str,
                to_party=DUNIN7_PARTY,
                extra_metadata={"reason": "account_deletion"},
            )
            db.add(flow)
            zeroed_flows.append(flow)
    if zeroed_flows:
        await db.flush()
        for flow in zeroed_flows:
            # FORAY_RESERVED_LOCATION: credit.balance_zeroing
            _foray_reserved_emit(
                "credit.balance_zeroing",
                {
                    "flow_id": str(flow.id),
                    "transaction_id": str(txid),
                    "asset_id": flow.asset_id,
                    "quantity": flow.quantity,
                    "from_party": flow.from_party,
                    "to_party": flow.to_party,
                    "turn_event_id": None,
                },
            )
    return txid
What data is actually available here
  • This site is conditional and variable-count: zero to len(CREDIT_ASSET_IDS) (3, per balance.py's CREDIT_HAIKU/CREDIT_SONNET/CREDIT_OPUS) records may be produced per call, one per asset tier where balance > 0. If the person has no positive balance in any tier, this site emits nothing at all — a legitimate "should not emit" outcome, confirmed structurally, not assumed.
  • flow.id — populated (await db.flush() before the emit loop, guarded by if zeroed_flows:).
  • asset_id — real, iterated from CREDIT_ASSET_IDS ("loomworks_credit_haiku"/"_sonnet"/"_opus") — genuinely tier-specific per record, not a single fixed value.
  • flow.quantity = balance — a real, queried int (await check_credit_balance(...)), the exact amount being zeroed.
  • person_str, DUNIN7_PARTY — as elsewhere.
  • No timestamp variable in scope.
The FORAY 4.2 record this produces
{
  "schema_version": "4.2",
  "timestamp": "2026-08-18T00:00:00Z",
  "F1": "LW_credit.balance_zeroing_b8c9d0e1",
  "F2": "b8c9d0e1-0008-4000-8000-000000000008",
  "F3": "9f8e7d6c-0000-4000-8000-0000000000f3",
  "F7": 47,
  "F8": "LOOMWORKS:loomworks_credit_sonnet",
  "F26": "credit.balance_zeroing",
  "arrangements": [],
  "accruals": [],
  "anticipations": [],
  "actions": [
    {
      "id": "ACT_BALANCE_ZEROING_b8c9d0e1",
      "F4": "credit_balance_zeroing",
      "F9": 47,
      "F22": [],
      "F23": [],
      "F24": []
    }
  ],
  "component_hashes": {
    "arrangements": "sha256:PLACEHOLDER",
    "accruals": "sha256:PLACEHOLDER",
    "anticipations": "sha256:PLACEHOLDER",
    "actions": "sha256:PLACEHOLDER"
  },
  "merkle_root": "sha256:PLACEHOLDER",
  "blockchain_anchor": {
    "kaspa_tx_id": null,
    "block_height": null,
    "confirmation_time_ms": null,
    "anchored_at": null
  }
}
Findings

Correction (Brief 24): F21 correctly absent, F9 = 47 stands alone, matching F7. Worked example shows one tier's record (loomworks_credit_sonnet); a full call would produce up to 3 sibling records sharing one txid but each its own FORAY evidence record (per this document's own no-F1-batching convention).

---

09
Credit ledger · write_referral_credit_flow

credit.referral_credit

src/loomworks/credit/flows.py:642
Source
extra: dict = {"referrer_person_id": referrer_str}
    if metadata:
        for k, v in metadata.items():
            if k != "converted_person_id":
                extra[k] = v

    txid = _new_transaction_id()
    flow = CreditFlowRow(
        transaction_id=txid,
        event_kind="referral_credit",
        asset_id=asset_id,
        quantity=amount,
        from_party=DUNIN7_PARTY,
        to_party=referrer_str,
        converted_person_id=converted_person_uuid,
        extra_metadata=extra,
    )
    db.add(flow)
    await db.flush()
    # FORAY_RESERVED_LOCATION: credit.referral_credit
    _foray_reserved_emit(
        "credit.referral_credit",
        {
            "flow_id": str(flow.id),
            "transaction_id": str(txid),
            "asset_id": asset_id,
            "quantity": amount,
            "from_party": flow.from_party,
            "to_party": flow.to_party,
            "turn_event_id": None,
        },
    )
    return txid
What data is actually available here

Enclosing function write_referral_credit_flow(*, referrer_person_id, asset_id, amount, db, metadata=None). Docstring confirms this function is shipped but not yet called anywhere ("Phase 47 ships this function but does not call it; Phase 48 wires conversion detection") — this site is live code, reachable, and structurally correct, but currently has zero real callers in the codebase as of HEAD.

  • flow.id — populated (flush before emit).
  • asset_id, amount — caller-supplied; worked example "loomworks_credit_sonnet" / 250.
  • referrer_str = str(referrer_person_id) — real person UUID, in flow.to_party.
  • DUNIN7_PARTY = "dunin7", in flow.from_party.
  • converted_person_uuid — a real, optional UUID (the referee whose conversion triggered this credit), stored in the typed converted_person_id column but not in the emit payload — same forward-gap pattern as grant_id/authorized_by/auth_method/deletion_kind above, and arguably the most consequential instance of it: this is the one piece of data that would let a downstream reader distinguish *which* conversion this credit rewards, and it does not reach FORAY.
  • No timestamp variable in scope.
The FORAY 4.2 record this produces
{
  "schema_version": "4.2",
  "timestamp": "2026-08-18T00:00:00Z",
  "F1": "LW_credit.referral_credit_c9d0e1f2",
  "F2": "c9d0e1f2-0009-4000-8000-000000000009",
  "F3": "9f8e7d6c-0000-4000-8000-0000000000f3",
  "F7": 250,
  "F8": "LOOMWORKS:loomworks_credit_sonnet",
  "F26": "credit.referral_credit",
  "arrangements": [],
  "accruals": [],
  "anticipations": [],
  "actions": [
    {
      "id": "ACT_REFERRAL_CREDIT_c9d0e1f2",
      "F4": "credit_referral_credit",
      "F9": 250,
      "F22": [],
      "F23": [],
      "F24": []
    }
  ],
  "component_hashes": {
    "arrangements": "sha256:PLACEHOLDER",
    "accruals": "sha256:PLACEHOLDER",
    "anticipations": "sha256:PLACEHOLDER",
    "actions": "sha256:PLACEHOLDER"
  },
  "merkle_root": "sha256:PLACEHOLDER",
  "blockchain_anchor": {
    "kaspa_tx_id": null,
    "block_height": null,
    "confirmation_time_ms": null,
    "anchored_at": null
  }
}
Findings

Correction (Brief 24): F21 correctly absent, F9 = 250 stands alone, matching F7. Reachability finding, item 9: as noted above, this call site is currently unreached in production — the mapping is real and would fire correctly the moment Phase 48 wires a caller, but as of this brief's HEAD, credit.referral_credit has never actually executed.

---

10
Credit ledger · write_room_consumption_flows._emit (×3)

credit.consumption_token / credit.consumption_credit

src/loomworks/credit/room_consumption.py:41
Source
def _emit(flow: CreditFlowRow, txid: UUID) -> None:
    # FORAY_RESERVED_LOCATION: credit.<event_kind>  (Phase 64 widened payload)
    _foray_reserved_emit(
        f"credit.{flow.event_kind}",
        {
            "flow_id": str(flow.id),
            "transaction_id": str(txid),
            "asset_id": flow.asset_id,
            "quantity": flow.quantity,
            "from_party": flow.from_party,
            "to_party": flow.to_party,
            "turn_event_id": (
                str(flow.turn_event_id)
                if flow.turn_event_id is not None
                else None
            ),
        },
    )

# ... called 3x from write_room_consumption_flows:
#   _emit(token_in, txid)    -> credit.consumption_token
#   _emit(token_out, txid)   -> credit.consumption_token
#   _emit(credit_flow, txid) -> credit.consumption_credit
# All three calls happen only after "await db.flush()" for the
# respective row(s), so flow.id is genuinely populated at every call
# (unlike flows.py site 5's post-emit flush, and unlike flows.py site
# 3's pre-flush loop).
What data is actually available here

Helper _emit(flow, txid) is shared by all 3 calls inside write_room_consumption_flows(*, person_id, credit_asset_id, model, prompt_tokens, completion_tokens, engagement_id, turn_event_id, room, db). event_kind is computed dynamically (f"credit.{flow.event_kind}"), taking two distinct values across the 3 calls — this is one of the sites the census flags as "the two dynamic event_kind values" making the catalog entry non-static (item 9).

  • flow.id, flow.asset_id, flow.quantity, flow.from_party, flow.to_party — all real, all populated (flush confirmed before every call).
  • flow.turn_event_id — real UUID | None parameter, forwarded correctly here (unlike flows.py site 5, but like flows.py sites 3/4).
  • input_asset/output_asset come from responder_model_to_token_asset_pair(model)provider token assets, same LOOMWORKS: scheme mismatch finding as flows.py site 3.
  • credit_asset_id — real Loomworks-scheme tier for the third call.
  • engagement_id, room — real values, folded into extra_metadata only, not forwarded to the emit payload (same forward-gap pattern as flows.py).
  • No timestamp variable in scope.
The FORAY 4.2 record this produces

Two worked records shown, not one, because the event_kind is genuinely dynamic: the first (above) is one of the two consumption_token calls (token_in — the analogous token_out call is the same shape, different asset_id/quantity). The second (below) is the consumption_credit call.

Worked record 1
{
  "schema_version": "4.2",
  "timestamp": "2026-08-18T00:00:00Z",
  "F1": "LW_credit.consumption_token_d0e1f2a3",
  "F2": "d0e1f2a3-000a-4000-8000-00000000000a",
  "F3": "9f8e7d6c-0000-4000-8000-0000000000f3",
  "F7": 1204,
  "F8": "PROVIDER:claude_sonnet_5_input",
  "F26": "credit.consumption_token",
  "arrangements": [],
  "accruals": [],
  "anticipations": [],
  "actions": [
    {
      "id": "ACT_CONSUMPTION_TOKEN_d0e1f2a3",
      "F4": "credit_consumption_token",
      "F9": 1204,
      "F22": [],
      "F23": [],
      "F24": []
    }
  ],
  "component_hashes": {
    "arrangements": "sha256:PLACEHOLDER",
    "accruals": "sha256:PLACEHOLDER",
    "anticipations": "sha256:PLACEHOLDER",
    "actions": "sha256:PLACEHOLDER"
  },
  "merkle_root": "sha256:PLACEHOLDER",
  "blockchain_anchor": {
    "kaspa_tx_id": null,
    "block_height": null,
    "confirmation_time_ms": null,
    "anchored_at": null
  }
}
Worked record 2
{
  "schema_version": "4.2",
  "timestamp": "2026-08-18T00:00:00Z",
  "F1": "LW_credit.consumption_credit_e1f2a3b4",
  "F2": "e1f2a3b4-000b-4000-8000-00000000000b",
  "F3": "9f8e7d6c-0000-4000-8000-0000000000f3",
  "F7": 4,
  "F8": "LOOMWORKS:loomworks_credit_sonnet",
  "F26": "credit.consumption_credit",
  "arrangements": [],
  "accruals": [],
  "anticipations": [],
  "actions": [
    {
      "id": "ACT_CONSUMPTION_CREDIT_e1f2a3b4",
      "F4": "credit_consumption_credit",
      "F9": 4,
      "F22": [],
      "F23": [],
      "F24": []
    }
  ],
  "component_hashes": {
    "arrangements": "sha256:PLACEHOLDER",
    "accruals": "sha256:PLACEHOLDER",
    "anticipations": "sha256:PLACEHOLDER",
    "actions": "sha256:PLACEHOLDER"
  },
  "merkle_root": "sha256:PLACEHOLDER",
  "blockchain_anchor": {
    "kaspa_tx_id": null,
    "block_height": null,
    "confirmation_time_ms": null,
    "anchored_at": null
  }
}
Findings

Correction (Brief 24): F21 correctly absent from both worked records — each is a single-Action record with nothing else to allocate against. F9 stands alone in each (1204 and 4 respectively), matching each record's own F7. Item-9 finding, carried from flows.py site 3: the two consumption_token calls share the same PROVIDER: scheme-mismatch issue — credit.consumption_token records here are not genuinely Loomworks-scheme assets. Second item-9 finding, new to this site: downstream of this emit, draw_down_fifo(...) (line 143-149) links this spend to the specific grant lot(s) that funded it — a real, meaningful cross-reference (consumption_flow_id=credit_flow.id) that exists in Loomworks' own ledger but has no FORAY-side counterpart field populated at this site; the lot linkage is invisible to FORAY entirely.

---

11
Credit ledger · apply_reconciliation_correction

credit.corrective

src/loomworks/credit/proposal_applier.py:433
Source
flow_kwargs = CorrectiveForayFlowRenderSpecialist.build_flow_row_kwargs(
        shape_intent=shape_intent,
    )
    txid = uuid.uuid4()
    extra_metadata = dict(flow_kwargs.get("flow_metadata", flow_kwargs.get("extra_metadata", {})))
    extra_metadata["applied_by"] = str(person_id)
    extra_metadata["shape_event_id"] = str(shape_event.id)
    flow = CreditFlowRow(
        transaction_id=txid,
        event_kind="corrective",
        asset_id=flow_kwargs["asset_id"],
        quantity=flow_kwargs["quantity"],
        from_party=flow_kwargs["from_party"],
        to_party=flow_kwargs["to_party"],
        extra_metadata=extra_metadata,
    )
    db.add(flow)
    await db.flush()
    # FORAY_RESERVED_LOCATION: credit.corrective
    _foray_reserved_emit(
        "credit.corrective",
        {
            "flow_id": str(flow.id),
            "transaction_id": str(txid),
            "asset_id": flow_kwargs["asset_id"],
            "quantity": flow_kwargs["quantity"],
            "from_party": flow.from_party,
            "to_party": flow.to_party,
            "turn_event_id": (
                str(flow.turn_event_id) if flow.turn_event_id else None
            ),
        },
    )
What data is actually available here

Enclosing function apply_reconciliation_correction(*, proposal_id, person_id, db). person_id is a real UUID parameter (the Operator approving the correction) — but per the function's own docstring caveat quoted above, the flow itself is written under _BOOTSTRAP_ACTOR (system attribution), not under an ActorRef for person_id; person_id reaches only extra_metadata['applied_by'], confirmed by line 419, one line before the CreditFlowRow construction — not the emit payload, same forward-gap pattern as every other flows-family site.

  • flow.id — populated (flush before emit).
  • flow_kwargs["asset_id"], ["quantity"], ["from_party"], ["to_party"] — real values, but computed by CorrectiveForayFlowRenderSpecialist.build_flow_row_kwargs(shape_intent=shape_intent), a function outside this file, not inspected as part of Brief 23 (out of the sixteen call sites' scope; the shape/render specialist machinery is a distinct subsystem). The worked JSON below uses representative values consistent with the corrective-flow concept, marked as such.
  • txid — fresh uuid.uuid4().
  • proposal_id — real UUID parameter, not referenced anywhere in the emit payload or in extra_metadata shown here — the very thing this correction corrects has no pointer in the FORAY record (item 9's headline finding for this site, see below).
  • shape_event.id — a real, freshly-created UUID (the ShapeEvent row built earlier in this function, lines 371-399), captured into extra_metadata['shape_event_id'] but not forwarded to the emit payload either.
  • No timestamp variable captures into the emit payload: datetime.now(UTC) is called twice in this function (lines 375, 389) but both populate the sibling ShapeEvent's created_at/confirmed_at, not a variable that reaches the credit.corrective emit — the emit call itself captures no timestamp.
The FORAY 4.2 record this produces
{
  "schema_version": "4.2",
  "timestamp": "2026-08-18T00:00:00Z",
  "F1": "LW_credit.corrective_f2a3b4c5",
  "F2": "f2a3b4c5-000c-4000-8000-00000000000c",
  "F3": "9f8e7d6c-0000-4000-8000-0000000000f3",
  "F7": 12,
  "F8": "LOOMWORKS:loomworks_credit_sonnet",
  "F26": "credit.corrective",
  "arrangements": [],
  "accruals": [],
  "anticipations": [],
  "actions": [
    {
      "id": "ACT_CORRECTIVE_f2a3b4c5",
      "F4": "credit_corrective",
      "F9": 12,
      "F22": [],
      "F23": [],
      "F24": []
    }
  ],
  "component_hashes": {
    "arrangements": "sha256:PLACEHOLDER",
    "accruals": "sha256:PLACEHOLDER",
    "anticipations": "sha256:PLACEHOLDER",
    "actions": "sha256:PLACEHOLDER"
  },
  "merkle_root": "sha256:PLACEHOLDER",
  "blockchain_anchor": {
    "kaspa_tx_id": null,
    "block_height": null,
    "confirmation_time_ms": null,
    "anchored_at": null
  }
}
Findings

Item-9 headline finding, as flagged by the brief itself: credit.corrective's emit payload carries no pointer to proposal_id (the reconciliation proposal it corrects) or to any prior flow/transaction it amends. F3 above is person_id (the approving Operator), following this document's stated convention, but this is the *approver*, not necessarily whose balance is corrected — flow_kwargs['to_party']/['from_party'] (computed by the out-of-scope render specialist) are what actually determine the corrected party, and were not independently inspected. Per the brief's explicit instruction, this is not resolved here — a cross-record reference of this kind is governed by Validation Scope v0.3 R2, currently unruled (the validator's checkRefsResolve only indexes ids from a record's own four component arrays, per this session's earlier finding — cross-record references are structurally unvalidatable under the 4.2 validator today). Stated plainly, left open.

Correction (Brief 24), and the sharpened form of this site's headline finding: F21 is correctly absent here too — this record has no other component to reference. But this site is exactly where a real allocation would be most meaningful (a corrective flow settling against the specific proposal/prior-flow it corrects), and the single-Action-per-record structure makes that structurally impossible today: F21.ref can only point at an element already present in the *same* record, and credit.corrective never carries an Arrangement/Accrual/Anticipation for proposal_id to attach to. So this is not merely "the pointer is missing" (as v0.2 stated) — it is that the current per-call-site, single-Action-record design cannot carry this pointer via F21 at all, regardless of what data is available. A cross-record reference (F2/F1 pointing at the corrected record's own identifiers, carried in F25 residue, or a restructured multi-component record) would be needed, and both routes still run into the same unruled Validation Scope v0.3 R2 question this document already declines to resolve.

---

12
Governance · append_event

memory.<event_kind>

src/loomworks/memory/events.py:273
Source
async def append_event(
    *,
    engagement_id: UUID,
    object: MemoryObject,
    event_kind: str,
    actor: ActorRef,
    event_id: UUID,
    db: AsyncSession,
) -> MemoryEventRow:
    """Append an event for `object` to the memory event log. ..."""
    ...
    event = MemoryEventRow(
        event_id=event_id,
        engagement_id=engagement_id,
        engagement_version=next_version,
        object_id=object.id,
        object_type=object.object_type,
        object_version=object.version,
        event_kind=event_kind,
        payload=payload,
        provenance=object.provenance.model_dump(mode="json"),
        timestamp=object.created_at,
        actor_id=actor.id,
        actor_kind=actor.kind,
        actor_instruction_version=actor.instruction_version,
    )
    db.add(event)
    ...
    await db.flush()
    ...
    # FORAY_RESERVED_LOCATION: memory.<event_kind>
    # Per CR-B (Phase 62) design D4 + D5: the single memory_events
    # write site emits one reserved-location event per write. The
    # payload carries the event_id and the anchor_priority hint from
    # _ANCHOR_PRIORITY (None for event kinds outside the registry).
    _foray_reserved_emit(
        f"memory.{event_kind}",
        {
            "event_id": str(event.event_id),
            "anchor_priority": _ANCHOR_PRIORITY.get(event_kind),
        },
    )
    return event
What data is actually available here

event_kind: str is a caller-supplied parameter, not enumerated in this file — the census-noted "dynamic event_kind" pattern applies here too: memory.{event_kind} can be memory.engagement_committed, memory.shape_produced, or any of the ~20 kinds enumerated in _ANCHOR_PRIORITY (or one outside it, in which case anchor_priority is None).

  • event.event_id = event_id, the caller-minted UUID parameter — confirmed by the docstring as deliberately required, not optional-with-fallback, specifically to avoid a fabricated value; this is a genuinely strong identifier.
  • event.created_at/object.created_atthis is one of the three sites in the whole census with a real timestamp variable: timestamp=object.created_at (line 204) is set on the MemoryEventRow from the caller-supplied object.created_at — a real datetime, though it reflects when the caller constructed object, not necessarily this exact append_event execution.
  • object.id, object.engagement_id, actor.id, actor.kind — all real, all in scope (object: MemoryObject, actor: ActorRef, both required parameters) — but none of these reach the emit payload, which carries only event_id and anchor_priority. This is the site's own version of the forward-gap pattern: rich identity data (object id, actor id, engagement id) is available and simply not passed to _foray_reserved_emit.
  • _ANCHOR_PRIORITY.get(event_kind) — real dict lookup against the confirmed ~20-entry registry in foray/anchor_priority.py; None for any kind outside it.
The FORAY 4.2 record this produces
{
  "schema_version": "4.2",
  "timestamp": "2026-08-18T14:32:07Z",
  "F1": "LW_memory.engagement_committed_a3b4c5d6",
  "F2": "a3b4c5d6-000d-4000-8000-00000000000d",
  "F3": "UNATTRIBUTED",
  "F7": 0,
  "F8": "LOOMWORKS:NONE",
  "F26": "memory.engagement_committed",
  "arrangements": [],
  "accruals": [],
  "anticipations": [],
  "actions": [
    {
      "id": "ACT_MEMORY_a3b4c5d6",
      "F4": "engagement_committed",
      "F9": 0,
      "F22": [],
      "F23": [],
      "F24": [],
      "F25": {
        "event_id": "a3b4c5d6-000d-4000-8000-00000000000d",
        "anchor_priority": "critical"
      }
    }
  ],
  "component_hashes": {
    "arrangements": "sha256:PLACEHOLDER",
    "accruals": "sha256:PLACEHOLDER",
    "anticipations": "sha256:PLACEHOLDER",
    "actions": "sha256:PLACEHOLDER"
  },
  "merkle_root": "sha256:PLACEHOLDER",
  "blockchain_anchor": {
    "kaspa_tx_id": null,
    "block_height": null,
    "confirmation_time_ms": null,
    "anchored_at": null
  }
}
Findings

Governance-shaped, per Root §5: F7: 0. Correction (Brief 24): v0.2 stated F8: null — illegal under the schema (F8 is "type": "string" at transaction level, required, non-nullable). No Root or wire-skill guidance names what string a zero-asset governance record should carry for a required field. F8 above is now the stated placeholder "LOOMWORKS:NONE", following this document's own scheme-prefix convention rather than an unrelated ad hoc string — recorded here as a design choice made in the absence of explicit governance, not as a real asset-type identifier. F2 uses event_id (the real, caller-minted, non-fabricated identifier).

F3 finding: no UUID reaches this emit site at allevent_id is a memory-event identifier, not a person/record-owner UUID, and actor.id's semantic type varies by actor.kind (only person/companion genuinely map to a human UUID; contributor/agent do not) and, per source, actor.id is not even passed into the emit payload regardless. Correction (Brief 24): v0.2 stated F3: null here — the schema's OwnerForm requires a non-empty string (minLength: 1); null is not a legal value under either of F3's two admissible forms and would fail schema validation outright. F3 above is now the stated placeholder string "UNATTRIBUTED" — clearly not a real identity, not derived from any source variable, present only because the schema mandates a non-empty string and no genuine value exists to supply. The finding stands: no UUID reaches this site; the placeholder is a schema-compliance necessity, not a substitution for the missing fact.

Timestamp: genuinely available (object.created_at), the value shown (2026-08-18T14:32:07Z) stands in for that real, in-scope variable — one of only 3 of 16 sites where this is true.

F26 dynamism: event_kind ranges over ~20 known values plus any unregistered value — the FORAY catalog entry for memory.* is not a single static entry; each concrete event_kind is its own transaction type in practice.

---

13
Governance · _execute_enum_setting

audit.setting_change

src/loomworks/orchestration/tune_setting.py:544
Source
async def _execute_enum_setting(
    *,
    person_id: UUID,
    setting_label: str,
    setting_key: str,
    spec: Any,
    current: Any,
    direction: str,
    db: AsyncSession,
    engagement_id: UUID | None = None,
) -> dict[str, Any]:
    ...
    try:
        committed = await set_setting(
            person_id=person_id,
            setting_key=setting_key,
            value=new_value,
            db=db,
        )
    except (InvalidSettingValueError, UnknownSettingError):
        return {"action": ACTION_ERROR, "setting_label": setting_label, "setting_key": setting_key}

    # CR §A.2 -- audit alongside the substrate write. Best-effort
    # per §A.4: the setting write is already committed at this point;
    # an audit-write failure is logged and swallowed.
    await _audit_setting_change(
        actor_person_id=person_id,
        setting_key=setting_key,
        previous_value=current,
        new_value=committed,
        engagement_id=engagement_id,
        db=db,
    )
    # FORAY_RESERVED_LOCATION: audit.setting_change
    _foray_reserved_emit(
        "audit.setting_change",
        {"setting_key": setting_key, "action": action},
    )
    return {
        "action": action,
        "setting_label": setting_label,
        "setting_key": setting_key,
        "direction": direction,
        "previous_value": current,
        "new_value": committed,
        "value_plain": _value_in_plain_words(setting_key, committed),
    }
What data is actually available here

Correction of my own Brief 21 finding, stated explicitly: Brief 21's report claimed "nothing says whose setting changed" at the audit/settings trio. That was true only of the emit payload's own two keys; it understates what the function scope actually holds. person_id: UUID (real, required parameter) and engagement_id: UUID | None are both in scope for the entire function, and are passed one call earlier, to _audit_setting_change(actor_person_id=person_id, ..., engagement_id=engagement_id, db=db) (lines 535-542) — immediately before the FORAY emit. The identity data exists and is used for the audit trail; it is simply not forwarded into _foray_reserved_emit's own payload, which carries only setting_key and action.

  • setting_key — real str parameter, e.g. "voice_reply_style".
  • action — real, one of ACTION_TUNED/ACTION_RESET/ACTION_ERROR/ACTION_NO_CHANGE/ACTION_UNKNOWN_DIRECTION (module constants, resolved earlier in the function body).
  • current, committed (previous/new values) — both real, both passed to _audit_setting_change one line above the emit, not forwarded to it.
  • No timestamp variable in scope.
The FORAY 4.2 record this produces
{
  "schema_version": "4.2",
  "timestamp": "2026-08-18T00:00:00Z",
  "F1": "LW_audit.setting_change_b4c5d6e7",
  "F2": "b4c5d6e7-000e-4000-8000-00000000000e",
  "F3": "9f8e7d6c-0000-4000-8000-0000000000f3",
  "F7": 0,
  "F8": "LOOMWORKS:NONE",
  "F26": "audit.setting_change",
  "arrangements": [],
  "accruals": [],
  "anticipations": [],
  "actions": [
    {
      "id": "ACT_AUDIT_b4c5d6e7",
      "F4": "setting_change",
      "F9": 0,
      "F22": [],
      "F23": [],
      "F24": [],
      "F25": {
        "setting_key": "voice_reply_style",
        "action": "tuned"
      }
    }
  ],
  "component_hashes": {
    "arrangements": "sha256:PLACEHOLDER",
    "accruals": "sha256:PLACEHOLDER",
    "anticipations": "sha256:PLACEHOLDER",
    "actions": "sha256:PLACEHOLDER"
  },
  "merkle_root": "sha256:PLACEHOLDER",
  "blockchain_anchor": {
    "kaspa_tx_id": null,
    "block_height": null,
    "confirmation_time_ms": null,
    "anchored_at": null
  }
}
Findings

F3 finding — corrected from Brief 21: person_id genuinely IS in scope here, used one line above the emit for the audit write. F3 = str(person_id) is used above, not null, unlike site 12 (memory.*) where no UUID reaches the emit site at all. This document explicitly does not use the emit payload's own narrow contents as the boundary of "available data," per the brief's item 3 instruction.

Item-9 finding — the {setting_key, action}-only payload: despite person_id, engagement_id, current, and committed all being real, in-scope, and even used one line earlier for the audit write, none of them reach the FORAY emit. This is a genuine, source-confirmed gap between what Loomworks *has* at this call site and what it currently *sends* — not a data-availability problem, a wiring gap.

---

14
Governance · _execute_numeric_setting

audit.setting_change

src/loomworks/orchestration/tune_setting.py:670
Source
async def _execute_numeric_setting(
    *,
    person_id: UUID,
    setting_label: str,
    setting_key: str,
    spec: Any,
    current: Any,
    direction: str,
    db: AsyncSession,
    engagement_id: UUID | None = None,
) -> dict[str, Any]:
    ...
    try:
        committed = await set_setting(
            person_id=person_id,
            setting_key=setting_key,
            value=new_value,
            db=db,
        )
    except (InvalidSettingValueError, UnknownSettingError):
        return {"action": ACTION_ERROR, "setting_label": setting_label, "setting_key": setting_key}

    # CR §A.2 -- audit alongside the substrate write. previous_value is
    # None for a nullable setting tuned from its unset state.
    await _audit_setting_change(
        actor_person_id=person_id,
        setting_key=setting_key,
        previous_value=current_f,
        new_value=float(committed),
        engagement_id=engagement_id,
        db=db,
    )
    # FORAY_RESERVED_LOCATION: audit.setting_change
    _foray_reserved_emit(
        "audit.setting_change",
        {"setting_key": setting_key, "action": action},
    )
    return {
        "action": action,
        "setting_label": setting_label,
        "setting_key": setting_key,
        "direction": normalized_direction,
        ...
    }
What data is actually available here

Same function shape and same correction as site 13: person_id, engagement_id, current_f (the previous numeric value, possibly None for a nullable setting never set), and committed/float(committed) (the new numeric value) are all real and all passed to _audit_setting_change one line above the emit — not forwarded into the emit payload itself, which is identical in shape to site 13's ({setting_key, action} only).

  • setting_key, action — as site 13.
  • No timestamp variable in scope.
The FORAY 4.2 record this produces
{
  "schema_version": "4.2",
  "timestamp": "2026-08-18T00:00:00Z",
  "F1": "LW_audit.setting_change_c5d6e7f8",
  "F2": "c5d6e7f8-000f-4000-8000-00000000000f",
  "F3": "9f8e7d6c-0000-4000-8000-0000000000f3",
  "F7": 0,
  "F8": "LOOMWORKS:NONE",
  "F26": "audit.setting_change",
  "arrangements": [],
  "accruals": [],
  "anticipations": [],
  "actions": [
    {
      "id": "ACT_AUDIT_c5d6e7f8",
      "F4": "setting_change",
      "F9": 0,
      "F22": [],
      "F23": [],
      "F24": [],
      "F25": {
        "setting_key": "blur_intensity",
        "action": "tuned"
      }
    }
  ],
  "component_hashes": {
    "arrangements": "sha256:PLACEHOLDER",
    "accruals": "sha256:PLACEHOLDER",
    "anticipations": "sha256:PLACEHOLDER",
    "actions": "sha256:PLACEHOLDER"
  },
  "merkle_root": "sha256:PLACEHOLDER",
  "blockchain_anchor": {
    "kaspa_tx_id": null,
    "block_height": null,
    "confirmation_time_ms": null,
    "anchored_at": null
  }
}
Findings

F3, same correction as site 13: person_id in scope, used above for the audit write; F3 = str(person_id).

Item-9, same finding as site 13, plus one more: _execute_enum_setting and _execute_numeric_setting are two independent functions with byte-identical _foray_reserved_emit("audit.setting_change", {"setting_key": ..., "action": ...}) call shapes — this duplication itself (two call sites doing exactly the same emit) is worth noting for any future build brief: a single shared helper (mirroring room_consumption.py's _emit pattern) would remove the duplication.

---

15
Governance · record_turn

conversation.turn

src/loomworks/orchestration/conversation_turns.py:270
Source
row = ConverseTurnRow(
        person_id=person_id,
        engagement_id=engagement_id,
        role=role,
        content=content,
        classified_intent=classified_intent,
        input_mode=input_mode,
        completeness_check_prefix=completeness_check_prefix,
        structured_data=structured_data,
        organized_view_citation=organized_view_citation,
        composition=composition,
        operation_outcome=operation_outcome,
        # CR-2026-094 §4 -- denormalized actor, mirroring append_event
        # (events.py:169-171) + actor_display_name for the surface label.
        actor_id=actor.id,
        actor_kind=actor.kind,
        actor_instruction_version=actor.instruction_version,
        actor_display_name=actor.display_name,
    )
    db.add(row)
    await db.flush()
    await db.refresh(row)

    # FORAY_RESERVED_LOCATION: conversation.turn
    # CR-2026-094 Step 4 (§7 / §9 / D4) -- mirrors append_event's
    # reserved-location emit (events.py) so BOTH Memory-population paths
    # (assertion + conversation turn) are seam-marked. Payload carries
    # the turn id and actor_kind -- the namespaced "conversation.turn"
    # kind matches the "memory.{event_kind}" naming convention.
    _foray_reserved_emit(
        "conversation.turn",
        {"turn_id": str(row.id), "actor_kind": actor.kind},
    )
    return _row_to_turn(row)
What data is actually available here

Enclosing function record_turn(*, person_id, engagement_id, role, content, actor, ..., db). person_id: UUID is a real, required parameter — in scope, but not forwarded to the emit payload, which carries only row.id and actor.kind.

  • row.id — populated: await db.flush() then await db.refresh(row) both run immediately before the emit (lines 258-259).
  • row.created_atthe second of the three sites with a genuinely available, confirmed-populated timestamp: ConverseTurnRow.created_at uses a Python-side default that fires at flush time (confirmed by the model's own source comment in orchestration/models.py), and await db.refresh(row) at line 259 pulls that value back into the in-process object before the emit — this is the strongest timestamp claim of the three (memory/events.py's object.created_at is caller-set before the call; this one is genuinely fresh at write time).
  • actor.kind — real, in the emit payload. actor.id — real, not in the emit payload, though person_id (a stronger, unambiguous person UUID) is separately available and also not forwarded.
  • engagement_id: UUID | None — real, optional, not forwarded.
The FORAY 4.2 record this produces
{
  "schema_version": "4.2",
  "timestamp": "2026-08-18T14:47:52Z",
  "F1": "LW_conversation.turn_d6e7f8a9",
  "F2": "d6e7f8a9-0010-4000-8000-000000000010",
  "F3": "UNATTRIBUTED",
  "F7": 0,
  "F8": "LOOMWORKS:NONE",
  "F26": "conversation.turn",
  "arrangements": [],
  "accruals": [],
  "anticipations": [],
  "actions": [
    {
      "id": "ACT_CONVERSATION_d6e7f8a9",
      "F4": "conversation_turn",
      "F9": 0,
      "F22": [],
      "F23": [],
      "F24": [],
      "F25": {
        "turn_id": "d6e7f8a9-0010-4000-8000-000000000010",
        "actor_kind": "person"
      }
    }
  ],
  "component_hashes": {
    "arrangements": "sha256:PLACEHOLDER",
    "accruals": "sha256:PLACEHOLDER",
    "anticipations": "sha256:PLACEHOLDER",
    "actions": "sha256:PLACEHOLDER"
  },
  "merkle_root": "sha256:PLACEHOLDER",
  "blockchain_anchor": {
    "kaspa_tx_id": null,
    "block_height": null,
    "confirmation_time_ms": null,
    "anchored_at": null
  }
}
Findings

F3 finding: person_id is genuinely, unambiguously in scope for the entire function (unlike actor.id, whose semantic type varies with actor.kind) — but it is not in the emit payload, so per the brief's literal instruction ("the UUID... name which variable at the site actually holds it") the payload itself carries no F3-eligible value. Correction (Brief 24): v0.2 stated F3: null — illegal under the schema's OwnerForm (non-empty string required). F3 above is now the stated placeholder "UNATTRIBUTED", for the same schema-compliance reason as site 12, not a substitution for person_idperson_id's real, nearby, unused availability is the actual finding and stands unchanged.

Timestamp: confirmed genuinely populated at emit time, the strongest of the three timestamp-bearing sites — the value shown stands in for row.created_at.

---

16
Governance · put_setting_route

audit.setting_change

src/loomworks/api/routers/me_settings.py:164
Source
@router.put(
    "/me/settings/{setting_key}",
    ...
)
async def put_setting_route(
    setting_key: str,
    body: SettingRequest,
    person: Principal = Depends(get_current_principal),
    db: AsyncSession = Depends(get_db_session),
) -> SettingResponse:
    # Read-before-write so the FORAY audit row records the full
    # (previous, new) transition.
    try:
        previous = await get_setting(
            person_id=person.id, setting_key=setting_key, db=db
        )
    except UnknownSettingError:
        previous = None

    try:
        normalized = await set_setting(
            person_id=person.id,
            setting_key=setting_key,
            value=body.value,
            db=db,
        )
    except UnknownSettingError as exc:
        raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=str(exc)) from exc
    except InvalidSettingValueError as exc:
        raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=str(exc)) from exc

    # FORAY-audit-for-settings CR post-C5 -- best-effort audit row on
    # every successful PUT. engagement_id is None for this path
    # because /me/settings is person-scoped; the audit row captures
    # actor + key + transition + timestamp.
    try:
        await write_setting_change_event(
            actor_person_id=person.id,
            setting_key=setting_key,
            previous_value=previous,
            new_value=normalized,
            engagement_id=None,
            db=db,
        )
    except SQLAlchemyError:
        logger.exception(
            "audit write failed for PUT /me/settings/%s "
            "(person=%s); continuing -- setting write is authoritative",
            setting_key, person.id,
        )
    # FORAY_RESERVED_LOCATION: audit.setting_change
    _foray_reserved_emit(
        "audit.setting_change",
        {"setting_key": setting_key, "action": "tuned_button"},
    )
    await db.commit()
What data is actually available here

Enclosing route put_setting_route(setting_key, body, person: Principal = Depends(get_current_principal), db). person.id is a real, unambiguous person UUID from the authenticated principal — this is the strongest identity claim of the entire trio (no actor.kind ambiguity, no optional-parameter uncertainty; it's the route's own auth boundary), used one call earlier (write_setting_change_event(actor_person_id=person.id, ...), lines 148-155) but again not forwarded to the emit payload.

  • setting_key — real, from the route path parameter.
  • "tuned_button" — a hardcoded literal, not a computed value — this is the one site among the audit trio whose action field is not derived from an enum of possible outcomes; it's always this one string, distinguishing button-driven changes from voice/companion-driven ones (action at sites 13/14 varies: ACTION_TUNED/ACTION_RESET/etc.).
  • previous/normalized (the transition values) and engagement_id=None (explicit, commented: person-scoped route, no engagement) — all real, all passed to write_setting_change_event one block above, not forwarded to the FORAY emit.
  • No timestamp variable in scope reaching the emit (the docstring/comment says the audit row "captures... timestamp," but that is the separate write_setting_change_event audit-trail write, not a variable available to the _foray_reserved_emit call itself).
The FORAY 4.2 record this produces
{
  "schema_version": "4.2",
  "timestamp": "2026-08-18T00:00:00Z",
  "F1": "LW_audit.setting_change_e7f8a9b0",
  "F2": "e7f8a9b0-0011-4000-8000-000000000011",
  "F3": "9f8e7d6c-0000-4000-8000-0000000000f3",
  "F7": 0,
  "F8": "LOOMWORKS:NONE",
  "F26": "audit.setting_change",
  "arrangements": [],
  "accruals": [],
  "anticipations": [],
  "actions": [
    {
      "id": "ACT_AUDIT_e7f8a9b0",
      "F4": "setting_change",
      "F9": 0,
      "F22": [],
      "F23": [],
      "F24": [],
      "F25": {
        "setting_key": "voice_reply_style",
        "action": "tuned_button"
      }
    }
  ],
  "component_hashes": {
    "arrangements": "sha256:PLACEHOLDER",
    "accruals": "sha256:PLACEHOLDER",
    "anticipations": "sha256:PLACEHOLDER",
    "actions": "sha256:PLACEHOLDER"
  },
  "merkle_root": "sha256:PLACEHOLDER",
  "blockchain_anchor": {
    "kaspa_tx_id": null,
    "block_height": null,
    "confirmation_time_ms": null,
    "anchored_at": null
  }
}
Findings

F3 finding: person.id is genuinely in scope, unambiguous, and even stronger than sites 13-15's person_id (it comes straight from the authenticated Principal, no optionality). F3 = str(person.id) used above — again, not because the emit payload carries it (it doesn't), but because the brief instructs naming the variable that holds it at the site, and this is it.

Item-9 finding, same shape as sites 13/14, third instance: {setting_key, action}-only payload, with real, richer data (person.id, previous, normalized, engagement_id) available one call away and not forwarded. Across the full trio (sites 13, 14, 16), the same wiring gap repeats three times, independently, in three different call sites — worth stating once, here, as the cumulative shape of the finding rather than three isolated coincidences.

action value is a literal, not computed: distinguishes this site from 13/14, where action is one of several possible enum values.

---

Live validation results

All seventeen records (site 10 produces two) were submitted to POST /api/validate-foray against the live FORAY endpoint.

#Event kindResultErrorsWarningsNotes
1credit.issuancePASS[][][]
2credit.provisioningPASS[][][]
3credit.consumption_token` (worked leg)PASS[][][]
4credit.consumption_creditPASS[][][]
5credit.suspensionPASS[][][]
6credit.reactivationPASS[][][]
7credit.deletionPASS[][][]
8credit.balance_zeroingPASS[][][]
9credit.referral_creditPASS[][][]
10acredit.consumption_token` (room, worked leg)PASS[][][]
10bcredit.consumption_credit` (room)PASS[][][]
11credit.correctivePASS[][][]
12memory.engagement_committedPASS[][][]
13audit.setting_change` (enum)PASS[][][]
14audit.setting_change` (numeric)PASS[][][]
15conversation.turnPASS[][][]
16audit.setting_change` (button)PASS[][][]

Source: loomworks-engine at HEAD eb9392f5999ed13922024b9c306e9dfbc854f4c8, read-only. Every source line is copied verbatim from that commit.

Governing rulings: Asset-Type Reframe decision sheet v0.3 (R1 Yes, R2 scheme-qualified); FORAY Root Data Set v0.7; ratified catalog addendum v1.1. The reframe is what makes the eleven credit sites expressible at all — under the pre-reframe currency-only reading, none of them had an honest value for F8.

Two findings that outrank the rest: every one of the sixteen records is a single-Action record with nothing else in it to reference — no allocation, no cross-record link, is structurally possible under the current per-call-site emitter design. And at nine of the sixteen sites, real identifying data (a grant id, an approver, a person id) is genuinely in scope one line above the emit call and is simply never forwarded into the payload. Neither is a FORAY problem; both are upstream of any adaptor.

DUNIN7 — Done In Seven LLC — Miami, Florida