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.
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.
| # | File | Event kind | Component | Disposition |
|---|---|---|---|---|
| 1 | credit/flows.py:121 | credit.issuance | Action | Real credit grant; F21 nets to F9; grant_id available but not forwarded. |
| 2 | credit/flows.py:183 | credit.provisioning | Action | Institutional-only (provider→dunin7); no person UUID in function scope; F3 = "dunin7". |
| 3 | credit/flows.py:302 | credit.consumption_token` (×4 loop) | Action | Provider token asset, not Loomworks-scheme — F8 uses PROVIDER: prefix, breaking this doc's default convention; row-id flush-timing open question. |
| 4 | credit/flows.py:363 | credit.consumption_credit | Action | Real oracle-converted debit; no cross-link to the 4 token-leg records at site 3. |
| 5 | credit/flows.py:410 | credit.suspension | Action | Synthetic loomworks_account_status asset, qty 1; **flow.id read before flush** (structural gap, ordering differs from siblings). |
| 6 | credit/flows.py:446 | credit.reactivation | Action | Same synthetic asset; flush-before-emit (ordering differs from site 5). |
| 7 | credit/flows.py:481 | credit.deletion | Action | Same synthetic asset; triggers site 8 downstream with no cross-record link. |
| 8 | credit/flows.py:532 | credit.balance_zeroing` (0–3× loop) | Action | Conditional, variable count (0–3 records); legitimately emits nothing when no positive balance exists. |
| 9 | credit/flows.py:642 | credit.referral_credit | Action | Correct mapping; function currently has zero live callers (Phase 48 not yet wired). |
| 10 | credit/room_consumption.py:41 | credit.consumption_token` / `credit.consumption_credit` (dynamic, ×3) | Action | Same provider-scheme mismatch as site 3 for the 2 token legs; FIFO lot draw-down (real, downstream) has no FORAY-side link. |
| 11 | credit/proposal_applier.py:433 | credit.corrective | Action | **No pointer to proposal_id** — the thing it corrects. Unruled per Validation Scope v0.3 R2; stated, not resolved. |
| 12 | memory/events.py:273 | memory.<event_kind>` (dynamic, ~20+ kinds) | governance-shaped | F7: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". |
| 13 | orchestration/tune_setting.py:544 | audit.setting_change | governance-shaped | person_id genuinely in scope (used for audit write one line up) but not forwarded — {setting_key, action}-only payload. |
| 14 | orchestration/tune_setting.py:670 | audit.setting_change | governance-shaped | Identical shape/gap to site 13; duplicated call-site logic across two sibling functions. |
| 15 | orchestration/conversation_turns.py:270 | conversation.turn | governance-shaped | Strongest timestamp of the 16 (row.created_at, confirmed post-refresh); person_id in scope, not forwarded. |
| 16 | api/routers/me_settings.py:164 | audit.setting_change | governance-shaped | person.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.
write_issuance_flowcredit.issuance
src/loomworks/credit/flows.py:121Source
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 txidWhat data is actually available here
flow.id— the newCreditFlowRowprimary key, populated byawait db.flush()on line 119, one line before the emit.txid— the transaction id,_new_transaction_id()(a freshuuid.uuid4()), line 105.asset_id— caller-suppliedstrparameter; no fixed value at this site. Worked example uses"loomworks_credit_sonnet".amount— caller-suppliedint, must be> 0(checked line 101-104).flow.from_party=DUNIN7_PARTY="dunin7"(institutional, not a UUID).flow.to_party=str(person_id)—person_idis a realUUIDparameter, this IS a person-scoped site.flow.turn_event_id— not set on thisCreditFlowRowconstruction (noturn_event_id=kwarg passed), so this is alwaysNoneat this site; the ternary at lines 130-132 is dead code for this call site specifically (issuance is not turn-triggered).grant_id— realUUIDparameter, folded intoextra_metadatabut 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.
---
write_provisioning_flowcredit.provisioning
src/loomworks/credit/flows.py:183Source
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 txidWhat 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 | Noneexists as a parameter and IS folded intoextra_metadata(line:extra["authorized_by"] = str(authorized_by)) when present, but likegrant_idat 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 all — person_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.
---
write_consumption_flows (token loop, ×4)credit.consumption_token
src/loomworks/credit/flows.py:302Source
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 ownawait 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 forcredit_flowlater at line 361, AFTER this loop. Finding:row.idat this loop (lines 298-315) is read from ORM objects that have beendb.add()-ed but not yet flushed — whetherrow.idis populated depends on whether the DB assigns the PK client-side (e.g. a UUID default) or server-side.CreditFlowRow.idtype was not independently re-verified as part of Brief 23; flagged as a finding rather than assumed.row.asset_id— one ofclassifier_input_asset("anthropic_haiku_4_input"),classifier_output_asset("anthropic_haiku_4_output"), orresponder_input_asset/responder_output_asset(unpacked from the caller-suppliedresponder_model_token_pairtuple) — these are Anthropic provider token assets, NOT Loomworks credit assets. This is one of the sites where theLOOMWORKS:scheme prefix is wrong on its face (item 9 finding, see below).row.quantity— real token counts (classifier_input_tokensetc., caller-suppliedint).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 realUUIDparameter — genuinely populated at this site (unlike site 1).engagement_id— realUUIDparameter, folded into each row'sextra_metadatabut 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.
---
write_consumption_flows (credit debit)credit.consumption_credit
src/loomworks/credit/flows.py:363Source
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 txidWhat 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-suppliedstrparameter (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 computedint, the sum of fourconvert_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_idreaches the emit payload,engagement_iddoes 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.
---
write_suspension_flowcredit.suspension
src/loomworks/credit/flows.py:410Source
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 txidWhat data is actually available here
flow.id— finding:db.add(flow)happens, then the emit fires, andawait db.flush()happens after the emit (last line beforereturn) — the opposite order from sites 1/2/4.flow.idis 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=1is a literal, a state flag not a real quantity.person_id— real UUID parameter, inflow.to_party.requested_by,expires_at— real parameters (an operator/actor UUID and a realdatetime), both folded intoextra_metadatabut not forwarded to the emit payload —expires_atin 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_idhardcodedNonein 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.
---
write_reactivation_flowcredit.reactivation
src/loomworks/credit/flows.py:446Source
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 txidWhat 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— realstrparameter (how the reactivation was authenticated), folded intoextra_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.
---
write_deletion_flowcredit.deletion
src/loomworks/credit/flows.py:481Source
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 txidWhat data is actually available here
flow.id— populated (flush before emit).person_id,deletion_kind(realstr, e.g."self_service"/"operator"— not forwarded to emit payload).- Same
ACCOUNT_STATUS_ASSET/quantity=1pattern. - 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).
---
write_balance_zeroing_flows (loop, 0-3×)credit.balance_zeroing
src/loomworks/credit/flows.py:532Source
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 txidWhat data is actually available here
- This site is conditional and variable-count: zero to
len(CREDIT_ASSET_IDS)(3, perbalance.py'sCREDIT_HAIKU/CREDIT_SONNET/CREDIT_OPUS) records may be produced per call, one per asset tier wherebalance > 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 byif zeroed_flows:).asset_id— real, iterated fromCREDIT_ASSET_IDS("loomworks_credit_haiku"/"_sonnet"/"_opus") — genuinely tier-specific per record, not a single fixed value.flow.quantity=balance— a real, queriedint(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).
---
write_referral_credit_flowcredit.referral_credit
src/loomworks/credit/flows.py:642Source
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 txidWhat 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, inflow.to_party.DUNIN7_PARTY="dunin7", inflow.from_party.converted_person_uuid— a real, optionalUUID(the referee whose conversion triggered this credit), stored in the typedconverted_person_idcolumn but not in the emit payload — same forward-gap pattern asgrant_id/authorized_by/auth_method/deletion_kindabove, 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.
---
write_room_consumption_flows._emit (×3)credit.consumption_token / credit.consumption_credit
src/loomworks/credit/room_consumption.py:41Source
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— realUUID | Noneparameter, forwarded correctly here (unlikeflows.pysite 5, but likeflows.pysites 3/4).input_asset/output_assetcome fromresponder_model_to_token_asset_pair(model)— provider token assets, sameLOOMWORKS:scheme mismatch finding asflows.pysite 3.credit_asset_id— real Loomworks-scheme tier for the third call.engagement_id,room— real values, folded intoextra_metadataonly, not forwarded to the emit payload (same forward-gap pattern asflows.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.
{
"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
}
}{
"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.
---
apply_reconciliation_correctioncredit.corrective
src/loomworks/credit/proposal_applier.py:433Source
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 byCorrectiveForayFlowRenderSpecialist.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— freshuuid.uuid4().proposal_id— real UUID parameter, not referenced anywhere in the emit payload or inextra_metadatashown 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 (theShapeEventrow built earlier in this function, lines 371-399), captured intoextra_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 siblingShapeEvent'screated_at/confirmed_at, not a variable that reaches thecredit.correctiveemit — 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.
---
append_eventmemory.<event_kind>
src/loomworks/memory/events.py:273Source
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 eventWhat 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-mintedUUIDparameter — 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_at— this is one of the three sites in the whole census with a real timestamp variable:timestamp=object.created_at(line 204) is set on theMemoryEventRowfrom the caller-suppliedobject.created_at— a realdatetime, though it reflects when the caller constructedobject, not necessarily this exactappend_eventexecution.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 onlyevent_idandanchor_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 inforay/anchor_priority.py;Nonefor 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 all — event_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.
---
_execute_enum_settingaudit.setting_change
src/loomworks/orchestration/tune_setting.py:544Source
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— realstrparameter, e.g."voice_reply_style".action— real, one ofACTION_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_changeone 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.
---
_execute_numeric_settingaudit.setting_change
src/loomworks/orchestration/tune_setting.py:670Source
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.
---
record_turnconversation.turn
src/loomworks/orchestration/conversation_turns.py:270Source
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()thenawait db.refresh(row)both run immediately before the emit (lines 258-259).row.created_at— the second of the three sites with a genuinely available, confirmed-populated timestamp:ConverseTurnRow.created_atuses a Python-side default that fires at flush time (confirmed by the model's own source comment inorchestration/models.py), andawait 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'sobject.created_atis 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, thoughperson_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_id — person_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.
---
put_setting_routeaudit.setting_change
src/loomworks/api/routers/me_settings.py:164Source
@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 whoseactionfield is not derived from an enum of possible outcomes; it's always this one string, distinguishing button-driven changes from voice/companion-driven ones (actionat sites 13/14 varies:ACTION_TUNED/ACTION_RESET/etc.).previous/normalized(the transition values) andengagement_id=None(explicit, commented: person-scoped route, no engagement) — all real, all passed towrite_setting_change_eventone 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_eventaudit-trail write, not a variable available to the_foray_reserved_emitcall 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 kind | Result | Errors | Warnings | Notes |
|---|---|---|---|---|---|
| 1 | credit.issuance | PASS | [] | [] | [] |
| 2 | credit.provisioning | PASS | [] | [] | [] |
| 3 | credit.consumption_token` (worked leg) | PASS | [] | [] | [] |
| 4 | credit.consumption_credit | PASS | [] | [] | [] |
| 5 | credit.suspension | PASS | [] | [] | [] |
| 6 | credit.reactivation | PASS | [] | [] | [] |
| 7 | credit.deletion | PASS | [] | [] | [] |
| 8 | credit.balance_zeroing | PASS | [] | [] | [] |
| 9 | credit.referral_credit | PASS | [] | [] | [] |
| 10a | credit.consumption_token` (room, worked leg) | PASS | [] | [] | [] |
| 10b | credit.consumption_credit` (room) | PASS | [] | [] | [] |
| 11 | credit.corrective | PASS | [] | [] | [] |
| 12 | memory.engagement_committed | PASS | [] | [] | [] |
| 13 | audit.setting_change` (enum) | PASS | [] | [] | [] |
| 14 | audit.setting_change` (numeric) | PASS | [] | [] | [] |
| 15 | conversation.turn | PASS | [] | [] | [] |
| 16 | audit.setting_change` (button) | PASS | [] | [] | [] |