Move docs/ package mirror into document-navigator plugin

Relocate the ~6k-file docs tree from the repo root into
plugins/document-navigator/docs/ so the plugin is self-contained and
portable. docs/superpowers/ (specs and plans) stays at the repo root.

Moved via cp+rm rather than git mv because directory rename() fails with
EPERM on this WSL /mnt DrvFs mount; git rename-detection pairs the
identical-content files at commit time.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-30 01:10:00 +01:00
parent fe3fedf42e
commit 9bf56a806b
6022 changed files with 12437 additions and 0 deletions

View File

@@ -0,0 +1,85 @@
# `helpers/helpers.ts` — packing, keys, and grid primitives
<!-- begin:auto-docs -->
_(no submodules)_
<!-- end:auto-docs -->
## Purpose
This module is the shared kernel of utility functions used by the analyser,
the solver strategies, and the optimisers. It owns the canonical
representation of a pixel index (a packed `y * width + x` integer), the
canonical colour key (`"r,g,b"`), the `computeBounds` reduction over a
packed-pixel set, and the boolean-grid builders that drive the
maximal-rectangle sweep and per-layer covering.
## Features
- `pack` / `unpackX` / `unpackY` give the package a single, branch-free way
to convert between `(x, y)` and a single integer. Using a `Set<number>`
of packed indices is dramatically cheaper than a `Set<string>` of
`"x,y"`.
- `colourKey` / `parseKey` round-trip an RGBA without committing to alpha;
the solver does not need alpha for keying.
- `computeBounds` is the only place we touch unpack-loop machinery for
bounds computation; everywhere else delegates here.
- `isFullyAvailable`, `rectCoversAnyRequired`, and `countRequired` are the
three predicates the optimiser relies on; they share an early-exit
pattern that keeps the solver O(area × candidates) rather than
O(area² × candidates).
- `buildAvailableGrid` / `buildRequiredGrid` allocate the 2-D `boolean[][]`
masks used by the cover strategies.
## Usage: Basic
```ts
import { pack, unpackX, unpackY } from "@suaveplan/emblem-solver";
const w = 8;
const idx = pack(3, 2, w); // 19
unpackX(idx, w); // 3
unpackY(idx, w); // 2
```
## Usage: Advanced
```ts
import {
buildAvailableGrid,
buildRequiredGrid,
isFullyAvailable,
} from "@suaveplan/emblem-solver";
const opaque = new Set<number>([0, 1, 2, 3]);
const earlier = new Set<number>();
const avail = buildAvailableGrid(2, 2, opaque, earlier);
const req = buildRequiredGrid(opaque, 2, 2);
isFullyAvailable({ x: 0, y: 0, w: 2, h: 2 }, avail); // true
```
## API Reference
| Symbol | Kind | Description |
|---|---|---|
| `pack(x, y, w)` | fn | Row-major packed index |
| `unpackX(i, w)` | fn | Recover `x` |
| `unpackY(i, w)` | fn | Recover `y` |
| `colourKey(rgba)` | fn | `"r,g,b"` |
| `parseKey(str)` | fn | `RGBA` with `a:1` |
| `computeBounds(set, w)` | fn | Tight bounding `Rect` |
| `isFullyAvailable(rect, grid)` | fn | All cells `true`? |
| `rectCoversAnyRequired(rect, req)` | fn | Any overlap? |
| `countRequired(rect, req)` | fn | Overlap count |
| `buildAvailableGrid(w, h, opaque, earlier)` | fn | 2-D opaque mask minus earlier layers |
| `buildRequiredGrid(set, w, h)` | fn | 2-D mask from packed pixel set |
## Implementation Notes
The functions are deliberately monomorphic over `boolean[][]`/`number` for
predictable JIT performance. The bounding-box reduction uses `±Infinity`
sentinels so it works for any non-empty set. The available-grid builder
skips earlier-layer pixels in O(1) per packed index — important when the
solver iterates orderings exhaustively over a colour set. None of these
helpers allocate beyond the grids they explicitly build; the predicates
return as soon as their early-exit condition is met, so worst-case work is
bounded by `rect.w * rect.h`.