DUNIN7 · LOOMWORKS · RECORD
record.dunin7.com
Status Current
Path phases/phase-63-editor-refinement/loomworks-phase-63-step-0-inspection-brief-v0_1.html
DUNIN7 · Loomworks · Phase 63 · Step 0 Inspection Brief

Pre-flight Verification

Grounding the Phase 63 scoping note against current code state before Change Request drafting
v0.1·2026-05-23·Working draft
What this document is

Step 0 of Phase 63's methodology cadence. The Phase 63 scoping note v0.1 names what the phase will do and rests on several assumptions about the current state of the loomworks-engine codebase and the loomworks-record Pages Functions. This brief names each assumption as a numbered verification, says what file or module CC should read to verify it, and says what should come back.

CC executes the verifications and produces a findings report. Findings either confirm the scoping (Step 0 closes clean; Change Request drafting proceeds) or surface deltas — places where current code state diverges from what the scoping assumed. Deltas get absorbed into a scoping note v0.2 before the Change Request opens. This is the standard halt-and-surface discipline applied to pre-flight inspection.

Eleven verifications total, organized by the area of Phase 63 work they ground. Each is numbered for easy reference in the findings report (V1 through V11). The brief is written so CC can execute it without referencing other documents; everything CC needs to know about what to verify is in this brief.

Section 1

Verifications grounding Piece 2 — FORAY narrative-event wiring

Piece 2 of Phase 63 adds editor commits as FORAY narrative events in the audit.foray_events table. The scoping note assumes a particular extension pattern. The following verifications confirm that pattern exists as described and surface its concrete shape.

V1

The existing setting-change writer pattern

Read src/loomworks/audit/events.py in the loomworks-engine repository. The scoping note assumes there is exactly one writer helper today: write_setting_change_event(...). Verify this is the case. Report the exact function signature, the event_type constant naming convention, and the payload shape convention (what keys are expected in the JSONB payload).

Expected finding

A single writer helper with signature taking actor_person_id: UUID, the setting key and previous/new values, an optional engagement_id, and a database session. A constant like EVENT_TYPE_SETTING_CHANGE = "setting_change". Payload shape documented in the helper's docstring or by example.

What to report back

Quote the actual function signature, the actual event-type constant, and one example call-site (probably in orchestration/tune_setting.py or api/routers/me_settings.py). If the pattern is different from expected, name the difference explicitly.

V2

The audit.foray_events table shape

Read the Alembic migration that created the audit.foray_events table (likely migrations/versions/0068_audit_foray_events.py based on prior inspection). The scoping note assumes the table is structurally extensible — that adding new event types like editor_commit requires no schema migration. Verify this.

Expected finding

A table with columns: id, tx_id, event_type (VARCHAR), actor_person_id, engagement_id (nullable), payload (JSONB), signature (nullable), timestamp. No event-type discriminator table, no plug-in registry, no constraint on event_type values. The migration docstring should explicitly anticipate additional event types.

What to report back

The actual column list, any constraints that might block new event types, and the relevant docstring text. If the table has constraints that would block "editor_commit" as a value, name them.

V3

The best-effort writing convention

Read both call sites that use the existing write_setting_change_event writer (the orchestration/tune_setting.py file and the api/routers/me_settings.py file). The scoping note states the audit row is best-effort — wrapped in try/except SQLAlchemyError, logged on failure, but the business transaction succeeds even if the audit row doesn't land. Verify this convention.

Expected finding

Both call sites wrap the writer call in try/except SQLAlchemyError. On exception, they log a warning and continue. The setting change commits regardless of audit-row outcome.

What to report back

Quote the actual exception handling pattern. If the convention is different at the two call sites (one strict, one best-effort), surface that — it suggests the convention isn't yet stable.

Section 2

Verifications grounding Piece 3 — Audit viewer and read API

Piece 3 of Phase 63 builds a viewer on record.dunin7.com that presents FORAY narrative events back to the operator. The viewer requires a public read API on loomworks-engine that does not exist today. The following verifications ground the read-API design in the engine's existing API conventions.

V4

The engine's existing API router conventions

Read src/loomworks/api/routers/ in the engine repository. The scoping note's read-API design will follow the same conventions as existing routers. Report the conventions: what framework (FastAPI assumed), what authentication pattern is used on routes today, what response models look like (Pydantic), what pagination pattern exists if any.

Expected finding

FastAPI routers organized by resource. Routes use dependency injection for authentication. Pydantic response models with explicit schemas. Pagination patterns either via offset/limit query params or cursor-based.

What to report back

Name three to five existing routers (with file paths). Quote one route's signature including authentication dependency. Quote one Pydantic response model. Name the pagination pattern if one exists.

V5

The engine's API host and exposure

Read the engine's deployment configuration and any API host references (likely in pyproject.toml, environment-variable docs, or a hosts/CORS configuration). The scoping note's deployment-architecture question (whether record.dunin7.com's Pages Functions call engine API directly or proxy through their own Functions) hinges on how the engine API is exposed today.

Expected finding

The engine API is hosted at some address — possibly api.loomworks.dunin7.com per prior context, possibly elsewhere. CORS may or may not allow record.dunin7.com origin. Authentication may be session-based or token-based.

What to report back

The API host (or hosts) the engine is configured to serve. The CORS configuration if visible. The authentication mechanism. Anything that would block or complicate a Cloudflare Pages Function (running on record.dunin7.com) calling the engine API directly.

V6

Whether any read-API surface for any FORAY table exists today

Search the engine for any HTTP routes that read FORAY rows back — either narrative events from audit.foray_events or value flows from credit.foray_action_flows. The scoping note assumes no such routes exist today.

Expected finding

No routes exposing either FORAY table. Internal SQLAlchemy selects may exist in business logic (the prior inspection noted reconciliation_evaluator and conversion_observer use selects against ForayActionFlowRow), but no HTTP read API.

What to report back

Confirm or contradict the assumption. If any read-API surface exists for any FORAY table, name the route(s) and the file. If internal selects exist that could be lifted into an API surface easily, name them as candidates for reuse.

Section 3

Verifications grounding Piece 1 — Editor refinement

Piece 1 of Phase 63 changes the version-bump operation in the editor at record.dunin7.com. The current editor code lives in the loomworks-record repository. The following verifications ground the editor-code changes in the current state of those files.

V7

The current version-bump implementation in the editor

Read functions/api/save.ts and tools/static/editor.js in the loomworks-record repository. The scoping note assumes the current version-bump operation copies file content unchanged to the new versioned path and archives the old. Verify this. Report the exact code path that handles version-bump saves.

Expected finding

In save.ts, a code path that handles the "save as new version" mode: computes the new path from the current path's version number, creates the new file with the request body's content, moves the old file to archive/. No content transformation between old and new.

What to report back

Quote the version-bump code path. Name where the new content comes from (request body, presumably). Confirm that no content transformation happens. Identify the natural place where a version-string scanner would attach — before the new file is written, with results surfaced to the operator for approval.

V8

Version-string patterns present in documents today

Survey existing HTML documents in the loomworks-record repository — particularly the architecture spec, the operating instructions, and the Phase 63 scoping note. Find where version strings appear in each. The scanner Piece 1 builds needs to recognize each pattern.

Expected finding

Version strings appear in: HTML <title> tags, the doc-version-line div in the document body, sidebar version labels (in the architecture spec specifically), document footer text. Markdown documents may use frontmatter or section headers. The patterns vary by document template.

What to report back

List each distinct pattern found, with one example per pattern (file path, line number, the exact text). The CR can then specify a scanner pattern set that covers them all.

V9

The editor's current after-save behavior

Read tools/static/editor.js for how the editor handles the response from a save operation. The scoping note states that after a version-bump save, the editor stays pointed at the now-archived predecessor. Verify this in code.

Expected finding

After a successful save response, the editor modal either closes (forcing manual reopen) or remains open with no change to its breadcrumb or buffer state. No automatic redirect to the new versioned path.

What to report back

Quote the response-handling code. Identify the natural place where an auto-reopen-at-new-path behavior would attach.

Section 4

Verifications grounding identity flow

The FORAY writer call needs the operator's UUID as the actor identity. The scoping note assumes this UUID is known to the engine through its own person system but doesn't name how the editor at record.dunin7.com would know it.

V10

How the editor knows the operator's UUID today

Read functions/api/_shared.ts in loomworks-record and any related authentication code. Cloudflare Access authenticates the operator (by email via One-time PIN) and may forward identity headers to Pages Functions. The scoping note's audit work needs the operator's UUID — not their email — as the FORAY actor.

Expected finding

The Pages Function knows the authenticated email via Cf-Access-Authenticated-User-Email header (per Phase 62 Finding 3 — currently not forwarded successfully, which is why commits attribute to a generic editor@record.dunin7.com). The UUID is not currently known to the Pages Function. The engine has a person table that maps email to UUID, but the Pages Function would need to either: (a) call an engine endpoint to resolve email-to-UUID, or (b) read the UUID from a different authentication mechanism.

What to report back

Confirm what identity information the Pages Function has access to today. Name whether any UUID resolution mechanism exists or what would need to be built. This is a real design question Phase 63 must settle — the brief surfaces it explicitly rather than absorbing it silently.

Section 5

Verification grounding the architecture spec's "Substrate operating" claim

The architecture spec states "every state-changing action carries a FORAY flow row." The prior FORAY inspection found this is approximately true for two surfaces (credit flows, setting changes) but not for memory events (where readiness wiring exists but no rows are emitted). The scoping note treats the architecture spec's framing as conceptually accurate; Step 0 verifies the framing-to-reality fit one more time.

V11

Confirmation that FORAY narrative events are emitted today, and only by setting changes

Search the engine for all call sites of write_setting_change_event (or any future narrative-event writer). The scoping note assumes setting changes are the only narrative-event surface today. Editor commits will be the second.

Expected finding

Two call sites for write_setting_change_event: orchestration/tune_setting.py (Companion-spoken path) and api/routers/me_settings.py (button-clicked PUT). No other narrative-event writers exist.

What to report back

Confirm or contradict. If other narrative-event writers exist that the prior inspection missed, name them — they may be patterns Phase 63 should follow more closely than setting changes.

Section 6

What CC produces from this brief

A findings report. Structure: eleven sections numbered V1 through V11, each answering the verification's "What to report back" prompt with grounded specificity. Quoted code or exact file paths where it makes the picture concrete. For each finding, one of three outcomes:

  • CONFIRMED. The scoping note's assumption holds. Brief restatement of what was found.
  • CONTRADICTED. The scoping note's assumption does not hold. What the actual situation is, and what aspect of the scoping note's Piece 1, 2, or 3 needs reframing.
  • NUANCED. The assumption holds in part but is more complex than the scoping note treats it. What the nuance is, and whether it changes anything load-bearing for Phase 63.

Plus a short summary at the end of the report: are there any contradicted or nuanced findings that would require a scoping note v0.2 before Change Request drafting opens? If none, Phase 63 proceeds to CR drafting. If any, Claude.ai produces a scoping note v0.2 absorbing the findings, then CR drafting follows.

A note on inspection depth

The verifications above ask for specific code citations and exact patterns rather than narrative summaries. This is deliberate. The Change Request that follows Step 0 will reference these patterns by file and line number; vague findings produce vague Change Requests. CC should read enough code to quote what's actually there, not just describe what's there in general terms.

That said: don't over-read. A pattern is verified by reading the function that implements it and one or two call sites. Reading every file in a module is excessive for a Step 0 inspection. Read enough to ground the verification with confidence; stop there.