LJValheim volunteer roadmap
Comfy × Valheim · Lumberjacks P7

Comfy × Valheim — Lumberjacks Volunteer Roadmap

M0 CLOSED — FROZEN RELEASE LIVE AND PUBLIC · VOLUNTEER PLATFORM NOT READY

The validated, hash-recorded P7 run observed 83,220 eligible server-to-client ZDO revisions in one strict single-client window. All 83,220 were durably received by Lumberjacks and closed as applied or safely superseded with durable acknowledgement; zero eligible revisions used native ZDO delivery. This 100% denominator covers that declared ZDO delivery window only, not every Valheim packet, RPC, simulation, ownership decision, Steam login, or base peer-transport function.

Updated 2026-07-30T12:47:25.358Z ComfyNetworkSense 0.5.35 comfy-lumberjacks-p7 authoritative consumer ceiling 2 window p7-primary-v1
01 · CURRENT TRUTH

Protect the proof; earn the platform.

The validated, hash-recorded one-client result is real. Volunteer readiness and concurrent correctness have separate, visible gates.

Proved now

One enrolled client closed the complete observed all-prefab ZDO window through Lumberjacks priority delivery with exact durable accounting.

See the validated result ↓

Not proved yet

  • Safe public credential transport and authoritative admission.
  • A clean no-hand-edit package for a non-developer.
  • Per-session and per-recipient retained proof.
  • Two simultaneous consumers with isolated pending and ACK state.
  • Lumberjacks-owned candidate relevance, simulation, or non-ZDO RPCs.

Next actions

  • PAUSED · 2026-07-28 — NETWORKING LANE ON HARD HOLD. Every remaining networking step needs live two-human Steam observation, and none is scheduled; the lane parks at a green machine-state with its resume path recorded in fieldlab/PINNED-networking-lane-2026-07.md. Effort moves to the adoption track: A7 Community Workbench — a public catalog of the tools a volunteer can run today, each with an honest status, a cold-start package, one discussion thread, and a named first task. No live network authority changes during the pause.
  • CURRENT - 2026-07-24 - P7 Gateway and server remain on admitted release m30-rolecontrol-20260723-r1. The public client-pull pointer is m31-motionphase-20260724-r1, retaining the admitted m30 mod identity; OMEN and i5 installed the same verified package and client DLL through Companion with rollback backups. The i5 workbench now recovers a post-sleep Valheim bind-mount stall through its durable interactive Docker task without starting the game. CRE-E06 attributes phase evidence through final contiguous APPLY and OBSERVE role segments, rejects OBSERVE-side APPLY activity as contradictory, and keeps writer identity explicitly unresolved. CRE-E07 rejected fixed delay; CRE-E08 then derived a 100-200 ms relative-transit adaptive candidate that passed its repeatable synthetic A/B gate while retaining first-burst limitations. No new DLL was built. The next live gate is one bounded straight-movement role reversal with shared phase summaries; no broader network authority changed.
  • COMPLETE · M0 RELEASE FREEZE — A1–A5 closed 2026-07-16: source frozen, candidate r2 reproducible from clean tagged checkouts, sanitized bundle and FieldLab catalog committed, promotion drill passed with artifact-only rollback, and the golden-proof evidence set published immutably with byte-verified hashes.
  • COMPLETE · PROMOTION FINALIZED — P7 runs under a durable image pin: the temporary compose override is retired, the base compose resolves LUMBERJACKS_GATEWAY_IMAGE from the host environment across reboots, and VM-side gateway rebuilds fail closed. The path proved out on r2 and has since carried m1-clean-20260717-r1.
  • ACTIVE · M1 — Mod identity m30-rolecontrol-20260723-r1 remains live on P7 with the transport boundary collapsed by default, a side NET SHOW/HIDE recovery tab, alpha fault switches, client-pull updates, redacted Companion diagnostics, retained two-machine captures, bounded apply/observe role control, and the m31 client-only motion-phase evidence build. Public TLS preserves enrolled recipients through WebSocket setup and exposes a config-preserving update package; native Valheim still owns simulation, ownership, non-ZDO RPCs, relevance, and presentation unless a tester explicitly enables local motion apply. Distinct-recipient fan-out and role-reversal visual proof remain a two-owned-account canary gate. TLS/Caddy still gives anonymous requests private-socket capability and remains accepted only for the known-cohort alpha; stop-ship before widening.
  • LIVE (normal play) · AoI BAND-SHAPING — distance-band area-of-interest is armed permanently on P7 as of 2026-07-21 (near <30m full rate · mid 30–64m thinned to 5Hz · far >64m dropped · landmarks by granted reach), mod-side on the redirect producer (ADR 0011). It reshapes the eligible ZDO set upstream: at the densest single-player build ~85% of candidates drop, losslessly. Open before it earns full trust: the far→approach re-sync of a dropped static object, and multi-player density.
  • LIVE · M1 — Gateway image m30-rolecontrol-20260723-r1 serves the local Companion surfaces, m31-motionphase-20260724-r1 runtime client-pull pointer, Wave 0 handoff packet, and public credential-free Companion bootstrap lane. Modpack current.json is verified by Gateway on every request, and Companion bootstrap r26 includes the operator scripts required by the UI command surface.
  • AFTER M1 · PARALLEL — Build M2's reversible guest package, M3's seal-before-reset per-run ledger and retained dashboards, and M4a's recipient isolation and producer loss safety.
  • WIDEN ONLY AFTER · M4b + M5 — Require the real two-client correctness packet and one exact-release invited-volunteer SYSTEM PROVEN receipt before admitting a cohort.

What is being replaced in this test?

Valheim still decides which world-object revisions a player should receive. The server mod redirects those eligible revisions through Lumberjacks, the Gateway stores and leases them, and the enrolled client mod applies them on Unity's main thread before acknowledging a terminal outcome.

The exact denominator100% means 83,220 of 83,220 eligible ZDO revisions observed in the declared strict one-client window closed through Lumberjacks, with zero eligible native ZDO sends. It does not mean 100% of Valheim networking.
1 · SELECT

Native Valheim

Build the peer-specific list of world-object revisions.

BoundaryCandidate relevance and inference remain native today.
2 · REDIRECT

Lumberjacks server adapter

Intercept eligible revisions, attach stable ordering metadata, and redirect the declared ZDO delivery path.

BoundaryProducer loss safety and per-peer readiness are M4a work.
3 · STORE AND LEASE

Lumberjacks Gateway

Durably record envelopes and make pending work available to the authenticated consumer.

BoundaryThe current queue is safe only at the one-consumer ceiling; recipient isolation is M4a.
4 · APPLY

Lumberjacks client adapter

Poll in the background, marshal onto Unity's main thread, invoke RPC_ZDOData, and validate the outcome.

BoundaryUnity remains the game engine and compatibility target.
5 · ACKNOWLEDGE

Lumberjacks client and Gateway

Acknowledge only an applied or safely superseded terminal outcome and retain the accounting result.

BoundaryPer-run retained volunteer proof is M3 work.
Terms used on this page
ZDO
Zone Data Object: Valheim's persistent networked world-state record for an object such as a structure piece, item, creature, or environmental object.
Eligible revision
A ZDO revision selected by Valheim for the declared intercepted delivery scope during the strict test window. It is the denominator for the current cutover claim.
Strict window
A named evidence-producing interval in which eligible ZDO delivery must use Lumberjacks and any eligible native send is a failure.
Candidate relevance
The judgment that decides which world objects a particular peer should receive. Valheim still owns this plane today.
Recipient
An opaque Gateway delivery subject derived from an enrolled Steam account; clients never choose another recipient's identity.
Safely superseded
A received revision that no longer needs application because a validated newer state already makes its effect redundant.
Durable receipt
Gateway confirmation that an envelope is persisted and can survive normal process restart and replay.
Producer outbox
Server-side retry state that preserves an eligible revision until the Gateway confirms durable acceptance.
Public source (BSL 1.1)
This project's source is publicly visible and licensed under Business Source License 1.1 with the community-steward safe harbor, converting to AGPL-3.0-only at the recorded Change Date. That is not an OSI-approved license, so the accurate term is public source, not the similar-sounding common one. See LICENSE and LICENSING.md. A 2026-07-23 journal record used the imprecise term; journal records are append-only, so it stands with this correction beside it.
02 · CRITICAL PATH

Two lanes, one honest widening point.

The graph is generated from each milestone's declared dependencies. Build the single-volunteer experience without waiting for the queue redesign; keep capacity at one until recipient isolation passes.

Volunteer experience

A safe one-seat pilot with immutable packaging, preflight, proof, and rollback.

Multiplayer correctness

Recipient isolation, loss-safe delivery, and real two-account proof.

Evidence-backed widening

The proven volunteer journey and two-client correctness join before measured cohorts.

Network authority

Shadow, validate, and replace Valheim relevance and the remaining network planes.

Adoption program

The community-facing program: honest trust, legible tuning, replay workbooks, a turnkey local lab, delegable community support, and first federation light — owner-controlled, opt-in, built in the open.

03 · MILESTONES

State is a gate, not a percentage.

A milestone moves only when its exit statement is supported by reproducible evidence.

M0

Freeze the known-good release and evidence

COMPLETE
shareddepends on foundation

Turn the exact working Gateway, mod, deployment, world, and evidence into a reproducible release.

OwnsReproducible source-to-binary release identity, immutable evidence publication, deployment verification, and tested rollback artifacts.Does not ownNew admission, packaging, dashboard, or multiplayer behavior.
  • Commit the exact Gateway/mod/deployment sources without discarding unrelated work.
  • Build the promoted Gateway image and mod package exactly once from clean, tagged checkouts; retain the current working image only as the rollback artifact.
  • Generate a complete release manifest and verify source, build, package, OMEN, GCP, assembly, configuration, world, protocol, and cold-start identities.
  • Catalog FieldLab runs as immutable gold, valid, negative, historical, or superseded evidence.
  • Harden and exercise Gateway and mod rollback so restoration verifies runtime readiness and exact artifact hashes instead of rebuilding partial backed-up source.
Exit gate · met
  • A fresh checkout reproduces the declared artifacts and a cold start reports the manifest's exact runtime hashes.
  • Rollback artifacts and the Era16 world snapshot are present, restore without a source rebuild, and pass readiness plus exact-hash verification in the documented drill.
  • The validated P7 baseline is published at an immutable repository revision, and no secret appears in tracked or generic artifacts.
Inputs
  • Validated, hash-recorded local P7 baseline; immutable public publication is pending M0.
  • Current Gateway image digest, mod DLL SHA-256, deployment receipt, world snapshot, and FieldLab run packets.
  • The 2026-07-16 owner observation confirmed that OMEN, GCP, and the declared 0.5.31 artifacts align at runtime, while dirty source provenance still prevents clean-checkout reproduction.
  • The live Gateway image was built from a non-Git source copy. Normalized cutover/runtime sources match the working tree, but roadmap-only sources differ and the existing capture manifest and rollback scripts omit required identities and readiness checks.
Closing evidence
  • Closed 2026-07-16. Promoted release m0-clean-20260716-r2: reproducible candidate manifest at docs/roadmap/m0-clean-build-candidate-r2.json; checkpoint receipts at docs/roadmap/m0-a3-release-bundle-receipt.json, m0-a4-promotion-drill-receipt.json, and m0-a5-publication-receipt.json.
  • Published golden-proof evidence set (immutable, byte-verified)
  • Promotion finalized 2026-07-16: the r2 release runs on P7 with the temporary compose override retired; the base compose pins the promoted image from the host environment (reboot-path verified, no container recreate, health ok) and VM-side gateway rebuilds fail closed.
M1

Make identity and admission authoritative

IN PROGRESS
shareddepends on M0

Bind the actual joining Steam account to enrollment, compatibility, and capacity.

OwnsSteam enrollment identity, least-privilege authorization, strict admission, the enforced one-seat reservation, and validated public TLS.Does not ownRecipient-scoped queue semantics, producer loss safety, guest installation, traffic-proof presentation, or volunteer readiness scheduling.
  • Add enrollment list, revoke, expiry, last-used state, and unique active SteamID rules.
  • Split admin, producer, consumer, telemetry, and public proof permissions.
  • Make strict admission fail closed and reserve one authoritative seat.
  • Add certificate-validating TLS for public volunteer traffic.
  • Treat reverse-proxy source-address capability inheritance as a consciously accepted known-alpha risk; before access widens beyond the owner's known cohort, preserve the real client address through trusted proxies and replace implicit private-source Admin with explicit operator and workload authorization.
Exit gate · not yet met
  • An invited, enrolled, compatible account is accepted through the strict admission decision.
  • Uninvited, revoked, expired, mismatched, replayed, and over-capacity clients are rejected with actionable reasons.
  • Consumer credentials cannot reach admin, producer, reset, compaction, handshake-mutation, or arbitrarily named recipient operations.
  • A public request cannot inherit private-plane capabilities solely because it arrived through a trusted reverse proxy.
  • Strict admission fails closed when its authority is unavailable, and no reusable credential crosses an unencrypted public link.
Inputs
  • M0 immutable release identity and protocol manifest.
  • Existing Steam OpenID enrollment, Gateway handshake responder, and client-auth middleware.
Closing evidenceNone recorded; this exit gate remains open.
M2

Ship a boring, reversible guest package

IN PROGRESS
volunteerdepends on M1

Replace hand copying and hand-edited config with an immutable generic package plus a personal one-use bootstrap.

OwnsThe immutable guest artifact, one-use bootstrap, installer, preflight, redacted diagnostics, generated guide, backup, and uninstall experience.Does not ownThe per-session traffic ledger, dashboard conservation verdict, participation receipt, or concurrent delivery isolation.
  • Package the DLL, manifest, checksums, installer, preflight, diagnostics, uninstall, guide, and notices.
  • Find Steam libraries, stop on a running game, back up existing files, and merge only Lumberjacks config keys.
  • Verify release, BepInEx, TLS, enrollment, Gateway, server, persistence, and capacity before launch.
  • Redact credentials and direct Steam identity from diagnostics.
Exit gate · not yet met
  • A non-developer completes enrollment through READY TO JOIN in roughly ten minutes without editing configuration or sending a secret to the operator.
  • Clean install and existing-BepInEx upgrade paths preserve unrelated files and install the exact declared DLL atomically.
  • The bounded diagnostic bundle is redacted, and uninstall restores the prior state without removing files the package does not own.
  • The guide is generated from the release manifest so versions, hashes, endpoint, password policy, and feature claims cannot drift independently.
Inputs
  • M0 immutable guest release and compatibility manifest.
  • M1 enrollment bootstrap, TLS endpoint, `/enrollment/me`, readiness, and capacity contracts.
Closing evidenceNone recorded; this exit gate remains open.
M3

Make traffic proof definitive and durable

QUEUED
volunteerdepends on M1

For the enforced one-seat window, prove each selected ZDO revision reached durable Gateway storage, the authenticated client, Unity application or safe supersession, and a durable terminal acknowledgement.

OwnsThe capacity-one per-run ledger, conservation pipeline, volunteer/operator/public dashboard views, bounded append-only boundary telemetry, sealed receipt, and final verdict rules.Does not ownConcurrent recipient queue isolation, producer outbox correctness, or the real two-client gate; those belong to M4a and M4b.
  • Replace destructive empty-server reset with a run-scoped OPEN -> CLOSING -> SEALED lifecycle; stop suppression on last-peer transition and open the next epoch only after the prior seal is fsynced.
  • Bind receipts, pending delivery, terminal applied/superseded outcomes, and consumer telemetry to run_id; persist sealed summaries in the WAL through restart and compaction.
  • Show live deltas, rates, queue age, applied/superseded outcomes, native sends, gaps, failures, and release identity.
  • Keep readiness, routing mode, live evidence, participation, and final system verdict on separate axes; reserve PROVEN for a sealed receipt.
  • Start with a schema-versioned append-only boundary event stream, not a unified identity platform: emit only identity.resolved, authorization.decided, zdo.batch.queued, and request.completed while preserving the in-memory request context and never reinterpreting historical rows.
  • Bound and rotate physical JSONL segments by size and date using flush, close, and atomic rename; the first parser only validates required fields and reports basic event, decision, capability, missing-value, and duration counts.
Exit gate · not yet met
  • At the one-consumer ceiling, a seeded envelope visibly advances through every conservation stage and closes in a retained receipt.
  • Deliberate fallback, stale readiness, missing sequence, persistence failure, native eligible send, or unauthorized recipient request changes the correct live axis to FAULT or the sealed verdict away from PROVEN.
  • An idle heartbeat remains IDLE, never proof, and a run that closes without qualifying traffic becomes INCONCLUSIVE.
  • A Gateway request records schema-versioned identity, authorization, and completion observations, one accepted ZDO receipt batch records one queue observation, and closed historical rows remain unchanged.
  • No event records a reusable credential or raw private identity; any stable cross-event pseudonym is opaque or keyed rather than a plain hash of an enumerable identifier.
  • A service restart or WAL compaction does not erase or alter the sealed run, its release identity, conservation result, or canonical receipt hash.
  • Late old-run messages and a fast reconnect cannot mutate the next run or suppress traffic into a closing epoch; a forced incomplete close is retained with a non-PROVEN verdict.
Inputs
  • M0 immutable release identity and hash-recorded P7 metric vocabulary.
  • M1 enrollment, readiness, authorization, and run-identity contracts.
  • The top-level conservation proof pipeline in this roadmap source.
  • The 2026-07-16 owner observation captured exact live closure, then observed the empty-server reset erase the Gateway receipt denominator before any per-run receipt was sealed.
Closing evidenceNone recorded; this exit gate remains open.
M4a

Prove automated recipient isolation and loss safety

IN PROGRESS
multiplayerdepends on M1

Remove the shared-window queue and producer-loss hazards while preserving the peer identity available at Valheim's per-peer sync-list boundary.

OwnsRecipient-scoped durable queue semantics, exact per-peer readiness, stable delivery identity, structured terminal outcomes, reconnect/takeover rules, and the producer outbox.Does not ownReal Steam-client quality, human onboarding, or cohort capacity claims.
  • Key durable delivery by world epoch, opaque recipient, and stable delivery ID.
  • Derive recipient from credentials; scope pending and structured ACK outcomes server-side.
  • Require an exact per-peer readiness lease and define reconnect/takeover behavior.
  • Advance native peer bookkeeping only after durable Gateway acceptance, backed by a producer outbox.
Exit gate · not yet met
  • Two and then ten synthetic consumers cannot poll, inspect, acknowledge, block, or close another recipient's work.
  • Duplicate producer POST, poll, terminal ACK, reconnect, lease takeover, Gateway restart, WAL replay, and boundary crash tests converge idempotently.
  • Every recipient closes its own conservation equation, and producer outbox recovery produces neither loss nor double application.
Inputs
  • M1 opaque recipient, consumer credential, and least-privilege authorization contracts.
  • Valheim's existing per-peer sync-list boundary and FieldLab crash/replay fixtures.
Closing evidence
  • Gateway-only M4a stage-1 proof in progress: recipient policy, default-off frozen-producer compatibility, N=2/N=10 synthetic isolation, recipient-keyed activity leases, additive WAL replay fixtures, and per-recipient durable-receipt conservation tests are implemented and remain undeployed. Producer outbox recovery and the stage-3 mod recipient emitter are explicitly open.
M4b

Prove two real Steam clients

GATED
multiplayerdepends on M4a

Move the automated recipient model through two simultaneous real Valheim clients before any multi-seat invitation exists.

OwnsThe first real concurrent correctness result across dense/shared and separated regions, reconnects, restarts, and save/reload.Does not ownExternal volunteer onboarding or claims beyond two real clients.
  • Exercise both clients in the same dense build zone and in opposite map regions.
  • Run the known dense and extreme FieldLab route while one client disconnects and rejoins.
  • Restart the Gateway with backlog, restart the server, rejoin, and verify save/reload integrity.
  • Close each recipient independently with exact release, routing, persistence, and queue evidence.
Exit gate · not yet met
  • Two distinct ready recipients complete the declared real-client matrix with zero cross-delivery and zero cross-acknowledgement.
  • The strict window records zero eligible native ZDO sends, zero missing or terminal rejects, independently closed queues, and healthy persistence.
  • Neither client exhibits a correctness or world-integrity failure through restart, reconnect, and save/reload.
Inputs
  • M4a automated isolation and loss-safety exit evidence.
  • Two owned Steam accounts, the exact promoted release, Era16 snapshot, and validated FieldLab route.
Closing evidenceNone recorded; this exit gate remains open.
M5

Run the one-seat external canary

GATED
volunteerdepends on M2M3

Invite one trusted non-developer only after the host has proved the exact cold-started deployment and rollback path.

OwnsThe first end-to-end non-developer volunteer journey from informed invite through retained participation receipt and clean uninstall.Does not ownConcurrent delivery correctness; the optional 60-minute play extension is useful evidence but is not required to close M5.
  • Host preflight before sending the invite; freeze deployments during the window.
  • Complete the required setup and 20-minute guided dense/frontier/quiet-drain route described in the first-canary time budget.
  • Offer, but do not require, a 60-minute ordinary-play extension only after the required guided run closes cleanly.
  • Automatically seal the run packet and collect a sub-60-second experience survey.
  • Stop on correctness, persistence, queue-age, native-send, version, application, or world-integrity failures.
Exit gate · not yet met
  • One non-developer completes the required setup and guided cards without manual configuration and sees personal fresh Lumberjacks traffic while testing.
  • The platform retains PARTICIPATION COMPLETE independently from the PROVEN, DEGRADED, or INCONCLUSIVE system verdict and captures the sub-60-second survey.
  • The volunteer can uninstall cleanly, and no credential or direct identity leaks into public evidence.
  • The operator reproduces and validates the sealed packet; an optional ordinary-play extension is reported separately and cannot hold participation completion hostage.
Inputs
  • M2 clean-package, preflight, diagnostics, backup, and uninstall exit evidence.
  • M3 capacity-one dashboard, conservation, receipt, restart, and verdict exit evidence.
  • Cold-started host preflight, Era16 snapshot, rollback drill, scheduled run, and declared first-canary time budget.
Closing evidenceNone recorded; this exit gate remains open.
M6

Widen in evidence-backed waves

GATED
wideningdepends on M4bM5

Move from the owned two-account gate to 2–4 and then 5–8 invited players only when correctness and capacity evidence permit.

OwnsEvidence-backed promotion from the proven two-client model and volunteer journey to 2–4 and then 5–8 real-player cohorts.Does not ownLumberjacks relevance/inference authority or claims extrapolated solely from synthetic clients.
  • Measure join-to-first/priority/full-load, queue age/slope, frame hitches, Gateway latency, WAL, CPU, memory, disk, and egress.
  • Exercise same-zone contention, separated regions, reconnects, restarts, and normal play.
  • Compare against validated, hash-recorded native and P7 baselines without treating synthetic bots as real-player capacity.
  • Automatically stop widening on any correctness failure.
Exit gate · not yet met
  • The 2–4-player wave closes independently for every recipient with bounded queues, healthy persistence, and no correctness failure.
  • The 5–8-player soak meets the predeclared QoL and capacity envelope recorded in its run packet.
  • Published capacity limits are supported by real-player queue, compute, memory, disk, egress, and experience evidence rather than synthetic extrapolation.
Inputs
  • M4b two-real-client correctness exit evidence.
  • M5 end-to-end external-volunteer exit evidence.
  • Validated native/P7 baselines and predeclared per-wave QoL and capacity measures.
Closing evidenceNone recorded; this exit gate remains open.
M7

Move inference and remaining authority into Lumberjacks

IN PROGRESS
authoritydepends on M6

Run active lab experiments against Valheim's relevance, ownership, replication, presentation, and remaining RPC judgments now; keep production promotion gated on the earlier real-player milestones and bounded evidence.

OwnsShadowing, validating, and promoting Lumberjacks relevance/inference and later authority planes one bounded claim at a time.Does not ownUnmeasured transport replacement or removal of Steam/Valheim compatibility dependencies that still provide value.
  • Shadow Lumberjacks interest management beside Valheim's per-peer candidate list.
  • Measure the current motion arrival, drain/coalescing, binding, and presentation phases before changing client authority or interpolation.
  • Measure omissions, extra sends, bytes, CPU, queue age, and visible pop-in by class and region.
  • Promote one safe object class or policy at a time with strict rollback.
  • Evaluate base-transport replacement on measured value rather than assumption.
Exit gate · not yet met
  • The authority matrix and retained evidence show every declared promoted plane is Lumberjacks-owned.
  • Any remaining Steam/Valheim dependency is explicitly classified as bootstrap, identity, or compatibility.
  • Every promoted class or policy has paired shadow/strict evidence and a tested rollback path.
Inputs
  • M6 real-player correctness, quality, and capacity exit evidence.
  • Lumberjacks interest-management design at docs/network/interest-management.md.
  • FieldLab native, shadow, and strict route fixtures.
  • Creative-runtime lab receipts now prove a deterministic pressure gate, both real Gateway motion routes, bounded sequence freshness, reconnect behavior, topology-derived fanout accounting, direct versus latest-wins/expiry consumer behavior, and the checked-in frame-bound motion apply model without changing live gameplay authority.
  • CRE-E06 now provides cumulative motion phase rollups plus role-tail APPLY/OBSERVE attribution. Synthetic two-bundle receipts prove either-machine APPLY, setup-time role-transition isolation, ambiguous-role rejection, OBSERVE-control contradiction detection, and missing-client rejection; the formal Wave 0 gate refuses human interpretation unless attribution is ready.
  • CRE-E07 replayed chase-latest against fixed 50/100/150/200 ms buffered interpolation under stable and three-sample-burst arrivals. The 200 ms buffer removed burst stalls only by increasing current-time error, so fixed buffering was not promoted.
  • CRE-E08 used relative arrival-minus-send variation and sequence gaps without synchronized clocks. A 50 ms floor was rejected; the derived 100-200 ms fast-rise/slow-decay candidate passed repeatable synthetic safety and A/B criteria across stable, burst, jitter, and loss shapes, but no DLL or live authority change was promoted.
Closing evidenceNone recorded; this exit gate remains open.
A1

Trust & Rhythm

COMPLETE
adoptiondepends on foundation

Publish what the mod captures and how to opt out, set honest alpha expectations, and make the weekly community cycle a copy-paste rhythm — so the next person who joins meets trust, not surprises.

OwnsThe plain-language trust surface and the weekly community operating rhythm: what is captured and how to opt out, alpha support expectations, a delegable weekly cycle, and stream-ops hygiene.Does not ownTuning legibility, replay tooling, the turnkey lab, community-support pipelines, or projection/peering.
  • Data & trust note: enumerate every captured field, state who sees what and how to opt out (capture ships off by default), and surface it at /data-and-trust and from onboarding.
  • Alpha expectations + down-state templates: what alpha means, the weekly response rhythm, and how and where to report.
  • Weekly rhythm + templates: the feedback -> roadmap -> changelog -> GM-touch-base cycle with a "you said -> did / won't / later" convention.
  • Stream-ops hygiene: a pre-stream checklist and a secret-rotation table so a live screen-share can never leak a key or a player identity.
Exit gate · met
  • Every field in the data-trust note maps to a real capture-code line, and it renders on /community and links from onboarding.
  • A new volunteer can answer, from the docs alone: is this normal, who do I tell, what do I include, when will I hear back.
  • The weekly cycle is a checklist with templates, and every secret-rotation target names where the key lives and the rotate command.
Inputs
  • The client-side capture code and the aggregates-only public telemetry API.
  • Positioning and adoption-strategy voice rules (owner-controlled, opt-in, never surveillance).
Closing evidence
  • Shipped 2026-07-23: docs/data-and-trust.md (plus the served /data-and-trust page and onboarding link), docs/alpha-expectations.md, docs/weekly-rhythm.md, docs/stream-ops-hygiene.md, and docs/templates/.
A2

Legible Tuning

IN PROGRESS
adoptiondepends on A1

Turn folklore weights into chains of evidence — every knob inventoried and every tuning change ledgered — and let each GM conversation also answer an open governance question.

OwnsMaking manual netcode tuning legible: a citable knob -> hypothesis -> evidence -> verdict ledger, per-decision provenance in the hot path, and a GM interview instrument so each hands-on session also answers an open governance question.Does not ownOffline replay tooling, the turnkey lab, or any change to the tuning values themselves.
  • Tuning ledger: inventory every netcode knob (key, location, current value) and open an append-only knob -> hypothesis -> before/after -> verdict ledger.
  • Decision provenance: emit a per-decision trace when the netcode drops, defers, or reprioritizes, so a player-visible artifact is attributable to a specific filter and score (pending).
  • GM interview guide: a ~20-minute instrument closing the governance open questions, with an answer-capture template and a findings-routing file.
Exit gate · not yet met
  • The knob inventory covers every tunable in code/config with file:line, and any current value traces to its ledger entry or a pre-ledger marker.
  • A recorded decision produces exactly one trace that reconciles with the aggregate counters (pending decision-provenance).
  • The interview guide fits one page, requires no internals of the GM, and routes answers into a findings file.
Inputs
  • A1 rhythm and templates.
  • The mod config surface (PluginConfig.cs) and the scoring code (ScoreCalculator.cs).
  • The governance open questions.
Closing evidence
  • Shipped 2026-07-23: network/tuning-ledger.md (knob inventory + entry template + git-history backfill) and the GM interview guide, capture template, and governance-findings docs. Decision-provenance (the hot-path trace + tests) is still open.
A3

Replay & Workbooks

QUEUED
adoptiondepends on A2

Make tuning a replay -> adjust -> diff loop with no game required, back every knob with a tradeoff card, and end each doc chapter in something executable that proves it is still true.

OwnsOffline legibility of tuning: a counterfactual replay notebook, one tradeoff card per knob, a VOD-chaptering training library, and the runnable-proofs convention that keeps docs from rotting.Does not ownLive tuning application, the lab stack, or projection.
  • Counterfactual replay notebook: re-run the scoring math over a recorded session under adjustable weights and diff outcomes.
  • Tradeoff cards: one card per knob — what it controls, which axis it moves, the observable that proves it.
  • VOD chaptering: turn white-glove stream VODs into a searchable training library via the offload lane.
  • Runnable proofs: the convention that each doc ends in a single command that verifies it, plus a proof runner.
Exit gate · not yet met
  • The replay reproduces recorded owner-election winners (or lists every mismatch), and changing a weight yields an explained diff.
  • Card count equals the knob-inventory count and every current value grep-verifies.
  • The proof runner runs the seed proofs from a fresh checkout and reports pass/fail per doc.
Inputs
  • A2 knob inventory and ledger.
  • A committed recorded-session fixture (still needed; capture is client-side).
Closing evidenceNone recorded; this exit gate remains open.
A4

Turnkey Lab

QUEUED
adoptiondepends on A2

Bring the whole server-side system up with docker compose on your own machine, so seeing your own kill land on your own localhost dashboard is the demo.

OwnsA local, one-command server-side lab: an inventory-and-gap pass, a named docker-compose stack, first-run lab keys and the secrets/sauce boundary, and a scripted localhost demo.Does not ownClient-side install (the mod rides the player's Steam), production deploy, or peering.
  • Inventory & gap pass: every service, its containerization status, and the gap list to "docker compose up".
  • Compose stack: named services (valheim-server, gateway, telemetry, dashboard, config-site) with healthchecks, readable as the architecture diagram.
  • Lab keys & boundary: generate all needed keys on first run; document what ships (sauce) versus what stays (secrets).
  • Localhost demo: a scripted, dry-run-verified walkthrough from compose up to your event on your dashboard.
Exit gate · not yet met
  • A fresh machine reaches a working stack from one command, following only the written steps.
  • compose up needs zero hand-provided secrets, and the compose file reads as the architecture diagram.
  • Time-to-first-event is measured and stated.
Inputs
  • The existing gateway, dashboard, and telemetry images and the fieldlab autonomous compose as a starting asset.
Closing evidenceNone recorded; this exit gate remains open.
A5

Community Scale

QUEUED
adoptiondepends on A2

Shape support and contribution so a trained volunteer — not just the operator — can run them, and each hands-on onboarding session gets measurably shorter.

OwnsMaking community support and contribution delegable beyond the operator: a symptom -> tool support runbook, a quest-content contribution pipeline with visible author credit, and a GM-driven integration playbook.Does not ownCode-contribution workflow, automated moderation, or projection/peering.
  • Support runbook: map the top community-reported failure modes to the diagnostic that resolves them (mostly existing gateway tools).
  • Quest-content pipeline: author -> review -> smoke-test -> sign -> ship -> credit, run one quest end-to-end with a visible credit.
  • GM-driven integration: a playbook for a trained GM to drive parts of the next GM's integration, with the operator as safety net.
Exit gate · not yet met
  • Every runbook entry's first check is copy-paste executable by a volunteer with no codebase knowledge.
  • One quest completes the whole pipeline including a visible author credit.
  • The integration segment map is complete and a trained GM could run their segments from the guide alone.
Inputs
  • A1 expectations and rhythm.
  • The gateway support-tool surface and the quest config site.
Closing evidenceNone recorded; this exit gate remains open.
A6

Projection

LATER
adoptiondepends on A4

Make the turnkey lab the node all along — same gateway surface, same signed-config trust — so projection becomes "turn on peering", then exchange one small signed artifact between two boxes.

OwnsFirst federation light: a node-shape contract that keeps every lab instance identical to a future node, config signing hardened from checksum to a real trust mechanism, and a minimal read-only peering pilot.Does not ownDiscovery/registry, more than two nodes, or any cross-node gameplay authority.
  • Node-shape contract: testable invariants plus a conformance script, keeping every instance node-shaped.
  • Signing hardening: an honest threat model of today's keyless checksum, then the sequenced gap-closing to a real trust mechanism.
  • Peering pilot: two node-shaped instances exchange a signed aggregate tile, read-only, with staleness and signature status shown.
Exit gate · not yet met
  • The node-shape invariants are each testable and the conformance script reports honestly, including its own coverage gaps.
  • The signing threat model cites real code, and any implemented gaps fail closed.
  • A peer tile shows live peer aggregates with a valid-signature indication; tampered or stale data is visibly flagged, and no gameplay behavior changes on either node.
Inputs
  • A4 lab stack and the secrets/sauce boundary.
  • The telemetry record schemas and the gateway contracts.
Closing evidenceNone recorded; this exit gate remains open.
A7

Community Workbench

IN PROGRESS
adoptiondepends on A2

A public catalog of the tools a volunteer can actually run today — each with an honest status, a way to run it locally, one place to talk about it, and a named first task — so helping has an on-ramp and ownership has a ladder.

OwnsThe public catalog surface (/workbench), per-tool one-pagers, cold-start packages, the ownership-graduation ladder with its append-only OWNERS ledger, and the recovery pointers for pruned-but-recoverable pieces.Does not ownReviving any pruned pipeline (that is a volunteer's first ownership task), the offline replay notebook (A3), the turnkey lab (A4), the quest-content review pipeline (A5), or any change to the networking lane (on hard hold).
  • workbench.json + a generator mirroring the roadmap pattern (render/check, generator-enforced honesty invariants, no scripts in output).
  • /workbench and /workbench/downloads routes with mount-override publishing, so catalog updates are a file copy, not a deploy.
  • First-wave one-pagers and cold-start packages: quest picker + absorption engine, ComfyStewardView, community telemetry pages, Steam self-service join.
  • One discussion thread per tool with a stated batch-reply rhythm, and the ownership ladder recorded in an append-only ledger.
Exit gate · not yet met
  • Every catalog status is verifiable from a repo path or a live URL, and the generator rejects a status the evidence does not back.
  • Each first-wave tool runs cold from its published package or public repo on a machine with only its stated prerequisite.
  • Each tool links one live discussion thread and one named first task, and any non-unclaimed ownership state anchors to a ledger entry.
  • The page renders from JSON with no hand edits and no script tags.
Inputs
  • A2 legibility work and the roadmap generator pattern.
  • The public comfy repo as the recovery source for pruned pieces.
  • The adoption strategy, positioning, and persona docs.
Closing evidenceNone recorded; this exit gate remains open.
04 · READINESS

Who may we responsibly invite—and how do they know it counted?

Host preflight happens before an invitation is sent. A known-red deployment never becomes volunteer troubleshooting, and joining alone is not participation completion.

Readiness

May this participant start the scheduled test now?

NOT READYAt least one mandatory enrollment, release, service, capacity, persistence, or rollback check is not green.
READY TO JOINEvery mandatory preflight check for this participant and scheduled run is green.

Routing mode

Which delivery path is the session using?

LUMBERJACKS ACTIVEThe declared strict ZDO delivery path is active.
NATIVE RECOVERYThe strict session has stopped and the operator has explicitly selected the labeled native recovery path.
NO ACTIVE SESSIONNo evidence-producing run is active.

Live evidence

What is the ledger doing right now?

IDLEServices are healthy but no recent qualifying traffic proves cutover.
FLOWINGFresh qualifying traffic is advancing through the conservation pipeline.
DRAININGNo new qualifying work is expected and the remaining durable queue is closing.
FAULTA live invariant, persistence, routing, application, or visibility check has failed.

Participation

Did the volunteer's effort produce a usable packet?

PARTICIPATION INCOMPLETEThe requested attempt or bounded observation/evidence packet has not yet been retained.
PARTICIPATION COMPLETEThe volunteer attempted the assigned work and the platform retained a usable packet, even if a defect was found.

Final system verdict

What did the sealed run prove about the declared network test?

PENDINGThe run is not sealed; PROVEN is never a live-session label.
PROVENThe sealed receipt closes every declared correctness gate.
DEGRADEDThe sealed receipt records a fallback, error, performance problem, or failed invariant.
INCONCLUSIVEThe run closed without enough qualifying traffic or evidence; the receipt names what was missing.

One external volunteer

NOT READY
  • M0–M3 pass.
  • Strict capacity remains one.
  • Owner passes the same clean-package flow immediately beforehand.
  • Host preflight and rollback drill are green.
  • All reusable public credentials use validated TLS.
  • The invite names the versioned test cards, duration, data policy, and recovery path.
  • The dashboard supports before, during, and after-run states with a retained participation receipt.

Concurrent volunteers

NOT READY
  • M4a automated isolation and M4b real two-account gates pass.
  • M5 proves the complete external-volunteer journey and retained receipt.
  • Each peer has an independent readiness lease and durable recipient ledger.
  • No peer can alter another peer's routing or closure.
  • Capacity is supported by observed queue, compute, disk, and egress evidence.
INVITED → INFORMED → READY → TESTING → PARTICIPATION COMPLETE

Volunteer participation contract

A volunteer succeeds by completing or attempting the assigned work and returning a usable evidence packet. Finding a networking defect is valuable successful participation; it does not require the system test itself to pass.

draft-v1 · Planned for the first canary; invitations are not open until M0-M3 close.

1 · INVITE

Know the work before accepting

The page states the experiment, assigned test cards, expected time, risks, captured data, support, and recovery path.

2 · READY

Install and preflight without hand edits

Steam enrollment, exact release, BepInEx, TLS, Gateway, server, capacity, readiness, and rollback checks are green.

3 · TESTING

See Lumberjacks and the next action

The personal dashboard shows LUMBERJACKS ACTIVE, current card instructions, and fresh received/applied/acknowledged traffic.

4 · RECEIPT

Know that participation counted

A retained pseudonymous receipt separates participation completion from the networking verdict and includes the submitted observations.

Two independent receipt outcomes

Participation records whether the volunteer's effort counted. The system verdict separately records what the sealed networking run proved.

Participation

Did the volunteer's effort produce a usable packet?

PARTICIPATION INCOMPLETEThe requested attempt or bounded observation/evidence packet has not yet been retained.
PARTICIPATION COMPLETEThe volunteer attempted the assigned work and the platform retained a usable packet, even if a defect was found.

Final system verdict

What did the sealed run prove about the declared network test?

PENDINGThe run is not sealed; PROVEN is never a live-session label.
PROVENThe sealed receipt closes every declared correctness gate.
DEGRADEDThe sealed receipt records a fallback, error, performance problem, or failed invariant.
INCONCLUSIVEThe run closed without enough qualifying traffic or evidence; the receipt names what was missing.

First-canary time budget

The required commitment is explicit; the ordinary-play extension is optional and declining it never reduces participation status.

requiredtarget ≤10 min

Setup and preflight

Redeem the invite, install the exact package, pass preflight, choose a backed-up character, and reach READY TO JOIN.

required~20 min

Guided quality route

Complete T02 dense arrival, T03 rapid frontier travel, and T05 quiet drain.

required<1 min

Experience survey

Return the bounded observation report so participation can close independently of the system verdict.

optional opt-inup to 60 min

Ordinary play extension

Offered only after the required guided route closes cleanly; declining it does not reduce participation status.

Versioned test cards

The invite assigns a small subset. Each card tells the volunteer what to do, what to notice, how long it takes, and what the instrumentation proves.

T01planned first pilot · required

Setup and first join

~10 min
Exercise
Redeem, install, preflight, choose a backed-up character, and join.
Notice
Confusing, manual, failed, or unexpectedly slow steps.
Evidence
Enrollment → readiness → admission → first apply.
T02planned first pilot · required

Dense spawn arrival

~5 min
Exercise
Remain in the portal/building area until visually usable.
Notice
Missing art/buildings, severe pop-in, freezes, or corruption.
Evidence
Priority-playable/full-drain time and frame hitches.
T03planned first pilot · required

Rapid frontier travel

~10 min
Exercise
Fly rapidly into a direction not previously visited.
Notice
Tree/terrain pop-in, stalls, and movement responsiveness.
Evidence
Priority rate, queue slope/age, and first-useful delivery.
T04planned optional

Elaborate build revisit

~10 min
Exercise
Approach and circle a known complex construction.
Notice
Recognition/completion time and incorrect pieces.
Evidence
Dense apply, supersession, starvation, and full closure.
T05planned first pilot · required

Quiet drain

~5 min
Exercise
Stop in wilderness and wait without teleporting.
Notice
Late pop-in, pauses, disconnects, or unexpected activity.
Evidence
Backlog drain, oldest age, idle state, and conservation.
T06planned controlled

Controlled reconnect

~10 min
Exercise
Disconnect and rejoin only when assigned by the operator.
Notice
Lost state, duplicates, blank screen, and join friction.
Evidence
Resume, dedupe, lease, and outstanding-delivery recovery.
T07after M4b

Two-client isolation

~20 min
Exercise
Two players occupy shared, then separated regions.
Notice
Cross-player stalls or inconsistent world state.
Evidence
Recipient isolation and independent queue closure.

Participation receipt

  • Run ID, participant alias, timestamps, and assigned/completed/attempted card revisions.
  • Exact mod, Gateway, server, protocol, deployment, world epoch, and artifact hashes.
  • Enrollment, preflight, admission, readiness, and qualifying-traffic results.
  • Per-recipient received, applied, superseded, acknowledged, pending, native, and failure summary.
  • Submitted observations plus diagnostic/survey packet status.
  • Separate participation status and system verdict with plain-language reasons.
  • Support, privacy/deletion, recovery, and uninstall links.
05 · PROOF & RISK

Validated result beside the remaining no-go facts.

The latest owner observation corroborates the data path but does not replace or widen the historical 83,220-revision baseline. Live delivery and the formal sealed verdict remain visibly separate.

OWNER OBSERVATION

Enrolled TLS session reached the token-bound Lumberjacks UDP motion lane

P7 Gateway-only image m12-motionauthws-20260722-r1 admitting frozen mod release m12-motion-20260722-r1; public TLS WebSocket plus UDP 4005. · 2026-07-23 06:42-06:45 UTC

informs M1 + M7
Observed deliveryFLOWING
Formal system verdictINCONCLUSIVE
Eligible1
Durable0
Applied0
Superseded0
Acknowledged0
Pending / native0 / 0
Why not PROVENThis is a transport-ingress canary, not a sealed game run. One valid enrolled session received valheim_motion_available=true, advertised UDP port 4005, and sent the exact 50-byte fixture. Gateway telemetry advanced received and received_udp once with zero invalid, unauthorized, or stale drops. Relay remained zero because no second distinct enrolled recipient was connected; same-recipient echo is intentionally suppressed.
Milestone effectM1 now preserves enrollment identity through public TLS WebSocket setup, and M7 has its first real Lumberjacks-owned player-motion transport slice. Distinct-recipient fan-out, WebSocket fallback, and opt-in presentation remain the two-account canary gate. Anonymous Caddy traffic still inherits private-socket capabilities and remains stop-ship before widening.

Operational note: Gateway image sha256:c361c8fc6d823d7be935e43221f69eb948355c9a35b516263316306a2805c97f was rebuilt from committed source 002b12c, pinned as m12-motionauthws-20260722-r1, and admits frozen mod m12-motion-20260722-r1. Health was good; TCP 42317 and UDP 4005 were published; the alpha seat gate remained disabled with the compatibility capacity value present exactly once.

Evidence · local_onlyP7 enrolled WebSocket and UDP motion ingress canary — Documented in infra/gcp/p7/VALHEIM-MOTION-CANARY.md; no enrollment identifiers, credentials, or private diagnostic URLs are included in the public roadmap.

What definitive traffic proof must conserve

Each eligible revision advances through an accountable route and terminal outcome. Retries do not create new unique work, and a heartbeat alone cannot close this chain.

candidate
Valheim selects a peer-specific eligible ZDO revision. Stable candidate identity and the declared eligibility scope establish the denominator.
route
The server records either a native send or a Lumberjacks redirect intent. Every candidate has exactly one route decision.
durable receipt
The Gateway durably accepts the redirected envelope. A stable delivery identity prevents retries from increasing the unique denominator.
delivery
The authenticated consumer leases or polls its pending envelope. The recipient comes from the credential and the ledger records pending or leased state.
Unity outcome
The client validates an exact application or safe supersession on Unity's main thread. Only a validated terminal outcome is eligible for acknowledgement.
durable acknowledgement
The Gateway records the applied or safely superseded terminal outcome. The sealed per-run ledger retains the final conservation result.
Conservation equations
  • candidate decisions = native sends + redirect intents
  • redirect intents = durable receipts + producer outbox pending
  • durable receipts = acknowledged applied + acknowledged superseded + leased or pending
Strict closure requires
  • native eligible sends = 0
  • producer outbox pending = 0
  • leased or pending = 0
  • durable receipts = acknowledged applied + acknowledged superseded

Validated, hash-recorded P7 authoritative priority ZDO baseline

One enrolled client · persistent all-prefab ZDO redirect · 2026-07-16 UTC

Eligible revisions83,220
Durably redirected83,220
Terminally acknowledged83,220
Eligible native sends0

83,220 of 83,220 eligible ZDO revisions in the declared strict single-client window closed through Lumberjacks; this is not a denominator for all Valheim networking.

Eligible revisions in declared window83,220
Durable receipts83,220
Exact applications72,946
Safe supersessions10,274
Acknowledgements83,220
Pending0
Eligible native-only sends0
Priority tagged83,220 (100%)
Observed reject / duplicate / retry0 / 0 / 0
Poll / ACK / telemetry failures0 / 0 / 0
Peer-ready → first apply6.721 s
Peer-ready → complete102.114 s
Publication · publishedThe sanitized publication set is public and immutable at https://github.com/djcdevelopment/comfy/blob/433f1cc33605561ae1287db9cd8f37125d795c5d/fieldlab/evidence/p7-gold-run-20260716-011112-authoritative-priority-cutover/PUBLICATION.md — pushed 2026-07-16 after the A4 promotion drill passed (receipt: docs/roadmap/m0-a4-promotion-drill-receipt.json, evidence public at Comfy e6a1402). Published bytes re-verified against the recorded SHA-256 hashes after push.

Known no-go findings

  • The current p7-primary-v1 queue and ACK state are shared; two consumers can steal or close each other's peer-specific records.
  • Redirect readiness is not yet bound to the exact joining peer.
  • Native peer bookkeeping advances before durable Gateway acceptance, leaving a producer-side loss window.
  • Live enrollment does not yet exclusively gate Valheim admission.
  • Anonymous requests through Caddy still inherit private-socket capabilities; accepted only for the known-cohort alpha and stop-ship before widening.
  • The self-service personalized package is live, but clean-machine install, upgrade, and uninstall still need an external volunteer proof.
  • The Lumberjacks motion lane has only passed single-recipient ingress; distinct-recipient fan-out, fallback, and opt-in presentation remain unproved live.
  • Current dashboard proof is aggregate and resettable rather than per-run and per-recipient; the 2026-07-16 owner observation saw the empty-server reset erase 81,241 live receipt records two seconds after disconnect.
  • Acceptance telemetry defaults are too large for volunteers.
06 · AUTHORITY

What Lumberjacks owns—and what it does not.

The claim grows one authority plane at a time. Compatibility dependencies remain visible.

PlaneCurrent stateBoundary
Invite / Steam enrollmentPartialImplemented, but not yet the sole live admission roster.
Valheim admissionPartialGateway responder exists; must bind actual SteamID, enrollment, release, readiness, and capacity.
Eligible server-to-client ZDO deliveryProved for one clientValidated, hash-recorded strict P7 window; concurrent queue isolation is not yet proved.
Candidate relevance / inferenceNativeValheim still creates the peer-specific candidate list.
ZDO applicationLumberjacks adapterClient poller applies and validates on Unity's main thread before ACK.
Player-motion transportObserve-first Lumberjacks canaryEnrolled clients can carry measured motion over token-bound UDP with binary WebSocket fallback; native presentation remains the default until a tester opts into apply.
Ownership / simulation / non-ZDO RPCNativeLater authority-plane work.
Steam login / base peer transportNative by designMay remain bootstrap and compatibility unless replacement adds measured value.
07 · COMMIT NOTES

Implementation journal

Every non-merge commit appends one note. Newest entries appear first; history remains append-only.

verification Lumberjacks A7

Land the permanent-invite render

Impact: The public page now carries the never-expiring invite in both hero and footer, published from 6b38b3c.

Verification (1)
  • workbench:check green byte-for-byte; invite renders in both slots.
Recorded by Claude · associated with the Git commit containing this note
implementation Lumberjacks A7

Retire the invite expiry clock with a never-expiring replacement

Impact: The provisioning bot gains a guild-invite command with the same yes-ceremony as its content writes; it minted a never-expiring invite on the same channel and recorded it, so the fourteen-day warning countdown the offline check carried is gone for good. The old invite is left to lapse on its own - every copy already shared keeps working until then. The page now carries the permanent invite. Operator rationale stands recorded: the hosting moves within a year, so link lifetime was never the constraint.

Verification (1)
  • Bot self-test 93/93 including six new guild-invite checks (replacement on same channel, never expires, old invite never revoked, no-op when permanent); live mint verified via the Discord API.
Recorded by Claude · associated with the Git commit containing this note
documentation Lumberjacks A7

Correct the trust-review report's test arithmetic

Impact: The completion report claimed 37 guard tests by double-counting: 28 was already the combined total (19 generator + 9 verifier). The count is now stated correctly - the guards themselves were never miscounted, only the prose.

Verification (1)
  • node --test over both suites: 28 tests, 28 pass.
Recorded by Claude · associated with the Git commit containing this note
verification Lumberjacks A7

Land the thread-wired render

Impact: The public workbench artifact now links the MCP Mod Channel thread on its Discuss row, MC-1 completes in-thread via the derived default, and the page is published from 42c2115.

Verification (1)
  • workbench:check green byte-for-byte; both guard suites 28/28.
Recorded by Claude · associated with the Git commit containing this note
implementation Lumberjacks A7

Wire the MCP Mod Channel card to its real thread

Impact: The operator's provisioning run created the MCP mod channel thread from seed 10 (plan 23bc2b88476e, exactly one create). MC-1 completes in the tool's own thread again: the forum-interim completion override is deleted, done_when says in-the-thread, and the Discuss row links the thread - the derived tool-thread default now carries it. The one-pager matches.

Verification (1)
  • Bot apply receipt + provision-state entry; workbench render/check green; verify-live confirms the new thread lives in the expected guild under the forum.
Recorded by Claude · associated with the Git commit containing this note
implementation Lumberjacks M3

Keep the schema gate from boot-looping the stack under compose --wait

Impact: Two independently correct changes broke each other. The boot-determinism work made the systemd unit start with docker compose up -d --wait plus Restart=on-failure, and the schema repair added a one-shot dbschema service to the default service set. Verified locally: docker compose up -d --wait exits 1 on a one-shot that succeeded, reporting 'container ... exited (0)'. On P7 that would have failed every ExecStart and retried every 30 seconds - the exact failure --wait was added to prevent. dbschema is now behind a schema profile so it is not in the waited set, and the ordering guarantee moved into the unit as ExecStartPre docker compose run --rm dbschema, which auto-enables the profile and starts postgres through its own depends_on. The four depends_on service_completed_successfully gates are gone because compose auto-enables a dependency's profile and would pull the service back into the waited set. Trade-off recorded in both files: a bare docker compose up -d on the VM no longer applies the schema, so the unit is the authoritative starter. The local stack keeps the direct gate because nothing there uses --wait. Also reconciled the environment.example comment that still described LUMBERJACKS_ROOT as boot-critical because postgres bind-mounts init.sql through it - true of the old compose, false since the schema repair landed.

Verification (2)
  • Reproduced the interaction: compose up -d --wait against a successful one-shot exits 1 with 'exited (0)'. With the profile applied, run --rm exits 0 and up -d --wait exits 0.
  • docker compose config on the P7 stack: dbschema absent from the default and tls profiles, present under the schema profile; caddy's tls profile unaffected.
Evidence: infra/gcp/p7/RUNBOOK-schema-repair.md
Recorded by Claude · associated with the Git commit containing this note
documentation Lumberjacks M3

Retire the LUMBERJACKS_ROOT declaration that nothing reads

Impact: LUMBERJACKS_ROOT was documented as a required runtime declaration in the P7 README and environment.example long after it stopped resolving to a real path, and docker-compose.yml no longer consumes it at all. That stale required-marker is how a schema-less database survived undetected: the variable looked load-bearing, so nobody checked that the path it named still existed. Removed from both, with an explicit do-not-reintroduce note pointing at the schema runbook. The operator still has to remove the line from the box, and should read it first because it is the forensic evidence. Also recorded why bootstrap.sh.tftpl is deliberately left alone: it is metadata_startup_script, already drifted, and force-replaces the VM on apply, so it belongs to the terraform reconcile effort rather than a docs cleanup.

Verification (1)
  • docker compose config parses the P7 stack with LUMBERJACKS_ROOT empty; every remaining mention in infra/ is historical prose, not a lookup.
Evidence: infra/gcp/p7/RUNBOOK-schema-repair.md
Recorded by Claude · associated with the Git commit containing this note
documentation Lumberjacks M1

Record the boot and publish-gate decisions as ADRs and retro them

Impact: Two signals that reported the opposite of reality got closed at the mechanism and written down as durable decisions rather than as incident notes. ADR 0014 states that a service managing other services must fail loudly, must not report success before it has converged, and must retry - with the corollary that where two mechanisms can start the same thing, one is authoritative and the other is only for crash recovery. It also records what was deliberately NOT changed: the database health fan-in stays, because loosening it would trade one visible failure for four silent crash-loops. ADR 0015 states that bytes whose exact value is load-bearing get their line endings pinned by the repository rather than left to a contributor's git configuration, covering generated artifacts that are hashed and published and files that are parsed on Linux, with the corollary that a failing verification gate must be diagnosed before it is acted on. The session retrospective carries the timeline, five engineering-seat reads, and six numbered lessons, including one that grades a prior lesson as acted-on yet still recurring because it had been captured narrowly instead of as a repo-wide mechanism. Two open decisions are registered: what the cloud VM is still for now that the community surface is served elsewhere and demos need no VM, and when to spend a cold restart proving the boot fixes given that half of them need an infrastructure reconcile that has been deferred all along. The handoff's machine-state bullet is corrected and now points at the runbook and the ADR.

Verification (1)
  • The append-only journal was reconciled across a concurrent branch by union on id ordered by timestamp, preserving each record's original bytes rather than re-serializing them - a first attempt reformatted all 288 historic records and was discarded and redone, and the journal now diffs against the concurrent branch as two insertions and zero removals. The generated HTML was re-rendered from the merged inputs rather than hand-resolved; roadmap check reports OK with generated HTML current. The ADR index lists both new records. Every boot claim in the new documents is labelled UNVERIFIED against the machine, which stays stopped by policy.
Recorded by Codex · associated with the Git commit containing this note
implementation Lumberjacks M3

Apply the game schema on every stack start, not once per volume

Impact: The P7 game database had no tables at all, so every gameplay-event INSERT failed and the /community Gameplay Feed and Quests panels could never populate. Schema reached Postgres only through docker-entrypoint-initdb.d, which runs once on an empty data directory and is skipped silently forever after - and P7's data directory is a persistent bind mount, so that window opened once per disk. The 2026-07-24 state-disk replacement consumed it, four days after the repo unification moved init.sql under Lumberjacks/ and left the compose mount path naming no file (Docker materializes a missing bind source as an empty directory, so nothing complained). init.sql is now idempotent and complete at all 13 GameDbContext tables, including natural_resources and region_profiles which existed only in an EF migration that has never been applied anywhere. A one-shot dbschema service applies it on every start and gates the four .NET services behind service_completed_successfully, so a missing schema is a loud startup failure instead of an empty public panel. Also on record: /api/v0/telemetry/regions serves a hardcoded WorldState seed and is not a database health signal.

Verification (3)
  • Reproduced the P7 state locally (existing cluster wiped to zero tables, both incident errors verbatim), then repaired it: dbschema exit 0, 13 tables, the regions SELECT returns 0 rows and the events INSERT returns INSERT 0 1.
  • Schema applied three times consecutively at exit 0; docker compose config resolves both mounts to the real file with the gate on all four services.
  • Game.Gateway builds Release with 0 warnings and 0 errors; Game.Gateway.Tests 207/207 pass.
Evidence: infra/gcp/p7/RUNBOOK-schema-repair.md Lumberjacks/infra/docker/init.sql
Recorded by Claude · associated with the Git commit containing this note
documentation Lumberjacks A7

Retro the live demo session and register the two questions it raised

Impact: The 2026-07-29 retro gains its third addendum, covering a live-operations session with zero commits: the P7 stack was brought up for a remote demo and taken back down, the empty-world tick numbers were framed as a floor rather than as evidence of scale, the ask to have automated clients play each other was declined against the pinned networking hold and its own removal commit, and a graceful-stop hazard the operator memory already describes verbatim was re-fired and then cleaned up (699 MB of orphaned partials removed, world verified intact by size and md5). fieldlab's register gains the two decisions that session surfaced: pruning the stale world auto-backups, declined in favour of keeping recovery copies of a 9.16M-ZDO world; and restoring the swarm harness from its removal commit, left open and gated behind lab clients only the operator can seed.

Verification (1)
  • Documentation only - no code, config, or infrastructure changed by this commit; roadmap check --staged green.
Recorded by Codex · associated with the Git commit containing this note
verification Lumberjacks A7

Clear the false stale-render reading on the live workbench

Impact: The live AM4 workbench was recorded as still serving the pre-review render, pending an operator republish. It is not: the served page is byte-exact with the committed render whose provenance stamp names a commit descended from the trust review, and a full post-publish verification of the live funnel returns PASS across 69 checks with zero failures and zero warnings. No republish is owed. The misreading came from a line-ending trap rather than a deployment problem: scripts/workbench-verify-live.mjs hashes the local HTML as a raw Buffer, and the repository carried no .gitattributes, so a Windows checkout with core.autocrlf=true produced a CRLF working copy whose digest could never match a server serving LF. The gate failed against a deployment that was byte-correct, which is the worst kind of gate failure - it invites an unnecessary republish and teaches the operator to distrust a passing check. A .gitattributes now pins generated and Linux-destined files to LF: generated HTML because its bytes are hashed and published, and shell scripts, systemd units and compose files because they are parsed on Linux where a carriage return is a syntax error. Stored blobs were already LF - git add --renormalize staged nothing - so this changes only what a checkout writes into the working tree, and it removes a class of failure that depended on one contributor's git configuration rather than on anything in the repository.

Verification (1)
  • Measured directly: the raw CRLF working copy hashed to 2bb23be9, the LF-normalized bytes to 976f51cc, and 976f51cc is exactly the value the live funnel reports in its X-Workbench-Sha256 header. After refreshing the working tree under the new attributes the local file hashes to 976f51cc and npm run workbench:verify-live -- --post-publish reports PASS, 69 checks, 0 failed, 0 warnings, including the served-page-hash-matches-local-render check that previously could not pass on this machine.
Recorded by Codex · associated with the Git commit containing this note
implementation Lumberjacks M1

Make the P7 boot path deterministic instead of hand-built

Impact: A cold stop/start of the P7 VM left six containers in Created with nothing serving while SSH answered normally. Root cause: nothing in the repo ever installed or enabled comfy-lumberjacks-p7.service - the GCE startup script set up disk, swap, docker and the ops agent and stopped, so the unit's enablement was hand-made state on the box, which is exactly the 'no hand-built state to lose' the cost runbook cited to justify stop/start as safe. Three compounding defects: a failed ConditionPathExists silently SKIPS a unit (inactive, no error, no log - the 'alive over SSH, serving nothing' signature), docker compose up -d returns at Created so Type=oneshot marked the unit active while nothing ran, and with no Restart= a single transient failure parked the stack permanently. Every service hard-depends on postgres condition service_healthy, so postgres is a single fan-in point whose failure leaves every dependent in Created. The unit now uses AssertPathExists, --wait, Restart=on-failure with an unlimited start burst, and a clean-slate down before every start; the startup script installs and enables the unit from the deployed checkout and orders the docker daemon after the state-disk mount, which was previously unguarded and could resolve bind mounts against the empty mountpoint on the root disk. Also found: COMPOSE_PROFILES=tls was missing from environment.example while the live box had it, so rebuilding the env file from the template would have produced a stack with no TLS terminator and no error, because an unselected profile is not a failure.

Verification (1)
  • Staged and UNVERIFIED against the VM, which stays stopped. infra/gcp/p7/RUNBOOK-boot-determinism.md carries the diagnosis, the by-hand apply steps (the startup-script fix needs terraform, which is off the table from this checkout), and a next-boot procedure that captures the wedged-boot evidence before the fix destroys it. The README and cost-runbook claims that a systemctl restart proved the reboot path are marked falsified rather than replaced - a restart never exercises the mount race or the shutdown teardown.
Recorded by Codex · associated with the Git commit containing this note
decision Lumberjacks A7

Unblock the link-carrying Discord posts on the current funnel URL

Impact: provision.json site_base_url is set to the live AM4 funnel, so the four link-carrying seeds and the new MCP Mod Channel seed resolve their placeholders and are ready for the operator's next provisioning run. Operator call recorded 2026-07-29: the hosting will move to a different server within a year, and a link with that lifetime is acceptable - the URL is already public on every published page, and the P7 cutover recipe replaces it when the move happens.

Verification (1)
  • Bot self-test 87/87; check reports all posts render clean with placeholders resolved.
Recorded by Claude · associated with the Git commit containing this note
verification Lumberjacks M2

Make the guest-package tests runnable on a fresh checkout

Impact: tests/test_guest_package.py built every case against a sealed release bundle that .gitignore deliberately keeps out of the repo, so five of the six tests failed on any clean clone for want of a machine-local build artifact. The tooling tests now build against a committed synthetic release fixture under tests/fixtures/guest-package/, which exercises the same paths because no guest-package script parses the DLL. The one question a fixture cannot answer, whether the real sealed DLL still matches the manifest shipped beside it, became its own test that runs where the bundle exists and skips with an explicit reason where it does not.

Verification (1)
  • python -m unittest discover -s tests is green on a clean worktree: 9 tests, 7 run, 2 skip. Both sealed-release tests pass with the bundle restored, and a one-bit flip of the sealed DLL fails the hash check, so it is not vacuous. The generator built the real release end-to-end after the refactor. Privacy scan of tests/ is clean, and three C:\Users\derek findings in the old test file are gone.
Recorded by Codex · associated with the Git commit containing this note
documentation Lumberjacks A7

Report the trust review completion and teach the new recipes

Impact: The completion report in docs/audit answers the review's nine sections: the MC-1 contradiction and its two-track resolution, the completion schema, how counts compute (11 actionable, now true), production and preview provenance with the shipped false stamp reproduced as a test, twelve offline guards, the full remote-check inventory with a passing 60-check live receipt, 37 green guard tests, and what stays unverified until the operator republishes. HANDOFF and BUILDING teach the two-phase render, the new npm scripts, and the thread-URL recipe including the MC-1 override removal.

Verification (1)
  • Fold inspected at 1280x800 via DOM measurement: stamp, counts, invite, and honesty content all above the fold; live pre-publish receipt PASS 60/0/0.
Recorded by Claude · associated with the Git commit containing this note
implementation Lumberjacks A7

Resolve the verify-live bot token exactly as the provisioning bot does

Impact: The verifier now mirrors workbench_discord.py's token resolution (env var, env-named file, then workbench-discord.token or discord.env under the user profile), so a machine where the bot can post is a machine where the verifier can verify. First live pre-publish run against the AM4 funnel: 60 checks, 0 failed, 0 warnings - invite, all 8 member-only destinations, all 11 task destinations, 28 GitHub URLs, 4 repo-visibility checks, 8 routes.

Verification (1)
  • verify-live pre-publish PASS receipt at captures/workbench-verify-live.json, 2026-07-29T15:59Z; verifier suite 9/9.
Recorded by Claude · associated with the Git commit containing this note
verification Lumberjacks A7

Land the schema-derived policy render

Impact: The public page now derives its access-policy sentences, links every LICENSING.md mention, says the project operator, and is published from a3e14a2.

Verification (1)
  • workbench:check green byte-for-byte.
Recorded by Claude · associated with the Git commit containing this note
implementation Lumberjacks A7

Derive access policy from the schema and name the operator by role

Impact: The access-policy sentence on every card is now computed from source.kind and code_contributions instead of living as prose in source.note - the sentence was byte-identical in three notes and nearly so in a fourth, a drift surface the schema already owned. Notes keep only tool-specific facts, and validation refuses policy vocabulary or a note contradicting the structured rights. LICENSING.md joins OWNERS.md in the named-means-linked rule (it was named six times and linked zero). The ladder's stage 4 now says the project operator, defined once in OWNERS.md with why the role has authority - the page no longer names a person a stranger was never introduced to, and the catalog refuses person names outright. Four doc rows that named public files inertly now link them.

Verification (1)
  • workbench:test 28/28 including the source-note contradiction, vocabulary ban, person-name ban, derived-line variants, and LICENSING parity negative; rendered page has zero person names, seven derived access lines, all LICENSING.md mentions linked.
Recorded by Claude · associated with the Git commit containing this note
implementation Lumberjacks A7

Verify live destinations before and after every workbench publish

Impact: New release-path verifier (workbench:verify-live) proves everything the page asks a visitor to click: the Discord invite resolves to the expected guild and has not expired (cross-checked against provision-state), every member-only thread URL exists in that guild via the bot token (fail-closed when the token is absent), every GitHub URL answers 200 and declared-public repos really are public, the site routes answer 200 on-origin, and post-publish the downloads stream with the claimed digest, size, and header while the served page hash equals the local render. Failures are classed per check with a JSON receipt under captures/. Publish-WorkbenchAssets now runs the pre-publish pass as Gate 4 and the full pass after the upload. Render and check stay fully offline - live state belongs to the release path only.

Verification (1)
  • 9 new node --test cases drive the verifier through a canned transport: green path, 404 deep link, expired invite, wrong-guild thread, wrong-digest and truncated downloads, missing-token fail-closed, off-origin redirect; workbench:test 23/23.
Recorded by Claude · associated with the Git commit containing this note
verification Lumberjacks A7

Land the actionable-count render with its source stamp

Impact: The public page now counts only tasks a stranger can complete today (11, all actionable - true since MC-1 routes to the forum), shows the MCP Mod Channel Discuss row as a real forum link, and names its source commit 9828ff0.

Verification (1)
  • workbench:check green byte-for-byte; hero anchor and Discuss row inspected in the rendered output.
Recorded by Claude · associated with the Git commit containing this note
implementation Lumberjacks A7

Make the task count mean actionable-now and fix the MC-1 contradiction

Impact: First tasks gain a completion model: by default a task completes in its tool's thread and is actionable exactly when that thread exists - a thread-less tool now fails the build instead of shipping an uncompletable task, which is how MC-1 shipped. An explicit completion object routes a task to the main forum meanwhile or marks it blocked with a reason; blocked tasks render visibly with the reason and leave the hero count, which now means actionable-now (with a separate blocked tally when nonzero). MC-1 becomes completable today: its done_when names the forum honestly and the card's Discuss row links it. Thread-creation prep landed for the operator's next provisioning run: seed 10, a provision.json entry, and the bot now resolves ACCESS-URL from source.href for not-published tools. Hardcoded task-count prose and a wrong headline tool count are build failures. Also removed a stray NUL byte in the generator that made grep treat it as binary.

Verification (1)
  • workbench:test 14/14 including negatives 1-3 and the completion derivation matrix; discord bot self-test 87/87; live catalog renders 11 actionable, MC-1 Discuss row resolves to the forum.
Recorded by Claude · associated with the Git commit containing this note
verification Lumberjacks A7

Land the first production-stamped workbench render

Impact: The committed workbench.html now names its source commit - Published from 29e2698 - replacing the false uncommitted-working-tree claim the page carried since the 11:50 UTC render. From here every committed render either names the input commit or fails check.

Verification (1)
  • workbench:check green byte-for-byte including the stamp; stamp sha matches git log -1 over the provenance inputs.
Recorded by Claude · associated with the Git commit containing this note
implementation Lumberjacks A7

Stamp workbench provenance from the source commit, two-phase

Impact: The workbench freshness line becomes two honest modes: a deterministic Published-from stamp naming the last commit that touched workbench.json or the generator, and a Preview stamp for uncommitted inputs that can never publish. check now compares the artifact byte-for-byte when the inputs are clean and refuses a preview stamp in a clean tree - the exact false claim the committed page carried until today - while Publish-WorkbenchAssets gains Gate 0: clean provenance inputs plus a production stamp before any upload. The generator gains exports behind a CLI guard, and the first guard tests land: 8 node --test cases on throwaway git fixtures, including both provenance negatives (production stamp over dirty inputs, preview stamp in a clean tree).

Verification (1)
  • npm run workbench:test 8/8 green; render and check exercised in preview, production, and no-git modes on fixture repos; publish script parse-checked.
Recorded by Claude · associated with the Git commit containing this note
documentation Lumberjacks A7

Retro the decision-lifecycle and delegated-governance session

Impact: The 2026-07-29 retro gains an addendum covering the second session: the review that found eight of twelve pending decisions were tasks in decision costumes, the lifecycle Derek adopted (registers are queues, one decision one home, the named First Stranger gate), and the six delegated calls shipped as rubber-stamped artifacts with a single circle-back trigger. Five prior lessons graded for follow-through (both applicable ones acted-on, including the max_tokens fix proven live by this retro's own offload); five new lessons recorded on classification-before-decision, durable principles, named triggers, delegation provenance, and verify-before-registering. Offload provenance stated honestly: one flash draft, minor-fixes verdict, judgment seats kept frontier.

Verification (1)
  • Follow-through table reconciled against the morning retro's lessons; commit table reconciled against git log d8337dc..9fe12f1.
Evidence: fieldlab/retro/SESSION-RETRO-2026-07-29.md
Recorded by Claude · associated with the Git commit containing this note
documentation Lumberjacks A7

Decide the delegated governance batch and ship its instruments

Impact: Derek delegated the six future-facing register entries; each is now decided, documented, and live. CLA.md v1.0 (plain-language, sign-by-sentence, ledger at docs/legal/cla-signatures.md) closes PD-1's instrument slot - a DCO transfers no rights and Baseline's model needs the tree owned. SECURITY.md ships with GitHub private vulnerability reporting enabled on the repo as the primary channel plus a tagged mailbox fallback and honest solo-maintainer promises. Every public audit finding now carries a standing disposition in docs/audit/2026-07-29-findings-disposition.md. The AI-contribution bar is symmetric and disclosure-based - built by one human directing many agents, judged on verification not provenance. Reply cadence affirms batch rhythm without a calendar promise; the P7 cutover checklist gains the posted-content URL re-sync step. Every artifact records the decision mode (agent-decided under recorded delegation, operator rubber stamp) and the circle-back: the First Stranger gate's first firing - first alpha tester live or first contribution inquiry.

Recorded by Claude · associated with the Git commit containing this note
documentation Lumberjacks A7

Adopt the decision lifecycle and seed PD-1 and PD-2

Impact: docs/decisions/ now exists as the canonical home for long-lived decision rationale: PD-1 records the governance-and-contributions posture with its operating principle and leaves the contributor-agreement instrument explicitly open; PD-2 names the First Stranger gate once and collects every deferred security-posture item under it as a due-list. The root register is realigned to the queue-not-archive lifecycle - resolved entries compressed to one-liners linking their durable home, two stale priority rankings reclassified to re-rank at adoption resume, the duplicate direct-join entry closed, and six newly identified true decisions registered (contributor instrument, disclosure path, audit-findings disposition, AI-contribution bar, reply cadence, cutover URL re-sync). AGENTS.md drops the expired TEMP RULE and states the lifecycle; the cost runbook points its external-cohort wording at the named gate.

Recorded by Claude · associated with the Git commit containing this note
deployment Lumberjacks A7

Make the am4 roadmap page track the mount

Impact: The lj-workbench container was recreated with LUMBERJACKS_ROADMAP_HTML pointing at the mounted roadmap.html, so /roadmap now serves the tree's render instead of the image-baked copy that had gone stale by eight journal notes. Served hashes verified for both pages after the recreate; health, join, and the download route all answer 200. Content updates to either public page are now one file copy.

Verification (1)
  • X-Roadmap-Sha256 equals the local render sha; X-Workbench-Sha256 unchanged and equal; /health /join /workbench/downloads/quest-picker all 200 post-recreate.
Evidence: HANDOFF-2026-07-29.md
Recorded by Claude · associated with the Git commit containing this note
documentation Lumberjacks A7

Retro the recoverable-pieces landing session

Impact: fieldlab/retro/SESSION-RETRO-2026-07-29.md records the session that landed both recoverable tools' raw material byte-exact, synced every surface, and republished the page: what shipped commit by commit, the four design corrections that mattered, the follow-through on every 2026-07-28 lesson, and five new lessons - including the root cause of the prior session's HEARTH unreliability (max_tokens starving thinking-model output) and the classifier-blocked exporter commit left explicitly for the operator.

Verification (1)
  • Lesson follow-through table reconciled against SESSION-RETRO-2026-07-28.md; commit ledger reconciled against git log on both repos.
Evidence: fieldlab/retro/SESSION-RETRO-2026-07-29.md
Recorded by Claude · associated with the Git commit containing this note
deployment Lumberjacks A7

Sync the Recoverable-pieces thread to the re-landed raw material

Impact: The live Recoverable pieces thread now carries the dated update pointing volunteers at recipes/camera-gallery/ and recipes/quest-submission-bridge/ in baseline, applied from the operator-approved receipt (plan ba37ecab31d2). A fresh plan pass shows the thread matches the repo; the four tool threads remain blocked by design while site_base_url is null.

Verification (1)
  • workbench_discord.py plan after apply reports no pending change for the thread; provision-state.json records the applied content.
Evidence: tools/workbench/discord/receipts/2026-07-29-plan.md
Recorded by Claude · associated with the Git commit containing this note
planning Lumberjacks A7

Stage the Recoverable-pieces thread update for operator approval

Impact: The Discord sync receipt shows exactly one pending change: the Recoverable pieces thread gains the dated update pointing at the re-landed raw material. The four tool threads stay blocked by design while provision.json site_base_url is null, so an apply cannot touch them. Applying remains operator-gated: apply --yes --expect-plan ba37ecab31d2.

Verification (1)
  • workbench_discord.py plan wrote the receipt; plan hash ba37ecab31d2; nothing was written to Discord.
Evidence: tools/workbench/discord/receipts/2026-07-29-plan.md
Recorded by Claude · associated with the Git commit containing this note
verification Lumberjacks A7

Prove the landed recoverable raw material byte-exact and runnable

Impact: All 24 landed files' HEAD blobs equal their archive source blobs at ae81c83. All five landed Python scripts compile. The bridge demo runs end to end from the landed copy: one payload consumed, review markdown carries the Thrall rank and evidence path, and the inbox walks pending to accepted to exported, drafting the /slayer submit command with two transitions journaled. The contract fixture consumes cleanly, the camera dry-run prints its cut plan against the landed timeline sample, entrypoint links pass, generated outputs stay invisible to git, and the tree is clean with exactly the four landing commits on top.

Verification (1)
  • 24/24 sha equality; 5/5 py_compile; bridge smoke assertions green; fixtures smoke green; video_to_gallery --dry-run exit 0; unittest tests.test_entrypoint_links OK; git status empty.
Evidence: plans/recoverable-pieces-landing-workbook.md
Recorded by Claude · associated with the Git commit containing this note
planning Lumberjacks A7

Write the find-land-document workbook for recoverable pieces

Impact: plans/recoverable-pieces-landing-workbook.md records the reusable playbook the 2026-07-29 landings executed: three find-lanes anchored on d75ffb2/57654fd/ae81c83, the migrate-vs-document decision record, byte-exact landing mechanics with the sha proof, the doc-sync surface list, the verification suite, and a model-tier legend so deterministic tools and cheaper models carry the mechanical steps. Result ledger cites C1-C3.

Verification (1)
  • Workbook cross-checked against the executed run: every command in F1-F3 is the one actually run, with its recorded output.
Evidence: plans/recoverable-pieces-landing-workbook.md
Recorded by Claude · associated with the Git commit containing this note
documentation Lumberjacks A7

Point the workbench truthfully at the re-landed recoverable raw material

Impact: Both recoverable tool cards, the workbench catalog entries, the Discord seed, and the cold-pickup handoff now say where the pieces actually are: byte-exact unwired copies at recipes/quest-submission-bridge/ and recipes/camera-gallery/ alongside the archive links. The camera card's wrong pre-prune ref cc322ee is corrected to d75ffb2/57654fd, the catalog piece list gains the four real files it was missing, and the handoff carries a dated addendum for the posted threads and the live am4 URL. Statuses stay recoverable-not-running and QB-1/CG-1 stay the claiming tasks.

Verification (1)
  • npm run workbench:render and workbench:check pass: 7 tools, 2 recoverable, generated HTML current.
Evidence: Lumberjacks/docs/workbench/workbench.json
Recorded by Claude · associated with the Git commit containing this note
implementation Lumberjacks A7

Land the camera-gallery raw material byte-exact from the archive

Impact: The pruned camera flythrough pipeline raw material - segment 1's working waypoint extractor, the segment 2-4 briefs, video_to_gallery.py, and both sample fixtures - is back in-repo at recipes/camera-gallery/, byte-identical to the public comfy archive at ae81c83 (= pre-prune 57654fd), with provenance, the MIT boundary, and the samples' privacy note recorded. CG-1 stays the claiming task; the valheim-camera-proof kit stays archive-only. Segment 3 remains the real gap.

Verification (1)
  • All 9 landed files' index shas equal the archive source blob shas; video_to_gallery.py argparse confirms the documented --dry-run and --duration flags.
Evidence: recipes/camera-gallery/PROVENANCE.md
Recorded by Claude · associated with the Git commit containing this note
implementation Lumberjacks A7

Land the quest-submission-bridge raw material byte-exact from the archive

Impact: The pruned back half of the quest submission bridge - bridge_consumer.py, review_inbox.py, their fixtures, and the original QUEST/PROOF briefs - is back in-repo at recipes/quest-submission-bridge/, byte-identical to the public comfy archive at ae81c83 (which equals pre-prune ref 57654fd), with provenance and the MIT license boundary recorded. QB-1 stays the claiming task; nothing is wired to the live mod.

Verification (1)
  • All 15 landed files' index shas equal the archive source blob shas; archive handoffs tree at ae81c83 is tree-identical to baseline pre-prune 57654fd:handoffs.
Evidence: recipes/quest-submission-bridge/PROVENANCE.md
Recorded by Claude · associated with the Git commit containing this note
documentation Lumberjacks A7

Make every reply-rhythm promise match reality

Impact: The pinned forum post, the catalog page footer, and the retained long-form announcement all now say the same true thing the short announcement says: every thread gets read, and replies come when the operator checks in - he is currently sharing time with other projects. The old roughly-twice-a-week promise is gone from every member-facing surface, synced to Discord through the bot's diff pass and to the public page by file copy, both hash-verified.

Verification (1)
  • Bot plan reports Discord matches the repo after the update; served page hash equals the local render through the public edge.
Evidence: Lumberjacks/docs/workbench/discord/05-pinned-how-this-works.md; Lumberjacks/docs/workbench/workbench.json
Recorded by Claude · associated with the Git commit containing this note
documentation Lumberjacks A7

Rewrite the announcement in the operator's own words

Impact: The announcement now says the true thing in the operator's own voice: built for fun, then because it looked promising, discoveries beyond expectation, cannot do it alone, the community paved the paths, other projects need him now, the work is left where others can look, borrow, and suggest, and he will be back to build more. Reply expectations adjusted to match - replies come when he checks in, rather than a promised twice-weekly rhythm.

Verification (1)
  • Opening kept nearly verbatim from the operator's draft; links verified against the live site and forum.
Evidence: Lumberjacks/docs/workbench/discord/drafts/00-announcement-SHORT-20260729.md
Recorded by Claude · associated with the Git commit containing this note
documentation Lumberjacks A7

Cut the announcement to a length people read

Impact: The long-form announcement draft is superseded by a short form per the operator: two sentences, a four-tool list, two ground rules, one call to action - keeping the load-bearing facts (the pause was a choice, statuses are honest, replies batch about twice a week, the server is not open but the tooling is, nothing is owed by anyone) and cutting everything else.

Verification (1)
  • All links in the short form resolve against the live site and forum; the long draft is retained beside it for the record.
Evidence: Lumberjacks/docs/workbench/discord/drafts/00-announcement-SHORT-20260729.md
Recorded by Claude · associated with the Git commit containing this note
implementation Lumberjacks A7

Post the four tool threads and wire the loop closed

Impact: The bot posted the four held tool threads to the live forum from their seed files, verbatim, against a reviewed plan hash - quest picker, ComfyStewardView, community telemetry, and the Steam join flow - with the recoverable-pieces and how-this-works posts already in place from the earlier apply. Every catalog card now links its real discussion thread, the republished public page carries all six, and the announcement draft is filled with the live address and staged for the operator to post himself: the one message the bot is hard-coded to never send. The full loop the rollout promised is now closed end to end: a stranger can reach the public catalog, download a verified kit, run it cold, and land in the right thread to say what happened.

Verification (1)
  • Apply matched the reviewed plan hash exactly and reported four creates and nothing else; thread URLs recorded in provisioning state; the page re-rendered, republished by file copy, and re-verified by served hash through the public edge.
Evidence: tools/workbench/discord/provision-state.json; Lumberjacks/docs/workbench/workbench.json; Lumberjacks/docs/workbench/discord/drafts/00-announcement-READY-20260729.md
Recorded by Claude · associated with the Git commit containing this note
implementation Lumberjacks A7

Take the Workbench public on the AM4 funnel

Impact: The Community Workbench is on the public internet at the AM4 tailnet funnel address: Tailscale terminates TLS at the edge and Caddy splits the front door - the community surfaces (catalog, downloads, roadmap, community pages, the join flow, the aggregates API) serve unauthenticated from an explicit allowlist, the operator boundary surface is blocked at the funnel because the gateway would see the proxy as loopback, unmatched paths get an honest 404, and the operator's existing gallery keeps its authentication at every deep path with only its bare-root index moving under a subpath. Root redirects to the storefront. The join card now points at the live HTTPS endpoint - which retires the old plaintext-credential caveat - and states plainly that the full Steam round-trip on this host is unproven and is exactly first task SJ-1. The GCP VM remains the later lean step for the game world itself, since UDP cannot ride the funnel.

Verification (1)
  • Public sweep from outside the tailnet path: root 302 to the storefront, all community surfaces 200 without credentials, the served page hash equals the repo render through the funnel, the download is hash-exact with a correct integrity header, ops returns 403, gallery surfaces return 401 without credentials, junk paths 404; the updated page republished as a file copy and re-verified by served hash.
Evidence: HANDOFF-2026-07-29.md; Lumberjacks/docs/workbench/workbench.json; Lumberjacks/scripts/workbench.mjs
Recorded by Claude · associated with the Git commit containing this note
verification Lumberjacks A7

Confirm every Workbench loop on the AM4 local lane

Impact: Stabilization now runs on local hardware per the operator: AM4 hosts the workbench-enabled Gateway on the tailnet, and every loop the P7 deploy would have proven is verified there instead - the served catalog page is hash-identical to the repo render, both cold-start kits download hash-exact with correct integrity headers and a wire-downloaded kit runs cold with the corrected config path, the telemetry starter kit's own poller reads the live aggregates API off a simulation ticking at twenty hertz, the navigation sweep is green, and the operator boundary surface correctly refuses a non-operator vantage. The GCP deploy becomes the later lean-and-mean step; the community threads and announcement wait on the public site either way, since the local lane's addresses mean nothing off the tailnet.

Verification (1)
  • All checks executed from a second machine over the tailnet against the running container; page and zip hashes compared against the repo's own values, not self-reported ones.
Evidence: HANDOFF-2026-07-29.md; tools/workbench/Publish-WorkbenchAssets.ps1; Lumberjacks/docs/workbench/workbench.json
Recorded by Claude · associated with the Git commit containing this note
decision Lumberjacks A7

Resolve the Valheim server password question: accept open direct-join with no password while the cohort is the operator and name-known friends

Impact: Closes the last blocking item before a deploy could bring a joinable world back up. The public docs that describe the server as Steam-unlisted but password-free are accurate as written and need no change. The consequence a volunteer would otherwise miss is now on the steam-join card: the invite gates the enrollment flow, not the world, so anyone who knows the address can direct-connect without it. Revisit at the first external cohort, the same gate that makes TLS and rate limiting non-optional

Verification (1)
  • Confirmed nothing is joinable today regardless of the setting: the P7 VM is TERMINATED and the local host runs the Gateway container only, no Valheim server. New sentence renders outside any disclosure, workbench:check green, zero-loss holds at 235 strings, and the page republished to the local host
Recorded by Codex · associated with the Git commit containing this note
verification Lumberjacks A7

Verify the Discord invite against the API and add a build guard for its expiry

Impact: The invite resolves but expires 2026-08-28, so on that date the page's only entry point for a non-member dies while the href stays well-formed and allowlisted — the one failure no existing guard could see. The date is now recorded beside the invite and workbench:check warns inside 14 days and fails once past it. Server verification level is 0, so no phone or email gate blocks a volunteer

Verification (1)
  • GET /invites/TSHTD38yV confirmed VALID, guild 1531911987074957442, lands in #general, expires_at 2026-08-28T06:33:12+00:00. Guard negative-tested on all three branches: 4 days out warns and passes, an expired date fails with the regenerate instruction, null passes silently
Recorded by Codex · associated with the Git commit containing this note
verification Lumberjacks A7

Close the print question honestly: the rule meant to force disclosures open does not work, so remove it and say so on the printed page

Impact: The stylesheet carried a guarantee it did not provide. Measured in Chromium 148, a collapsed disclosure body reports checkVisibility false and zero innerText with details:not([open]) > *:not(summary){display:block !important} applied — identical to without it, because the UA hides the contents through an internal slot author CSS cannot reach. The rule is gone and a print-only note states which two per-card sections do not print. Everything a decision rests on already lives outside <details> and prints

Verification (1)
  • Probe compared three states on the real page: collapsed (not visible, 0 chars), collapsed with the print rule applied (not visible, 0 chars), genuinely open (visible, 392 chars). Print note confirmed display:none on screen; 7 status_detail blocks still render with 0 inside a disclosure; workbench:check green and zero-loss holds at 235 strings
Recorded by Codex · associated with the Git commit containing this note
implementation Lumberjacks A7

Normalise CRLF before base64-encoding the remote bash script in the three publish scripts that were missing it

Impact: Whether a publish succeeded depended on how git checked the file out, not on the code. A here-string carries the .ps1's own line endings; on a Windows clone those are CRLF, so the remote shell reads 'set -euo pipefail\r' and aborts after the uploads have already landed in /tmp. Promote-GatewayImage.ps1 normalises and never broke; Publish-WorkbenchAssets, Publish-Modpack and Publish-CompanionBootstrap cloned the pattern without it

Verification (1)
  • Reproduced on a real publish once git rewrote Publish-WorkbenchAssets.ps1 to CRLF (163 CR-bearing lines); after the fix the same publish completes and all three gates pass. Gateway image m31-workbench-20260729-r2 cut against HEAD, deployed, and re-verified: seven Community routes 200 and both downloads stream with X-Download-Sha256 equal to the catalog's claim
Recorded by Codex · associated with the Git commit containing this note
implementation Lumberjacks A7

Pin the workbench download pointer contract with tests so producer and consumer cannot drift again

Impact: The tools.json key mismatch that made every /workbench/downloads/{id} answer 503 is now a test failure rather than a deploy failure. Seven tests pin the documented shape, the exact 'tools'-key regression, and the refusals for a mismatched digest or size; a committed sample pointer is deserialized into the endpoint's own record, and the publish script gained a third gate that re-parses the JSON it is about to upload and compares its key shape to that same sample. Both sides are now pinned to one file

Verification (1)
  • Full solution suite green in the sdk:9.0 container (580 passed, 0 failed; Game.Gateway.Tests 200 to 207). Proven load-bearing by mutation: renaming the consumer record's downloads field to tools fails compilation, and the revert rebuilt byte-identical to the passing layer digest. The publish gate was exercised by extracting its shipped text and running it under PowerShell 5.1 - 'downloads' accepted, 'tools' refused, malformed sha256 refused
Recorded by Claude · associated with the Git commit containing this note
documentation Lumberjacks A7

Reconcile the gate files to the post-builder state

Impact: The cold-pickup handoff and the operator checklist now state current truth: the repository is public and two prior decisions resolve themselves (the roadmap links work for everyone; the public-source claim is literally true); the audit trail is committed; the Discord forum is live on the new server with the four tool threads held until deploy; ENDtoEND.txt is verified absent from the public repo with zero git history. Two operational facts surfaced: the P7 VM has been stopped since 2026-07-25 - the site has been down four days, current burn is roughly the storage floor, and the deploy session must start the VM first - and the public repo now advertises password-free direct-join, a live operator decision (server password vs accept) queued before the VM comes back up.

Verification (1)
  • VM status from a read-only gcloud describe; visibility from gh repo view; transcript absence from git log across all refs; the workbench Discord wiring was already completed by the builder sessions and needed no edits.
Evidence: HANDOFF-2026-07-29.md; DEREK-BATCH-1.md; DECISIONS-PENDING.md
Recorded by Claude · associated with the Git commit containing this note
verification Lumberjacks A7

Rehearse the workbench deploy on local hardware instead of GCP, and fix the download pointer key mismatch it exposed

Impact: Every /workbench/downloads/{id} would have returned 503 on the real deploy: the publish script emitted the artifact array under 'tools' while WorkbenchDownloadEndpoints deserializes 'downloads' and treats a null list as an invalid pointer. No test covers that shape, so the first real deploy was the detector. GCP stays stopped, preserving the VM spend for actual UAT

Verification (1)
  • Gateway image m31-workbench-20260729-r1 cut locally and verified from the shipped /app/Game.Gateway.dll (admits frozen mod m30-rolecontrol-20260723-r1). Deployed to local hardware over the tailnet: all seven Community routes return 200, X-Workbench-Sha256 matches the published artifact, and after the pointer fix both downloads stream 200 with X-Download-Sha256 equal to the sha256 the catalog page advertises
Recorded by Codex · associated with the Git commit containing this note
documentation Lumberjacks A7

Close four workbench trust gaps: a real Discord invite so member-only links are no longer the only way in, git-derived freshness replacing the hand-entered timestamp, OWNERS.md linked everywhere it is promised, and stage-three contribution rights declared per tool

Impact: A first-time visitor can now actually reach the community: join then Start Here then a tool thread, with the member-only links labelled as such. The displayed freshness can no longer go stale because it is derived from git rather than typed. All four OWNERS.md promises resolve. Each of the seven tools declares its own stage-3 right, so ComfyStewardView no longer inherits a commit-access promise its all-rights-reserved licence cannot honour

Verification (1)
  • Six new guards each negative-tested to confirm they fail: missing invite, proprietary tool claiming code contributions, ladder promising commit access globally, reintroduced updated_at, stage_3_reward contradicting code_contributions, and a tool missing contribution. npm run workbench:render and workbench:check green; zero-loss sweep over 235 content strings; five inert discussion placeholders confirmed still inert and confirmed not to trip the invite rule
Recorded by Codex · associated with the Git commit containing this note
documentation Lumberjacks A7

Correct the workbench source claims: baseline is public, so three cards no longer say private-until-claimed and ladder stage 3 grants commit access rather than the ability to read the code

Impact: Eight statements on a page whose whole premise is that its statuses match reality were falsified the moment djcdevelopment/baseline went public. All three private-until-claimed source blocks now render live links into the repo, the two always-visible stage-3 access mentions are gone, and stage 3's reward is restated as commit access

Verification (1)
  • gh repo view confirmed baseline, comfy, ComfyStewardView and Lumberjacks are all PUBLIC; all four linked source paths verified to exist; npm run workbench:render && npm run workbench:check; zero-loss sweep over 225 content strings; zero residual private-until-claimed or stage-3-access strings in source or rendered HTML
Recorded by Codex · associated with the Git commit containing this note
implementation Lumberjacks A7

Rework the Community Workbench page for first-time volunteers: tools before ladder, a scannable tool index, promoted access and first-result, and two native details disclosures per card

Impact: The catalog reads as a storefront rather than an encyclopedia. Nothing was deleted: a 222-string zero-loss check confirms every sentence in workbench.json still renders, and new check() guards fail the build if status_detail, requirements, or download digests are ever moved inside a disclosure

Verification (1)
  • npm run workbench:render && npm run workbench:check; zero-loss sweep over 222 content strings; browser pass at 1280x800 and narrow width confirming the index clears the fold and all 7 status_detail blocks render uncollapsed
Recorded by Codex · associated with the Git commit containing this note
implementation Lumberjacks A7

Name the credential file in the ignore rules

Impact: The bot credential was already covered by a wildcard, but the file that actually appeared at the repository root is now listed by its own name as well, at the root and at any depth. A pattern is easy to skim past when someone is checking whether their secret is safe; a named line answers the question directly. Verified that the credential has never been committed on any branch: the path has never existed in any tree, no file of that kind has ever existed in the repository's history, and a content search across every reference finds no commit that ever added or removed the value.

Verification (1)
  • Ignore rules exercised against the filename at the root, nested under the tool directory, and at arbitrary depth, plus the two wildcards, each reporting which rule catches it. History checked four ways - index, full-history path log across all refs, an object listing of every blob path ever recorded, and a content search of every reference for the value itself.
Evidence: .gitignore
Recorded by Claude · associated with the Git commit containing this note
planning Lumberjacks A7

Refresh the forum handoff with what is actually live

Impact: The handoff block that goes to the agent updating the catalog page now states verified live facts instead of the pre-provisioning prediction: two threads posted, no member replies yet, nothing exported, and the candidate journal not yet existing. It calls out that five of the seven tools will carry a null discussion link until the catalog deploys and that one tool never gets a thread at all, so nulls read as the designed state rather than as missing data, and it records that the page generator already allowlists the forum's link host, so the thread URLs will render as live links.

Verification (1)
  • Message counts, author identity and reply counts read back from the live server; the generator's link allowlist read out of its source rather than assumed; downstream file state checked on disk.
Evidence: tools/workbench/discord/WORKBOOK.md
Recorded by Claude · associated with the Git commit containing this note
deployment Lumberjacks A7

Open the community workbench forum

Impact: The forum went live on the new community server, provisioned from this repository rather than by hand. The channel carries the eight-tag taxonomy with required tags on and the post-guidelines text, the how-this-works guide is posted and pinned, and the recoverable-pieces thread is open and tagged. The four tool threads that link to the catalog page are deliberately held back until that page is deployed, so nobody arrives at a placeholder or a missing page. The live plan hash matched the receipt approved before the bot was ever invited, which means the operator approved precisely what shipped.

Verification (1)
  • Confirmed against the live server after the run rather than trusting the tool's own report: channel type, required-tags flag, sort order and guidelines text read back as configured, all eight tags present with the four status tags correctly restricted, both posts present with the pinned one pinned. A second plan comes back with no work to do, which is the idempotence claim holding on real infrastructure instead of a fixture.
Evidence: tools/workbench/discord/receipts/2026-07-29-plan.md; tools/workbench/discord/provision-state.json
Recorded by Claude · associated with the Git commit containing this note
implementation Lumberjacks A7

Accept the operator's own credential file and prove it before use

Impact: The credential reader only understood a bare token or one specific key name, so an env-style file whose line was named differently was read back with the key name still attached and failed as an unauthorized response with nothing to point at. It now accepts either shape - bare token, or a named line in any of the common spellings, quoted or not, with or without a byte-order mark or carriage returns - and rejects a placeholder or an id on length before it can become a mystery failure, without ever echoing the value. A new read-only identity check reports the bot, whether it can see the server, and whether the channel exists, and prints the authorization link itself when the bot has not been added yet, so the operator never has to go looking for an application id. The refusal to read a credential from inside the working tree stays, and the ignore rule was widened to cover the filename that actually appeared, because this repository commits and pushes without being asked.

Verification (1)
  • 85 of 85 self-test assertions, including ten credential-file layouts a Windows operator can produce and four malformed ones that must be refused. Verified live against the real credential: identity confirmed read-only, no writes attempted, and the tool correctly reported that the bot has not yet been authorized onto the server.
Evidence: tools/workbench/discord/workbench_discord.py; .gitignore
Recorded by Claude · associated with the Git commit containing this note
implementation Lumberjacks A7

Write the operator's runnable steps in his own shell

Impact: The forum setup instructions handed the operator a bash one-liner - a directory create chained to a file write with the shell-and operator - on a Windows PowerShell 5.1 box, where that separator is a parse error and neither command exists. Every runnable snippet in the workbook, the setup doc and the tool README is now PowerShell with Windows paths and one command per block. The token file gets an explicit ascii encoding, because PowerShell 5.1 writes a byte-order mark on its utf8 setting and a mark in front of a bearer token surfaces only as an unauthorized response much later; the token reader now also strips one if it finds it, so both spellings work.

Verification (1)
  • Every fenced command block across the three documents re-audited programmatically for shell-and separators and unix-only commands; token loading exercised against all three byte layouts a Windows operator can produce - mark plus carriage returns, bare ascii, plain newline - all three now yield the same token. Self-test still 69 of 69.
Evidence: tools/workbench/discord/WORKBOOK.md; Lumberjacks/docs/workbench/discord/09-discord-bot-setup.md
Recorded by Claude · associated with the Git commit containing this note
planning Lumberjacks A7

Write the wrap-up workbook for the forum rollout

Impact: The forum provisioning work now has a tick-box workbook covering the one-time bot setup, the provisioning run, the second run that follows the catalog deploy, and the feedback pass - plus a paste-ready handoff block for the next agent describing where the thread URLs come from, which catalog fields they fill, which generated file must never be hand-edited, and which rules bind that agent too. Written because three separate hands are touching this in sequence and the ordering constraint between the forum posts and the catalog deploy is easy to miss.

Verification (1)
  • Steps cross-checked against the tool's own subcommands and the plan hash on the approved dry-run receipt; the seven-tools-to-six-posts mapping and the unthreaded tool are stated explicitly rather than left to be rediscovered.
Evidence: tools/workbench/discord/WORKBOOK.md
Recorded by Claude · associated with the Git commit containing this note
implementation Lumberjacks A7

Make forum provisioning survive a lost state file

Impact: The provisioner tracked which messages belong to a managed post only through its own state file. If that record were lost, a post whose body spans two messages would have looked one message short and the next converge run would have appended a duplicate continuation to a live community thread. The tool now rediscovers a post by reading the thread: the opening message plus the unbroken run of its own messages that follow it, stopping at the first reply from anyone else. A member reply in the thread is left untouched and a post someone wrote by hand is still recognised as unmaintainable rather than edited.

Verification (1)
  • 69 of 69 self-test assertions, including a new case that wipes the state record, adds a member reply to a two-message post, and asserts the next plan is a no-op with the reply intact. The approval receipt's plan hash is unchanged, so the dry run already approved still applies.
Evidence: tools/workbench/discord/workbench_discord.py
Recorded by Claude · associated with the Git commit containing this note
implementation Lumberjacks A7

Provision the workbench forum from the repository

Impact: The community forum is now config-as-code: the forum channel, its eight-tag taxonomy, its post-guidelines text and its six opening posts are all generated from files already in this repository, and re-running the tool converges on drift - a deleted tag returns, a hand-edited pinned post is restored to the written text - instead of duplicating anything. The tool does structure and never conversation: there is no code path that sends a sentence nobody wrote in the repo, mentions are disabled on every write, and the announcement post is on a denylist no flag can lift, so replies to the community stay the operator's own on the operator's own rhythm. It also replaces the external export step that feeds the feedback distiller. Standard library only, no resident process, batch-run on demand.

Verification (1)
  • 64 of 64 self-test assertions pass offline against a simulated guild: taxonomy parsing, the placeholder guard, message chunking, a full greenfield provisioning run, idempotent re-plan, drift detection and repair, refusal to mangle a hand-pasted post, and the export handing off cleanly into the feedback distiller. Two dry-run receipts generated for operator approval; nothing has been written to any live server.
Evidence: tools/workbench/discord/; Lumberjacks/docs/workbench/discord/09-discord-bot-setup.md; tools/workbench/discord/receipts/2026-07-29-plan-offline.md
Recorded by Claude · associated with the Git commit containing this note
decision Lumberjacks A7

Open pull requests and rename the ladder stage to Contributor

Impact: Three operator calls land: pull requests are open to anyone with something to contribute, with the operator as the sole approval gate (CONTRIBUTING.md rewritten; the CLA-versus-DCO instrument stays an open item, narrowed); ladder stage 3 is renamed from Steward to Contributor because Steward is an overloaded term on the server - the license suite's community-steward safe harbor and the ComfyStewardView product name are deliberately unaffected; and the public comfy archive's community data stays as-is, with consent from everyone named, misattributions already corrected on request, and the live quest data on record as donated by active volunteer GMs. A new Discord server exists and a task is queued to provision the workbench forum from the repo's own seed files.

Verification (1)
  • Rename applied contextually across ten ladder artifacts with product, license, and persona usages preserved and documented per file; workbench render and check green after the JSON edit; register and checklist entries carry the operator's rationale verbatim where it matters.
Evidence: CONTRIBUTING.md; Lumberjacks/docs/workbench/workbench.json; DECISIONS-PENDING.md
Recorded by Claude · associated with the Git commit containing this note
decision Lumberjacks A7

Commit the held audit trail

Impact: Per the operator's call, docs/audit joins history: the 36-hour independent audit, the GCP burn-rate review, the contributor-onboarding review brief, and its annotated fresh-eyes results. The review's own recommendation argued these memos double as newcomer orientation; they are now visible to git instead of sitting untracked. The remaining audit-related decisions stay tracked on the operator checklist.

Verification (1)
  • Four files, docs-only, previously untracked by explicit design; no content edited on the way in.
Evidence: docs/audit/2026-07-24-independent-36h-audit.md; docs/audit/2026-07-25-gcp-burn-rate-review.md; docs/audit/2026-07-29-contributor-onboarding-review.md
Recorded by Claude · associated with the Git commit containing this note
documentation Lumberjacks A7

Run the contributor-onboarding cleanup batch

Impact: The fresh-eyes review's agent-executable fixes are in: three stale handoff files now redirect at the canonical one and four pre-Valheim greenfield-era docs carry archive notices; five living docs' references to pruned files are annotated with honest recovery refs (fieldlab-native docs to the pre-prune commit, comfy-origin material to the public archive) and the fieldlab ADR index's dead canon line now points at the living roadmap, strategy, and lane pin; a START-HERE page tags every area live, paused, built-not-deployed, cockpit, or historical; BUILDING.md consolidates the two build environments and the commit ceremony out of agent-facing docs; a 26-term GLOSSARY disambiguates the three things called workbench; and the decisions register's own pre-lint wording is corrected. Historical records - retros, the journal, the prune audit, frozen status JSON - were deliberately left verbatim.

Verification (1)
  • Banner edits verified insert-only below each notice; the links pass documented 17 skips with reasons and kept two recovery mechanisms distinct; both new reference docs cite a repo source per claim.
Evidence: START-HERE.md; BUILDING.md; GLOSSARY.md; fieldlab/docs/adr/README.md
Recorded by Claude · associated with the Git commit containing this note
decision Lumberjacks A7

Correct the cost runbook to operator truth

Impact: The operator's corrections override the burn memo's framing: the early overspec was deliberate limit-testing with 800-plus headless connections, and 2 vCPU with 16 GB is the declared floor, so the 8 GB downsizes are rejected and only a same-shape e2-highmem-2 family swap remains, priced after invoiced data exists. The disk growth is self-inflicted prod-cadence backups running during dev loops on an heirloom world preserved elsewhere - a new lever flips the valheim-server to the existing dev backup posture with a written re-arm rule. Today's cohort is the operator's own three accounts plus name-known friends, so duty-cycle scheduling loses its product-hours weight and the aggressive stopped-except-sessions default becomes natural. Sequencing set: billing export tonight, full shakedown at end of night, first scheduled restart watched once as the last unproven claim.

Verification (1)
  • Every changed dollar figure either traces to the memo or is explicitly deferred to invoiced data; the backup lever stages an on-box grep before any env change and preserves the atomic world-save mechanism untouched.
Evidence: infra/gcp/p7/RUNBOOK-cost-and-cycle.md; DECISIONS-PENDING.md
Recorded by Claude · associated with the Git commit containing this note
documentation Lumberjacks A7

Stage the GCP cost and cycle-time runbook

Impact: Four independent levers with staged commands the operator runs himself: BigQuery billing export first (turns plus-or-minus twenty percent estimates into invoiced truth), orphaned-snapshot cleanup as list-first-then-eyeball (the dead 250 GB lineage, live state-v2 dailies explicitly untouched), VM scheduling with an honest duty-cycle ladder (about twenty-five dollars a month at eight hours nightly, more only with longer off-hours or stacking), and machine right-sizing. Both stop-start levers carry the live-alpha-server downtime warning in bold with a post-in-Discord-first instruction, and the no-terraform-apply rule heads the document with the destroy plan quoted. What makes any of this viable now is recorded plainly: the deploy lane is baked, image-pinned, and restart-predictable.

Verification (1)
  • Every dollar figure traces to the burn memo; project, VM, zone, and service names traced to infra docs; restart-predictability claim checked against the systemd unit and compose restart policies with the first real scheduled restart hedged as the remaining live proof.
Evidence: infra/gcp/p7/RUNBOOK-cost-and-cycle.md; docs/audit/2026-07-25-gcp-burn-rate-review.md
Recorded by Claude · associated with the Git commit containing this note
decision Lumberjacks A7

Arm tonight's operator-in-the-seat test rule and queue the GCP lever decision

Impact: A dated temp rule (expires 2026-07-29 05:00 PT, self-deleting) tells every builder session in this repo to forgo unit tests when the contract or seam is highly likely to be integration-tested shortly by the operator himself - the operator-in-the-seat mode distinction applied for one night, per-change judgment, with irreversible or production-critical changes still tested. A root CLAUDE.md now points Claude sessions at AGENTS.md so working rules reach every agent brand. The GCP spend and cycle-time question enters the decision register with a staged runbook on the way: the deploy lane being baked and predictable is what makes revisiting the always-on VM posture viable.

Verification (1)
  • Rule carries its own expiry and deletion instruction; register entry names the live-game-server constraint explicitly.
Evidence: AGENTS.md; CLAUDE.md; DECISIONS-PENDING.md
Recorded by Claude · associated with the Git commit containing this note
decision Lumberjacks A7

Record the product boundary: Baseline is the toolkit, HEARTH is the lab

Impact: Derek's canonical product framing is now written down: Baseline is a toolkit for building a whole community on Valheim - identity baked in, telemetry first-class, vertical integration paths from server through transpiling, and headless/automated/MCP-driven testing - serving communities that already run mods, spreadsheets, bots and checklists so they spend less time on tracking and more on creating; forking pieces out is the highest compliment. HEARTH/Mechnet, the operator's personal AI lab, is explicitly NOT part of any Baseline deliverable, and community-facing automation must run without it. The handoff doc now carries the boundary rule; the privacy scanner's machine-path rule doubles as its guard.

Verification (1)
  • Boundary audited against everything shipped this session: no HEARTH endpoints, keys, or lab paths in the zips, the Workbench page, or the one-pagers; both new automation scripts are deterministic and LLM-free by design.
Evidence: docs/baseline-vision-and-boundary.md; HANDOFF-2026-07-29.md
Recorded by Claude · associated with the Git commit containing this note
documentation Lumberjacks A7

Land the cold-pickup handoff

Impact: HANDOFF-2026-07-29.md at the repo root is the canonical resume point for any agent or the operator: session state, what shipped, pending items by actor, commit ceremony and gotchas, a key-file index, and step-by-step resume recipes for the thread-URL fill, the deploy batch, zip rebuilds, and un-pinning the networking lane. The execution-status postscript on the operator's plan file points here.

Verification (1)
  • Every path the handoff cites was existence-checked before writing; git state cross-checked against the doc's claims (HEAD c6314d3, only docs/audit untracked).
Evidence: HANDOFF-2026-07-29.md
Recorded by Claude · associated with the Git commit containing this note
implementation Lumberjacks A7

Build the top of the cognitive-lift portfolio

Impact: Three research agents surveyed solo-maintainer practice, modding-community norms, and agent-automation patterns; 13 deduplicated ideas were scored in a weighted matrix and the top five built: a journal-to-announcement drafter that assembles never-auto-posted Discord draft skeletons from the roadmap journal, a forum tag taxonomy rendering the existing ownership ladder into Discord triage, a bug-fix-shaped first-task authoring lens backed by newcomer merge-rate evidence, an Already-answered one-pager section plus a seven-reply saved-replies starter set, and a batch feedback distiller that turns Discord thread exports into an append-only candidate-issues journal with nothing auto-filed. Both scripts are deterministic and work with the local LLM fleet down; ranks six through thirteen are staged as backlog, several deliberately parked until the first real volunteer exists.

Verification (1)
  • Drafter self-test 11 of 11 and distiller self-test 15 of 15 green; the drafter ran against the real journal and produced the first draft covering this session's eight entries; DiscordChatExporter schema verified from that project's source before the distiller was written.
Evidence: plans/cognitive-lift-portfolio.md; tools/workbench/new_announcement_draft.py; tools/workbench/distill_feedback.py; Lumberjacks/docs/workbench/discord/07-forum-tags-setup.md
Recorded by Claude · associated with the Git commit containing this note
documentation Lumberjacks A7

Stage the Discord seeds and the ownership ledger

Impact: The rollout's Discord layer exists as reviewable files, not posts: an announcement that states the pause plainly and is explicitly not a verdict on anyone, one thread seed per first-wave tool with achievable first tasks, a pinned how-this-works post covering the batch-reply rhythm and graceful step-back, and one thread for the two revivable pieces where reviving is the claiming path. OWNERS.md opens the append-only ownership ledger all 7 tools report unclaimed into. Derek review gates everything: nothing posts until the announcement batch, and DEREK-BATCH-1.md carries every open decision including the StewardView license posture.

Verification (1)
  • Every status claim in the drafts traces to a repo path the drafting agent read; tone checked against the positioning and adoption strategy docs; no post was made anywhere.
Evidence: Lumberjacks/docs/workbench/discord/00-announcement.md; Lumberjacks/docs/workbench/OWNERS.md; DEREK-BATCH-1.md
Recorded by Claude · associated with the Git commit containing this note
implementation Lumberjacks A7

Ship the cold-start kits behind a privacy gate

Impact: Two downloadable kits now exist: a quest-picker kit with a synthetic sample guild, verified to run from a fresh folder with only Python and openpyxl, and a telemetry starter kit that polls the public aggregates-only v0 API with the standard library. Every zip passes a mandatory deny-list privacy scanner (real player handles, guild workbooks, tailnet hosts, SteamIDs, credentials, machine paths, the server IP) before it can be built, and the publish script refuses any artifact whose hash does not match what the public page claims. A real cross-tool defect found during verification is fixed: the picker told players the pruned config path while the mod reads comfy-network-sense - a silent failure for every volunteer until now. Per-tool one-pagers land alongside.

Verification (1)
  • Scanner self-test passes all 12 rules on clean and poisoned fixtures; both zips built CLEAN through the gate; the quest-picker zip extracted and ran cold in a fresh directory, and the rendered picker carries the corrected config path with zero stale references.
Evidence: tools/workbench/Test-WorkbenchZipPrivacy.ps1; tools/workbench/New-WorkbenchZip.ps1; recipes/quest-catalogs/render_quest_picker.py; Lumberjacks/docs/workbench/tools/quest-picker.md
Recorded by Claude · associated with the Git commit containing this note
documentation Lumberjacks A7

Correct the licensing term on the public journal

Impact: A 2026-07-23 journal record used the wrong licensing term for this project. The accurate term is public source under Business Source License 1.1 with the community-steward safe harbor, converting to AGPL-3.0-only at the recorded Change Date. Journal records are append-only, so the original stands with this correction beside it; a glossary entry now defines the term, and the generator refuses the inaccurate phrase in any newly written note or roadmap field.

Verification (1)
  • Guard proven fail-closed: a deliberately mislabeled test note was rejected before any file was written; render and check pass with the glossary entry present.
Evidence: Lumberjacks/scripts/roadmap.mjs; LICENSING.md
Recorded by Claude · associated with the Git commit containing this note
implementation Lumberjacks A7

Open the /workbench catalog surface

Impact: The Community Workbench is built: workbench.json (7 tools, 5-stage ownership ladder, honesty invariants) renders through workbench.mjs into a self-contained /workbench page served like the roadmap (mount-override, per-request reload), with a fail-closed /workbench/downloads lane that verifies SHA-256 per request. Statuses state what runs and what does not: no rate limiting on the join flow yet, StewardView license under review, recoverable pieces marked claimable. Nav links added across the community pages. Not yet deployed - the page and packages ship together in one gated deploy batch.

Verification (1)
  • workbench:check green (7 tools, validators proven fail-closed via 16 mutation tests); Gateway built clean in the sdk:9.0 container with 6/6 roadmap endpoint tests passing; roadmap re-rendered after the nav change.
Evidence: Lumberjacks/docs/workbench/workbench.json; Lumberjacks/scripts/workbench.mjs; Lumberjacks/src/Game.Gateway/Endpoints/WorkbenchViewEndpoints.cs
Recorded by Claude · associated with the Git commit containing this note
documentation Lumberjacks A7

Fix the share-blockers ahead of the Workbench catalog

Impact: The guest-package installer finally has a README (its reissue TODO quoted as a known gap); the quest vertical-slice architecture doc now carries a banner mapping which layers are live, which moved into the mod, and which were pruned to the public archive; the MCP mod-channel gateway accepts COMFY_GATEWAY_PYTHON instead of a hardcoded other-repo venv path while staying localhost dev-only; and the missing gm-template example is explicitly labeled as Workbench first task QP-1 in sources.json.

Verification (1)
  • Every path in the banner verified against the tree by the fixing agent; sources.json re-validated as JSON; no binding or behavior changes to the gateway.
Evidence: tools/guest-package/README.md; docs/quest-vertical-slice-architecture.md; network/mcp/etc/start-comfy-gateway.cmd; recipes/quest-catalogs/sources.json
Recorded by Claude · associated with the Git commit containing this note
decision Lumberjacks M7 · A7

Pin the networking lane and open the Community Workbench milestone

Impact: The networking lane parks on a deliberate hard hold at a green machine-state: every remaining step needs live two-human Steam observation and none is scheduled; the hold, its pinned items, and a one-command resume path are recorded in fieldlab/PINNED-networking-lane-2026-07.md. Adoption milestone A7 Community Workbench opens to carry the shifted effort: a public catalog of tools a volunteer can run today with honest statuses, cold-start packages, per-tool discussion threads, and an ownership ladder. The 2026-07-23 to 07-25 stretch is closed by a session retrospective; no live network authority changes during the pause.

Verification (1)
  • Working tree clean except docs/audit (deliberately held for review); every path the pin document references resolves; roadmap render and staged checks green.
Evidence: fieldlab/PINNED-networking-lane-2026-07.md; fieldlab/retro/SESSION-RETRO-2026-07-28.md; plans/remaining-human-tests.md
Recorded by Claude · associated with the Git commit containing this note
implementation Lumberjacks M7

Stage the patch-load A/B rollup, built but never run

Impact: Hot Harmony patch bodies now accumulate per-call timing and emit per-interval rollups to perf-patchload.jsonl behind a new default-off Perf key perfPatchLoadRollupEnabled, with a lab runbook for an inert-versus-armed A/B comparison; volunteer telemetry is unchanged. The benchmark has not been run: lab clients client01/client02 remain unseeded and that one-time Steam login stays a pinned human step. COMMANDS.md now records that the netcode probe is console-started only after the config-surface cull.

Verification (1)
  • Mod compiled clean (Release, net48) with the plugin-copy guard; the new key defaults off; no benchmark run or evidence folder exists yet and the runbook says so.
Evidence: fieldlab/docs/runbook-patchload-ab-benchmark.md; fieldlab/experiments/patchload-ab/patchload-lab.cfg; network/mod/ComfyNetworkSense/CHANGELOG.md
Recorded by Claude · associated with the Git commit containing this note
decision Lumberjacks M7

Adopt a Harmony patch policy

Impact: A written policy now governs ComfyNetworkSense Harmony patches: attribute prefix/postfix applied in Awake as the default shape, transpilers only for surgical call-site swaps that must degrade to a no-op, an inlining escalation ladder, load-bearing patch ordering recorded at the patch site, and detour cost measured rather than assumed. It codifies existing practice so hot-path changes stay deliberate; no code changed.

Verification (1)
  • Policy patterns cross-checked against the mod: the ZdoSendCadenceOverride transpiler, ZdoRedirect/NetcodeProbe priority ordering, and UnpatchSelf teardown all match the written rules.
Evidence: fieldlab/docs/harmony-patch-policy.md
Recorded by Claude · associated with the Git commit containing this note
verification Lumberjacks M7

Derive an adaptive motion playout candidate

Impact: Repeat deterministic replay rejected a 50 ms bracket floor, then showed a bounded 100-200 ms relative-transit policy can reduce aggregate disturbed-path stalls and large corrections versus chase while spending less delay than fixed 200 ms; no DLL or live authority changed.

Verification (1)
  • Both 180-row v2 runs normalized equal; five safety invariants and all seven AuthorityLab tests passed; the retained v1 run documents the rejected floor.
Evidence: fieldlab/experiments/creative-runtime/cre-e08-adaptive-presentation-replay/experiment.md; fieldlab/experiments/creative-runtime/cre-e08-adaptive-presentation-replay/runs/pure-20260725T045003Z/receipt.json; fieldlab/experiments/creative-runtime/cre-e08-adaptive-presentation-replay/runs/pure-20260725T045003Z-repeat/comparison/comparison.json
Recorded by Codex · associated with the Git commit containing this note
implementation Lumberjacks M7

Recover the i5 workbench after sleep

Impact: The bounded i5 repair lane now detects a non-answering Companion bind mount, restarts Docker through a durable interactive task, preserves failure diagnostics, and restores the exact client package without starting Valheim.

Verification (1)
  • Post-SSH Companion status remained readable; readiness returned ready_for_two_client_gate; the scheduled task permits battery operation, does not stop on battery, starts when available, and has no execution time limit.
Evidence: tools/i5/Repair-I5DockerDesktop.ps1; tools/i5/README.md
Recorded by Codex · associated with the Git commit containing this note
implementation Lumberjacks M7

Attribute motion phase evidence by client role

Impact: Two-client receipts now isolate the final APPLY and OBSERVE segments, reject OBSERVE-side apply activity as contradictory, and keep competing-writer identity explicitly unresolved before any live visual claim.

Verification (1)
  • Role-attribution fixtures passed for either-machine APPLY, setup role transitions, ambiguous roles, contradictory OBSERVE activity, and missing-client rejection; PowerShell parse checks passed.
Evidence: fieldlab/experiments/creative-runtime/cre-e06-motion-phase-rollups/experiment.md
Recorded by Codex · associated with the Git commit containing this note
verification Lumberjacks M7

Reject fixed motion interpolation delay

Impact: Deterministic replay showed that smaller fixed buffers retain synthetic burst stalls and corrections, while 200 ms removes them only by increasing current-time error; no client DLL or authority change was promoted.

Verification (1)
  • Final 60-row run and repeat normalized equal; four safety invariants passed; AuthorityLab build and all seven tests passed in the .NET 9 container.
Evidence: fieldlab/experiments/creative-runtime/cre-e07-presentation-replay/runs/pure-20260725T040847Z/receipt.json; fieldlab/experiments/creative-runtime/cre-e07-presentation-replay/runs/pure-20260725T040847Z-repeat/comparison/comparison.json
Recorded by Codex · associated with the Git commit containing this note
implementation Lumberjacks M7

Unify two-client motion phase evidence

Impact: Wave 0 and the physical feel window now share one fail-closed bundle analyzer; synthetic fixtures prove both-client success and missing-client rejection before a live join window.

Verification (1)
  • Bundle adapter fixtures, bounded-command contracts, live-gate fixtures, expected-result-grid fixtures, and PowerShell parse checks passed.
Evidence: fieldlab/experiments/creative-runtime/cre-e06-motion-phase-rollups/Test-BundleAdapter.ps1; fieldlab/scripts/Summarize-TwoClientMotionPhaseBundles.ps1; tools/i5/Start-TwoClientCapture.ps1
Recorded by Codex · associated with the Git commit containing this note
implementation Lumberjacks M7

Separate package and admitted mod readiness

Impact: Wave 0 preflight now permits fast client-pull package pointers while still requiring both clients to match that package, its hash, and the Gateway-admitted mod identity.

Verification (1)
  • The corrected audit returned ready_for_two_client_gate for package m31, admitted/Gateway mod m30, matching OMEN/i5 package hashes, profiles, configs, P7 readiness, and readable telemetry.
Evidence: tools/i5/Test-Wave0Readiness.ps1
Recorded by Codex · associated with the Git commit containing this note
implementation Lumberjacks M7

Pin disposable clients to exact mod artifacts

Impact: The autonomous Valheim lab can now stage a caller-selected DLL and block before launch unless the shared payload hash matches it, preventing concurrent dirty worktree builds from contaminating experiment receipts.

Verification (1)
  • PowerShell syntax passed; clean artifact refresh staged SHA-256 1e875984fde1; preflight matched that hash and stopped before launch because the disposable Steam install/profile is not seeded.
Evidence: fieldlab/docs/runbook-headless-valheim-lab.md
Recorded by Codex · associated with the Git commit containing this note
deployment Lumberjacks M7

Publish motion phase client package

Impact: The public client-pull pointer now serves the clean CRE-E06 build; OMEN and i5 installed the same verified package and DLL with rollback backups while Gateway and server remain on the admitted m30 identity.

Verification (1)
  • Public manifest matched m31 package SHA-256 ef5ced82655f; both Companion installs succeeded; both client DLLs matched SHA-256 1e875984fde1; both games remained closed.
Evidence: docs/roadmap/m31-motionphase-client-package.json
Recorded by Codex · associated with the Git commit containing this note
implementation Lumberjacks M7

Add bounded client motion phase rollups

Impact: Existing client JSONL and Companion captures now separate receive, drain/coalesce, bind, render, error, freshness, and source-agnostic interframe displacement without per-frame files or broader Valheim authority.

Verification (1)
  • ComfyNetworkSense Release build passed; CRE-E06 fixture assertions passed; two-client phase orchestration dry-run passed.
Evidence: fieldlab/experiments/creative-runtime/cre-e06-motion-phase-rollups/experiment.md
Recorded by Codex · associated with the Git commit containing this note
verification Lumberjacks M7

Modeled the current motion apply loop

Impact: Repeat source-derived receipts show receive coalescing is already latest-per-object while render work scales with frame rate and fresh remotes; runtime phase costs and visual causality remain deliberately unclaimed.

Recorded by Codex · associated with the Git commit containing this note
verification Lumberjacks M7

Bounded transient presentation consumption

Impact: Repeat lab receipts show latest-wins and expiry reduce deterministic presentation apply work while preserving final fresh state; placement remains an explicit client, per-recipient, or pre-fanout decision and no live authority changed.

Recorded by Codex · associated with the Git commit containing this note
verification Lumberjacks M7

Measured motion fault and fanout behavior

Impact: Retained WebSocket and UDP receipts show stale rejection, gap and wrap acceptance, authenticated resume behavior, detached-token rejection, and topology-aware relay accounting without changing live gameplay authority.

Recorded by Codex · associated with the Git commit containing this note
verification Lumberjacks M7

Route the runtime envelope through real Gateway transport

Impact: Proves selected presentation work reaches WebSocket fallback and bound UDP while deferred and dropped work remains absent, without changing Valheim authority.

Verification (1)
  • Both 47-row receipts validated; each path delivered 9 of 9 selected frames in sequence and suppressed 23 of 23 non-selected decisions.
Evidence: fieldlab/experiments/creative-runtime/cre-e02-gateway-pressure-route/runs/gateway_udp-20260724T141258Z/receipt.json
Recorded by Codex · associated with the Git commit containing this note
implementation Lumberjacks M7

Add a deterministic creative runtime envelope experiment

Impact: Proves bounded selective degradation and semantic routing in pure lab runs without changing Valheim authority.

Verification (1)
  • Two 38-row receipts validated, normalized comparison matched, and AuthorityLab tests passed 7 of 7.
Evidence: fieldlab/experiments/creative-runtime/cre-e01-runtime-envelope/runs/pure-20260724T133947Z/receipt.json
Recorded by Codex · associated with the Git commit containing this note
implementation Lumberjacks A1

Add quiet provenance and license links to public surfaces

Impact: Every public Gateway dashboard now carries a low-key Baseline, Lumberjacks, Comfy, and license-details footer, while the root README identifies Baseline as canonical and makes the legal map unambiguous.

Recorded by Codex · associated with the Git commit containing this note
decision Lumberjacks M0

Publish the transparent stewardship framework

Impact: Defines public evidence, private-person defaults, configurable delayed aggregate trends, and a narrow independent-review path for community trust.

Recorded by Codex · associated with the Git commit containing this note
decision Lumberjacks M0

Allow small community stewards to earn bounded profit

Impact: Eligible independent operators can now keep profit without a separate agreement while serving at most 100 active members, remaining under USD 25,000 in aggregate annual community revenue, publishing the exact deployed source, and protecting player data; larger organizations use a flexible negotiated path.

Verification (1)
  • Root and standalone Lumberjacks licenses carry matching steward, scale, revenue, source-offer, aggregation, and large-organization boundaries.
Evidence: LICENSE.md
Recorded by Codex · associated with the Git commit containing this note
implementation Lumberjacks M2

Make the local Companion a source-aware reconstruction workbench

Impact: Adds a local /workbench hierarchy over roadmap and goal sources, stamps Docker source identity, and preserves redacted immutable snapshots without moving Steam credentials into the local image.

Recorded by Codex · associated with the Git commit containing this note
decision Lumberjacks M0

Adopt community-first source licensing boundaries

Impact: Current releases permit noncommercial community deployment only with a public reproducible source offer; commercial production use now requires a separate agreement, third-party material is explicitly excluded, and each version has a dated AGPL conversion.

Verification (1)
  • Root and standalone Lumberjacks license terms agree on community, commercial, source-offer, and Change Date boundaries.
Evidence: LICENSE.md
Recorded by Codex · associated with the Git commit containing this note
implementation Lumberjacks M7

Add a low-touch physical two-client feel window

Impact: Coordinates readiness, concurrent capture, bounded apply-observe roles, and named motion patterns on the existing OMEN/i5 Companion lane without keyboard automation or authority promotion.

Recorded by Codex · associated with the Git commit containing this note
implementation Lumberjacks M7

Add atomic multi-client disposable lab coordinator

Impact: The local authority lane can refresh and preflight multiple disposable clients before any starts, clean up partial starts, and aggregate receipts for the eventual two-player shadow/strict run.

Recorded by Codex · associated with the Git commit containing this note
implementation Lumberjacks M7

Add operator-touch gate and closed lab capture wrapper

Impact: Disposable lab runs now fail before human login when payload, runtime, Valheim seed, or existing profile is missing; closed probe evidence can flow through Docker AuthorityLab normalize/replay without manual file movement.

Recorded by Codex · associated with the Git commit containing this note
implementation Lumberjacks M7

Add bounded disposable lab-client automation, MCP motion mailbox, and native candidate replay

Impact: Restores existing-profile autojoin only for profile-gated headless/rendered clients; adds verified refresh/start/stop lifecycle, bounded MCP motion commands, native JSONL normalization/replay, and explicit evidence boundaries without changing P7 authority.

Recorded by Codex · associated with the Git commit containing this note
implementation Lumberjacks M7

Add Gateway-backed M7 authority experiment drivers

Impact: Runs E02 recipient queue and E03 motion relay through real Gateway WebSocket, WAL restart, and bound UDP seams before native capture or P7 promotion.

Recorded by Codex · associated with the Git commit containing this note
implementation Lumberjacks M7

Start the deterministic M7 authority experiment lab

Impact: Adds synthetic E00-E03 receipts, bounded failure evidence, linked policy decisions, and discovery status tooling before any live authority promotion.

Recorded by Codex · associated with the Git commit containing this note
implementation Lumberjacks M1

Parameterize P7 Valheim world backups

Impact: Moves the dev P7 backup posture into explicit environment knobs so idle imported worlds do not generate unbounded hourly zip churn, while production can turn bounded backups on with retention limits.

Recorded by Codex · associated with the Git commit containing this note
implementation Lumberjacks M1

Classify Wave 0 defect fallback

Impact: The Wave 0 fallback path now has Suggest-Wave0DefectPacket.ps1, which reads failed live receipts, annotations, and the visual seal to recommend a defect kind and exact New-Wave0DefectPacket command before an agent retains the named defect packet.

Verification (1)
  • Test-Wave0DefectPacketFixtures.ps1 classified the bad role-reversal fixture as role_reversal_failed, and Test-Wave0Prelive.ps1 returned ready_for_derek_two_client_join with the classifier command in the return packet.
Recorded by Codex · associated with the Git commit containing this note
implementation Lumberjacks M1

Expand Wave 0 return packet evidence

Impact: The Wave 0 return packet now indexes the full pre-live evidence set, including roadmap freshness, auto-wait fixtures, visual-seal fixtures, named-defect fixtures, and two-machine bundle smoke, so the operator handoff matches the actual gate coverage instead of an older four-check subset.

Verification (1)
  • New-Wave0ReturnPacket.ps1 generated ready_for_derek_two_client_join with the expanded evidence rows, and Test-Wave0Prelive.ps1 returned ready_for_derek_two_client_join using the expanded return packet.
Recorded by Codex · associated with the Git commit containing this note
implementation Lumberjacks M1

Add Wave 0 roadmap freshness gate

Impact: The Wave 0 pre-live audit now fails when the living roadmap source, rendered HTML, or public /roadmap page does not name the live P7 modpack, Gateway, and Companion bootstrap releases, catching stale public status before a tester is asked to join.

Verification (1)
  • Test-Wave0RoadmapFreshness.ps1 returned wave0_roadmap_freshness_passed, and Test-Wave0Prelive.ps1 returned ready_for_derek_two_client_join with the new roadmap-freshness step included.
Recorded by Codex · associated with the Git commit containing this note
documentation Lumberjacks M1

Refresh public roadmap current release truth

Impact: The public roadmap current-focus block now matches the verified Wave 0 runtime state: P7, OMEN, and i5 are aligned on m30-rolecontrol-20260723-r1, Companion bootstrap r26 is published, and the remaining gate is the live two-client apply/observe visual proof.

Verification (1)
  • P7 manifest and i5 link checks verified r26 bootstrap availability and the awake i5 lane before the roadmap refresh.
Recorded by Codex · associated with the Git commit containing this note
implementation Lumberjacks M4b

Verify Companion bootstrap command coverage

Impact: The Companion bootstrap builder now rejects packages that omit PowerShell scripts referenced by the Companion Wave 0 command surface, preventing a repeat of the package gap where UI commands were present but the downloaded bundle could not run them.

Recorded by Codex · associated with the Git commit containing this note
verification Lumberjacks M4b

Publish Companion bootstrap r26 with operator scripts

Impact: The public Companion bootstrap now points at companion-bootstrap-20260723-r26; the downloaded package hash matches the manifest and includes the Wave 0/i5 operator scripts referenced by the Companion handoff commands.

Recorded by Codex · associated with the Git commit containing this note
implementation Lumberjacks M4b

Add Wave 0 auto-wait live gate

Impact: The Wave 0 lane now has Wait-Wave0LiveGate.ps1, a bounded wrapper that can start before/during client joins, wait for P7 peer_count to reach the live threshold, then delegate to the existing live gate; Companion and return packets now prefer the low-touch wait command.

Recorded by Codex · associated with the Git commit containing this note
implementation Lumberjacks M4b

Add i5 Docker recovery lane

Impact: The i5 deploy lane now has a bounded Repair-I5DockerDesktop command that recovers Docker Desktop Linux engine readiness, recreates the Companion with both compose files, verifies the Wave 0 packet endpoint, and emits a JSON receipt instead of requiring operator KVM work.

Recorded by Codex · associated with the Git commit containing this note
verification Lumberjacks M4b

Publish Companion bootstrap r24

Impact: The public credential-free Companion bootstrap now points at companion-bootstrap-20260723-r24; the downloaded package hash matches the manifest and contains the Wave 0 packet endpoint, redacted Companion status, and init-enabled Docker Compose service.

Recorded by Codex · associated with the Git commit containing this note
implementation Lumberjacks M4b

Add Companion Wave 0 handoff packet

Impact: The local Companion now exposes read-only Wave 0 handoff packets as Markdown and JSON, redacts raw enrollment ids from status, and runs the Docker Companion service with init enabled to reduce zombie-container rebuild failures on remote test clients.

Recorded by Codex · associated with the Git commit containing this note
verification Lumberjacks M4b

Publish Companion bootstrap with Wave 0 defect fallback

Impact: The public credential-free Companion bootstrap now points at companion-bootstrap-20260723-r23; the downloaded package hash matches the manifest and the packaged Companion status endpoint contains the named-defect fallback command for the two-client Wave 0 handoff.

Recorded by Codex · associated with the Git commit containing this note
implementation Lumberjacks M4b

Expose Wave 0 defect fallback in Companion

Impact: The Companion Wave 0 panel and status endpoint now show both allowed exit paths for the remaining two-client gate: seal the visual evidence when it passes, or retain a named defect packet when visual proof is inconclusive or cannot be sealed.

Recorded by Codex · associated with the Git commit containing this note
verification Lumberjacks M4b

Publish Companion bootstrap with complete Wave 0 command chain

Impact: The public credential-free Companion bootstrap now points at companion-bootstrap-20260723-r22; the downloaded package hash matches the manifest and the packaged Companion status endpoint contains the final visual-evidence seal command for the two-client Wave 0 handoff.

Recorded by Codex · associated with the Git commit containing this note
implementation Lumberjacks M4b

Expose complete Wave 0 command chain in Companion

Impact: The local Companion Wave 0 panel now exposes the full operator sequence: first live gate, first visual annotation, role reversal, reversal annotation, and final visual-evidence seal, reducing the remaining two-client test to a visible checklist instead of reconstructed chat context.

Recorded by Codex · associated with the Git commit containing this note
verification Lumberjacks M4b

Publish Companion bootstrap with Wave 0 panel

Impact: The public credential-free Companion bootstrap now points at companion-bootstrap-20260723-r21, and the downloaded package hash matches the manifest, so a fresh alpha install receives the local Wave 0 live-gate panel without GitHub auth or manual file transfer.

Recorded by Codex · associated with the Git commit containing this note
implementation Lumberjacks M4b

Expose Wave 0 live-gate status in Companion

Impact: The local Companion now shows a Wave 0 live-gate panel and serves a redacted status endpoint that tells an operator whether local setup, P7 telemetry, peer count, and recent capture evidence are ready before running the two-client apply/observe proof.

Recorded by Codex · associated with the Git commit containing this note
documentation Lumberjacks M4b

Record P7 cost-hygiene infra defaults

Impact: The P7 infrastructure defaults now reflect the live n2-highmem-2 cost-sized VM and disable noisy Cloud Logging ingestion while retaining on-VM docker logs and OTLP metrics/traces for alpha diagnostics.

Recorded by Codex · associated with the Git commit containing this note
verification Lumberjacks M4b

Align living roadmap current release with m30 runtime

Impact: The public roadmap current-release block now reflects the deployed m30 role-control Gateway and ComfyNetworkSense runtime identity, matching the P7/OMEN/i5 readiness receipts used by the Wave 0 return packet.

Recorded by Codex · associated with the Git commit containing this note
deployment Lumberjacks M4b

Deploy m30 role-control release to P7, OMEN, and i5

Impact: P7 now runs Gateway m30 and the matching ComfyNetworkSense server DLL; the public client-pull manifest points at the rebuilt m30 package, and both OMEN and i5 installed it through Companion without browser copy/paste.

Recorded by Codex · associated with the Git commit containing this note
verification Lumberjacks M4b

Record m30 role-control release candidate artifacts

Impact: The m30 role-control candidate has public-safe artifact evidence for the mod DLL, client-pull package, and local Gateway/service images, while explicitly marking that P7 and clients still run m29 until promotion.

Recorded by Codex · associated with the Git commit containing this note
implementation Lumberjacks M4b

Cut m30 role-control release candidate

Impact: The role-control live-gate work now has a distinct mod release identity and locally verified Gateway image admission target, avoiding changed DLL bytes being published under the prior m29 identity.

Recorded by Codex · associated with the Git commit containing this note
implementation Lumberjacks M1

Add bounded Companion apply-role control for Wave 0 live gate

Impact: The live gate can set OMEN/i5 APPLY versus OBSERVE ONLY through the existing local Companion command lane, then verify the split before moving characters, reducing manual tester touch and preventing ambiguous role-reversal evidence.

Recorded by Codex · associated with the Git commit containing this note
verification Lumberjacks M4b

Add synthetic Valheim motion relay proof

Impact: Gateway motion admission now has a focused non-human test seam for distinct-recipient fan-out, same-recipient suppression, unauthorized sessions, malformed frames, duplicate or old sequence rejection, and source-ZDO binding before asking for another live two-client course.

Verification (1)
  • Docker .NET 9 SDK focused Gateway test run passed ValheimMotionRelayTests: 6 total, 6 passing.
Evidence: tests/Game.Gateway.Tests/ValheimMotionRelayTests.cs
Recorded by Codex · associated with the Git commit containing this note
verification Lumberjacks M1

Smoke m29 telemetry without players

Impact: A post-deployment no-player smoke capture against P7 m29 verified that the public telemetry endpoints, local Companion diagnostics, and transport-capture writer are live after the heartbeat-age deployment. The rebuilt OMEN Companion emits final_local_motion.server_ping_age_ms and server_ping_age_jitter_ms; the run remains INCONCLUSIVE for movement because no peer window was present.

Verification (4)
  • Companion diagnostics reported local installed_release m29-heartbeatage-20260723-r1 and public Gateway m29-heartbeatage-20260723-r1
  • Transport capture 20260723-212034-m29-post-companion-rebuild-smoke returned bad_sample_count=0, verdict no_peer_window, and capture_identity.gateway_version m29-heartbeatage-20260723-r1
  • The same capture emitted final_local_motion.server_ping_age_ms and server_ping_age_jitter_ms instead of legacy-only rtt/jitter names
  • i5 remained offline, so no two-client or i5 install proof was attempted
Recorded by Codex · associated with the Git commit containing this note
deployment Lumberjacks M1

Deploy heartbeat-age release to P7 and OMEN

Impact: P7 now runs Gateway m29-heartbeatage-20260723-r1 admitting the same m29 mod release; the dedicated Valheim server runtime and cold-start ComfyNetworkSense DLL hashes are 697f318f9dda7d5273253b787549de16c89abc9f1c365970c8944d917bc08424. The public client-pull manifest now points at m29-heartbeatage-20260723-r1 with package sha256 2b3cbb54eccc1860a3e93bc01586c17878cbc5e5ffd6e7d37f0c51cbca256475, and OMEN installed that package through Companion. i5 was not changed because the optional tailnet lane reported the laptop offline.

Verification (5)
  • Promote-GatewayImage.ps1 reported status=promoted and running image sha256:7de2f45200b0da97f34dbce8b9f08b70ea931c6bfe1a991e8b3d568e706d5a35
  • deploy-network-sense.ps1 reported ModReady=True and ServerReady=True with runtime and cold-start DLL sha256 697f318f9dda7d5273253b787549de16c89abc9f1c365970c8944d917bc08424
  • Public /api/v0/valheim/modpack/manifest reports release and mod_release m29-heartbeatage-20260723-r1 with package sha256 2b3cbb54eccc1860a3e93bc01586c17878cbc5e5ffd6e7d37f0c51cbca256475
  • OMEN Companion install returned ok=true for release m29-heartbeatage-20260723-r1
  • tools/i5/Test-I5Link.ps1 reported i5 lane DOWN; offline is normal for the roaming laptop
Recorded by Codex · associated with the Git commit containing this note
implementation Lumberjacks M1

Cut heartbeat-age mod release

Impact: ComfyNetworkSense now has a new immutable release identity for the heartbeat-semantics correction: m29-heartbeatage-20260723-r1. The release cut verified the net48 mod DLL carries that identity and the Gateway image lumberjacks-gateway:m29-heartbeatage-20260723-r1 admits the same mod release; a repo-local modpack builder now creates the small Companion package from the local Valheim payload while preserving personalized config.

Verification (3)
  • dotnet build network/mod/ComfyNetworkSense/ComfyNetworkSense.csproj -c Release succeeded
  • Test-GatewayImageRelease.ps1 confirmed lumberjacks-gateway:m29-heartbeatage-20260723-r1 admits m29-heartbeatage-20260723-r1
  • New-AlphaModpack.ps1 produced Comfy-P7-Alpha-Mods-m29-heartbeatage-20260723-r1.zip sha256:c192ba6980286899243d915d728dd6b3a870ac9cd9243d549ed9d99ffa7f7d2b
Evidence: network/mod/ComfyNetworkSense/ComfyNetworkSense.cs tools/modpack/New-AlphaModpack.ps1
Recorded by Codex · associated with the Git commit containing this note
implementation Lumberjacks M1

Name Valheim heartbeat age separately from RTT

Impact: Client telemetry now records server_ping_age_ms and variation with explicit ZRpc heartbeat provenance; legacy rtt_ms aliases remain during alpha while HUD, scoring, Companion summaries, and the retained probe stop presenting heartbeat age as round-trip latency.

Recorded by Codex · associated with the Git commit containing this note
implementation Lumberjacks M1

Added preemptive alpha seam receipts: client-local motion readiness is separated from Gateway relay deltas, and the motion mod reports direct ZDO, ZDO-object, player-index, unresolved, and index-rebuild resolution counters.

Impact: Future two-client runs can stop at the failing integration boundary instead of treating missing Gateway deltas as native motion or repeatedly asking a tester to reproduce the same lookup failure.

Recorded by Codex · associated with the Git commit containing this note
deployment Lumberjacks M1

Deploy m20 player-object index fallback and Companion r20

Impact: P7 Gateway, dedicated server, OMEN, and i5 now run the m20-playerindex-20260723-r1 release; the Companion bootstrap pointer is r20. The release adds a bounded live Player/ZNetView index fallback after direct ZDO and ZDOMan scene lookup fail, ready for the next controlled APPLY test.

Recorded by Codex · associated with the Git commit containing this note
deployment Lumberjacks M1

Cut and align m19 ZDO-resolution release across Gateway, server, clients, and Companion lanes

Impact: The m19-zdoresolve-20260723-r1 mod/Gateway identity is now sealed and published; P7, OMEN, and i5 all point at the same verified client package while the dedicated server reports ready. The release includes the ZDO-object motion lookup fallback and client-local capture truth.

Recorded by Codex · associated with the Git commit containing this note
implementation Lumberjacks M1

Add ZDO-object fallback for Lumberjacks motion presentation lookup

Impact: Motion packets now resolve through ZDOMan and the ZNetScene ZDO overload after direct ZDOID lookup fails, targeting the observed alpha failure where UDP motion arrived but no remote GameObject was found. Live clients remain unchanged until the paired mod release is published.

Recorded by Codex · associated with the Git commit containing this note
implementation Lumberjacks M1

Add bounded Companion-driven motion test control and honest counter classification

Impact: The local Companion can now deliver allow-listed movement patterns to a running client mod with JSONL receipts, while capture verdicts distinguish active motion readiness from counters that advance without an active motion lane.

Recorded by Codex · associated with the Git commit containing this note
decision Lumberjacks A2

Accept the background git automation (solo open-source sample)

Impact: Records Derek's decision to go forward with the repo automation that auto-commits Gateway work and force-pushes/rewrites main: baseline is a solo open-source working sample, so no collaborators are disrupted by a history rewrite. Checked off in DECISIONS-PENDING.md; memory updated to ACCEPTED. Decision record only.

Recorded by Codex · associated with the Git commit containing this note
verification Lumberjacks M1

Mark the runtime modpack as current in release history

Impact: The update page now highlights the verified runtime modpack row separately from the Gateway image release, so operators can distinguish the current downloadable package from the server image that serves the page.

Verification (1)
  • Live P7 m28 page marks m17-motionstate as current; runtime modpack manifest and first history row agree.
Evidence: image digest sha256:eafabacad2842267c09b0a74fd2b4f4a4abe89d9260befe33581045ae65a24dd
Recorded by Codex · associated with the Git commit containing this note
verification Lumberjacks M1

Verify runtime-driven release history

Impact: The m27 Gateway serves the current runtime modpack pointer as the first release-history row and retains prior static entries below it, preventing future client-pull releases from falling out of the public table.

Verification (1)
  • Live page reports Gateway m27, first history row m17-motionstate, and current manifest m17-motionstate.
Evidence: commit pending
Recorded by Codex · associated with the Git commit containing this note
implementation Lumberjacks M1

Make public release history follow the runtime modpack pointer

Impact: The update page now derives its first historical row from the verified runtime modpack manifest and appends the prior static alpha history, so future client-pull packages cannot silently be omitted from the release table. Gateway m27 is live on P7 with the frozen admitted mod identity unchanged.

Verification (1)
  • Gateway m27 passed the image gate and the full container suite; the live page reports m17-motionstate first and retains the prior release row.
Evidence: image digest sha256:4181681d014844e6476b4a96a05c029b11a93f702a546c40fc985f99bdb13f0c
Recorded by Codex · associated with the Git commit containing this note
deployment Lumberjacks M1

Promote release-history Gateway m26

Impact: P7 now serves Gateway m26-releasehistory-20260723-r1, which keeps the frozen m15 admitted mod identity and corrects the public pre-signin release table to include the current m17-motionstate package followed by the four prior releases. The live update page and runtime modpack manifest agree.

Verification (1)
  • Gateway telemetry reports m26; the public update page reports m26 and lists m17-motionstate first; current modpack manifest remains m17-motionstate.
Evidence: image digest sha256:4e2262f3a6aa108136239be14dd87b914abe90ff976aafc385ac6e9081e86745
Recorded by Codex · associated with the Git commit containing this note
verification Lumberjacks M1 · M7

Publish Companion r25 capture-truth contract

Impact: Companion r25 records observed motion states and final WebSocket/UDP readiness in per-run evidence, treats missing or stale Valheim heartbeat telemetry as incomplete, and exposes the same evidence in the OMEN/i5 two-client comparison. This is diagnostic evidence only; distinct-recipient fan-out and opt-in presentation remain gated.

Verification (1)
  • OMEN and i5 report companion-bootstrap-20260723-r25; a five-second two-client idle smoke produced zero bad samples on both machines.
Evidence: commits 8afe022 and 2fe26e9
Recorded by Codex · associated with the Git commit containing this note
documentation Lumberjacks A2

Session retro 2026-07-23 and pending-decisions register

Impact: Adds fieldlab/retro/SESSION-RETRO-2026-07-23.md (the offload-orchestration adoption session: M1 plus M2-1/M2-3 plus the A1-A6 track, and the discovery that the repo automation force-pushes and rewrites main) and DECISIONS-PENDING.md (open substrate-gap and next-step decisions). Documentation only.

Recorded by Codex · associated with the Git commit containing this note
deployment Lumberjacks M1

Promote motion-state dashboard Gateway

Impact: P7 now runs Gateway image m25-motiondash-20260723-r1, still admitting mod identity m15-hudrecover-20260723-r1. Public /community, OMEN Companion, and i5 Companion all include the motion_state/client-readiness text, while /api/v0/telemetry/valheim remains fresh with motion_state=idle and zero peers.

Recorded by Codex · associated with the Git commit containing this note
deployment Lumberjacks M1

Publish motion-state Companion bootstrap

Impact: P7 now serves companion-bootstrap-20260723-r24 with SHA-256 9b75174e711c579c6cc1edebb9292ebb51d91ec0166ba60db1f554a5d332b253. The bootstrap carries the Companion dashboard change that displays client motion_state and WebSocket/UDP readiness beside aggregate motion counters.

Recorded by Codex · associated with the Git commit containing this note
implementation Lumberjacks M1

Show motion client state in builder dashboards

Impact: Companion and the public community trace now include the Valheim heartbeat's motion_state plus WebSocket/UDP readiness beside aggregate ingress counters. A zero-frame window can now be read as idle, observing, or error instead of an ambiguous native-motion-only baseline.

Recorded by Codex · associated with the Git commit containing this note
documentation Lumberjacks A2

Add A1-A6 adoption milestone track to the volunteer roadmap

Impact: Adds an adoption track and milestones A1 Trust and Rhythm (complete) through A6 Projection to the living roadmap, so community/adoption commits journal under A1-A6 instead of being mislabeled as netcode M-milestones. A1 and A2 exit evidence record the shipped M1/M2 adoption docs. Roadmap data only; no runtime behavior change.

Recorded by Codex · associated with the Git commit containing this note
deployment Lumberjacks M1

Promote motion-state Gateway and current-head modpack

Impact: The earlier m16 package was superseded before testing because the server deploy rebuilt the DLL at current HEAD. P7 now runs Gateway image m24-motionstate-20260723-r1, still admitting mod identity m15-hudrecover-20260723-r1, and current.json points at m17-motionstate-20260723-r1 with package SHA-256 57d073b694dd660cc3a050d0772687553ba3cdb0978a62a4baa865167e7c022a. OMEN, i5, and the server all carry the matching current-head ComfyNetworkSense DLL hash, and /api/v0/telemetry/valheim now exposes motion_state plus UDP/WebSocket motion counters.

Recorded by Codex · associated with the Git commit containing this note
deployment Lumberjacks M1

Publish motion-state client-pull modpack

Impact: P7 current.json now points at m16-motionstate-20260723-r1, a config-preserving alpha modpack with SHA-256 a66c190c2f9dd2845ce87ed1bfeea58e65438d987b85b4bc32c76c909a216551. The package keeps the admitted mod identity m15-hudrecover-20260723-r1, so testers can pull the HUD/heartbeat motion-state diagnostics without requiring a Gateway image restart.

Recorded by Codex · associated with the Git commit containing this note
implementation Lumberjacks M1

Expose Lumberjacks motion lane state in alpha telemetry

Impact: The Valheim mod now reports observe-first motion state, UDP/WebSocket readiness, counters, and last error in its heartbeat, and the transport strip shows the same state in-game so two-client captures can distinguish idle, disconnected, observing, and failing motion lanes without changing native presentation.

Recorded by Codex · associated with the Git commit containing this note
deployment Lumberjacks M3

Publish burst-capture Companion bootstrap

Impact: Public Companion bootstrap r23 now carries the burst movement capture UI, adding a 30-second one-second-sample preset for sprint and stutter-step tests. OMEN and i5 were both restarted through the canonical Companion lanes and report r23 in redacted diagnostics; the public manifest verifies the r23 package hash.

Recorded by Codex · associated with the Git commit containing this note
implementation Lumberjacks M3

Explain read-only Companion mode

Impact: The Companion readiness banner now explicitly identifies the read-only dashboard state when Valheim is not visible, tells operators that updates require the Valheim folder mount, and names the i5 Start-I5Companion.ps1 lane. This addresses the i5/OMEN no-/valheim mount failure mode discovered through redacted diagnostics; public bootstrap r22 carries the guidance.

Recorded by Codex · associated with the Git commit containing this note
implementation Lumberjacks M3

Add redacted Companion diagnostics

Impact: The Companion now exposes a one-click redacted diagnostics JSON with local readiness, hashed enrollment identity, current public release pointers, live Gateway/Valheim/cutover/motion snapshots, and recent capture verdicts. OMEN and i5 were rebuilt and verified with no access-key/client-key fields; public bootstrap r21 carries the change.

Recorded by Codex · associated with the Git commit containing this note
deployment Lumberjacks M3

Show runtime modpack truth on latest-update page

Impact: The public /join/update page now shows a current downloadable mod pack box sourced from the runtime manifest before the historical release table, alongside the current Companion bootstrap. Gateway-only image m23-updatepage-20260723-r1 was cut and promoted to P7 while continuing to admit frozen mod release m15-hudrecover-20260723-r1; live telemetry and page HTML verify the deployment.

Recorded by Codex · associated with the Git commit containing this note
implementation Lumberjacks M3

Add Companion live transport readout

Impact: The Companion moving-parts panel now includes a compact live readout for peers, player names, Lumberjacks motion receive/relay counts, cutover mode, queue depth, and ack/apply counters, so alpha testers can see the active transport window without scanning tile prose or raw JSON. OMEN and i5 were rebuilt and verified; public bootstrap r20 carries the change.

Recorded by Codex · associated with the Git commit containing this note
implementation Lumberjacks M3

Add one-click Companion evidence bundles

Impact: Transport capture runs can now be downloaded as a single zip containing summary.json and samples.jsonl, and the Companion UI links that bundle from both the current capture result and recent capture history. OMEN and i5 were rebuilt and verified by downloading and inspecting bundle.zip; public bootstrap r19 carries the change.

Recorded by Codex · associated with the Git commit containing this note
implementation Lumberjacks M3

Add Companion transport capture presets

Impact: The Companion evidence panel now exposes 15 second smoke, 60 second movement, and 180 second session capture presets with explicit progress copy, so alpha testers can collect appropriately sized transport evidence without editing JSON or relying on a single hard-coded 60 second run. OMEN and i5 were rebuilt and smoke-captured; public bootstrap r18 carries the change.

Recorded by Codex · associated with the Git commit containing this note
implementation Lumberjacks M3

Add Companion capture interpretation

Impact: Transport capture summaries now include an explicit interpretation and next operator action for incomplete telemetry, Lumberjacks motion observed, native-only movement, and no-peer windows, so alpha testers can understand what their saved evidence proves without reading raw JSONL. OMEN and i5 were rebuilt and smoke-captured; public bootstrap r17 carries the change.

Recorded by Codex · associated with the Git commit containing this note
implementation Lumberjacks M3

Stamp release identity into Companion captures

Impact: Transport capture summaries now include Companion/bootstrap, Gateway, Valheim mod, server instance, cutover mode, and manifest identity, so a downloaded evidence bundle states which running stack produced the observation. OMEN and i5 were rebuilt and smoke-captured; public bootstrap r16 carries the change.

Recorded by Codex · associated with the Git commit containing this note
implementation Lumberjacks M3

Read nested Valheim heartbeat peers in Companion evidence

Impact: Companion live signals and transport captures now read peer count and server state from the actual nested Valheim heartbeat shape, so a two-client test will not incorrectly summarize an active peer window as zero peers. OMEN and i5 were rebuilt, and public bootstrap r15 carries the fix.

Recorded by Codex · associated with the Git commit containing this note
implementation Lumberjacks M3

Enrich Companion transport capture summaries

Impact: Transport captures now summarize observed player names and first/last/delta ranges for peer, motion, pending, active-consumer, acknowledged, and applied counters, so a tester's downloaded summary states what changed during the run without requiring manual JSONL inspection. OMEN and i5 were rebuilt and smoke-captured; public bootstrap r14 carries the update.

Recorded by Codex · associated with the Git commit containing this note
implementation Lumberjacks M3

Add Companion live signal stream

Impact: The local Companion dashboard now includes a compact rolling signal stream derived from public deployment, Valheim, cutover, and motion telemetry, so testers can see peer, player-name, queue, acknowledgement, applied, and Lumberjacks-motion counter changes without opening the operator-gated boundary page. OMEN and i5 were rebuilt, and public bootstrap r13 carries the stream.

Recorded by Codex · associated with the Git commit containing this note
implementation Lumberjacks M2

Show Companion bootstrap freshness locally

Impact: Companion now compares the local bootstrap release stamped by the packaged launcher with the public P7 bootstrap manifest, shows a direct download link when the local bundle is stale or unknown, and the r12 public bootstrap includes release metadata so future tester machines can prove which Companion bundle launched their dashboard.

Recorded by Codex · associated with the Git commit containing this note
implementation Lumberjacks M2

Point Companion bootstrap discovery at public P7 lane

Impact: The tracked latest-bootstrap manifest now advertises the public Gateway-hosted Companion bootstrap instead of private GitHub release assets, and the P7 bootstrap publisher rewrites that pointer after each public upload so tester links do not drift back to an authenticated channel.

Recorded by Codex · associated with the Git commit containing this note
deployment Lumberjacks M2

Serve Companion bootstrap from public P7 artifact lane

Impact: P7 now serves the credential-free Companion bootstrap through Gateway runtime endpoints backed by a mounted current.json pointer, so alpha testers can download the local dashboard bootstrap without GitHub auth while rapid Valheim mod/config updates remain on the authenticated client-pull lane.

Recorded by Codex · associated with the Git commit containing this note
implementation Lumberjacks M2

Add latest Companion bootstrap pointer

Impact: The Companion bootstrap publisher now maintains a tracked latest-bootstrap manifest with immutable GitHub release URLs and package SHA-256, giving operators and testers a stable way to discover the current Companion zip without relying on chat-pasted release links.

Recorded by Codex · associated with the Git commit containing this note
implementation Lumberjacks M2 · M3

Add capture verdict summaries

Impact: Companion and the PowerShell transport-truth fallback now stamp each capture summary with a verdict and final current-read, so downloaded evidence directly states whether a run saw Lumberjacks motion, native-only motion, incomplete telemetry, or no peer window.

Recorded by Codex · associated with the Git commit containing this note
implementation Lumberjacks M2 · M3

List recent Companion transport captures

Impact: Companion now lists recent local transport-truth captures with summary and sample download links, letting testers recover evidence after refresh without inspecting Docker volumes or running shell commands.

Recorded by Codex · associated with the Git commit containing this note
implementation Lumberjacks M2 · M3

Add one-button Companion transport capture

Impact: Companion can now capture a bounded transport-truth window from the browser, store summary and JSONL evidence in its data volume, and serve both files for download so alpha testers do not need a shell command to preserve movement/cutover evidence.

Recorded by Codex · associated with the Git commit containing this note
implementation Lumberjacks M3

Add transport-truth capture script

Impact: A bounded PowerShell capture now records Companion/Gateway deployment, Valheim peer, cutover, and motion counters into JSONL plus summary output so two-client movement tests can be preserved as evidence instead of screenshots.

Recorded by Codex · associated with the Git commit containing this note
implementation Lumberjacks M2 · M3

Add Companion current-read transport evidence

Impact: The local Companion now translates live Gateway, Valheim, cutover, and motion counters into a single operator-facing current read so alpha testers can tell whether movement is native Valheim or Lumberjacks motion without inspecting raw JSON.

Recorded by Codex · associated with the Git commit containing this note
implementation Lumberjacks M2 · M3

Expose motion counters in Companion moving-parts panel

Impact: OMEN and i5 Companion dashboards now surface /live/valheim-motion UDP/WebSocket receive and relay counters before a two-client movement test, making the Valheim-native versus Lumberjacks-motion boundary visible without operator API spelunking.

Recorded by Codex · associated with the Git commit containing this note
deployment Lumberjacks M2

Publish Companion bootstrap r2

Impact: New alpha testers can now download an immutable credential-free Companion bootstrap that includes the moving-parts status panel and /trace fallback behavior; the zip digest is recorded in a public-safe receipt.

Recorded by Codex · associated with the Git commit containing this note
implementation Lumberjacks M0 · M2

Add Companion moving-parts panel and version-pin repair

Impact: OMEN and i5 Companion dashboards now summarize the live client, modpack, Gateway, Valheim, and cutover state, and the P7 promotion lane updates LUMBERJACKS_VERSION so deployment telemetry matches the running image.

Recorded by Codex · associated with the Git commit containing this note
documentation Lumberjacks M1

Align data trust wording with event contract

Impact: The canonical data-and-trust doc and public page now describe gameplay identity as player id sent through the event actor_id field, reducing ambiguity before alpha testers opt in.

Recorded by Codex · associated with the Git commit containing this note
implementation Lumberjacks M1

Add public data and trust page

Impact: Alpha testers now have a linked public page that states what telemetry captures, what is never captured, where records live, who can see them, and how to opt out before installing the modpack.

Recorded by Codex · associated with the Git commit containing this note
implementation Lumberjacks M2

Add Companion trace URL alias

Impact: The local Companion now exposes /trace as the obvious builder URL for the private boundary diagnostics page, while preserving /ops/boundary for direct operator use.

Recorded by Codex · associated with the Git commit containing this note
implementation Lumberjacks M0

Add P7 Gateway image promotion lane

Impact: Gateway-only alpha updates can now promote a locally verified Docker image to P7 by archive hash and durable image pin, without copying source to the VM or rebuilding there.

Recorded by Codex · associated with the Git commit containing this note
implementation Lumberjacks M3

Refocused boundary diagnostics on the live append-only evidence stream.

Impact: The operator page now foregrounds recent normalized events and compact health signals, while open-segment tails are labeled separately from malformed records.

Recorded by Codex · associated with the Git commit containing this note
deployment Lumberjacks M2

Published the first immutable Companion bootstrap release.

Impact: The private alpha release channel now carries a generic Docker launcher and matching SHA-256 manifest, separate from Gateway image promotion and rapid mod/config packages.

Recorded by Codex · associated with the Git commit containing this note
implementation Lumberjacks M2

Handle missing GitHub releases during Companion publish preflight.

Impact: The immutable bootstrap publisher now treats an absent release as the expected creation path on Windows PowerShell instead of failing before upload.

Recorded by Codex · associated with the Git commit containing this note
implementation Lumberjacks M2

Added immutable GitHub publishing for the Companion bootstrap bundle.

Impact: The credential-free Docker bootstrap zip and its SHA-256 manifest can be released together without a Gateway image rollout; rapid mod/config releases remain on the client-pull lane.

Recorded by Codex · associated with the Git commit containing this note
implementation Lumberjacks M2

Hardened Companion bootstrap discovery and surfaced local updater version.

Impact: The generic Docker launcher now supports configured Steam libraries and an explicit Valheim path; the local page distinguishes its own updater version from the checked mod release.

Recorded by Codex · associated with the Git commit containing this note
implementation Lumberjacks M1

Added a generic Windows Docker Companion bootstrap bundle.

Impact: An already-enrolled tester can extract a loopback Companion bundle that finds Valheim, starts Docker Desktop, preserves local configuration, and opens the dashboard without copying a credential.

Recorded by Codex · associated with the Git commit containing this note
documentation Lumberjacks M1

Documented i5 Companion logon recovery

Impact: The i5 deploy lane now records the Docker Desktop logon launcher and loopback Companion recovery check, keeping Valheim startup and player configuration outside the task.

Recorded by Codex · associated with the Git commit containing this note
implementation Lumberjacks M1

Companion enforces game-closed confirmation for writes

Impact: Install and rollback now reject requests without explicit confirmation, so the compact Docker-safe checkbox is a real write boundary rather than a visual hint.

Recorded by Codex · associated with the Git commit containing this note
implementation Lumberjacks M1

Companion uses compact readiness checkboxes

Impact: Docker-backed local updates require an explicit game-closed confirmation before install, avoiding a false host-process signal while preserving immediate release feedback.

Recorded by Codex · associated with the Git commit containing this note
implementation Lumberjacks M1

Accept package metadata during Companion installs

Impact: The first real Companion install on OMEN verified the authenticated m15 package and preserved the local config, but exposed a root README.txt beside the Valheim payload. Companion now ignores non-payload package metadata while continuing to write only validated Valheim-relative entries. The live proof updated 31 files, retained a rollback backup, and left the config hash unchanged.

Recorded by Codex · associated with the Git commit containing this note
implementation Lumberjacks M1

Make the Companion updater workflow explicit

Impact: The local Companion page now presents the actual alpha sequence as visible readiness checks and gated actions: find Valheim, find config, confirm profile, stop the game, check the release, then install or roll back. Raw JSON moved into collapsed diagnostics so the primary page explains what to do next.

Recorded by Codex · associated with the Git commit containing this note
deployment Lumberjacks M1

Replace OMEN loopback dashboard with the Companion

Impact: OMEN now serves the Dockerized Companion on 127.0.0.1:8080 in place of the nginx-only dashboard. It reaches P7 through the authenticated host tunnel, preserving community, runtime manifest, and private boundary-trace views on one local origin; i5 remains pending because it is offline on the tailnet.

Recorded by Codex · associated with the Git commit containing this note
deployment Lumberjacks M1

Deploy Companion client-pull Gateway and publish the first runtime pointer

Impact: P7 now runs Gateway m18-companion-20260723-r1 while admitting the existing m15 mod. The current.json pointer was atomically published after Gateway start and the public manifest changed to the hash-verified package without recreating Gateway, establishing the no-restart mod/config release lane. The publisher now uses PowerShell 5.1-compatible no-BOM output and a sudo base64 remote script so remote failures cannot be reported as success.

Recorded by Codex · associated with the Git commit containing this note
implementation Lumberjacks M1

Add local Companion and client-pull modpack release pointer

Impact: A loopback-only ASP.NET Core Companion now preserves the :8080 dashboard while checking, hash-verifying, installing, and backing up authenticated mod packages from a Gateway runtime current.json pointer. Mod/config publication can change the mounted artifact without a Gateway image rollout or restart; first-install Steam enrollment remains browser based.

Recorded by Codex · associated with the Git commit containing this note
deployment Lumberjacks M2

Version post-Steam update download filenames

Impact: The Steam update callback now sends no-store cache headers and names the returned zip with the live Gateway release, admitted mod release, package hash prefix, and enrollment prefix so testers can tell whether the downloaded package is current. P7 runs Gateway release m17-updatefilename-20260723-r1 while continuing to admit the frozen m15-hudrecover mod.

Verification (1)
  • Gateway image build passed 123 contract, 250 simulation, and 194 Gateway tests; P7 public manifest reports m17-updatefilename-20260723-r1 with mod_release m15-hudrecover-20260723-r1; public /join/update returns Cache-Control: no-store and shows m17 as the current release row.
Evidence: docs/roadmap/m17-updatefilename-gateway-release.json src/Game.Gateway/Valheim/SteamEnrollmentEndpoints.cs src/Game.Gateway/Valheim/EnrollmentPages.cs
Recorded by Codex · associated with the Git commit containing this note
deployment Lumberjacks M2

Show recent releases on the update page

Impact: The pre-signin /join/update page now displays the current Gateway release plus the last four alpha releases, with UTC timestamps, mod versions, and short reasons. The route also sends no-store cache headers so operators can distinguish stale browser/proxy HTML from a stale downloaded zip.

Verification (1)
  • Gateway-only cut m16-updatehistory-20260723-r1 admits frozen mod m15-hudrecover-20260723-r1; Docker build passed 123 contract, 250 simulation, and 194 gateway tests; public /join/update returned 200 with Cache-Control: no-store, max-age=0 and showed m16 as the current release; public manifest reported release m16-updatehistory-20260723-r1 and mod_release m15-hudrecover-20260723-r1.
Evidence: docs/roadmap/m16-updatehistory-gateway-release.json src/Game.Gateway/Valheim/EnrollmentPages.cs
Recorded by Codex · associated with the Git commit containing this note
deployment Lumberjacks M1

Deploy transport strip recovery release to P7

Impact: ComfyNetworkSense 0.5.35 / m15-hudrecover keeps the NET SHOW recovery tab visible even when an older local config disabled the transport strip, then re-enables the strip when clicked. P7 now runs the matching Gateway admission image and serves a config-preserving Steam update package for this recovery build.

Verification (1)
  • New-ReleaseCut.ps1 confirmed the mod DLL and Gateway image both carry m15-hudrecover-20260723-r1; the P7 Valheim server reported ready on DLL sha256:9a8ea06923d711f97f275506cbf14969ee06dc81376e97ad97493f53b32d26d2; the public modpack manifest reported release/admitted-mod m15-hudrecover-20260723-r1 and package sha256:c847ae5787b1a6b8b3f67072509c1422fbf43a79d1219f93628ba98fea462b76.
Evidence: docs/roadmap/m15-hudrecover-server-mod-deploy.json fieldlab/docs/runbook-transport-truth-strip.md
Recorded by Codex · associated with the Git commit containing this note
deployment Lumberjacks M1

Deploy collapsible transport strip release to P7

Impact: ComfyNetworkSense 0.5.34 / m14-hudtoggle starts the alpha transport strip collapsed with a side NET SHOW/HIDE tab so low-resolution testers can reach Valheim menu buttons. P7 now runs the matching Gateway admission image and serves a config-preserving update package through the Steam update page.

Verification (1)
  • New-ReleaseCut.ps1 confirmed the mod DLL and Gateway image both carry m14-hudtoggle-20260723-r1; the P7 Valheim server reported ready on DLL sha256:a357cbd4feb1a889c82b05205e73d5309bb63dfad78a868e325f5c3bfa74ad39; the public modpack manifest reported release/admitted-mod m14-hudtoggle-20260723-r1 and package sha256:a1597bc98cd454ddc2f10bfa6767ce1c0d2af8f36bb8c14f88c5fad28ab06d74.
Evidence: docs/roadmap/m14-hudtoggle-server-mod-deploy.json fieldlab/docs/runbook-transport-truth-strip.md
Recorded by Codex · associated with the Git commit containing this note
deployment Lumberjacks M2

Deployed the Steam-bound portal update Gateway image to P7.

Impact: P7 now serves the latest modpack manifest and Steam-authenticated update download from m13-portal while continuing to admit the frozen m12-motion client mod.

Verification (1)
  • P7 health returned ok, the running Gateway image matched sha256:9a64656971151987af409676921fc8b476a852dbfea0f8b24e784e338dff3fd4, /join/update returned 200, and /api/v0/valheim/modpack/manifest reported release m13-portal-20260723-r1.
Evidence: docs/roadmap/m13-portal-gateway-release.json infra/gcp/p7/docker-compose.yml
Recorded by Codex · associated with the Git commit containing this note
implementation Lumberjacks M2

Added Steam-bound latest mod update downloads that preserve installed client config.

Impact: Alpha testers can pull current mod files through the portal without operator-mediated machine copies or ordinary credential rotation; first install and admin recovery remain separate paths.

Verification (1)
  • Gateway test project passed in the .NET 9 SDK container after adding config-preserving pack and enrollment lookup coverage.
Evidence: src/Game.Gateway/Valheim/SteamEnrollmentEndpoints.cs src/Game.Gateway/Valheim/ModPackBuilder.cs infra/gcp/p7/VOLUNTEER-ENDPOINT.md
Recorded by Codex · associated with the Git commit containing this note
deployment Lumberjacks M1

Pin the committed WebSocket motion Gateway on P7

Impact: Rebuilt m12-motionauthws-20260722-r1 from committed source 002b12c, verified 565 passing tests and the baked m12-motion-20260722-r1 admission identity, promoted exact image c361c8fc, and repeated the public enrolled TLS-to-UDP ingress canary successfully with zero invalid, unauthorized, or stale drops.

Recorded by Codex · associated with the Git commit containing this note
implementation Lumberjacks M1

Resolve enrolled identity before WebSocket motion sessions

Impact: Moved ASP.NET WebSocket feature setup ahead of the Valheim access gate, added a regression test, cut and deployed a Gateway-only image that still admits frozen mod m12-motion-20260722-r1, and proved public TLS plus token-bound UDP ingress with zero format, authorization, or stale drops. Distinct-recipient relay remains the two-account canary gate.

Recorded by Codex · associated with the Git commit containing this note
implementation Lumberjacks M1 · M7

Preserve enrollment identity through TLS proxy

Impact: A valid enrollment now takes precedence over Caddy's private socket peer, so the enrolled WebSocket retains its opaque recipient and can arm the m12 motion lane over TLS; promotion drills can also resume hash-checked preuploaded or already-loaded artifacts after Windows/IAP SCP failures.

Verification (1)
  • Container verification passed 564 tests, including private-proxy enrollment precedence.
Evidence: infra/gcp/p7/PROMOTION-DRILL.md
Recorded by Codex · associated with the Git commit containing this note
implementation Lumberjacks M7

Build authenticated Lumberjacks player-motion lane

Impact: The m12 candidate carries real observed Valheim player transforms over session-token UDP with serialized binary WebSocket fallback, an observe-first client and explicit apply switch, motion counters in the community trace, and a documented two-player canary; native Valheim remains the rollback path and FULL NETCODE remains NO.

Verification (1)
  • 75 mod tests and 563 containerized .NET tests pass; independent mod and Gateway codecs match the same exact 50-byte fixture; Terraform and Compose validate.
Evidence: infra/gcp/p7/VALHEIM-MOTION-CANARY.md
Recorded by Codex · associated with the Git commit containing this note
deployment Lumberjacks M7

Promoted the transport-boundary release to P7

Impact: P7 and OMEN now carry the exact 0.5.32 artifact; the dashboard reports the native-versus-Lumberjacks boundary, the full artifact rollback drill passed, and durable image pins were verified. The i5 artifact is staged but not installed.

Verification (1)
  • Validated release bundle; cold-start, rollback, restore and image/hash checks passed; P7 heartbeat reports 0.5.32 ready.
Evidence: docs/roadmap/m11-transport-build-candidate-v3.json
Recorded by Codex · associated with the Git commit containing this note
implementation Lumberjacks M7

Expose the live Valheim/Lumberjacks transport boundary

Impact: The in-game truth strip and community dashboard now distinguish native Valheim peer and receive semantics from Lumberjacks ZDO delivery, show unused WebSocket/UDP lanes, and record deliberate HTTP/MCP fault switches; the container release gate also excludes host test artifacts and preserves UTF-8 during release cuts.

Recorded by Codex · associated with the Git commit containing this note
deployment Lumberjacks M3

Show Valheim player names on the community dashboard

Impact: The public community Valheim card now uses accepted post-restart handshake history to show sanitized character display names beside the peer count, making live alpha sessions easier to understand without exposing Steam IDs, host names, UIDs, credentials, or positions.

Verification (1)
  • Docker Gateway release cut passed 559 tests; P7 runs m10-playernames-20260722-r1 as sha256:004bebddc5c74924c36942684f5b184bd510dd6aba9aa9bec73dd544eb8ab46d while admitting frozen mod m5-recipients-20260720-r1; OMEN /community serves the player-name aware script.
Evidence: src/Game.Gateway/Valheim/ValheimHandshakeService.cs src/Game.Gateway/Valheim/ValheimTelemetryHeartbeatService.cs src/Game.Gateway/Community/community.html docs/dashboard/viewing-the-surfaces.md
Recorded by Codex · associated with the Git commit containing this note
deployment Lumberjacks M3

Compact community dashboard with live trace rail

Impact: The public community page now hides idle baseline panels and promotes deployment, Valheim, cutover, tick health, and a single live trace rail so builder alpha testers see moving system signals instead of a screen full of empty cards.

Verification (1)
  • Docker Gateway release cut passed 557 tests; P7 runs m9-communitytrace-20260722-r1 as sha256:20bd957b44813dbdd457cdea489ffccc0eb4566807e969d1d70708e10fca8661 while admitting frozen mod m5-recipients-20260720-r1; OMEN /community serves the compact trace view through the operator tunnel.
Evidence: src/Game.Gateway/Community/community.html docs/dashboard/viewing-the-surfaces.md
Recorded by Codex · associated with the Git commit containing this note
deployment Lumberjacks M2 · M3

Deploy rough ZDO movement dashboard and alpha zip surface

Impact: Gateway now emits append-only ZDO poll, acknowledgement, and consumer-heartbeat boundary events alongside queued batches, and the operator boundary dashboard renders queued, polled, acknowledged, applied, per-stage duration, window, recipient, and recent-row views for builder alpha testing. The Steam-bound personal mod-pack download path remains the preferred no-paste installer flow and is documented with the dashboard surfaces. The durable alpha seat override now has an explicit named mode, LUMBERJACKS_ALPHA_SEAT_GATE=disabled, so operators do not confuse it with Valheim's native max-player count; the old numeric variable remains only for rollback compatibility.

Verification (3)
  • Docker verify passed: 557 tests across contracts, simulation, and gateway suites.
  • P7 runs Gateway image sha256:b3b351e13a56039e314dd17458d1ce301a82bb81cd215659041a8b0bb463dd4c as m8-zdostreamdash-20260722-r3 while admitting frozen mod release m5-recipients-20260720-r1 and preserving the disabled alpha seat gate.
  • OMEN /ops/boundary serves the new ZDO panels; public TLS /ops/boundary still returns 403.
Evidence: src/Game.Gateway/BoundaryEvents/BoundaryEventDiagnostics.cs src/Game.Gateway/Valheim/ValheimZdoRedirectEndpoints.cs src/Game.Gateway/Community/boundary.html docs/dashboard/viewing-the-surfaces.md infra/gcp/p7/docker-compose.yml
Recorded by Codex · associated with the Git commit containing this note
deployment Lumberjacks M1 · M3

Deploy operator boundary diagnostics dashboard

Impact: P7 now serves an operator-only /ops/boundary dashboard and /ops/boundary/summary API over the trusted tunnel, summarizing append-only identity, authorization, request, and ZDO queue boundary events without exposing the surface through public forwarded clients.

Verification (3)
  • Docker verify target built the full solution and ran 553 .NET 9 tests successfully.
  • Gateway-only image m7-boundarydash-20260722-r1 admits frozen mod release m5-recipients-20260720-r1 and is live on P7 as sha256:42c7df07e84f746d98d2821307df0cdeb05eed7aaa2e496985eaf7bc485cdfb9.
  • P7 /ops/boundary/summary over loopback returned boundary rows with zero writer drops/faults; simulated public X-Forwarded-For was refused with 403; OMEN proxy returned 200 for /ops/boundary.
Evidence: src/Game.Gateway/BoundaryEvents/BoundaryEventDiagnostics.cs src/Game.Gateway/Community/boundary.html tools/omen-dashboard/nginx.conf
Recorded by Codex · associated with the Git commit containing this note
deployment Lumberjacks M1

Make P7 alpha seat override durable across Gateway restarts

Impact: Gateway image m6-seatcapacity-20260722-r1 is live on P7 and applies VALHEIM_HANDSHAKE_SEAT_CAPACITY=0 at startup for p7-primary-v1, so two-player alpha testing no longer depends on an in-memory /handshake/config POST after every restart.

Verification (3)
  • Docker verify target built the full solution and ran 551 .NET 9 tests successfully.
  • The shipped Gateway image admits frozen mod release m5-recipients-20260720-r1 and P7 reports image sha256:fe9f7e8652ab3858f8d767c7ca98888ea33f9b67f6414201ba56de5964447d8f.
  • After Gateway recreate plus restart, /valheim/handshake/status/p7-primary-v1 returned seat_capacity 0 over the public TLS endpoint.
Evidence: src/Game.Gateway/Valheim/ValheimHandshakeStartup.cs infra/gcp/p7/docker-compose.yml fieldlab/docs/runbook-copresence-fanout-live-test.md
Recorded by Codex · associated with the Git commit containing this note
deployment Lumberjacks M1

Deploy admin rescue Gateway and refresh P7 mod-pack template

Impact: P7 now runs Gateway image m1-rescue-20260722-r1, still admitting the frozen m5-recipients-20260720-r1 mod release, with the admin rescue pack endpoint live. The P7 mod-pack template was refreshed to carry the current ComfyNetworkSense.dll hash used on OMEN, then a tester-specific rescue zip was issued without exposing bootstrap or client credentials in chat.

Recorded by Codex · associated with the Git commit containing this note
implementation Lumberjacks M1

Add admin rescue mod-pack download

Impact: Adds an admin-gated POST /api/v0/enrollment/pack operator path for known alpha testers whose Steam callback or stale install blocks setup. The endpoint selects an active enrollment by SteamID or enrollment ID, rotates the client credential, invalidates any pending bootstrap for that enrollment, and streams the same personalized drop-in zip as the public join flow so recovery no longer requires Discord key relay or manual config editing.

Recorded by Codex · associated with the Git commit containing this note
implementation Lumberjacks M4b

Add player-motion fast lane and measured send-cadence lever

Impact: The two-client alpha finding is now represented as code rather than speculation: player-character ZDOs can bypass static-world band shaping, and an off-by-default send-cadence override reports whether the loaded Valheim assembly exposes the helper seam before any A/B test uses it. Portal caching was left as the existing local implementation instead of duplicated.

Verification (2)
  • ComfyNetworkSense.Tests passed 71 tests.
  • ComfyNetworkSense Release build completed with zero warnings and zero errors.
Evidence: network/mod/ComfyNetworkSense/Core/Services/ZdoRedirectRunner.cs network/mod/ComfyNetworkSense/Core/Services/ZdoSendCadenceOverride.cs fieldlab/docs/runbook-alpha-player-motion-fast-lane.md
Recorded by Codex · associated with the Git commit containing this note
deployment Lumberjacks M1 · M3

Promote boundary-event Gateway to P7 and reproduce the Caddy authority boundary

Impact: Gateway-only release m3-boundary-20260722-r1 is live on P7, admits the frozen m5-recipients-20260720-r1 mod, writes durable boundary-event JSONL segments, and captures direct-public deny versus Caddy/TLS private-plane allow for the admin enrollment route as a stop-ship before widening.

Verification (3)
  • Docker image verifier read the shipped Gateway image and confirmed admitted mod release m5-recipients-20260720-r1; P7 health reports ok and the durable env pin names lumberjacks-gateway:m3-boundary-20260722-r1.
  • Boundary-event analyzer checked a complete-row P7 snapshot: 3586 rows, zero malformed, zero truncated, and all four event families present including zdo.batch.queued.
  • Direct public /api/v0/enrollment returned 401 while the same route through Caddy/TLS returned 200, reproducing proxy private-plane capability inheritance without exposing credentials.
Evidence: docs/build-release-runbook.md docs/roadmap/valheim-volunteer-roadmap.json
Recorded by Codex · associated with the Git commit containing this note
documentation Lumberjacks M3

Added scripts/build.ps1 and the containerized build-release runbook so Verify, GatewayImage, and AllImages use the same Dockerfile targets.

Impact: Operators have one repeatable PowerShell entry point and a checked-in procedure for the SDK 9 build, test, release identity, and image promotion boundaries.

Recorded by Codex · associated with the Git commit containing this note
implementation Lumberjacks M3

Unified the .NET build and release path around Lumberjacks/Dockerfile: solution restore, compilation, and tests now run in the SDK 9 verify stage inherited by shipping images; removed the redundant advisory Gateway SDK-container build and added the build/release runbook.

Impact: Host SDK version no longer determines release verification, the shipping image cannot bypass the solution test lane, and operators have one documented container path while the net48 mod build remains intentionally separate.

Recorded by Codex · associated with the Git commit containing this note
implementation Lumberjacks M3

Added the reduced boundary-event stream: four versioned JSONL events, bounded rotating writer, access observations, ZDO batch timing, and a basic check/summarize analyzer; P7 compose now has an opt-in durable volume.

Impact: Alpha operators can inspect identity/auth/completion and one queue boundary without changing authorization behavior; heavier tracing, integrity manifests, and identity-model refactoring remain deferred.

Recorded by Codex · associated with the Git commit containing this note
planning Lumberjacks M1 · M3

Reduced the first boundary-event slice to four events and simple rotation

Impact: The first implementation now persists only identity.resolved, authorization.decided, zdo.batch.queued, and request.completed. Request entry remains in memory; segments rotate by flush, close, and atomic rename; and the initial parser performs validation plus basic counts. Compression, sidecar manifests, hashing, trace reconstruction, schema-drift analysis, percentiles, derived databases, cross-service instrumentation, and principal-model refactoring remain deferred until real event history justifies them.

Verification (1)
  • Roadmap source validates and generated HTML is current.
Evidence: Lumberjacks/docs/roadmap/valheim-volunteer-roadmap.json
Recorded by Codex · associated with the Git commit containing this note
planning Lumberjacks M1 · M3

Recorded trusted-alpha boundary hardening and append-only contract history

Impact: The self-service flow is a material improvement over manual secret exchange while remaining an intentionally provisional alpha boundary. M1 now requires trusted-proxy-aware authorization and explicit operator/workload authority before access widens. M3 now names a smaller intermediate step before any unified identity platform: a schema-versioned append-only event stream for boundary decisions and one reconstructable request lifecycle, with rotated source segments and derived analyses. Protocol emulators, observer services, and formal attestation remain deferred until product contracts settle.

Verification (1)
  • Roadmap source validates and generated HTML is current.
Evidence: Lumberjacks/docs/roadmap/valheim-volunteer-roadmap.json
Recorded by Codex · associated with the Git commit containing this note
deployment baseline M0

Shipped distance-band AoI band-shaping to production P7 and armed it as normal play

Impact: Distance-band area-of-interest now runs mod-side on the ZDO redirect producer (ADR 0011): per observing peer, near (<30m) redirects every pass, mid (30-64m) is thinned to 5Hz, far (>64m) is dropped, and landmarks are delivered by granted reach. Validated live at the densest single-player build (auto-ported in via a rebuilt server-driven harness): ~85% of redirect candidates dropped, ~13% thinned, ~3% full-rate, 46,900 applied and acknowledged with zero superseded/rejected/native/pending and no duplicate storm. The measurement that justified it falsified the recovered 9,600-row pressure model (tick cost scales with player count, which the model omitted) and showed send-volume, not the AoI filter, is the tick ceiling. Load-bearing invariant: suppress, ack, and emit are three separate operations - a dropped far object is still acked to Valheim (skipping it causes a duplicate storm) but not emitted, and suppressed-not-emitted ZDOs must not touch the delivery-gate counters. Behind zdoBandShapingEnabled (default false) for instant rollback. Unvalidated: far-to-approach re-sync of a dropped static object, and multi-player density.

Verification (1)
  • P7 window p7-primary-v1: consumer applied 46900 = acknowledged 46900, superseded/rejected/native/pending/duplicates all 0; band-decision jsonl Drop:EmitThinned:EmitFull ~= 85:13:3; mod builds net48 0 warnings; ZdoBandPolicy unit tests green
Evidence: fieldlab/evidence/aoi-band-shaping-p7-baseline-20260721/README.md fieldlab/docs/adr/0011-aoi-lives-on-the-producer.md
Recorded by Claude · associated with the Git commit containing this note
documentation baseline M0

Rewrote the handoff as an ordered ten-task queue with why and how-to-test on each

Impact: The first handoff was a status page; this one is a work queue. Ten tasks, each stating what to do, why it matters and how you will know it worked, every one traceable to something found on 2026-07-21 rather than speculated. Ordered with sequencing made explicit: re-provision the local gateway off the retired repo and resolve the dev-build split-brain first because both are traps that cost time before they cost anything else; then the AoI line, which must run in order - add band-population counters, run the knee sweep, then add hysteresis and re-measure, because damping before measuring destroys the baseline and instrumenting after measuring means running the experiment twice; then the two-client isolation gate, which is the program's own stated next correctness gate and needs a human in the seat; then landmark reach as the payoff; then three tail-hygiene items. Each test section is concrete enough to execute - exact docker inspect format strings for the gateway, the specific assertion in ValheimZdoIntegrationContractTests that must change deliberately for the split-brain, the two curves plus the correlation check for the knee, and unit-testable oscillation cases for hysteresis. Retains the do-not-re-execute warning about the withdrawn config-surface recommendations, since that file still carries its original D2/D3 reasoning below the revision banner and a future session could reasonably act on it and delete the far-field proxy prototype.

Verification (1)
  • All nine relative links resolve; all six code citations checked against the working tree and land on the intended lines, including ValheimHandshakeService.cs:546, ValheimZdoRedirectAdmissionPolicy.cs:30, ZdoRedirectRunner.cs:337 and both InterestManager band comparisons; ten task headings present; no mojibake
Evidence: HANDOFF.md
Recorded by Codex · associated with the Git commit containing this note
documentation baseline M0

Wrote the session handoff; corrected the push state I had been misreporting

Impact: HANDOFF.md at repo root, deliberately short and linking out rather than restating. It leads with the three things that bite: the live comfy-gateway runs from the retired C:/work/comfy checkout so edits here do not reach the running 8720 surface, fieldlab/autonomous must not be deleted because it is that gateway's live definition plus a running Valheim server, and the P7 VM is still billing by decision. Then the four open register items with the gateway re-provision at the top, two ready-to-start paths, the design decisions that must be read before touching AoI, and an explicit do-not-re-execute pointing at the withdrawn config-surface recommendations. Also corrects a standing claim: I told Derek repeatedly through the session that the work was local and unpushed, which was true when said and stopped being true when the background flake-fix session pushed main - the reflog shows f945562 update by push, carrying 17 of the day's commits with it. Only the last two remain local. Nothing was damaged, but the state I had been asserting was stale and saying so is cheaper than letting him find it.

Verification (1)
  • All nine relative links in HANDOFF.md resolve; key count confirmed at 73; origin/main tip confirmed f945562 with 2 local commits ahead; the flake fix commit d5bed21 is present in history
Evidence: HANDOFF.md
Recorded by Codex · associated with the Git commit containing this note
documentation baseline M0

ADR 0010: consistency means predictable, not invariant

Impact: Derek's design principle, and a correction to how I first recorded it. He said consistent fidelity - even ugly or choppy - preserves immersion so long as it is consistent. I read that as hold everything constant and drafted a decision condemning adaptive degrade for changing behaviour under load. He corrected it: adaptive design is still consistent, it is predictive falloff. That distinction is the whole decision. Adaptive degradation is a deterministic function of an observable condition, so when it gets crowded it thins out is a rule a player learns immediately and then predicts correctly - the world having physics, not a break in immersion. It also beats holding full fidelity until collapse, because the collapse is the discontinuity. So the protected property is predictability rather than sameness. The mechanism is endorsed; what is defective is the missing damping at the threshold, since AdaptiveDegrade lifts the instant a broadcast fits again with no cooldown and no hysteresis, meaning at exactly budget it can answer differently tick to tick from a cause no player can perceive. That is indistinguishable from randomness at the player's end. The spatial boundary has the identical flaw with plain <= comparisons in InterestManager, so an entity at exactly 100.0 units flips bands every tick. Hysteresis is therefore reclassified as a fidelity requirement rather than a performance optimisation. The knee measurement is refined again: spread is only a defect when uncorrelated, so p99 divergence must be recorded against the density axis rather than as a scalar, because variance that tracks load is the system telling the truth while variance with no visible cause is the immersion killer. Also sets the tuning procedure - find the knee, back off to what holds under the worst band, run that everywhere - and accepts that this will lose throughput benchmarks on purpose.

Verification (1)
  • AdaptiveDegrade.cs:22-23 confirmed to state no cooldown and no hysteresis; its default is false; InterestManager.cs:113 and :118 confirmed to use plain <= against nearRadiusSq and midRadiusSq with no dead-band
Evidence: fieldlab/docs/adr/0010-consistency-is-predictability.md Lumberjacks/docs/network/aoi-knee-experiment-brief.md
Recorded by Codex · associated with the Git commit containing this note
documentation baseline M0

Redefined the AoI knee by variance onset rather than failure onset

Impact: Derek's framing correction: being both the trained perceiver and the builder is the ideal position for someone with extreme standards for consistent fidelity, not an odd one. The instrument was never meant to find the problem - he already knows where it is by feel - but to make what he perceives transmissible to a budget, a regression test, and a machine deciding what to drop under load. That reframes the target, and the brief had it wrong. Consistent fidelity is not a softer performance goal, it is a different one, and the knee should be defined by where p99 pulls away from p50 rather than by the first budget breach. A frame that is merely late sometimes feels worse than one uniformly slower, and by the time game.tick.overruns fires the experience has already degraded. The brief now asks for two curves from the same /tick read - variance onset as the knee that matters and failure onset as the hard ceiling - and predicts the first arrives meaningfully before the second, noting that if it does not, that is itself a finding. The supporting argument is that the telemetry schema Derek specified is already variance-oriented throughout: jitter beside rtt, p95 frame time beside average fps, correction count and magnitude, time since last authoritative update, and TickMetrics keeping p50/p99/max per phase rather than a mean. Measuring this system by averages would contradict what it was instrumented to care about.

Verification (1)
  • TickMetrics already keeps p50/p99/max per phase over a rolling ~100-tick window, so both curves come from the same endpoint read at no extra instrumentation cost
Evidence: Lumberjacks/docs/network/aoi-knee-experiment-brief.md
Recorded by Codex · associated with the Git commit containing this note
documentation baseline M0

Drew the sixteen twists of the audit and its follow-through

Impact: A companion poster to the conditional-logic audit SVG, recording the process rather than the findings. Sixteen times during the audit and its follow-through a confident claim reversed on inspection, and the poster lists each in order with who caught it: Derek three, a gemini-pro thread four, me six, a tool three. The shape is the point. Not one was careless - each was a correct inference from a boundary drawn too small, whether one repo, one file, one packed context or one thread's view. Gitignored var dir implied gone; InterestManager emits nothing implied the campaign would be blind; audit output describes files so it implied D3 was independent of D4. All locally valid, all wrong. The last three are near-misses that would have broken something running: deleting fieldlab/autonomous, which defines two containers live at the time; cutting a method from a comment that had drifted above the production redirect arming; and treating the matrix retirement as a gateway bounce when the live gateway runs from the retired repo. Each was caught by a check costing seconds - docker ps, an assertion before a delete, a git grep after one. Recorded because the audit's value was not the findings but the refusal to trust them.

Verification (1)
  • SVG parses as XML, all sixteen numbered nodes present and sequential, no coordinates outside the 1440x1810 canvas, no mojibake
Evidence: fieldlab/docs/audit-2026-07-21-the-twists.svg
Recorded by Codex · associated with the Git commit containing this note
implementation baseline M0

Retired the matrix MCP surface and removed the P3/P5 lab experiments; 88 config keys down to 73

Impact: Matrix retirement, source side: deleted matrix.py, removed the four /valheim/matrix custom HTTP routes from the gateway kernel that lazily imported it, and cleaned three providers lists including the argparse default in gateway.py. Both surviving providers still import cleanly. But the running gateway is untouched, and why is the finding: docker inspect reports the live comfy-valheim-lab-comfy-gateway-1 was launched from C:/work/comfy/fieldlab/autonomous/valheim-lab.compose.yml with COMFY_ROOT=C:/work/comfy and an image built 2026-07-15 from that repo's network/mcp. Baseline's copy of that compose is a faithful clone that has never driven anything. This is the same failure the P7 cutover fixed, for a local service - source edits in baseline do not reach the running gateway. Registered as its own decision because it is a re-provision rather than a bounce and the state root holds a live Valheim world. D3 plus D4 executed together on Derek's instruction: 15 keys, ZdoInjectionRunner, OwnershipObserveRunner, OwnershipPinRunner, and TryDriveNetcodeProbeAuto - the lab-window coupling that armed all of them from one place. Two near-misses, both caught by asserting before deleting. TryEnsurePrimaryRedirect, the PRODUCTION redirect arming, sits inside the line range a stale comment implied belonged to the probe auto-start; the comment had drifted above the wrong method, so cutting from it would have deleted the live serving path's arming. And NetcodeProbeMaxDetailRows, kept on the original reasoning, turned out to matter more than that reasoning knew - TryEnsurePrimaryRedirect reads it as the detail-row cap for the live redirect runner. The gateway-side injection surface was left in place because ValheimZdoInjectionService is referenced by ValheimHandshakeService. The mod's heartbeat no longer emits injection_applied, _rendered or _rejected; the gateway declares those nullable so they arrive unset with no contract change.

Verification (4)
  • Mod builds 0 warnings 0 errors; 73 declarations and 73 binds, down from 88; TryEnsurePrimaryRedirect confirmed still present and wired
  • comfy_gateway kernel plus both surviving toolsurfaces import cleanly after matrix.py removal; no live reference to toolsurface.matrix remains outside frozen docs and evidence
  • A pre-cut assertion that the excised block must not contain TryEnsurePrimaryRedirect aborted the first attempt and prevented deleting the production arming path
  • Game.sln 528/528 across three consecutive runs; one earlier run showed a single Game.Simulation.Tests failure that did not reproduce in four subsequent runs and could not have been caused by this change set, since the mod is not part of Game.sln - filed as a flake to chase separately
Evidence: fieldlab/docs/config-surface-decisions.md fieldlab/DECISIONS-PENDING.md
Recorded by Codex · associated with the Git commit containing this note
implementation baseline M0

Executed the safe recommendations and withdrew the unsafe ones after re-examination

Impact: Asked to clean up the outstanding recommendations, most of them did not survive contact with the code - which is the finding, not a failure. Executed: D7, where zdoRedirectEnabled still described itself as intended for private lab runs long after it began carrying production traffic, now corrected along with why it still defaults off, and where checking the neighbours showed only one key was actually rotten rather than the several assumed, since the ownership keys genuinely remain lab experiments. And D5, flipping zdoRedirectActiveSeconds and handshakeResponderActiveSeconds from 90 to 0, so the production posture is now the default and a VM configured from defaults no longer silently auto-disarms the redirect 90 seconds into a session. Withdrawn after re-reading: D2's three groups are all load-bearing - the priority probe writes the manifest the landmark design depends on, the shadow runner is entangled with the manual route walk kept when the swarm harness went, and the projection runner renders local-only Unity primitives without ZNetView or ZDO ownership, which is precisely the far-field proxy mechanism the landmark design needs and the only prior art for it in the repo. D3 is deferred with D4 because TryDriveNetcodeProbeAuto is the arming path for the ownership observe and pin runners. The orphan sweep also stopped short: matrix.py is lazily imported by three custom HTTP routes in the gateway kernel, so retiring it is kernel surgery on the running 8720 gateway plus a bounce. Most seriously, fieldlab/autonomous/valheim-lab.compose.yml was deleted as dead swarm scaffolding and then restored - docker ps shows it is the live definition of the running comfy-gateway and a Valheim server. Its client services are profile-gated and are now clearly marked in-file as unable to self-drive. ADR 0009 was corrected: it had claimed docker compose up would launch menu-idling clients, which is wrong since they sit behind a clients profile - an ADR arguing for verification against an independent source should not carry an unverified claim.

Verification (2)
  • Mod builds 0 warnings 0 errors; Game.sln 528/528; comfy_gateway.toolsurface.valheim imports cleanly with the dead autonomous_route profile removed; key count holds at 88; both ActiveSeconds defaults confirmed at 0.0f
  • docker ps confirmed comfy-valheim-lab-comfy-gateway-1 and comfy-valheim-lab-valheim-server-1 are running from the compose file before it was restored
Evidence: fieldlab/docs/config-surface-decisions.md fieldlab/docs/adr/0009-verify-against-an-independent-source.md
Recorded by Codex · associated with the Git commit containing this note
documentation baseline M0

Corrected the landmark discovery answer: the dual-channel lane split already solved it

Impact: The parallel-channel resolution recorded an hour ago was one layer too high. The real answer is the dual-channel transport, which was built for exactly this. InterestManager's own header states that reliable-lane messages - structure placed, entity removed - always go to the full region, and that the class only filters datagram-lane tick broadcasts. So the reliable lane is already region-wide and already exempt from interest filtering. And ValheimPriorityDeliveryPlanner.ReliableTiers already contains structural_anchor, the lighthouse tier, alongside player_critical, portal and storage_crafting. The routing exists; nothing needed inventing. The lane split is semantic rather than merely technical: reliable carries this exists or this changed, which is rare and region-wide, while datagram carries where it is right now, which is every tick and filtered. A static landmark is therefore pure reliable-lane traffic - one message when placed and zero datagrams forever, because it does not move. Its cost is a function of how often it changes, not of how far away it is, which is why it can be visible at 1500 metres for essentially nothing and why the aggressive datagram cut costs landmarks literally nothing. The priority manifest broadcast is one mechanism riding this lane, useful for announcing a set of landmarks at once, but it is an application-level convenience on top of the transport property rather than the property itself. Both the design note and the experiment brief were corrected to lead with the lane split.

Verification (1)
  • InterestManager's scope comment and the ReliableTiers set were both read directly before the correction was written; structural_anchor is confirmed present in ReliableTiers
Evidence: Lumberjacks/docs/network/landmark-reach-design.md Lumberjacks/docs/network/aoi-knee-experiment-brief.md
Recorded by Codex · associated with the Git commit containing this note
documentation baseline M0

Pre-registered the three-tier radius sweep, and settled that landmark discovery needs a parallel channel

Impact: Derek proposed increasing local sampling while aggressively cutting everything past roughly 30 yards. Checked against the recovered model the targeting is right and the lever is larger than it looks. At extreme density with combat_build, self at 0m and near at 50m both peak at 2000 updates per second and 1536 kbps, mid at 200m is an order of magnitude cheaper, and far at 500m is already exactly zero - so cutting harder at distance buys nothing and the entire budget lives in the near_20hz band from 0 to 50 metres. Area scales as the square of the radius, so pulling the full-rate radius from 50m to about 30m removes roughly 71 percent of the objects in the only expensive band. One caution changes the shape: Valheim activates and renders by zone at 64 metres, which is why the mod's NearbyRadiusMeters and BuildScanRadiusMeters both default to 64 and why the code uses ZoneSystem.GetZone and IsZoneLoaded. Thirty yards is inside one zone, so dropping an object at 27 metres leaves it visible and interactable while its state goes stale - present but wrong. The refinement is to thin the rate rather than drop the object, which is what the model's own thin_datagrams_to_5hz_defer_detail already describes, applied at 200m today instead of 30m. That yields full rate to 30m, thinned to the 64m zone boundary, dropped beyond. Derek then immediately spotted the hole: if everything past the boundary is dropped, a client can never learn a landmark exists at 500 metres, because the announcement would travel the path just severed. Un-cutting range to listen for distant great works would hand back exactly the saving. The resolution is that landmarks were never on that path - the priority manifest is broadcast rather than interest-filtered, the mod already subscribes via LumberjacksPriorityManifestListener, and InterestManager never consults it. The client hears an announcement naming a tier, position and reach, then spawns the far-field proxy locally; the real build is never replicated at range. That keeps per-tick churn bounded by the interest radius and landmark discovery bounded by how many great works exist rather than how far away they are. The aggressive cut is affordable precisely because discovery is a separate, sparse, distance-free channel.

Verification (3)
  • The band asymmetry was read from the recovered modeled-pressure-matrix.csv at density_band=extreme and event_profile=combat_build; far reports 0.00 updates per second and 0.00 kbps on every row
  • The 64m zone alignment was confirmed from the mod's own radius defaults and its use of ZoneSystem.GetZone and IsZoneLoaded
  • The broadcast endpoint and the mod-side manifest listener were both confirmed present, and InterestManager references neither, before the parallel-channel claim was written
Evidence: Lumberjacks/docs/network/aoi-knee-experiment-brief.md Lumberjacks/docs/network/landmark-reach-design.md
Recorded by Codex · associated with the Git commit containing this note
documentation baseline M0

Captured the landmark-reach design; repaired the mojibake, including a fresh instance I caused

Impact: Derek's design inverts the obvious approach to long-range visibility. Rather than making area-of-interest clever enough to show more at distance - unbounded, and worst exactly when the world is busiest - long-range presence becomes a scarce property that must be granted: a reward a master builder earns and places, pieces that are invisible up close but read as structure at great distance. The cost ceiling becomes a design parameter instead of an emergent property of how much people built, and the limitation becomes something the community can see and work toward rather than something the engine hides. It is also an inverted level of detail, since the proxy exists only at range where the real build is not loaded. The scoping primitive is mark-a-thing-and-define-its-reach, and Derek's intuition that the same mechanism serves itemid or ZDOid is correct for a concrete reason: ValheimPriorityObject already carries StableKey, which is already the planner's dedup and ordering key, plus an absolute Position, and the mod already filters by prefab stable hash in three places. The manifest even has a delivery wire already - a broadcast endpoint on the gateway and a listener in the mod. What is missing is one field, reach, since DistanceMeters currently means observation distance rather than visibility range; plus enforcement, since the delivery plan is advisory while the RANK is enforced at ZdoRedirectRunner.cs:337, which suggests a landmark exemption is a change to that predicate rather than a new subsystem; plus the proxy asset and swap rule, which is content work with no existing machinery; plus the earning mechanic. Separately, repaired 6 mojibake lines: 2 singly-encoded em-dashes in the volunteer platform plan and 4 doubly-encoded in ComfyNetworkSense.cs, left by earlier PowerShell round-trips - and one fresh instance I caused in this same session by doing exactly what lesson L-2026-07-21-9 forbids, an hour after grading that lesson as held.

Verification (3)
  • Mod builds clean after the comment repair; repo-wide grep for mojibake byte sequences now returns nothing across all .md and .cs
  • The corrupted README was reverted via git checkout and re-edited with the Edit tool; em-dash count verified at 8 with 0 mojibake sequences before proceeding
  • The repair targeted two codepoint-exact sequences measured from the actual files after a character-class heuristic silently matched nothing
Evidence: Lumberjacks/docs/network/landmark-reach-design.md
Recorded by Codex · associated with the Git commit containing this note
documentation baseline M0

Recorded the player-facing goals behind the AoI work, and read the 9,600-row grid as the specification it is

Impact: The findings record had the what and the how but not the why, and the why changes the design. Three player-facing limitations motivate all of it, in Derek's words: multi-person combat and exploring through an event; skirting the coast into the unknown fast enough that the world cannot keep up, where the failure is not a stutter but losing a character to terrain that had not arrived; and visiting the fantastical builds the community makes, where load time means the best thing the community produces is the hardest to share. The sharpest requirement is a lighthouse on the coast visible at distance, and it is a requirement rather than an anecdote because it isolates which of the two systems is at fault. A lighthouse barely needs updates - it does not move - so it is not a datagram-filtering problem; it needs to exist in the world at range, which is ZDO load order. The classifier already ranks structural_anchor at 2, above doors and chests and decoration, so System B already knows a tower outranks a rug. But InterestManager's Far band is dropped and the model's own third interest_bucket is far_suppressed, so past MidRadius nothing expresses that a particular object matters at range. Rank and distance never meet - the same gap the findings record identified, arriving from the opposite direction with an acceptance test a person can check from a boat. Re-read the recovered grid as a specification rather than a dataset: its three axes are exactly those three scenarios, its density bands are real sampled 500m cells rather than synthetic, its priority_expectation column is a five-level graded shedding ladder that the findings record had proposed as a new idea when it was specified in July, and its process_budget column is already three-state with 1,920 rows predicting yellow or red.

Verification (2)
  • Every axis value quoted was read from the recovered CSV: six density_bands with real-cell labels, four observer_ranges, four event_profiles, three interest_buckets, five priority_expectations, three process_budgets, and 1,920 non-green rows split 480 per observer range
  • The structural_anchor rank of 2 was read from LumberjacksPriorityClassifier, and the Far-band drop from InterestManager
Evidence: Lumberjacks/docs/network/area-of-interest-findings.md fieldlab/evidence/aoi-density-pressure-matrix-20260704/modeled-pressure-matrix.csv
Recorded by Codex · associated with the Git commit containing this note
documentation baseline M0

Closed the audit session: retro addendum, ADR 0009, decisions register, memory

Impact: Second retro of the day, appended rather than overwriting. The through-line arrived unplanned: five independent systems that report success while producing nothing - deploy-gateway.ps1 hashing the files it had just shipped so its integrity check could not fail, rollback-gateway.ps1 mutating /opt before failing on a build the stack forbids, the lab compose still launching clients that idle at the menu, 998 AoI result rows with avg_fps constant at 60.0 and the single real capture reporting all-zero network fields from Solo mode, and the fleet assay grading two empty builds a B/70 off the checkout it was handed. That last one was this retro's own second opinion, reaped from the previous session. ADR 0009 states the rule the five share: a check that reads its own output is not a check, and a verification must compare against a source it did not produce. Follow-through on the morning retro's nine lessons is graded in the addendum; L-2026-07-21-2, do not state a cause you have not read the code path for, regressed three times and is escalated as L-2026-07-21-13 with a specific habit fix - before asserting an absence, name the boundary searched and ask what lies outside it. Derek corrected the sharpest instance: I wrote that the AoI dataset was gone, and he pointed out the repos we cloned to make this one still hold it, which was true. Memory retired-repos-are-the-archive records that scope correction.

Verification (2)
  • Retro appended to the existing 2026-07-21 file, not overwritten; ADR index updated with 0009; every relative link in the addendum resolves
  • Fleet second opinion hearth-retro-20260721-baseline-618dfd6e reaped and recorded as no-verdict with the empty_build evidence
Evidence: fieldlab/retro/SESSION-RETRO-2026-07-21.md fieldlab/docs/adr/0009-verify-against-an-independent-source.md
Recorded by Codex · associated with the Git commit containing this note
documentation baseline M0

Recovered the AoI density-pressure dataset and wrote the knee-experiment brief

Impact: Derek was right that nothing is ever lost: all three artifacts of the 2026-07-04 density campaign survived in the retired C:/work/comfy checkout, in a gitignored var dir, and are now committed under fieldlab/evidence/aoi-density-pressure-matrix-20260704. Recovering them replaced a guess with a finding. The model is substantial and complete - 9,600 rows spanning density bands, observer ranges and event profiles, predicting estimated_udp_kbps, interest_bucket and a process_budget classification - and not one row has ever been checked against an observation. The measured side barely started: 96 cells planned, 1 done, 94 pending; results.jsonl holds 1,000 rows of which 998 are synthetic stubs from sim-viking clients reporting avg_fps of exactly 60.0 and bytes_out_per_sec of ~18,000 regardless of density band OR observer range, and exactly one is a real capture whose rtt, bytes and packets are all zero because the client sat in Solo mode and never connected. So the campaign produced zero networked measurements - not neglect, an unfinished run. Tested the hypothesis that the synthetic rows could still serve as a load proxy: they cannot, because they show no sensitivity to either variable that would be tuned. Also corrected an error in the findings doc: the claim that a tuning campaign would be blind for lack of instrumentation is wrong at the system level. TickMetrics already carries a 50ms tick budget, a game.tick.overruns counter that is precisely a knee detector, a duration histogram tagged per phase that isolates interest-filter cost from send cost, and TickBroadcaster already records entitiesSent versus entitiesCulled - all exposed over HTTP at /tick. The experiment is therefore instrumented today and needs only a config sweep plus the existing load driver.

Verification (2)
  • Every file and line citation in both new documents resolved against the working tree, including TickMetrics.cs:31 the budget constant, TickMetrics.cs:205 the overrun branch, TickBroadcaster.cs:342 the sent/culled record, and InterestManager.cs:16 the datagram-lane-only scope note
  • The load-proxy hypothesis was tested by grouping all 998 synthetic rows by density_band and by observer_range; bytes_out_per_sec varies 0.2 percent across the full range from empty control to extreme density and avg_fps is constant at 60.0, so sensitivity is nil
Evidence: Lumberjacks/docs/network/aoi-knee-experiment-brief.md fieldlab/evidence/aoi-density-pressure-matrix-20260704/README.md
Recorded by Codex · associated with the Git commit containing this note
documentation baseline M0

Wrote the area-of-interest findings record: what the testing learned and why none of it reached the code

Impact: Months of AoI and priority measurement never changed the engine that would have used it, and the reason turns out to be structural rather than negligent: the repo holds TWO independent notions of what matters most, built three months apart, measured separately, connected by nothing. System A is the Lumberjacks spatial interest manager from ADR 0015, accepted 2026-03-28 - distance bands at 100 and 300 units with a mid-band tick divisor. System B is the Valheim ZDO tier model built in July - seven ranks from player_critical to decorative_far. interest-management.md already states that the gateway does not re-run InterestManager tiers over the Valheim ZDO stream, and names the unclosed action: the next AoI audit must measure Valheim relevance selection separately from Lumberjacks player-tier filtering before any multi-client scalability claim. That audit never happened. Verified against source rather than taken from the audit passes: InterestManager has no byte accounting, no priority ordering within a band, no boundary hysteresis (plain <= at both comparisons) and no adaptive radius, and its shedding is a binary mid-band switch rather than a budget; it also filters datagram-lane broadcasts only, never the reliable lane. The measured evidence that should have driven change is strong and survives - the P7 gold run put 57.1 percent of 83,220 redirected ZDOs into the fast lane, and the host-capacity benchmark found message volume rather than CPU is what bends, with the knee at 400 bots. The density-pressure matrix data is genuinely gone: results.jsonl and modeled-pressure-matrix.csv were never tracked, which is the concrete cost of writing results to a gitignored var dir. Also preserved the most reusable lesson, that stationary load-test bots never cross a tier boundary so a naive AoI load test measures nothing.

Verification (2)
  • Every file and line citation in the document was resolved against the working tree; both line citations land on the intended code (InterestManager.cs:113 the near-band comparison, ZdoRedirectRunner.cs:337 the ImportanceAllows gate)
  • Four errors from the parallel passes were caught and are recorded in the document's provenance section rather than propagated - two files reported missing that exist but were unpacked, one advisory-vs-enforced conflation, and two evidence files reported missing including the strongest measured artifact we hold
Evidence: Lumberjacks/docs/network/area-of-interest-findings.md Lumberjacks/docs/benchmark-host-capacity-2026-07-12.md
Recorded by Codex · associated with the Git commit containing this note
implementation baseline M0

Removed the swarm/unattended-client harness from the mod; 107 config keys down to 88

Impact: The harness existed to run fleets of headless Valheim clients unattended during the independent-agent regime. Deleted rather than commented out, because git is the better archive - commented-out code rots silently, a commit SHA does not. Removed AutoCharacterSelectPatches.cs, which drove the character-select screen so a spawned container connected instead of idling at the menu, MatrixCheckinRunner.cs, which polled a gateway for benchmark cells and posted results back, the two auto-rehearsal wrappers in ComfyNetworkSense.cs, and 19 config keys across AutoJoin, Automation and Matrix. Two corrections surfaced while cutting, both against the audit's own grouping: RouteGodFlySafeguard was classified as swarm machinery but actually guards the MANUAL route walk from killing the character on a post-teleport fall, so it stayed; and the manual network_sense_rehearsal console command shares TryStartRehearsal and RunTeleportRoute with the auto path, so only the automatic wrappers went and the now-dead initiatedByAuto and autoRehearsal parameters were collapsed out of both signatures. The operator command is untouched. SWARM-HARNESS-REMOVED.md carries the recovery pointer, what stayed and why, the consumers left orphaned elsewhere - the autonomous compose files and the comfy-gateway matrix toolsurface, which is a registered MCP provider and must not be deleted casually - and the honest counter-argument that this was the only ready-made multi-client harness in the repo.

Verification (3)
  • Mod builds 0 warnings 0 errors after removal; Game.sln still 528/528
  • git grep for MatrixCheckinRunner, AutoCharacterSelectPatches, TryStartAutoRehearsal and TryCoupleAutoRehearsal across all .cs returns nothing
  • ConfigEntry declarations and config.Bind calls both counted at 88, down from 107, and RouteGodFlySafeguard confirmed retained
Evidence: network/mod/ComfyNetworkSense/SWARM-HARNESS-REMOVED.md fieldlab/docs/config-surface-decisions.md
Recorded by Codex · associated with the Git commit containing this note
documentation baseline M0

Completed the mod config inventory and turned it into decisions with counter-reasons

Impact: The first audit pass covered only 44 of the 107 ConfigEntry keys: it was given an 8000-token output budget and pro is a thinking model, so the thinking consumed the budget and the analysis sections never emitted. Re-run as three scoped passes with a 30000-token budget, splitting by property-name prefix so each thread owned a disjoint set. The 63 uncovered keys were the operationally important ones - ZdoRedirect, ZdoInjection, Ownership, HandshakeResponder and the Lumberjacks integration block. Two audit claims were checked and rejected. One said the ActiveSeconds timers are live time-bombs that drop the serving path 90 seconds in; ZdoRedirectRunner.cs:226-227 treats 0 as no cap and infra/gcp/p7/README.md:101 pins zdoRedirectActiveSeconds=0, so production is correctly configured - the real and narrower risk is that the safe value is recorded only in a runbook and in a .cfg that lives on the VM, with no reference production config tracked in this repo. The other recommended flipping the serving-path flags to default true; ZdoRedirectRunner.cs:50 states that zdoRedirectEnabled=false IS the standing rollback, and defaulting them on would mean a mod dropped into any server hijacks world sync on load. Recorded a better answer than either default: keep the flags off, flip the ActiveSeconds default from 90 to 0 so the safe value is the default and the finite lab window is opt-in, and version-control a reference production .cfg so the posture stops living only as VM state. Eight decisions, each with the strongest case against it stated rather than implied; acting on the three clean ones removes 40 of 107 keys without touching the serving path.

Verification (2)
  • All 107 keys accounted for across three disjoint passes; counted against the ConfigEntry declarations in PluginConfig.cs
  • The auto-disarm semantics were read directly from ZdoRedirectRunner.cs rather than taken from the audit, and the production override was located in the P7 runbook
Evidence: fieldlab/docs/config-surface-decisions.md fieldlab/docs/audit-2026-07-21-conditional-logic.svg
Recorded by Codex · associated with the Git commit containing this note
implementation baseline M0

Audited the accreted conditional logic; deleted two broken deploy scripts and repointed the local dashboard at the tunnel

Impact: Six gemini-pro threads over the mod, gateway, P7 deploy, release scripting and the parallel infra stacks, looking for conditional logic that only ever served the unattended-agent regime. Every finding was re-checked against the code before acting, and three did not survive: the release-cut scripts were reported as holding stale split-repo paths but resolve correctly to the merged root, the dashboard IP was reported stale but is a reserved static that answers TCP, and zone A never finished its analysis. Deleted rollback-gateway.ps1, which ran a docker compose build the P7 stack structurally forbids, after already copying source onto /opt, with a SourceRoot default pointing at a frozen historical commit; the P7 README now sends gateway rollback to the drill's phase 3, which re-pins the image and verifies both health and the exact image id. Deleted configure-player-gateway.sh for the same forbidden build plus a hardcoded public IP. The gateway rate limiter keyed its partitions on the caller's own X-Lumberjacks-Enrollment-Id header, which UseRateLimiter reads before ValheimClientAccessMiddleware has verified anything, so a caller could mint a fresh bucket per request and defeat the only limits bounding unauthenticated abuse; it now keys on the connection address, the only value that cannot be forged over the wire at that point. The omen-dashboard proxy pointed at the VM's public player port, which capped what it could ever show, because admin and dev surfaces are bound to the VM's loopback deliberately and are not published there at all; it now follows the SSH/IAP tunnel that start-gateway-tunnel.ps1 already opened, so the allowlist could widen to the live stats surfaces without the VM publishing anything new. Enrollment listing, handshake config and the join flow stay unforwarded. The audit is drawn up as an SVG for posterity.

Verification (3)
  • dotnet test Game.sln: 528/528 pass, unchanged by the limiter change
  • nginx -t against the real nginx:1.27-alpine image: configuration syntax is ok
  • Every widened proxy route was checked to exist in the gateway's endpoint map first; each carries limit_except GET because the same prefixes also hold reset, compact and stage
Evidence: fieldlab/docs/audit-2026-07-21-conditional-logic.svg Lumberjacks/tools/omen-dashboard/nginx.conf fieldlab/DECISIONS-PENDING.md
Recorded by Codex · associated with the Git commit containing this note
implementation baseline M1

Separated heartbeat liveness from primary admission; the gate stays strict

Impact: The telemetry endpoint returned 409 for a lumberjacks-primary heartbeat before calling Record, so a rejected beat never advanced _lastSeen. Under sustained load with peers connected - exactly when a session is busiest - every beat is rejected, the 15s staleness clock runs out, and the dashboard goes stale. What actually degraded was narrower and stranger than going blind: CutoverSnapshot reads its queue counters live from the redirect and consumer services, so pending, active_consumers and consumer_draining kept updating, while everything sourced from the last admitted beat - coverage_total, coverage_lumberjacks, coverage_native_only, mode, mod_version - froze. The coverage figures that prove the cutover is working were the ones that stopped moving, next to queue counters that visibly did not. The gate itself was left alone: a backlogged primary genuinely is not a fully authoritative window, and the 409 is the honest answer. RecordAndAdmit now records liveness and then answers admissibility, and the endpoint calls that one method rather than ordering two calls itself, because line order inside a lambda is what regressed here. Malformed beats are still never recorded - the 400 checks run ahead of admission. Both community pages already preferred consumer_draining over the stale headline, so they were written expecting a state the gate had made unreachable. Checked before landing that nothing gates on EnrollmentSnapshot.state, which now reads advertised rather than stale during backlog.

Verification (3)
  • New test RejectedPrimaryHeartbeatStillRefreshesLiveness was run against the old gate-then-record order and fails there (stale was True), so it catches the regression rather than merely passing
  • dotnet test Game.sln: 528/528 pass, up from 525/525 with three new tests
  • Grepped every consumer of stale/heartbeat_stale/advertised across cs, ts, js, html and py: no caller gates on the enrollment state string
Evidence: fieldlab/docs/adr/0008-liveness-is-not-admission.md Lumberjacks/src/Game.Gateway/Valheim/ValheimTelemetryHeartbeatService.cs Lumberjacks/tests/Game.Gateway.Tests/ValheimZdoAuthoritativeTelemetryTests.cs
Recorded by Codex · associated with the Git commit containing this note
implementation baseline M0

Repointed every retired-checkout-root reference at the merged repo

Impact: The cutover left 30 copy-pasteable commands across seven docs, plus four executable scripts, still aimed at C:\work\comfy and C:\work\lumberjacks. Those roots still exist on disk holding pre-cutover content, so the commands do not fail - they succeed quietly against stale code. The sharpest case was deploy-gateway.ps1, whose LocalRoot defaulted to C:\work\lumberjacks: it tars, hashes and ships two gateway source files, and both of them differ between that root and baseline, so running the documented deploy would have reverted the telemetry-heartbeat fix while its own hash check passed, because it hashes what it shipped. All four scripts (deploy-gateway.ps1, capture-release-manifest.ps1, fieldlab/scripts/start-comfy-gateway.ps1, network/mcp/etc/start-comfy-gateway.cmd) now derive their roots from their own location. The P7 runbook had warned at the top that both roots were retired while hardcoding them in eleven command blocks below; that contradiction is gone. Root AGENTS.md still described the retired two-repo roadmap ceremony and now defers to Lumberjacks/AGENTS.md. Separately, RoadmapViewEndpoints resolved its asset through a single string with an embedded forward slash, which Path.Combine preserves - green on Linux, two failures on Windows; it now combines two segments and the suite is 525/525.

Verification (3)
  • dotnet test Game.sln: 525/525 pass, up from 523/525
  • All four repointed scripts parse clean and resolve to C:\work\baseline roots
  • Repo-wide grep leaves only intentional prose, new explanatory comments, and frozen evidence archives
Evidence: infra/gcp/p7/scripts/deploy-gateway.ps1 AGENTS.md fieldlab/DECISIONS-PENDING.md
Recorded by Codex · associated with the Git commit containing this note
documentation baseline M0

Closed out the session: retro, three ADRs, plan outcome, decisions register

Impact: Session retrospective for the baseline cutover step-6 close and the repo prune. Three durable decisions became ADRs: 0005 carries an unreproducible release artifact forward with explicit provenance rather than rebuilding it into untested bytes, because the .NET 8 SDK embeds the git HEAD sha in the PDB; 0006 moves repo history to the credential-free P7 VM by git bundle rather than installing a token; 0007 sets prune-signal discipline after both git-history staleness and basename-orphan detection proved actively misleading in a subtree-merged monorepo. plan-baseline-cutover.md gains a section 7 recording that all six steps closed and that two of the plan's own assumptions were wrong. Five open decisions were appended to DECISIONS-PENDING: the VM's running cost, the reproducibility remedy, whether the VM gets a deploy key, whether the telemetry gate should tolerate load-induced backlog, and strict-roster posture for future acceptance windows.

Verification (1)
  • roadmap:check passes; ADR index updated with 0005-0007; every relative link in the retro and ADRs resolves
Evidence: fieldlab/retro/SESSION-RETRO-2026-07-21.md fieldlab/docs/adr/README.md fieldlab/DECISIONS-PENDING.md
Recorded by Claude · associated with the Git commit containing this note
implementation baseline M0

Pruned 279 of 1045 tracked files after a Gemini-backed per-zone audit

Impact: The consolidation carried across everything both source repos held, including a large body of content with no consumer in the merged program. Seven zones were reviewed in parallel, each packed through HEARTH to gcp-gemini-pro, with every proposed deletion re-examined by a skeptic agent that grepped for inbound references; 62 verdicts were overturned that way. Removed: the handoff tree including a second Valheim mod (comfy-control-surface) and a camera-flythrough exploration, community and strategy essays under docs, a generated repo-map snapshot and its generator, a Discord/Sheets harvest side project, rank-ladder recipes, a community-systems kit, and finished fieldlab experiment plans, scenarios and evidence. Lumberjacks/src and network/mod were excluded from review entirely, being the code that builds the five images serving production. Two signals were rejected as misleading: git-history staleness (the subtree merges date every file to the consolidation) and basename-orphan detection (196 of 199 apparent orphans were live C# referenced by namespace). A second pass removed 11 further orphans left by cross-zone inconsistency, and tests/test_entrypoint_links.py now discovers entrypoints instead of hardcoding them, so it no longer goes red whenever a directory is removed for unrelated reasons. Everything remains recoverable from git history and from the still-existing C:/work/comfy and C:/work/lumberjacks.

Verification (3)
  • Release pipeline intact after the prune: v3 bundle still validates, run-promotion-drill.ps1 plan-only still resolves all four gated identities, and docker compose config still resolves all five service images
  • roadmap:check passes; test_entrypoint_links passes with zero dangling links across every surviving README
  • The 5 test_guest_package failures are pre-existing and reproduce identically on main; confirmed by checking out main and re-running
Evidence: Lumberjacks/docs/roadmap/prune-audit-20260721.json
Recorded by Claude · associated with the Git commit containing this note
planning baseline M0

Root-caused the telemetry heartbeat 409; deferred the fix to the next release cut

Impact: The mod logs 'Lumberjacks telemetry heartbeat failed: HTTP/1.1 409 Conflict' during play. Not a fault: ValheimTelemetryHeartbeatService.CanAcceptPrimaryHeartbeat refuses any lumberjacks-primary heartbeat while a peer is connected unless the authoritative window is fully applied (IsAuthoritativeComplete requires redirect.Pending == 0 and consumer.Pending == 0). Any queue backlog therefore rejects the heartbeat by design, and it succeeds again once drained. Two mod-side defects make this look like a failure: LumberjacksTelemetryHeartbeatRunner reads only the first 256 bytes and parses the status line, discarding the gateway's explanatory body, and it logs at LogWarning so designed backpressure reads as an error. A third, larger question is a design wrinkle rather than a bug: the health signal is gated on a condition that load makes temporarily false, so a sustained busy session could exceed the 15s staleness window and show the dashboard as stale while the system is healthy. DEFERRED DELIBERATELY: any fix changes the mod, which is a frozen release artifact, so it would invalidate the world-tested clean_build_sha256 035faa87. Cheapest fix next cut: surface the response body and log at info. The staleness-under-load question needs a decision, not just a patch.

Verification (2)
  • Traced end to end: ValheimTelemetryHeartbeatEndpoints.cs line 42 returns Results.Conflict, gated by CanAcceptPrimaryHeartbeat at ValheimTelemetryHeartbeatService.cs line 168
  • Matches observation: 409s appeared only while a peer was connected with pending greater than zero; heartbeat_stale stayed false throughout and the acceptance sample was captured with pending at zero
Evidence: Lumberjacks/src/Game.Gateway/Valheim/ValheimTelemetryHeartbeatService.cs network/mod/ComfyNetworkSense/Core/Services/LumberjacksTelemetryHeartbeatRunner.cs
Recorded by Claude · associated with the Git commit containing this note
verification baseline M0

World-tested the baseline re-provision: m5 acceptance passes on all eight criteria

Impact: Closes plan step 6. A real player session against the re-provisioned P7 VM produced a coherent closure sample meeting every README section 9 criterion: 100 percent coverage over 148892 ZDOs, zero native-only, zero fallbacks, receipts equal to acknowledgements at 75112 with zero pending, complete true, persistence healthy, and zero rejected/duplicate/retried. The stack under test had all five services pinned by digest from a validated v3 bundle, a deployment source cut over from the retired comfy repo to a baseline checkout, and pins already proven across a systemd restart. The v2 manifest's reproducibility_gap is now closed in practice rather than on paper.

Verification (2)
  • Sample captured while the player was still connected; the window auto-resets when the server empties, so it cannot be reconstructed after the fact
  • Workload was real: applied=61096, superseded=14016, including a dense-construction castle load
Evidence: Lumberjacks/docs/roadmap/m5-v3-acceptance-receipt.json Lumberjacks/docs/roadmap/m5-v3-reprovision-receipt.json
Recorded by Claude · associated with the Git commit containing this note
implementation baseline M0

Re-provisioned comfy-lumberjacks-p7 from baseline; all five services now gated

Impact: Plan step 6. The VM's deployment source was a checkout of the RETIRED comfy repo at 8ca27eda with 471 dirty files, and its compose still built eventlog/progression/operatorapi from VM-local source - so the five-service release gate existed in the repo but had never existed on the VM. /opt/comfy is now a baseline checkout at ecbd6e3, compose pins all five by digest with no build: fallback, and the three sibling images were transported as OCI archives from the v3 bundle. The VM has no GitHub credentials, so history moved as a 24 MB incremental git bundle rather than a fetch - 8ca27eda turned out to be a genuine ancestor of baseline main, 232 commits back. Cut a v3 manifest for the release: gateway image and mod DLL are the original m5 artifacts carried forward unchanged, since the .NET 8 SDK embeds the git HEAD sha in the PDB and the mod therefore cannot be rebuilt to its shipped hash at any later commit.

Verification (4)
  • All four gated services report the exact manifest image ids after a systemctl restart, which is the reboot path (docker compose up -d, EnvironmentFile= only, no override file)
  • Mod DLL is 035faa87 at both the runtime and fallback paths, matching the world-tested artifact
  • Gateway health ok internally and publicly; eventlog/progression/operatorapi all 200; four dashboards 200
  • Authoritative window empty and healthy: persistence_healthy true, 0 receipts, 0 pending, 0 consumers
Evidence: Lumberjacks/docs/roadmap/m5-v3-reprovision-receipt.json Lumberjacks/docs/roadmap/m5-recipients-build-candidate-v3.json
Recorded by Claude · associated with the Git commit containing this note
documentation baseline M0

Corrected the drill runbook: the three sibling services do serve /health

Impact: The cold-start walkthrough claimed eventlog/progression/operatorapi expose no health endpoint. Probing the live P7 VM showed all three return 200 on /health at 4002/4003/4004. The drill still gates on identity rather than liveness for those three, which is the accurate reason, so the behaviour is unchanged and only the justification was wrong.

Verification (1)
  • curl against 127.0.0.1:4002-4004/health on comfy-lumberjacks-p7 returned 200 for all three
Evidence: infra/gcp/p7/PROMOTION-DRILL.md
Recorded by Claude · associated with the Git commit containing this note
implementation baseline M0

Promotion drill now transports all four gated images, not just the gateway

Impact: build-release-bundle.ps1 has always saved four OCI archives but run-promotion-drill.ps1 only scp+docker-loaded the gateway one. Harmless while eventlog/progression/operatorapi still built from VM-local source; a hard 'docker compose up' failure since the m5 cutover pinned them by digest with no build: stanza. Cold start now loads and tags all four and pins the three siblings in docker-compose.release.yml, whose lifetime is the release (phases 3-4 inherit it untouched, since only the gateway has a rollback identity). -Finalize retires both overrides and pins all four env vars, closing a silent-revert on the systemd reboot path. Also fixed roadmap.mjs checkStaged(), which compared repoRoot-relative paths against git's repo-root-relative output and so rejected correctly-staged commits under the monorepo layout.

Verification (4)
  • Plan-only drill run against a synthetic v3 fixture bundle records all four identities in drill-plan.json
  • A bundle carrying only the gateway archive fails closed: 'bundle is missing eventlog/eventlog.oci.tar'
  • Generated remote bash/YAML payloads rendered and inspected via AST extraction; no VM contact
  • roadmap:check passes; git rev-parse --show-prefix confirms the Lumberjacks/ prefix that broke --staged
Evidence: infra/gcp/p7/scripts/run-promotion-drill.ps1 infra/gcp/p7/PROMOTION-DRILL.md Lumberjacks/scripts/roadmap.mjs
Recorded by Claude · associated with the Git commit containing this note
documentation Comfy + Lumberjacks M0

Retired program-status.json; this roadmap is the one status surface now

Impact: program-status.json (the I0-I7 ladder's machine-readable status) still advertised an M4-unification stage as clear to run after later stages had already landed - a second surface competing with this one, stale in a way nothing caught. Its needs_derek/next_derek_touchpoint fields are now short pointers back here; phases/trust/infra stay intact as an accurate P0-P6 record, not deleted. Its dashboard artifact now shows a retirement banner instead of stale content.

Verification (1)
  • program-status.json still parses as valid JSON; dashboard.html regenerated and redeployed
Evidence: fieldlab/status/program-status.json fieldlab/status/README.md
Recorded by Claude · associated with the Git commit containing this note
implementation Comfy + Lumberjacks M0

Extended the release gate from gateway alone to all five P7 services

Impact: eventlog/progression/operatorapi built from build: context: ${LUMBERJACKS_ROOT:-/opt/lumberjacks} on the VM - whatever source happened to be checked out there, no release identity, no gate, no hash, drift raising no error. They are now pinned by image digest like gateway (build+hash+pin, no admission check - they have nothing to admit, unlike gateway/mod), with matching manifest schema v3 fields (schema bumped from v2's two-repo source.comfy_commit+lumberjacks_commit to one source.baseline_commit, following the cutover).

Verification (1)
  • docker compose config resolves all four required image vars; all four Dockerfile targets build clean against the merged tree; a full v3 manifest built from real artifacts round-tripped through build-release-bundle.ps1 and validate-release-bundle.ps1 end to end, status: valid
Evidence: infra/gcp/p7/docker-compose.yml infra/gcp/p7/scripts/build-release-bundle.ps1
Recorded by Claude · associated with the Git commit containing this note
implementation Comfy + Lumberjacks M0

Fixed the flagged stale rollback defaults in run-promotion-drill.ps1

Impact: The 2026-07-21T05:08 decision note recorded RollbackImageId/RollbackModSha256 as hardcoded M0-era values that PROMOTION-DRILL.md's own Phase 3 command never overrode, and warned the stale defaults remain in the repo and will catch the next operator. They now have no default at all and are required with -Execute, matching -RollbackModBackupPath's existing pattern; PROMOTION-DRILL.md's commands pass its own already-documented section-3 values explicitly instead of relying on a default that goes stale the moment the next release ships.

Verification (1)
  • PowerShell parser check passes on the edited script
Evidence: infra/gcp/p7/scripts/run-promotion-drill.ps1 infra/gcp/p7/PROMOTION-DRILL.md
Recorded by Claude · associated with the Git commit containing this note
implementation Comfy + Lumberjacks M0

Landed baseline: comfy and Lumberjacks merged into one repo, history preserved

Impact: comfy and Lumberjacks were two repos independently pinning the same release (source.comfy_commit + source.lumberjacks_commit), fighting over ownership of docker-compose.yml and the VM env-file template, and citing each other by absolute workstation path. All of that is now structural: comfy's history landed unmodified at the new repo's root (git show 433f1cc3 still resolves), Lumberjacks' full history landed under Lumberjacks/ via git subtree (preserved as the merge's second parent), and the ~30 files hardcoding a sibling-checkout path got PSScriptRoot-relative or repo-relative fixes. Evidence paths from here on are baseline-relative, not repo-name-prefixed - there is only one repo to be relative to.

Verification (1)
  • git log shows both original histories reachable; grep for the old absolute paths returns zero hits outside historical GitHub blob-SHA citations
Evidence: fieldlab/plan-baseline-cutover.md README.md
Recorded by Claude · associated with the Git commit containing this note
verification Lumberjacks M4a · M3

The release gate covers one of five services

Impact: A cross-repo audit found that the P7 stack pins only the gateway to a release image. eventlog, progression and operatorapi are built from source at whatever happens to sit in the VM Lumberjacks root, so they carry no release identity, no admission gate, and no hash in any manifest. The m5 manifest asserted a coherent release; it described one service out of five. That claim is now qualified in place rather than left standing. Neither repo had documented this, and no gate would surface it: a contract drift between the pinned gateway and an unpinned sibling produces no error and no reject, only wrong behaviour.

Verification (2)
  • comfy infra/gcp/p7/docker-compose.yml pins gateway to the release image while eventlog, progression and operatorapi use build: context LUMBERJACKS_ROOT
  • Lumberjacks has no release tooling of its own: every cut, verify, promote and rollback script for the Gateway artifact lives in the comfy repo
Evidence: docs/roadmap/m5-recipients-build-candidate.json
Recorded by Claude · associated with the Git commit containing this note
deployment Lumberjacks M4a · M3

Release m5-recipients-20260720-r1 recorded, including how it was deployed by hand

Impact: The cut that carried recipient-scoped delivery into production existed only as artifacts on one workstation and a hand-touched VM. The manifest now lives in git next to the M0 candidate, recording both source commits, the mod hash, the gateway image id, and the two runtime settings the image does not carry: ProducerEmitsRecipients, and the strict roster flag that is in-memory and dies on any container recreate. It also records the honest deployment method, which was manual image save/scp/load plus a copied compose file, and states plainly that rebuilding the VM from either repo would not reproduce the state this release was world-tested in. That gap is now written down rather than known only to whoever ran the window.

Verification (3)
  • validate-release-bundle.ps1 returned status valid for the bundle at comfy fieldlab/runs/releases/m5-recipients-20260720-r1
  • Both repos clean and at the manifest commits when the bundle was built; the bundle step refuses otherwise
  • Manifest records the superseded mod hash so the unfreeze of the previously frozen 0.5.31 artifact is traceable rather than silent
Evidence: docs/roadmap/m5-recipients-build-candidate.json
Recorded by Claude · associated with the Git commit containing this note
deployment Lumberjacks M4a · M4b · M3

Recipient-scoped delivery is live: a real player drained his own partition

Impact: Stage 3 and Stage 4 both landed in one window and legacy is no longer the only partition. The mod now stamps the destination peer Steam identity read off the socket at the per-peer sync-list boundary, and the Gateway translates that to its own opaque recipient on ingest, because the producer can only know a Steam identity and must not name a partition it cannot see. Cut m5-recipients-20260720-r1 both sides, deployed to P7, flipped ProducerEmitsRecipients. A real player session then produced real game ZDOs stamped with the joining player identity, and that enrolled client polled and received them under its own opaque recipient rather than legacy. Two consequences: M4a exit criteria finally have partitions to test against, and the correlated trace Stage 2 needed now exists, since correlation ids are populated on every submission where the frozen producer sent none.

Verification (4)
  • Gateway log during live play now reads mod_release=m5-recipients-20260720-r1, window_id=p7-primary-v1, a per-peer recipient, and a populated correlations list. Before this cut the same line read recipients=legacy, mod_release=(null), and an empty correlations list.
  • Enrolled consumer poll returned its own opaque recipient id rather than legacy, carrying real envelopes: sequences in the 35xxx range with populated prefab ids, correlation ids, and importance_class structural_anchor
  • Flag confirmed inside the container via printenv rather than from the env file, because the env file is read by the compose process and reaches nothing without a compose reference
  • NOT PROVEN: cross-delivery isolation with two simultaneous consumers, and behaviour under player_critical traffic. All observed envelopes were structural_anchor and only one consumer existed. Untested, not blocked.
Evidence: comfy infra/gcp/p7/docker-compose.yml
Recorded by Claude · associated with the Git commit containing this note
planning Lumberjacks M4a

M4a status corrected from queued to active

Impact: The roadmap described recipient isolation as not started while its Gateway was cut, promoted, and serving live traffic on P7 with the F1 property proven against the public endpoint. Queued was misleading to anyone reading the board. M4a is not complete and cannot be: its exit criteria are the N=2 and N=10 isolation matrix and per-recipient conservation equations, and none of those can be exercised while ProducerEmitsRecipients stays false, because every envelope files under legacy and no per-recipient partition exists to isolate. Active with a stated Stage 3 dependency is the honest position.

Verification (2)
  • Gateway image m4-clean-20260720-r1 running on P7, durable pin set, F1 proven live at Phase 5d
  • Isolation exit criteria remain unexercised: the flag is off by design and the frozen producer emits no recipient_id, so the enrollment partition is empty by construction
Evidence: docs/roadmap/valheim-volunteer-roadmap.json
Recorded by Claude · associated with the Git commit containing this note
decision Lumberjacks M1 · M4a

Promotion drill rollback defaults are stale and would overwrite the frozen mod

Impact: run-promotion-drill.ps1 hardcodes RollbackImageId to an M0-era image and RollbackModSha256 to the historical runtime mod b31697d2, and the runbook Phase 3 command overrides neither. RollbackModBackupPath is mandatory with -Execute and the rollback phase is unconditional, so running the documented command would have copied the historical mod over the deployed frozen artifact 94a3843e and restarted the Valheim server to verify it had. That is the same hazard New-GatewayReleaseCut.ps1 exists to prevent, reached through a different door: it invalidates the artifact every distributed guest package is pinned to. The promotion was therefore done directly, re-pin plus recreate with no build, which touches no mod at all. Decision: prefer direct promotion for Gateway-only cuts, and treat the drill as needing correct explicit rollback arguments before it is run again. The stale defaults remain in the repo and will catch the next operator.

Verification (4)
  • Drill plan recorded rollback.image_id sha256:358f5e11 while the VM was actually running sha256:3576d8e0, the m1 image; 358f5e11 does not exist in the local Docker image store at all
  • Deployed server mod read live from the VM as 94a3843e while the drill RollbackModSha256 default is b31697d2
  • run-promotion-drill.ps1 line 241 fails without RollbackModBackupPath when -Execute is passed, so the mod rollback phase cannot be skipped
  • Direct promotion verified clean: running image equals manifest image_id, durable pin updated, mod hash unchanged, and a real player session joined and produced traffic afterwards
Evidence: comfy infra/gcp/p7/scripts/run-promotion-drill.ps1
Recorded by Claude · associated with the Git commit containing this note
planning Lumberjacks M4a · M4b · M3

Stage 2 unification is gated on producer instrumentation, not harness engineering

Impact: plan-m4-unification.md models Stage 2 as a distinct engineering stage needing a harness change, because Invoke-ComfyLumberjacksIntegration.ps1 assumes it owns the server. This window showed the Stage 2 topology arising on its own out of ordinary play: the P7 server produced real ZDOs over loopback into p7-primary-v1 while a real enrolled principal authenticated from the public internet. The asymmetry that made Stage 2 look expensive, namely that the producer must be on loopback and the consumer must be public, is already satisfied by the P7 deployment shape rather than by anything the harness would build. What Stage 2 still cannot assert is the single correlated trace, and that is missing because the frozen 0.5.31 producer emits no correlation ids at all. The dependency therefore moves from harness work onto Stage 3 producer emission, and Stage 2 should be re-costed downward and re-sequenced behind Stage 3 instead of ahead of it.

Verification (4)
  • Gateway logs during a real player session, repeated continuously while the player was in world: ZDO submission accepted caller_identity=private-plane mod_release=(null) window_id=p7-primary-v1 recipients=legacy
  • Enrolled principal reaching the Gateway from the public internet proven separately at Phase 5c: /api/v0/valheim/enrollment/me returned the enrollment instead of 401 credentials_required, so the caller resolved as enrollment and not private-plane
  • mod_release=(null) on every real submission confirms the frozen producer sends no release identity, which is the designed absence-is-the-signal behaviour and not a fault
  • NOT PROVEN and still owed for Stage 2: that the player own client was the consumer draining p7-primary-v1 during play. That was inferred from an empty poll, not observed. The correlated eight-step trace remains unproven because correlations was empty on every real submission.
Evidence: docs/plan-m4-unification.md
Recorded by Claude · associated with the Git commit containing this note
deployment Lumberjacks M4a · M1

M4a recipient-isolation Gateway deployed to P7 and F1 closed live

Impact: The recipient work stopped being theoretical. Gateway image m4-clean-20260720-r1 was cut, transferred, and promoted on the P7 VM, and the F1 property was proven against the live public endpoint for the first time: an enrolled consumer on the public internet drained the frozen 0.5.31 producer recipient-less envelopes from the legacy partition and acknowledged them. Before the recipient fix this returned empty and the lane was dead. The frozen mod artifact was never touched.

Verification (5)
  • Cut identity verified from the shipped image rather than bin/Release: Test-GatewayImageRelease.ps1 read /app/Game.Gateway.dll out of the built image and confirmed admitted mod release m1-clean-20260717-r1
  • validate-release-bundle.ps1 returned status valid; OCI archive sha256 2ec2503b matched byte-for-byte after transfer to the VM
  • Phase 4 both halves: running container image sha256:0d99e547 equals the manifest gateway.image_id, and the durable pin in /etc/comfy-p7/environment names m4-clean-20260720-r1
  • Phase 5d live: pending/m4a-live-test-v1 returned recipient_id legacy with seq 900001 and 900002; ack returned acknowledged 2 unknown 0; re-poll empty
  • Deployed server mod hash unchanged at 94a3843e before and after the promotion
Evidence: comfy fieldlab/runs/releases/m4-clean-20260720-r1
Recorded by Claude · associated with the Git commit containing this note
documentation Lumberjacks M2

M2 status corrected from queued to active

Impact: The roadmap still described the guest package as not started while the artifact was built, committed, and review-closed. Comfy fe812c4 shipped the immutable self-verifying guest package and c101d4c closed the review follow-up; the generated pack exists at fieldlab/handoffs/guest-client-pack/comfy-guest-m1-clean-20260717-r1/ with a guide, manifest, and index. Three of the four tracked build steps are done. The status is now active rather than complete because the gate that matters is unchanged and still open: a non-developer completing enrollment in ten minutes without editing config or sending a secret. That gate needs a real human, and no synthetic fixture can close it.

Verification (1)
  • Guest pack artifacts present on disk (GUEST-GUIDE.md, manifest.json, guest-index.json, guest-package-inputs.json); roadmap check passes with the corrected status.
Evidence: docs/roadmap/valheim-volunteer-roadmap.json
Recorded by Claude · associated with the Git commit containing this note
documentation Lumberjacks M1 · M4a · M4b

Joined the local runtime proof and the remote deployment into one sequenced path

Impact: The program held two halves that had never met: a local Docker slice that closed the full correlated ZDO runtime but resolved every actor to private-plane, and an unexecuted runbook that can test enrollment identity but exercises no game runtime. The asymmetry is structural - ValheimClientAccessMiddleware.Resolve() checks source IP first, so loopback and RFC1918 short-circuit before enrollment headers are read - and no re-run of either harness closes it. The new plan also inverts the obvious unification: POST /receipts requires the Producer capability that public callers never get, so the producer must stay on the Gateway loopback and it is the CONSUMER that moves remote. M4a stage 1 is recorded as landed and correctly disabled: ProducerEmitsRecipients defaults false, which keeps delivery working under the frozen 0.5.31 mod, so two simultaneous players remain gated on the stage-3 producer emitter in Comfy rather than on M4a.

Verification (3)
  • Read the deployed admission path: ValheimZdoRedirectAdmissionPolicy.Evaluate returns allowed for schema 1 unconditionally, and ValheimZdoRedirectEndpoints validates only seq on the schema-1 branch, so the runbook Phase 5a seed still works verbatim after the schema-2 work.
  • Confirmed ProducerEmitsRecipients defaults false at both production call sites (ValheimZdoRedirectEndpoints.cs:258, ValheimZdoInjectionEndpoints.cs:62).
  • gcloud reports comfy-lumberjacks-p7 TERMINATED; the 07-19 integration evidence contains zero references to the P7 address, DuckDNS name, or project id, corroborating the local-only scope claim.
Evidence: docs/plan-m4-unification.md docs/runbook-m4a-stage1-live-test.md
Recorded by Claude · associated with the Git commit containing this note
documentation Comfy M1 · M3 · M4a

Mapped the accepted Comfy-to-Lumberjacks architecture.

Impact: Three source-derived public-safe SVGs make the runtime seam, local-versus-P7 topology, contracts, recurring jobs, operator pipeline, and proof harnesses reviewable without changing runtime state.

Verification (1)
  • Three SVGs parsed as XML and passed full-size headless render inspection; 13 Comfy repository tests and public-safety scans passed.
Evidence: Comfy fieldlab/integration/diagrams/README.md
Recorded by Codex · associated with the Git commit containing this note
verification Comfy M1 · M3 · M4a

Preserved the audited Comfy-to-Lumberjacks acceptance evidence.

Impact: A committed hash-inventoried packet now makes the local correlated runtime proof, partial receipt and acknowledgement snapshot, rollback state, readiness limits, and remaining risks durable without changing runtime code.

Verification (2)
  • Acceptance reran 15 Comfy contract tests, 13 Comfy repository tests, 159 Gateway tests, and the compact positive/negative correlation verifier.
  • Artifact metadata, source and curated hashes, rollback inputs, repository state, and temporary-container cleanup reconciled.
Evidence: Comfy fieldlab/integration/COMFY-LUMBERJACKS-ACCEPTANCE.md
Recorded by Codex · associated with the Git commit containing this note
verification Comfy M1 · M3 · M4a

Proved one real Comfy server-originated ZDO across the existing Lumberjacks boundary.

Impact: Importance-approved work now carries explicit schema, release, recipient, and correlation metadata through the Gateway to the real authoritative consumer; Importance-rejected work stays on Valheim's native path. This was local only; no GCP start or deployment occurred.

Verification (2)
  • 15 Comfy contract tests and 13 repository tests passed.
  • The real dedicated-server and headless-client harness observed the correlated positive sequence and proved a rejected correlation absent from Gateway and consumer logs.
Evidence: Comfy fieldlab/integration/comfy-lumberjacks-seam.md Comfy fieldlab/scripts/Invoke-ComfyLumberjacksIntegration.ps1
Recorded by Codex · associated with the Git commit containing this note
implementation Lumberjacks M1 · M3 · M4a

Admitted correlated Importance-approved ZDO work on the existing Gateway path.

Impact: The Gateway now authenticates producer identity, enforces the baked mod release for schema 2, honors the intended recipient, and exposes correlated consumer outcomes while retaining the frozen schema-1 rollback path.

Verification (2)
  • 159 Gateway tests passed in the Linux SDK container.
  • A real local dedicated-server slice authenticated private-plane, admitted release m4-integration-20260719-r1, routed legacy, and recorded an applied correlated result.
Evidence: Comfy fieldlab/scripts/Invoke-ComfyLumberjacksIntegration.ps1
Recorded by Codex · associated with the Git commit containing this note
decision Lumberjacks M1

Risk 12 decided: the Docker image payload is the reproducibility unit

Impact: Three independent no-cache builds show the shipped Game.Gateway.dll and pdb are byte-identical across two different HEADs, and all 48 published files identical for equivalent source. The image is declared the authoritative release artifact and local bin/Release non-authoritative. Image ids and the final layer digest remain nondeterministic even with identical payload; that boundary is documented rather than treated as a failure.

Verification (1)
  • A vs B (different HEADs): 47/48 identical, sole difference the regenerated Community/roadmap.html, a Content item that cannot reach the assembly. B vs C (identical source): 48/48 identical. Baked release id m9-repro-20260719-r1 read from all three images, verifier exit 0. Runtime config inputs identical across all three.
Evidence: docs/decision-release-reproducibility-risk-12.md
Recorded by Codex · associated with the Git commit containing this note
documentation Lumberjacks M1

Risk 12 documented: the shipped Gateway image build cannot see git

Impact: The image build context excludes .git, so no HEAD sha reaches the shipped DLL and the build-then-commit ordering defect applies only to the advisory bin/Release path. Proposes declaring the image the reproducibility unit; decides nothing until the acceptance test passes.

Verification (1)
  • Deduced from .dockerignore and the Dockerfile COPY set; the two-build acceptance test is specified in the document and has not yet been run.
Evidence: docs/decision-release-reproducibility-risk-12.md
Recorded by Codex · associated with the Git commit containing this note
implementation Lumberjacks M1

Release identity is verified from the shipped image, not a DLL that never ships

Impact: The baked release gate was inert on every deployed Gateway: the Dockerfile predated the mechanism and never passed the MSBuild property, so images carried the dev sentinel that ValheimReleaseIdentity maps to null. Arming StrictReleaseEnabled would have done nothing. The image now carries the value and a promotable build fails closed without it.

Verification (1)
  • Three regression cases green: a promotable build's id reaches the image, an uncut image is rejected by name, and a promotable build refuses both the sentinel and a malformed id. Confirmed against the live P7 container that the shipped DLL carried no attribute at all.
Evidence: fieldlab/evidence/p7-session-20260719-release-gate-defect/deployment-identifiers.md
Recorded by Codex · associated with the Git commit containing this note
implementation Lumberjacks M4a

Recipient scope resolution requires an explicit producer-emission argument

Impact: The unsafe recipient branch can no longer be selected by omitting an argument; both Gateway call sites already passed the configured value, so deployed behavior is unchanged and the frozen producer's delivery lane is unaffected.

Verification (1)
  • sdk:9.0 container 520/520 passing; both production call sites unchanged; test call sites now state producerEmitsRecipients explicitly.
Evidence: docs/runbook-m4a-stage1-live-test.md
Recorded by Codex · associated with the Git commit containing this note
implementation Comfy M2

Immutable self-verifying guest package shipped

Impact: Replaces the prose guest handoff with a deterministic, reversible package, installer, preflight, diagnostics, and receipt-driven uninstall; human enrollment through READY TO JOIN remains open.

Verification (1)
  • 13 Comfy unittest tests passed; both promoted release bundles validated; eight injected fault verdicts each named a check and remedy; live plugin LastWriteTime unchanged.
Evidence: fieldlab/evidence/m2-guest-package/README.md
Recorded by Codex · associated with the Git commit containing this note
verification Lumberjacks M4a

Fix frozen producer delivery compatibility and conservation proof

Impact: Default-off producer recipient emission keeps enrolled consumers draining the legacy bucket until the stage-3 producer cut; opt-in recipient partitioning remains available. Removed tautological Eligible/Durable proof and disclosed the deployment coupling.

Verification (3)
  • dotnet9 Gateway 154 total, 152 passing, 2 pre-existing Windows path failures
  • sdk:9.0 container 520/520 passing
  • FrozenProducerEnvelope_IsStillDrainedByAnEnrolledConsumer passed in frozen and recipient-emitting modes
Evidence: docs/handoffs/AGENT-QUESTIONS.md
Recorded by Codex · associated with the Git commit containing this note
implementation Lumberjacks M4a

Gateway recipient-scoped durable delivery stage 1

Impact: Adds server-derived recipient isolation, named legacy compatibility, recipient-keyed leases, additive WAL replay, and synthetic N=2/N=10 proof; remains undeployed with producer outbox open.

Verification (3)
  • dotnet9 Gateway 153 total, 151 passing, 2 pre-existing Windows path failures
  • sdk:9.0 container 519/519 passing
  • Mutation proof: scope 4 failures, lease 2 failures, WAL version 1 failure
Evidence: docs/plan-m4a-recipient-isolation.md
Recorded by Codex · associated with the Git commit containing this note
documentation Lumberjacks M1

Lockfile sheds 13 extraneous entries left over from the deleted npm workspaces

Impact: package-lock.json carried 13 entries marked extraneous for packages/* and services/* workspaces that were deleted when package.json narrowed its workspaces to clients/*, plus the orphaned optional-peer @types/node and undici-types records nothing depended on. npm install regenerated the lockfile as 151 pure deletions: no real dependency changed version, and the manifest again matches the two clients/* workspaces that actually exist.

Verification (1)
  • npm install reported up to date and rewrote only the stale records; npm ls exits 0 with no extraneous or missing packages; git diff on package-lock.json shows 151 deletions, 0 additions, and no version movement on any surviving entry.
Evidence: package-lock.json
Recorded by Claude · associated with the Git commit containing this note
implementation Lumberjacks M1

M1 stage 4 gap closed: self-serve bootstrap re-issue via Steam re-sign-in

Impact: An expired setup code no longer strands its volunteer behind an admin revoke plus re-invite. GET /join/reissue redoes the Steam OpenID sign-in - the identity root that created the enrollment - and a SteamID whose Active enrollment is still credential-less gets a fresh single-use code for the same enrollment. Designed with Derek before building, four decisions: Steam re-sign-in authenticates (not the expired code itself, which would have turned the browser artifact stage 4 neutralized into a long-lived re-issue credential, and not an operator-signed link, which is not self-serve); pending-only scope, so once the installer has minted a credential re-issue answers already_installed and recovery stays admin revoke + re-invite; the public join IP limiter plus a per-enrollment cooldown (LUMBERJACKS_REISSUE_COOLDOWN_MINUTES, default 15) and a lifetime chain cap (LUMBERJACKS_REISSUE_MAX_BOOTSTRAPS, default 10); and the enrollment is reused, not rotated - same EnrollmentId and RecipientId, so nothing downstream churns. The prior unused code is deleted from the store rather than flagged: a deleted record answers bootstrap_invalid under every past and future binary, so a rollback cannot resurrect a superseded code, and at most one bootstrap is live per enrollment. The chain is counted in a new BootstrapIssueCount enrollment field, additive on schema v3 - pre-existing records read 0 and get one spare re-issue, fine because the cap is an abuse bound, not a security invariant. The OpenID verification is extracted into one helper shared by both callbacks rather than duplicated, and the handoff text now points the volunteer at the re-issue URL instead of ask-the-operator. Gateway-only and undeployed, like the rest of stage 4; StrictRoster and stage-3 deploy state untouched.

Verification (1)
  • 504 of 504 solution tests pass in the .NET 9 SDK container (Gateway 138 = 132 baseline + 6 new; Contracts 120; Simulation 246). All four re-issue guards are mutation-verified rather than merely green: disabling supersede-deletion fails exactly Reissue_MintsAFreshCodeAndKillsThePriorOne, the chain cap exactly Reissue_ChainCapExhausts, the cooldown exactly Reissue_CooldownBlocksAnImmediateRepeat, and the pending-only check exactly Reissue_RefusesOnceInstalled - one guard, one test, no overlap. Coverage also proves an expired bootstrap recovers across a service restart (two service instances on one store), that unknown and revoked SteamIDs refuse with distinct reasons, that exhaustion refuses new codes without damaging the pending one, and that the re-issued token never appears in the store file. The two RoadmapViewEndpointsTests failures on the Windows host are pre-existing path-separator issues, absent in the container, unrelated. Not exercised against a real Steam callback - the OpenID verify is the same code the enrollment callback has always used.
Evidence: src/Game.Gateway/Valheim/SteamEnrollmentService.cs src/Game.Gateway/Valheim/SteamEnrollmentEndpoints.cs tests/Game.Gateway.Tests/SteamEnrollmentServiceTests.cs docs/plan-m1-strict-admission.md
Recorded by Claude · associated with the Git commit containing this note
documentation Lumberjacks M1

Current-focus text caught up: roster gate verified live, DNS name exists.

Impact: The roadmap no longer claims TLS is blocked on DNS or that the roster gate awaits real-join verification - gate 3 closed live 2026-07-17 and comfy-p7.duckdns.org points at the reserved static address; what remains is the ACME contact on the VM and the stage-3 cut, plus fail-closed admission in the next mod release.

Verification (1)
  • LJ 4c0897e records the live strict-window accept and the in-memory flag reverting on restart; comfy 29326eb records the DNS name and resolver verification.
Evidence: docs/roadmap/valheim-volunteer-roadmap.json
Recorded by Codex · associated with the Git commit containing this note
documentation Lumberjacks M1

Corrected stage 3's blocker list: DNS and firewall are done, only the ACME contact remains.

Impact: The plan no longer claims a DNS A record blocks stage 3 - comfy-p7.duckdns.org has pointed at the reserved static address since 2026-07-17; the sole remaining human input is the ACME contact address, set on the VM at next boot.

Verification (1)
  • comfy 29326eb records the name and public-resolver verification; comfy 2765ff9 opened 80/443.
Evidence: docs/plan-m1-strict-admission.md
Recorded by Codex · associated with the Git commit containing this note
verification Lumberjacks M1

Proved the release cut's pass verdict and solved risk 12's clone-vs-worktree mystery.

Impact: The release identity gate is now demonstrated in both directions (refuse and pass), and rebuild-to-verify's blocker is a named, reproducible decision: the SDK embeds git HEAD in the PDB, so the artifact hash moves with every commit and a cut built pre-commit can never be rebuilt from its release commit.

Verification (1)
  • Rehearsal cut m1-rehearsal-20260718-r1 (full non-WhatIf run, then reverted) returned OK with both DLLs agreeing; EnableSourceControlManagerQueries=false made a local clone and the working tree build byte-identical DLLs.
Evidence: docs/plan-m1-strict-admission.md comfy commits 877ff11 + 554488d
Recorded by Codex · associated with the Git commit containing this note
implementation Lumberjacks M1

M1 stage 4: a one-use bootstrap replaces the plaintext credential echo

Impact: Redeeming an invite no longer hands the browser a reusable secret. The Steam callback returned the config snippet with lumberjacksClientAccessKey in it, so the volunteer's long-lived credential landed in browser history, screenshots, and anything watching a plaintext response. It now returns a single-use setup code, and POST /join/bootstrap exchanges that code for the config exactly once. The access token is minted at consumption rather than parked in the store waiting to be collected, so it never exists at rest in any form, and an enrollment carries no credential at all until the installer acts - Verify answers bootstrap_pending and authenticates nothing, so a pending enrollment fails closed. POST rather than GET means the code cannot be spent by pasting a URL into a browser and stays out of history, referers, and access logs. The endpoint is public and rate-limited under the join limiter, deliberately outside the capability gate, because an installer has no credential to present yet. The store goes v2 to v3 in place on first save; v2 enrollments keep their token hash and keep verifying, so the deployed roster is unaffected. It does not close M1 gate 4 alone: the access token still crosses a plaintext link at consumption until stage 3 brings TLS. An expired bootstrap strands its volunteer, since one-active-per-SteamID refuses a second enrollment and re-issuing needs an admin revoke plus a fresh invite; the 24h TTL makes that unlikely rather than impossible, and self-serve re-issue is not built.

Verification (1)
  • 480 of 480 solution tests pass, 114 of them Gateway (109 baseline + 5 new), built and run in a .NET 9 SDK container. The single-use claim is mutation-verified rather than merely green: disabling the bootstrap.Used gate fails exactly Bootstrap_IsSingleUse and no other test. Coverage also asserts that the browser's code authenticates nothing (bootstrap_pending), that a revoke between invite and install beats a volunteer still holding the code, that expiry rejects, that a revoke-and-re-invite cycle mints a different token rather than resurrecting the old one, that neither the bootstrap nor the access token ever appears in the store file, and that a migrated v2 store still verifies its frozen-mod credential and rewrites as v3. Not deployed and not exercised against a real Steam callback.
Evidence: src/Game.Gateway/Valheim/SteamEnrollmentService.cs src/Game.Gateway/Valheim/SteamEnrollmentEndpoints.cs tests/Game.Gateway.Tests/SteamEnrollmentServiceTests.cs
Recorded by Claude · associated with the Git commit containing this note
implementation Lumberjacks M0

Pin the roadmap artifact and its sources to LF so a fresh clone cannot break byte verification

Impact: The repository had no .gitattributes, so roadmap.html's bytes depended on the accident of how a given checkout was made. scripts/roadmap.mjs writes LF; with core.autocrlf=true, the Windows default, a fresh clone checks the artifact out as CRLF, which changes the bytes. Three things then break at once: roadmap:check compares a CRLF file against a fresh LF render and fails with a spurious stale, telling the operator to regenerate a page that was never wrong; X-Roadmap-Sha256 stops matching the committed artifact, so the served page can no longer be verified byte-for-byte against the tree, which is the whole point of reporting it; and every render rewrites the files back to LF as permanent working-tree churn. This machine only avoided it because the generator wrote the files and git had not yet touched them. The two JSON sources are pinned for the same reason: the script writes them LF and would fight the checkout on every note. Comfy already pins its evidence folder this way.

Verification (1)
  • git check-attr reports text unset for all three paths, the LF-to-CRLF warnings they previously emitted are gone, and the artifact's SHA-256 is unchanged at cd808269, so the pin renormalizes nothing that was already committed. Roadmap check still passes.
Evidence: .gitattributes
Recorded by Claude · associated with the Git commit containing this note
planning Lumberjacks M1 · M4a

Cut the readiness lease from M1's exit gate; its only consumer is M4a, which already owns and defines it

Impact: M1's exit gate now requires an invited, enrolled, compatible account, and no longer requires a fresh readiness lease or a stale-lease reject. lease_stale was blocked rather than deferred: nothing issues a readiness lease - no endpoint, no record, no field - because M1 named it as a deliverable without ever saying who mints one, what it attests, or how long it lives. It was undefined in M1 because M1 has no consumer for it: M4a already owns exact per-peer readiness and reconnect/takeover rules, already requires an exact per-peer readiness lease in its work, and already tests lease takeover at its exit. M1 was holding a contract on M4a's behalf, so M4a's inputs stop claiming a readiness lease among the contracts M1 delivers, and M1's does_not_own gains volunteer readiness scheduling. Building it inside M1 would have hard-coded an identity model the stage-3 mod cut then inherits, to satisfy a gate whose only reader specifies the lease differently and per peer.

Verification (1)
  • Every edit was applied against exact-match source text, so a criterion that had drifted would have failed the amendment rather than being silently rewritten; roadmap check passes with the amended gate rendered. The destination was corrected before commit: an earlier revision moved the lease to M5, which the roadmap's own graph refutes - M4a depends on M1 alone, so a lease owned by M5 would make M4a wait on a milestone it does not depend on. Every surviving readiness-lease reference was re-read: M4a work and inputs, current_focus, and the concurrent-volunteers readiness requirement, which gates on M4a and M4b rather than on M1.
Evidence: docs/roadmap/valheim-volunteer-roadmap.json docs/plan-m1-strict-admission.md
Recorded by Claude · associated with the Git commit containing this note
implementation Comfy M0

Make the drill finalize the durable pin, or say loudly that it did not

Impact: Drill phases 2-4 pin the Gateway through docker-compose.promotion.yml, which compose does not auto-load, while LUMBERJACKS_GATEWAY_IMAGE in the host environment is never touched. A drill therefore ended with the candidate running, every receipt green, and the reboot path still resolving the previous release: the systemd unit runs plain docker compose up -d, which would revert the Gateway with nothing to indicate it happened. Hit for real promoting m1-clean-20260717-r1 - the container was on the candidate while the env still pinned the drill's M0 image - and caught only by checking the durable pin rather than the running container, which is exactly the check nobody performs when four receipts say ok. An earlier commit retired the override once, but the drill silently re-creates it every run, so the trap resets after each promotion. The new -Finalize switch executes the runbook's step 3 instead of leaving it a manual footnote: back up environment and override, point the pin at the promoted tag, delete the override, then prove the reboot path resolves the candidate and answers health. It stays a switch rather than an automatic step because drill-only runs prove rollback without promoting. Either way the restore receipt now records durable_pin, durable_pin_matches_candidate and override_retired, and a mismatch prints a warning naming the stale pin and what will happen on reboot.

Verification (1)
  • The script parses and both switches are declared, but -Finalize was not exercised end to end: P7 had already been finalized by hand, and re-running the drill would have stopped a server with a player about to connect. The shell it emits is the same sequence proven by hand minutes earlier.
Evidence: infra/gcp/p7/scripts/run-promotion-drill.ps1
Recorded by Claude · associated with the Git commit containing this note
deployment Lumberjacks M1

Promote m1-clean-20260717-r1 to P7: M1's Gateway work is live, roster gate still off

Impact: P7 now runs the M1 Gateway cut rather than m0-clean-20260716-r2. It is Gateway-only - the mod stays frozen at ComfyNetworkSense 0.5.31 - so the hashed-at-rest enrollment store, the capability split, per-surface rate limits, the one-seat reservation, the strict-admission roster gate, and the credential-derived consumer recipient are all live without a mod release. This retires the standing risk that stage 1's enrollment-store migration had never executed against real data: it has now run against the real store. StrictRosterEnabled ships default off, so strict roster admission is deployed but not enforcing; a roster miss refuses a join, so it stays opt-in per window until it is verified against real joins and can be flipped with a way back. The drill proved cold-start, rollback to the historical release, and restore, each health-checked and identity-verified; the durable environment pin was finalized by hand afterwards, because the drill at that time left the pin stale while the container ran the candidate.

Verification (1)
  • Verified from the release tag on db45cf2, the bundle manifest, and the drill's restore receipt dated 2026-07-17T05:34:10Z recording gateway_health=ok, gateway_image=sha256:3576d8e0, mod_runtime_hash=match and mod_fallback_hash=match. Not re-verified live: the P7 VM is currently TERMINATED, so the running image, the durable pin, and the migration's collapse outcome are asserted from receipts rather than observed.
Evidence: docs/plan-m1-strict-admission.md
Recorded by Claude · associated with the Git commit containing this note
implementation Comfy M0

Stop the promotion drill snapshotting backups of backups

Impact: Phase 1 archived all of the Valheim config directory, including the server's own hourly world zips under config/backups, so the snapshot scaled with backup history rather than world size: 44 GB across 75 files by 2026-07-17, against 8.6 GB of live worlds. Caught executing the drill for m1-clean-20260717-r1 with the server stopped for the whole gzip - 12 minutes in, 20.8 GB written and nowhere near done - and the archive heading for a volume with 58 GB free that also holds postgres, the ZDO WAL and the enrollment store. Filling it would have traded a stopped game server for a downed Gateway and a corrupted queue, so the drill was aborted, the partial archive removed and valheim-server restarted; nothing had been promoted, because phase 1 only reads and it never reached cold-start. It worked for M0/A4 only because config/backups was small then, and would have failed worse on every future release. Excluding them is safe precisely because they are backups: this drill snapshots the state a rollback needs, the live worlds plus the BepInEx runtime and config, and restoring one of the server's own zips has never been part of it. Not fixed: the drill still has no pre-flight disk check, so an oversized snapshot fails by filling the disk rather than by refusing.

Verification (1)
  • Verified on the VM that the archive scope goes 54 GB to 9.3 GB, and that a real tar with the exclude pattern emits zero members under config/backups/.
Evidence: infra/gcp/p7/scripts/run-promotion-drill.ps1
Recorded by Claude · associated with the Git commit containing this note
implementation Lumberjacks M1 · M4a

Derive the consumer's recipient from its credential, not its own claim

Impact: A client can no longer select which recipient it is recorded as. The consumer_id on the /consumer heartbeat is a GUID the client picks for itself, so every consumer telemetry key was a value the caller chose; where the caller presents an enrollment, the server-derived RecipientId now replaces it. It overrides rather than rejects on mismatch, because the frozen 0.5.31 mod never reads the value back and always sends its own GUID, so a mismatch is the normal case and rejecting it would refuse every real heartbeat. Callers with no enrollment keep the value they sent, since there is nothing to derive from. This was written off as needing the stage-3 mod cut and turned out Gateway-only. It is a precondition for M4a: when the queue becomes recipient-scoped, the recipient it is scoped by must already be server-derived, or isolation is enforced against a name the client chose.

Verification (1)
  • 469 of 469 solution tests pass.
Evidence: src/Game.Gateway/Valheim/ValheimZdoRedirectEndpoints.cs docs/plan-m1-strict-admission.md
Recorded by Claude · associated with the Git commit containing this note
implementation Lumberjacks M0

Gateway /roadmap re-reads its generated asset per request and reports the served bytes' SHA-256

Impact: The public roadmap no longer announces stale milestone state between releases. Republishing is one file copy into a mounted directory with no image rebuild and no restart, and X-Roadmap-Sha256 lets the served page be verified byte-for-byte against the committed artifact. The page itself stays deterministic, self-contained, and script-free: the drift was in how the Gateway read the asset, not in the asset.

Verification (1)
  • 109 of 109 Game.Gateway.Tests pass, including six new RoadmapViewEndpointsTests covering per-request refresh, an identical-length rewrite, BOM stripping, the fallback page, and mount resolution preferring a mounted asset only once present.
Evidence: src/Game.Gateway/Endpoints/RoadmapViewEndpoints.cs tests/Game.Gateway.Tests/RoadmapViewEndpointsTests.cs docs/roadmap/README.md
Recorded by Claude · associated with the Git commit containing this note
implementation Lumberjacks M1

M1 stage 2 landed: a one-seat reservation, and a strict-admission roster gate keyed on the actual joining Steam account. Both are Gateway-only and ship disabled or defaulted safe; neither is deployed yet.

Impact: Admission can consult the enrollment roster on the Gateway alone, without waiting for a mod release. An earlier plan revision had deferred this to the mod cut after concluding that no Steam identity reached the Gateway; the live handshake capture disproved that, because the dedicated server forwards the account identity it authenticates itself. The seat lease is refreshed by the authoritative consumer's own poll traffic rather than a fixed timer, so a holder who crashed or was overturned after admission cannot keep the single seat, and a volunteer reconnecting keeps their own.

Verification (1)
  • 469 solution tests pass, 13 of them new admission tests. Each gate was mutation-verified: stubbing it out fails only the intended cases, and forcing liveness never to expire fails only the expiry cases.
Evidence: docs/plan-m1-strict-admission.md
Recorded by Claude · associated with the Git commit containing this note
implementation Lumberjacks M1

M1 stage 1 landed: hashed-at-rest enrollment store with unique-active-SteamID, revoke/expiry/last-used/audit and server-derived recipient_id; capability split (admin/producer/consumer/telemetry) replacing the global shared-key grant; per-surface rate limits; admin list/revoke and /enrollment/me endpoints.

Impact: A public consumer credential can no longer reach producer, admin, reset, or compaction operations; secrets no longer exist in plaintext at rest; a v1 store migrates in place so the frozen 0.5.31 mod keeps working unchanged.

Verification (1)
  • 79/79 Gateway tests pass including 16 new store/capability-matrix tests; live container smoke booted the Gateway and exercised invite, list, revoke, and consumer surfaces with the store confirmed hash-only on disk; two pre-existing Game.Simulation TelemetryV0 failures reproduced at clean HEAD and are tracked separately.
Evidence: tests/Game.Gateway.Tests/ValheimClientAccessMiddlewareTests.cs docs/plan-m1-strict-admission.md
Recorded by Claude · associated with the Git commit containing this note
planning Lumberjacks M1

M1 kickoff plan committed at docs/plan-m1-strict-admission.md: current-state map of enrollment/admission/transport, gap table against the M1 gate, four implementation stages grouped into two Gateway release cuts plus one mod cut, and the admission acceptance matrix skeleton.

Impact: M1 work can start with a fixed order and a declared release-cut budget; the fail-open handshake, plaintext credential echo, and client-chosen consumer id are now named defects with stages that remove them.

Verification (1)
  • Survey drafted via a HEARTH-routed large-context pass over Gateway and mod sources; fail-open PassThrough, http-only transport guard, client-side consumer id, and the hardcoded capacity were each re-verified by hand at exact source lines.
Evidence: docs/plan-m1-strict-admission.md
Recorded by Claude · associated with the Git commit containing this note
deployment Lumberjacks M0 · M1

Finalized the r2 promotion and opened M1: the P7 compose override is retired in favor of a durable environment image pin, current_release now records m0-clean-20260716-r2, M0 is complete, and M1 strict admission is active.

Impact: The frozen release survives VM reboots under an exact image pin, VM-side gateway rebuilds fail closed, and platform work moves to authoritative identity and admission.

Verification (1)
  • Base-compose-only up left the running gateway untouched at image sha256:141bd9e5a2ce with health ok; the systemd reboot path resolved the promoted pin from the host environment; the retired override is backed up on the VM.
Evidence: docs/roadmap/m0-a4-promotion-drill-receipt.json comfy infra/gcp/p7/PROMOTION-DRILL.md section 7 (retirement procedure and receipt)
Recorded by Claude · associated with the Git commit containing this note
deployment Lumberjacks M0

M0 CLOSED: golden-proof publication flipped to published; evidence public and immutable on GitHub

Impact: The full M0 ladder A1-A5 is complete: frozen source, reproducible clean candidate, validated release bundle, passed promotion drill, and published hash-bound evidence. The volunteer-platform work (M1 strict admission) is unblocked.

Verification (1)
  • Comfy main and Lumberjacks master pushed; A5 PUBLICATION.md permalink at 433f1cc and A4 README permalink at e6a1402 both resolve on GitHub, and the published raw bytes re-hash to the recorded SHA-256 values.
Evidence: https://github.com/djcdevelopment/comfy/blob/433f1cc33605561ae1287db9cd8f37125d795c5d/fieldlab/evidence/p7-gold-run-20260716-011112-authoritative-priority-cutover/PUBLICATION.md docs/roadmap/m0-a4-promotion-drill-receipt.json
Recorded by Codex · associated with the Git commit containing this note
verification Lumberjacks M0

M0/A4 promotion drill passed: cold start from prebuilt artifacts, artifact-only rollback, restore — all receipts green

Impact: A4, the last active M0 checkpoint, is complete; M0 closure now needs only the owner pushes and the golden_proof.publication flip per the A5 receipt.

Verification (1)
  • Four drill receipts green (snapshot 51GB archive hashed, cold start 14:02:43Z, rollback 14:04:51Z, restore 14:07:06Z), exact image IDs and mod SHA-256 verified at both paths each transition, gateway health ok, owner live-validated the promoted server post-restore.
Evidence: docs/roadmap/m0-a4-promotion-drill-receipt.json Comfy fieldlab/evidence/m0-a4-promotion-drill-20260716 @ e6a1402
Recorded by Codex · associated with the Git commit containing this note
implementation Lumberjacks + Comfy M0

Stage M0/A5 publication set and fix byte-stability defect

Impact: Staged the sanitized gold FieldLab run packet in the Comfy repository and committed the A5 publication receipt. Fixed a latent A3 byte-stability defect where line-ending normalization caused checkout hash mismatches by explicitly marking the hash-bound evidence set with -text. A5 closure remains pending until the A4 drill passes, the owner pushes the Comfy revision to the remote, and the roadmap publication status flips.

Verification (3)
  • The staged publication set hashes match the M0/A5 receipt, including the byte-identical acceptance snapshot.
  • A two-pass secret scan (deterministic regex and independent semantic LLM review) confirmed the publication set is clean, with the deployment IPv4 redacted as <gcp-public-ip>.
  • The .gitattributes fix makes Git blob bytes, working-tree bytes, and recorded SHA-256 hashes identical for all six hash-bound files regardless of checkout configuration.
Evidence: docs/roadmap/m0-a5-publication-receipt.json Comfy fieldlab/evidence/p7-gold-run-20260716-011112-authoritative-priority-cutover/ (PUBLICATION.md + report.md + acceptance-snapshot.json) Comfy fieldlab/.gitattributes Comfy commits e9f9fe3 + 433f1cc
Recorded by Codex · associated with the Git commit containing this note
implementation Lumberjacks + Comfy M0

Publish M0/A3 bundle receipt and FieldLab catalog

Impact: Closed the A3 checkpoint: the sanitized release-bundle receipt is committed, the FieldLab run catalog classifies every run folder with the fixed evidence vocabulary, and the A4 no-build snapshot/rollback drill is prepared as a plan-only script and runbook awaiting the scheduled GCP window.

Verification (3)
  • Bundle m0-clean-20260716-r2 re-validated valid at 2026-07-16T10:15:55Z; the receipt records the manifest hash, all seven per-file bundle hashes, and catalog hashes.
  • The FieldLab catalog classifies all 125 run folders (1 gold, 17 negative, 37 superseded, 70 historical); every supersession reference resolves to a newer run of the same scenario.
  • Secret scan over the manifest, receipt, and catalog found no SteamID or credential-shaped values; the A4 drill ran plan-only and produced drill-plan.json without any GCP mutation.
Evidence: docs/roadmap/m0-a3-release-bundle-receipt.json Comfy fieldlab/runs/index.json + CATALOG.md Comfy infra/gcp/p7/PROMOTION-DRILL.md + scripts/run-promotion-drill.ps1 Comfy commit 582a0e0
Recorded by Claude · associated with the Git commit containing this note
implementation Comfy M0

Build and validate the local M0 release bundle

Impact: Added fail-closed bundle tooling and produced the r2 candidate bundle with an immutable manifest reference, mod DLL, OCI Gateway archive, source inputs, and per-file SHA-256 inventory.

Verification (3)
  • Bundle validator passed for release m0-clean-20260716-r2 and the standalone manifest passed schema, source, hash, and no-secret checks.
  • Bundle includes the 94a3843e...0ba3a8 mod, Gateway OCI image 141bd9e5...e86fb, Docker/build inputs, and a 96 MB image archive.
  • Builder refused dirty/mismatched sources by contract; no GCP mutation or live artifact replacement occurred.
Evidence: Comfy commit 0cd40f4 local bundle label m0-clean-20260716-r2
Recorded by Codex · associated with the Git commit containing this note
implementation Lumberjacks + Comfy M0

Record reproducible M0 candidate r2

Impact: Clean tagged checkouts now produce a repeatable mod candidate and Gateway image under pinned deterministic build flags; the candidate is deliberately not promoted over the historical runtime until the release package and rollback drill pass.

Verification (3)
  • Two clean Comfy builds produced identical SHA-256 94a3843e...0ba3a8; Gateway candidate image is 141bd9e5...e86fb.
  • Clean Gateway tests passed 46/46 and the candidate image passed a local dependency-backed /health smoke.
  • Candidate r2 records all eleven Valheim/BepInEx assembly hashes and both repository commits; no GCP mutation occurred.
Evidence: docs/roadmap/m0-clean-build-candidate-r2.json Comfy commit b32bb5e Lumberjacks commit a7c47b5
Recorded by Codex · associated with the Git commit containing this note
implementation Comfy + Lumberjacks M0

Make clean artifact builds byte-reproducible

Impact: Pinned CI/deterministic compiler identity and a stable source map for the mod and Gateway builds; this creates a reproducible candidate path without promoting the historical runtime artifact.

Verification (3)
  • Two consecutive mod Release builds now produce identical SHA-256 f725e252...c667c.
  • The build flags do not change the 0.5.31 IL; they stabilize PE timestamp/MVID/debug identity.
  • Gateway source build properties are committed for the next clean Docker candidate; no GCP mutation occurred.
Evidence: Comfy commit b32bb5e Directory.Build.props staged below
Recorded by Codex · associated with the Git commit containing this note
implementation Lumberjacks + Comfy M0

Build and record clean M0 candidate artifacts

Impact: Produced a clean-checkout Gateway image and mod candidate manifest without touching GCP or the proven runtime; M0/A2 remains open because the clean mod PE identity differs from the historical DLL.

Verification (3)
  • Detached clean commits built successfully: ComfyNetworkSense 0.5.31 and Gateway image 8444c761...caf39.
  • Clean Gateway test suite passed 46/46 in the .NET 9 SDK container; an isolated container returned /health 200 with local PostgreSQL.
  • Clean mod IL is equal to the historical runtime, but its 72-byte PE timestamp/MVID/debug identity differs; no promotion or redeploy occurred.
Evidence: docs/roadmap/m0-clean-build-candidate.json Comfy commit 408018f Lumberjacks commit 1eaadd8
Recorded by Codex · associated with the Git commit containing this note
implementation Comfy M0

Record P7 evidence and operator deployment surfaces

Impact: Captured the audited FieldLab evidence, MCP visibility, GCP topology, tunnel lifecycle, deployment, rollback, and invite scripts while preserving the generated identity-bearing historical dashboard outside the release.

Verification (3)
  • PowerShell scripts parse; Terraform formatting, MCP JSON parsing, and Python compilation pass.
  • No credential-shaped values were found in the staged ops/evidence candidates.
  • The existing manifest and rollback rebuild gaps remain explicit M0/A2 work; no GCP mutation was performed.
Evidence: Comfy commit 408018f infra/gcp/p7/README.md
Recorded by Codex · associated with the Git commit containing this note
documentation Lumberjacks M0 · M3

Freeze cutover topology, evidence, and operator surfaces

Impact: Captured the P7 network overview, volunteer execution plan, evidence boundaries, interest-management boundary, dashboard viewing instructions, and local OMEN roadmap serving contract without widening any proof claim.

Verification (3)
  • Documentation candidates contain no Steam identities or credential-shaped values.
  • The plan records the 81,241 live-complete but formally INCONCLUSIVE owner observation and the M0/A1-to-M0/A5 execution sequence.
  • Roadmap HTML and OMEN dashboard configuration remain self-contained and local-only.
Evidence: docs/network/valheim-volunteer-platform-plan.md tools/omen-dashboard/nginx.conf
Recorded by Codex · associated with the Git commit containing this note
implementation Lumberjacks M0

Freeze Gateway authoritative runtime and pilot enrollment

Impact: Captured the tested Gateway queue, priority ordering, retained telemetry, enrollment, client-access middleware, and dashboard liveness lineage as one-owner release code; volunteer admission and durable per-run proof remain gated by M1 and M3.

Verification (3)
  • Docker .NET 9 SDK test run passed all 46 Game.Gateway.Tests tests; host .NET 8 is retained and does not claim a net9 build.
  • Sanitized the enrollment test to use a synthetic Steam identity and found no Steam identity in the staged diff.
  • Current relaxed completion and broad pilot access are recorded as known M3/M1 boundaries, not volunteer readiness.
Evidence: Lumberjacks Gateway runtime commit staged below Comfy runtime commit 26bb55b
Recorded by Codex · associated with the Git commit containing this note
implementation Comfy M0

Freeze ComfyNetworkSense 0.5.31 runtime

Impact: Captured the tested mod source lineage that produced the aligned 0.5.31 artifact; the image and DLL remain rollback/runtime references until clean release packaging is complete.

Verification (3)
  • Clean isolated Release build passed with zero warnings and zero errors.
  • Output DLL version is 0.5.31 and SHA-256 matches the aligned runtime artifact b31697d2...d7b.
  • No Steam identity or credential was added to the public journal.
Evidence: Comfy commit 26bb55b network/mod/ComfyNetworkSense/manifest.json
Recorded by Codex · associated with the Git commit containing this note
planning Lumberjacks + Comfy FieldLab M0 · M1 · M2 · M3 · M4a · M4b · M5 · M6 · M7

Established the evidence-first volunteer roadmap and recorded the latest owner session.

Impact: Separates live delivery from sealed proof, records the reset-erased receipt defect, and makes M0/A1 source freeze the active checkpoint.

Verification (4)
  • Historical P7 baseline remains 83,220 of 83,220 with zero eligible native ZDO sends.
  • Owner session closed 81,241 of 81,241 eligible revisions with zero pending or eligible native sends; Gateway reset erased the live denominator, so the formal verdict is INCONCLUSIVE.
  • OMEN, GCP, and runtime 0.5.31 identities align, but the image was built outside a clean Git checkout and remains rollback-only until M0 creates a reproducible release.
  • Roadmap rendering, dependency, no-secret, staged-policy, HTTP, and served-byte checks pass.
Evidence: docs/network/valheim-volunteer-platform-plan.md src/Game.Gateway/Community/roadmap.html fieldlab/evidence/p7-primary-v1-authoritative-priority-zdo-20260716-v0531.md
Recorded by Codex · associated with the Git commit containing this note