docs: add OPSTACK-HANDOFF.md; install the 39 Unreal skills
Handoff: a pasteable resume prompt at the plugin root -- read order, exact state (Phase 0.5 green, Phase 1 done and measured, step 3 written but not compiled), the immediate next action, hard rules, open items, and the method lesson from this session. Skills: Jahni's UE library was at .claude/skills/core/<name>/SKILL.md, two levels deep, where Claude Code discovers skills one level deep -- so none of the 39 were loading. Flattened; 124 reference files intact, all frontmatter valid, folder names already matched their name: field. core/category.md left as documentation. Confirmed loading. They are untracked and cannot be tracked without un-ignoring .claude/ itself (git cannot re-include a file whose parent directory is excluded). Same shape as AUDIT P1; flagged, not actioned. Note for the next session: module-and-build-system documents PCHUsage, shared PCHs and IWYU -- the exact mechanism that blocked C10's settling experiment. That skill was in the repo, undiscovered, while it was worked out the slow way. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,103 @@
|
||||
# Handoff — VoxelForge operator stack, 2026-07-27
|
||||
|
||||
> Paste the block below into a fresh session. Everything it refers to is on disk and in git.
|
||||
|
||||
---
|
||||
|
||||
You're picking up an agreed refactor of the VoxelForge UE5 voxel plugin, on branch `experimental`
|
||||
(already checked out — do not create another). I'm Jahni. Design and progress are written down so you
|
||||
don't re-derive them.
|
||||
|
||||
## Read first, in this order
|
||||
|
||||
1. **`CLAUDE.md`** — project rules. **Rule #1 is absolute: never build, compile, or run the editor.**
|
||||
I build everything myself. When code is done, stop, say "ready to build", list the likely
|
||||
compile-error spots, and wait.
|
||||
2. **`OPSTACK-PROGRESS.md` — THE LAST ENTRY FIRST.** Append-only log of what is built vs merely
|
||||
written. This is the resume point.
|
||||
3. **`OPSTACK-PLAN.md`** — the plan. §2.5 op taxonomy, §2.6 acceptance bar, §4 phases, §5 invariants.
|
||||
4. **`OPSTACK-DECOMPOSITION.md`** — all 8 archetypes broken into ops, every param traced. §10.4 is
|
||||
the port order, §11 the open questions.
|
||||
5. **`AUDIT-2026-07.md` §C10** — read before touching the Maze equivalence test. Six builds were
|
||||
spent there; it is parked deliberately.
|
||||
6. **`CODEMAP.md`** — navigation. Trust symbol names over line numbers.
|
||||
|
||||
## Where things stand
|
||||
|
||||
**Phase 0.5 — DONE, green.** Five automation tests, all passing (Session Frontend → Automation,
|
||||
filter `VoxelForge`): `DensityPurity`, `ClassifyTileSoundness`, `DiffLayerContention`,
|
||||
`LiveEditInvalidation`, `OpStack.BoxVerdictFold`, `OpStack.MazeEquivalence`. They found and fixed a
|
||||
real bug (AUDIT C2 — five caches missing `LayoutVersion`).
|
||||
|
||||
**Phase 1 — DONE and verified.** `Maze` decomposes into **seven** ops with no contortion:
|
||||
`ConstantRock → LatticeCorridor → SdfRoughness → SdfCarve → Spine → Seal → Passage`. Measured:
|
||||
SDF reproduced **bit for bit**, **zero isosurface crossings** out of 20 000, window-invariant across
|
||||
worker threads, every box verdict survives brute force, and **23 of 60 tiles proved uniform** where
|
||||
`ClassifyTile` proves zero for any cave archetype. That last number is the perf case for the whole
|
||||
refactor, measured rather than argued.
|
||||
|
||||
**Phase 1 step 3 — WRITTEN, NOT COMPILED.** The stack is wired into `GetDensityAt` behind
|
||||
`UVoxelStrateDefinition::bUseOperatorStack`, with the ported-archetype list living only in
|
||||
`UVoxelStrateManager::UsesOperatorStackForChunk()`. **This is the immediate next thing to build.**
|
||||
|
||||
### The immediate next action
|
||||
|
||||
1. I build. Likely error spots: the `else switch` form in `GetDensityAt`, `FVoxelOpStack` as a
|
||||
`thread_local` (it is move-only, reset by move-assigning a temporary), the new include.
|
||||
2. Then the **visual A/B**, which is the last thing Phase 1 needs: tick `bUseOperatorStack` on a Maze
|
||||
strate, regenerate, compare against the same seed with it off. **Pass = recognisably the same
|
||||
maze** (same corridor scale, connectivity, feel). That is `OPSTACK-PLAN §2.6`'s bar — judged on a
|
||||
screenshot, not a diff.
|
||||
3. Then **Phase 2**, starting with the cheapest win: `FlatPlain` + `CrystalChamber` collapse into one
|
||||
op (`OPSTACK-DECOMPOSITION §3`). Ask me §3.1 first — whether the slab floor noise's Z term is
|
||||
intentional; if it can go, both archetypes become XY-pure and start skipping tiles.
|
||||
|
||||
## Hard rules that prevent real bugs
|
||||
|
||||
- **Density sign:** negative = solid, positive = air *at the mesher*. Inside the op stack the
|
||||
convention is INTERNAL (**positive = solid**), negated once by the caller. The SDF channel uses
|
||||
standard SDF convention, so `min()` means opposite things on the two channels. This is the #1
|
||||
source of confusion in the plugin — `VoxelDensityOp.h` explains it.
|
||||
- **Never run both density paths in one world**, and never compare them for equality (§C10).
|
||||
- Every cache key includes `LayoutVersion`; `ProcessQueue` stays `EQueueMode::Mpsc`; `Epoch` carries
|
||||
through every async path; don't "optimize" the `ARCHITECTURE §8.10` perf invariants.
|
||||
- Never edit `Binaries/`, `Intermediate/`, `*.generated.h`. Comments are French + English — match the
|
||||
surrounding file.
|
||||
- Commit per coherent unit with a real message. Never push. `main` is the known-good fallback.
|
||||
- Update `CODEMAP §3` for new/renamed symbols, `ARCHITECTURE §8` for design changes, tick phases in
|
||||
`OPSTACK-PLAN.md`, and append to `OPSTACK-PROGRESS.md`.
|
||||
|
||||
## ⚠️ The lesson from this session — it cost six builds
|
||||
|
||||
Chasing a 1-ULP difference in the Maze port, I proposed **five** hypotheses and every one was refuted
|
||||
by measurement: the `FVector` round-trip, a transcription slip, `/fp:fast` across translation units,
|
||||
inlining context, and compile-time-constant vs runtime parameters. Each was plausible. Each cost a
|
||||
build. What actually produced information was instrumenting — a bisect, a three-way comparison, a
|
||||
variable-isolation harness.
|
||||
|
||||
Worse, twice I reasoned confidently from a premise I hadn't checked (a build flag that had landed in
|
||||
the wrong module; a comparison that was circular by construction and could not fail).
|
||||
|
||||
**So: on any numeric discrepancy, instrument before hypothesising, and verify the premise before
|
||||
reasoning from it.** And know when to stop — Jahni called it, correctly, once the port was proven
|
||||
correct on every axis that affects the game and only the last rounding was unexplained.
|
||||
|
||||
## New this session: 39 Unreal skills are installed
|
||||
|
||||
`.claude/skills/<name>/SKILL.md` — they were nested one level too deep and invisible; now flattened
|
||||
and loading. Directly relevant: `automation-and-testing`, `coding-standards`,
|
||||
`module-and-build-system` (covers `PCHUsage` / shared PCH / IWYU — the exact thing that blocked
|
||||
§C10's settling experiment), `game-thread-performance`, `memory-and-gc`, `navigating-engine-source`.
|
||||
**Use them** — the one that would have explained the shared-PCH failure was sitting in the repo,
|
||||
undiscovered, while I worked it out the slow way.
|
||||
|
||||
## Known open items, deliberately not done
|
||||
|
||||
- **AUDIT C1** — unbounded `SeedF`, one line at six sites. Dormant at small seeds; applying it
|
||||
re-rolls the world's noise and forces a re-tune, so it wants its own build. **Still a real bug.**
|
||||
- **IWYU debt** — seven headers use engine types they never include; the plugin only compiles because
|
||||
of the shared PCH. Blocks `FPSemantics` experiments. Worth clearing on its own terms.
|
||||
- **AUDIT C10** — the parked ULP residue. Read it before reopening; five hypotheses are already
|
||||
refuted in a table there.
|
||||
- `OPSTACK-DECOMPOSITION §11` — five design questions for me, most importantly whether the two-channel
|
||||
`Eval` (already implemented) stays.
|
||||
@@ -811,3 +811,28 @@ connectivity, same feel. That is §2.6's bar, and it is the last thing Phase 1 n
|
||||
`OPSTACK-DECOMPOSITION §10.4` starts with FlatPlain + CrystalChamber collapsing into one op.
|
||||
|
||||
---
|
||||
|
||||
## 2026-07-27 — session handoff written. 39 UE skills installed.
|
||||
|
||||
**`OPSTACK-HANDOFF.md`** added at the plugin root: a pasteable resume prompt for a fresh session.
|
||||
Read order, exact current state, the immediate next action, the hard rules, the open items, and the
|
||||
method lesson from this session.
|
||||
|
||||
**39 Unreal skills installed.** Jahni dropped a UE skills library into `.claude/skills/`, but nested
|
||||
as `.claude/skills/core/<name>/SKILL.md` — two levels deep, where Claude Code discovers skills one
|
||||
level deep at `.claude/skills/<name>/SKILL.md`. None were being loaded. Flattened (39 SKILL.md, 124
|
||||
reference files, all frontmatter valid, folder names already matched `name:`); `core/category.md`
|
||||
left in place as documentation. Confirmed loading.
|
||||
|
||||
⚠️ **They are untracked**: `.gitignore` starts with `*`, and git cannot re-include a file whose parent
|
||||
directory is excluded, so nothing under `.claude/` can be tracked without un-ignoring the directory
|
||||
itself. Same shape as AUDIT P1. Flagged to Jahni, not actioned — vendoring a reference library into
|
||||
the plugin repo is his call.
|
||||
|
||||
**Immediately relevant to open work:** `module-and-build-system` documents `PCHUsage` / shared PCH /
|
||||
IWYU — i.e. the exact mechanism that blocked §C10's settling experiment. That skill was in the repo,
|
||||
undiscovered, while it was worked out the slow way. Worth reading before clearing the IWYU debt.
|
||||
|
||||
**Next single action unchanged:** build Phase 1 step 3, then the visual A/B on a Maze strate.
|
||||
|
||||
---
|
||||
|
||||
Reference in New Issue
Block a user