Date: 2026-08-18 (v0.3 revision 2026-08-20)
Brief: Brief 23, W1–W2; corrected at Brief 24, Brief
29, and this v0.3 revision Supersedes:
loomworks-foray-census-v0_1.md and
loomworks-foray-mapping-v0_1.md (Brief 21) in content.
Neither file is deleted; both remain as historical record of the
pre-reframe, blocked mapping attempt. This document replaces
them as the reference — self-contained, nothing deferred to
either. Grounding:
loomworks-engine at main, HEAD
eb9392f5999ed13922024b9c306e9dfbc854f4c8, read-only. Every
source line below is copy-pasted from the file at that commit, not
retyped from memory or from Brief 21’s report. Governing rulings
applied: Asset-Type Reframe decision sheet v0.3, R1 (YES) and
R2 (SCHEME-QUALIFIED); FORAY Root Data Set v0.7; ratified catalog
addendum v1.1. F8 is a scheme-qualified asset-type
identifier; ISO 4217 is one admissible scheme among others; the reframe
is what makes the eleven credit sites mappable at all.
Status: documentation only. No code, no client, no
emitter, no test. POST /api/anchor was not called at any
point.
Correction notice (Brief 24, 2026-08-18): the
sixteen JSON records in the original v0.2 pass (this same file, prior to
this correction) were structurally wrong — built without checking
against foray-api/schema/foray-transaction-v4_2.schema.json
and the wire skill while being written. Every Action element was missing
id, and the three required reference arrays
F22/F23/F24; F9
(settled amount) was omitted; F21 entries used an invented
{party, currency, amount} shape (a double-entry accounting
pair) instead of the real {ref, ref_type, amount, currency}
allocation shape; component_hashes was an
array-of-placeholders per component instead of one placeholder string
per component key; blockchain_anchor used invented field
names instead of the real
kaspa_tx_id/block_height/confirmation_time_ms/anchored_at.
All sixteen JSON blocks below have been rebuilt against the
actual schema and skill — see each site’s “Correction (Brief
24)” note where its shape or reasoning changed. The prose analysis
around them (source quotes, data-availability findings, F1/F2/F3
reasoning, timestamp findings) was correct in the original pass and is
unchanged except where a specific JSON-shape error forced a correction
to the sentence describing it (noted inline, per site). Two structural
corrections apply schema-wide: (1) no site carries an F21
entry — every one of the sixteen records is a single-Action
record with no Arrangement/Accrual/Anticipation for an allocation to
reference, so F21 is correctly omitted everywhere, not just where v0.2
happened to show one; (2) F3/F8 cannot be
null — the schema requires both as non-empty
strings; the two sites where v0.2 stated F3: null or
F8: null (governance sites with no genuine identity/asset)
now carry stated placeholder strings ("UNATTRIBUTED",
"LOOMWORKS:NONE"), marked explicitly as schema-compliance
placeholders, not real values.
Live validation (W3):
POST /api/validate-foray was authorized for this brief. The
first attempt was blocked by the session’s outbound-network permission
layer (an auto-mode classifier denial on POST to an external host);
scoped access was then explicitly granted for this purpose, and
all seventeen records in this document were submitted — 17/17
valid, 0 errors, 0 warnings, 0 notes. A PASS confirms
shape-conformance to the ruled 4.2 wire (including E7
malformed-reference-entry, E9 ref_type mismatch, E8
allocation-sum, E14 currency resolution, W3 number-spelling); it does
not certify that content is true — the placeholder
F3/F8 values at sites 12–16 are schema-legal
strings, not real facts, per each site’s own stated finding. Full
per-record results in the separate “Brief 24 W3” section below.
Correction notice (v0.3, 2026-08-20) — precision, not a
defect. Two descriptive asides in this document characterised
E7/E9 as “in-record reference
resolution.” That phrasing was accurate when written and became
imprecise when Brief 26 narrowed both codes the same week:
E7 now fires only on a reference entry
that is not a string; E9 only on a
ref_type contradicting a component actually present in the
record; a well-formed reference that does not resolve is note
N4, and the record stays valid. Both phrases are tightened
in this revision. No substantive claim in this document was
wrong — the Brief 29 notice below already stated Brief 26’s
change correctly, and no record in this set carries any reference for
the distinction to bear on. Recorded because FORAY initially reported
this to Loomworks as a document-level error, which overstated it; the
correction to that report travels separately.
Correction notice (Brief 29, 2026-08-20):
F4-code-list-and-f26-status-decision-sheet-v0_4.md ruled
F4 and F26 as closed, catalog-governed code
lists — F4 per-component, F26
snake_case-canonical. Every F4 value in this
document already matched the ruled list exactly, unchanged.
Every F26 value has been re-cast from the dotted
form this document originally used (credit.issuance,
memory.engagement_committed,
audit.setting_change, etc.) to the ruled snake_case form
(credit_issuance, engagement_committed,
setting_change, etc.) — see the “F26 (transaction
type)” convention note below for the full reasoning, including the
distinction this surfaces between F26 (FORAY’s catalog
field) and Loomworks’ own event_kind string (unchanged,
still shown in dotted form throughout the section headers and W2 table,
correctly — that’s a verbatim source-code fact, not F26). All
seventeen corrected records were re-validated live: 17/17 valid, 0
errors, 0 warnings, 0 notes — identical clean result to Brief
24’s run; none of these records carry
F21/F22–F24 references, so Brief
26’s R2 change (dangling references now recorded as note N4 rather than
rejected) has nothing to act on in this document, and no incidental
validation difference was observed. Full per-site before/after values in
the separate Brief 29 report.
| # | File | Line | event_kind |
Component | One-line 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. |
F8 scheme choice. The brief permits one consistent
code (LOOMWORKS:CREDIT) unless the source data suggests a
better name. It does. credit/balance.py defines three
concrete, tier-identified credit assets —
loomworks_credit_haiku,
loomworks_credit_sonnet, loomworks_credit_opus
(CREDIT_HAIKU/CREDIT_SONNET/CREDIT_OPUS)
— and room_consumption.py’s own module docstring states the
design intent directly: “Tier-identified (debits the specific tier —
never a generic credit, so cost-plus pricing has something to
price).” Collapsing three tiers into one generic
LOOMWORKS:CREDIT code would erase exactly the distinction
the system was built to preserve. F8 =
LOOMWORKS:<asset_id>, where
<asset_id> is the site’s own real
asset_id value —
LOOMWORKS:loomworks_credit_sonnet,
LOOMWORKS:loomworks_account_status, etc. — one consistent
scheme prefix (LOOMWORKS:), applied to whatever the source
data actually names. Where asset_id is a caller-supplied
parameter with no fixed value in source (issuance, provisioning,
referral credit all accept asset_id: str), a representative
real tier is used for the worked example and the parameterization is
stated.
F26 (transaction type) — Correction (Brief 29,
2026-08-20).
F4-code-list-and-f26-status-decision-sheet-v0_4.md ruled
F26 closed and snake_case-canonical, built in part from this document’s
own dotted-form values (credit.issuance,
memory.engagement_committed,
audit.setting_change, etc.), re-cast to snake_case
(credit_issuance, engagement_committed,
setting_change). Every F26 value in
the seventeen records below has been updated to the ruled snake_case
form. This surfaces a distinction the original v0.2 pass
conflated: F26 (FORAY’s own catalog field) is not
the same string as Loomworks’ event_kind (the
literal value passed to _foray_reserved_emit,
e.g. "credit.issuance", "credit.suspension") —
v0.2 simply copied the emit-call string into F26 verbatim,
which happened to look identical because no ruling had yet fixed F26’s
canonical shape. This document’s section headers, the W2 summary
table’s event_kind column, and every quoted-from-source
line still correctly show Loomworks’ real, unchanged
event_kind strings (dotted form) — those are verbatim facts
about Loomworks’ source code and are untouched by this
correction. Only the JSON records’ own F26 field
changed. One divergence worth naming once rather than at each site:
three sites’ F4 and F26 now differ in
substance, not just shape — write_suspension_flow’s
F4 is account_suspension (the component: what
changed) while its F26 is credit_suspension
(the transaction: which family it belongs to); same pattern at
write_reactivation_flow (account_reactivation
/ credit_reactivation) and write_deletion_flow
(account_deletion / credit_deletion). This is
correct per the ruling, not an inconsistency — F4 names the
component, F26 names the transaction as a whole, and the
ruled lists show real divergence between them elsewhere in the corpus
too.
F1/F2 identifier scheme. Loomworks is, relative to
FORAY, an external originating system — this is adaptor-mediated
origination under ratified ruling OQ-7: “F2 carries the
originating system’s key verbatim… distinct from F1.” So:
F2 = the site’s own Loomworks-native identifier
verbatim (the flow_id, event_id, or
turn_id UUID, as a string, unchanged) — this is the
field-map-sheet-confirmed source key. F1 = a
FORAY-side evidence-record identifier, constructed here as
LW_<event_kind>_<first 8 hex of the source UUID>
for legibility, consistent with the wire skill’s own
DOMAIN_YYYY_QN_DESCRIPTOR style. Finding, stated
once rather than sixteen times: no F1-minting scheme exists in
Loomworks today — this brief invents a legible one for the worked
examples; an actual adaptor’s F1 minting convention is an open design
decision, not yet made anywhere in either repo.
F3 (record owner). Per the brief’s own instruction
and the seed’s language (“The UUID is what other Loomworks records
reference; it is what FORAY attests against”):
F3 = str(person_id), cleartext
form, wherever person_id is in scope — a valid
OQ-8 cleartext value (any non-sha256:-prefixed string).
Institution-only sites (no person party at all) use the institutional
party string as F3 instead, named as such.
Timestamp. Per claim discipline, an in-record
timestamp is a submitter assertion, not proof — anchor time
is what FORAY actually proves. Checked precisely per site, not
assumed: most of the sixteen sites capture no
wall-clock variable at all before the emit call (confirmed by grep — no
datetime.now()/utcnow() in
flows.py, room_consumption.py,
tune_setting.py, or me_settings.py). Three
sites do have a real timestamp in scope: memory/events.py
(object.created_at, set by the caller before
append_event runs),
orchestration/conversation_turns.py
(row.created_at, a Python-side default populated by
await db.refresh(row) immediately before the emit), and
credit/proposal_applier.py (a
datetime.now(UTC) call exists in the same function, for a
sibling object’s created_at, not captured into a variable
that reaches the credit.corrective emit itself).
This is reported per site below, not glossed over —
where no variable exists, the worked JSON’s timestamp is
the moment-of-emission wall clock as an adaptor would need to capture it
fresh, explicitly marked as constructed rather than sourced.
Placeholder fields, stated once. Every record’s
component_hashes and merkle_root use the
canonical pre-anchoring placeholder form
("sha256:PLACEHOLDER" per component array, per the wire
skill’s own template); blockchain_anchor is all-null.
Neither is computed here — that is the anchoring pipeline’s job, not the
adaptor’s.
write_issuance_flow — credit.issuanceFile / line:
src/loomworks/credit/flows.py:121
Source (verbatim):
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 txidData genuinely available at this point (real variable names):
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).datetime.now()/utcnow() call anywhere in this
function.FORAY 4.2 record this site would produce:
{
"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
}
}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_flow —
credit.provisioningFile / line:
src/loomworks/credit/flows.py:183
Source (verbatim):
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 txidData genuinely available at this point (real variable names):
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.FORAY 4.2 record this site would produce:
{
"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
}
}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_tokenFile / line:
src/loomworks/credit/flows.py:302
Source (verbatim):
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
),
},
)Data genuinely available at this point (real variable names):
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.FORAY 4.2 record this site would produce:
{
"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
}
}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_creditFile / line:
src/loomworks/credit/flows.py:363
Source (verbatim):
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 txidData genuinely available at this point (real variable names):
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).FORAY 4.2 record this site would produce:
{
"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
}
}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_flow — credit.suspensionFile / line:
src/loomworks/credit/flows.py:410
Source (verbatim):
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 txidData genuinely available at this point (real variable names):
flow.id — finding:
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
payload — expires_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.FORAY 4.2 record this site would produce:
{
"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
}
}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_flow —
credit.reactivationFile / line:
src/loomworks/credit/flows.py:446
Source (verbatim):
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 txidData genuinely available at this point (real variable names):
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.FORAY 4.2 record this site would produce:
{
"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
}
}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_flow — credit.deletionFile / line:
src/loomworks/credit/flows.py:481
Source (verbatim):
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 txidData genuinely available at this point (real variable names):
flow.id — populated (flush before emit).person_id, deletion_kind (real
str,
e.g. "self_service"/"operator" — not forwarded
to emit payload).ACCOUNT_STATUS_ASSET/quantity=1
pattern.FORAY 4.2 record this site would produce:
{
"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
}
}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_zeroingFile / line:
src/loomworks/credit/flows.py:532
Source (verbatim):
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 txidData genuinely available at this point (real variable names):
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.FORAY 4.2 record this site would produce:
{
"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
}
}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_flow —
credit.referral_creditFile / line:
src/loomworks/credit/flows.py:642
Source (verbatim):
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 txidData genuinely available at this point (real variable names):
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.
FORAY 4.2 record this site would produce:
{
"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
}
}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_creditFile / line:
src/loomworks/credit/room_consumption.py:41
Source (verbatim):
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).Data genuinely available at this point (real variable names):
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).FORAY 4.2 record this site would produce:
{
"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
}
}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_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
}
}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_correction —
credit.correctiveFile / line:
src/loomworks/credit/proposal_applier.py:433
Source (verbatim):
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
),
},
)Data genuinely available at this point (real variable names):
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.
FORAY 4.2 record this site would produce:
{
"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
}
}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_event —
memory.<event_kind>File / line:
src/loomworks/memory/events.py:273
Source (verbatim):
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 eventData genuinely available at this point (real variable names):
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_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 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.
FORAY 4.2 record this site would produce:
{
"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": "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
}
}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_setting —
audit.setting_changeFile / line:
src/loomworks/orchestration/tune_setting.py:544
Source (verbatim):
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),
}Data genuinely available at this point (real variable names):
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.
FORAY 4.2 record this site would produce:
{
"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": "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
}
}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_setting —
audit.setting_changeFile / line:
src/loomworks/orchestration/tune_setting.py:670
Source (verbatim):
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,
...
}Data genuinely available at this point (real variable names):
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.
FORAY 4.2 record this site would produce:
{
"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": "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
}
}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_turn —
conversation.turnFile / line:
src/loomworks/orchestration/conversation_turns.py:270
Source (verbatim):
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)Data genuinely available at this point (real variable names):
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_at — the 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.
FORAY 4.2 record this site would produce:
{
"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
}
}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_route — audit.setting_changeFile / line:
src/loomworks/api/routers/me_settings.py:164
Source (verbatim):
@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()Data genuinely available at this point (real variable names):
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).
FORAY 4.2 record this site would produce:
{
"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": "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
}
}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.
Confirmed against loomworks-engine HEAD
eb9392f5999ed13922024b9c306e9dfbc854f4c8, re-derived from
source via
grep -n "_foray_reserved_emit\|FORAY_RESERVED_LOCATION\|def write_"
across all seven files, not carried forward from Brief 21’s report.
Total: 16. Breakdown: 11 credit / 3 audit / 1 memory / 1
conversation. This matches Brief 21’s frozen breakdown exactly.
No addition, removal, or move found. The two counting
traps Brief 21 named (the module docstring’s line-16 reference in
flows.py, which mentions _foray_reserved_emit
in prose but is not a call site; and the emitter’s own file,
loomworks/foray/__init__.py, which defines
_foray_reserved_emit but does not call it) were both
re-confirmed excluded by this brief’s own independent read, not assumed
from the prior count.
One re-classification, not a drift: Brief 21 (and this document’s own
site numbering) counts write_balance_zeroing_flows (site 8)
and
write_suspension_flow/write_reactivation_flow/write_deletion_flow
(sites 5-7) among the “eleven credit” sites — all four use the synthetic
ACCOUNT_STATUS_ASSET, not a real currency/credit amount
under the pre-reframe reading. This was already Brief 21’s disposition
and is unchanged; noted here only because a careless reader of “credit
sites” might expect all eleven to be monetary in the ordinary sense, and
four of them are not.
Checked against loomworks-candidate-seed-v0_14.md
(confirmed highest version via ls | sort -V in
loomworks-record/candidate-seeds/loomworks/; its
-amendment-v0_1.md companion also read) at
loomworks-record HEAD
37226814dbd1227b7610e65bddd81295ce000a20.
No conflict found. The seed’s only two touchpoints relevant to this mapping:
F3 convention (§“A note on conventions”) is built from;
consistent by construction, not merely non-conflicting.LOOMWORKS: scheme choice made in this document
is exactly the kind of internal-mechanism decision the seed defers
rather than commits to — there is nothing in the seed for it to
conflict with, and the seed’s own posture (defer, don’t specify) is
itself consistent with the Asset-Type Reframe’s ruling that FORAY
governs no scheme vocabulary.No mention of “credit,” “currency,” or any asset-type vocabulary appears anywhere in the seed or its amendment — confirmed by full-text search, not partial grep. The eleven credit mappings introduce no seed-level commitment that did not already exist.
DUNIN7 — Done In Seven LLC — Miami, Florida FORAY — Loomworks→FORAY mapping — full call-site documentation — v0_2 — 2026-08-18
Each site’s “does not map cleanly” findings (item 9) were re-read against the rebuilt JSON. Result, site by site:
**Correction (Brief 24):**.PROVIDER: vs LOOMWORKS:) unaffected; F21
restated as correctly absent; row-id flush-timing open question
unaffected.credit.corrective) —
this finding changed in kind, not just in wording. v0.2
described the missing pointer to proposal_id as an absent
field in an otherwise-plausible F21 allocation. Under the corrected
shape, the finding sharpens: F21 cannot exist at this site at
all under the current per-call-site, single-Action-record
design, regardless of whether proposal_id were
forwarded into the payload — there is no
Arrangement/Accrual/Anticipation in the record for an F21 entry’s
ref to resolve against. The missing pointer is not a
data-availability gap alone; it is a structural ceiling on what this
record shape can express. Restated in full at site 11.F9: 0, and never carried a v0.2 F21). New finding
surfaced by this brief, not present in v0.2: v0.2’s
F3: null (sites 12, 15) and F8: null (sites
12–16) were schema-illegal — OwnerForm and
transaction-level F8 both require non-empty strings. This
is a genuine defect in v0.2’s JSON construction, not merely a stylistic
gap; it is now corrected at each site with an explicitly marked
placeholder, and the underlying findings (no UUID at site 12,
person_id/person.id in-scope-but-unforwarded
at sites 13/14/15/16) are unchanged and still stand.No finding was silently dropped. Two findings changed in substance (site 11’s structural-ceiling reframing; the newly-surfaced F3/F8 schema-illegality at sites 12/15/16), both stated explicitly above and inline at their sites.
Performed on all sixteen sites (seventeen records — site 10
carries two). Outbound POST access to
https://foray.dunin7.com/api/validate-foray was granted for
this specific purpose after the gate was first held open on this exact
gap; every record in this document was then submitted, not only the four
originally scoped (the four-minimum was written when live access looked
uncertain — once it was actually available, all seventeen were
checked).
Result: 17/17 valid, 0 errors, 0 warnings, 0 notes, across
every record. Each call returned HTTP 200 with
{"valid": true, "schema_version": "4.2", "validated_version": "4.2", "conversion_applied": null, "labels": [], "errors": [], "warnings": [], "notes": []}
— full per-record results below.
| # | Site | valid |
errors |
warnings |
notes |
|---|---|---|---|---|---|
| 1 | credit.issuance |
true | [] | [] | [] |
| 2 | credit.provisioning |
true | [] | [] | [] |
| 3 | credit.consumption_token (worked leg) |
true | [] | [] | [] |
| 4 | credit.consumption_credit |
true | [] | [] | [] |
| 5 | credit.suspension |
true | [] | [] | [] |
| 6 | credit.reactivation |
true | [] | [] | [] |
| 7 | credit.deletion |
true | [] | [] | [] |
| 8 | credit.balance_zeroing |
true | [] | [] | [] |
| 9 | credit.referral_credit |
true | [] | [] | [] |
| 10a | credit.consumption_token (room, worked leg) |
true | [] | [] | [] |
| 10b | credit.consumption_credit (room) |
true | [] | [] | [] |
| 11 | credit.corrective |
true | [] | [] | [] |
| 12 | memory.engagement_committed |
true | [] | [] | [] |
| 13 | audit.setting_change (enum) |
true | [] | [] | [] |
| 14 | audit.setting_change (numeric) |
true | [] | [] | [] |
| 15 | conversation.turn |
true | [] | [] | [] |
| 16 | audit.setting_change (button) |
true | [] | [] | [] |
Interpretation, held to claim discipline: a PASS
confirms the record conforms to the ruled 4.2 shape — schema requireds,
F21 structure, reference well-formedness (E7 fires only on a non-string
reference entry; E9 only on a ref_type that contradicts a
component actually present — vacuously satisfied here, since no record
in this set carries any reference), allocation-sum (E8, likewise vacuous
— no F21 entries exist anywhere in this set), currency resolution (E14,
satisfied since F8 is present at transaction level in every
record), and canonical number spelling (W3, zero flags). It does
not confirm the content is true —
F3/F8’s placeholder values at sites 12–16 are
schema-legal strings, not real facts, exactly as stated at each site; a
PASS on those records is a pass on shape, not a certification that
"UNATTRIBUTED"/"LOOMWORKS:NONE" are meaningful
identities or assets. No validation failure occurred, so no site
required a choice between fabricating data and reporting a blocked
finding — the brief’s instruction on that point did not need to
be invoked.