aiquadtreejs 0.5.5 → 0.5.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/llms-full.txt CHANGED
@@ -13,338 +13,140 @@ The short index lives at `llms.txt` (see https://llmstxt.org/).
13
13
 
14
14
  # aiquadtreejs
15
15
 
16
- [![npm version](https://img.shields.io/npm/v/aiquadtreejs.svg)](https://www.npmjs.com/package/aiquadtreejs)
17
- [![CI](https://github.com/yshengliao/aiquadtreejs/actions/workflows/ci.yml/badge.svg)](https://github.com/yshengliao/aiquadtreejs/actions/workflows/ci.yml)
18
- [![License](https://img.shields.io/badge/license-MIT-brightgreen.svg)](LICENSE)
19
- [![AI Generated](https://img.shields.io/badge/AI_Generated-Claude_Code_Opus_4.7_Max-blueviolet.svg)](https://www.anthropic.com/claude-code)
20
- [![繁體中文](https://img.shields.io/badge/lang-繁體中文-red.svg)](README_ZHTW.md)
16
+ Tiny 2D quadtree for per-frame rebuild collision broadphase. Insert AABBs, retrieve candidates, then run precise collision checks yourself.
21
17
 
22
- > A tiny 2D quadtree for per-frame rebuild collision broadphase. `insert` AABBs, `retrieve` candidates, `clear`. Caller does precise hit-testing. Designed for PixiJS games with 500–10,000 active entities.
18
+ > **Status: 0.5.8 - stable 1.0-track surface.** The root entry is the public API.
23
19
 
24
- Part of the [ai\*js micro-runtime ecosystem](https://github.com/yshengliao) — see also [aifsmjs](https://github.com/yshengliao/aifsmjs) (FSM), [aiecsjs](https://github.com/yshengliao/aiecsjs) (ECS), [aibridgejs](https://github.com/yshengliao/aibridgejs) (cross-context RPC), [aieventjs](https://github.com/yshengliao/aieventjs) (event emitter), [aipooljs](https://github.com/yshengliao/aipooljs) (object pool), and [aiaudiojs](https://github.com/yshengliao/aiaudiojs) (Web Audio shell).
25
-
26
- > **Status: 0.5.1 published.** `insert()` now validates object geometry (non-finite coords, negative dimensions throw `QuadtreeError`); 22 new tests (J/K groups). `retrieveInto(region, target)` is a steady-state zero-allocation broadphase (reused internal scratch + caller buffer); property-based dedup invariants. ≥95% coverage, ≤2 KB gzip.
27
-
28
- ---
29
-
30
- ## Why aiquadtreejs
31
-
32
- Naïve pairwise collision detection on `N` entities is `O(N²)`. At 1,000 entities that's a million comparisons per frame, which at 60 Hz is already a budget killer; at 10,000 entities it's a non-starter. A quadtree replaces the dense outer loop with a spatial filter: each entity asks "who could I possibly collide with?" and the tree returns a small candidate set — sub-linear on average for well-distributed inputs (worst case is `O(N)` when every object overlaps the query region). The precise hit test then runs only on candidates, dropping the actual comparisons by one or two orders of magnitude in typical game distributions.
33
-
34
- `aiquadtreejs` makes four deliberate trade-offs:
35
-
36
- - **Per-frame rebuild, not move-tracking.** Tracking which leaf an entity migrated into between frames is doable but error-prone; `clear()` + re-`insert()` is faster in practice and easier to reason about. This mirrors the Kontra.js philosophy. (`clear()` resets the root node and drops the child array; subdividing fresh next frame is cheap because the inner subdivision logic touches at most `maxLevels = 4` levels.)
37
- - **Set-based dedup on `retrieve`.** An AABB that straddles a quadrant boundary lands in multiple leaves. Without dedup the caller sees the same candidate two or four times and pays double for the precise hit test. The Set guarantees each candidate appears once.
38
- - **2D AABB only — no 3D, no R-tree, no KD-tree, no Circle / Line primitives.** Those are real techniques for real problems but they sit in a different size class. Keep this library at ≤ 2 KB gzipped and let user-land bring in heavier broadphase when needed.
39
- - **No precise hit-test.** Broadphase libraries that also do collision response always grow. The contract here ends at "here are the candidates"; pixel-perfect or shape-specific tests belong to whatever physics layer you already have.
40
-
41
- Why not just import `@timohausmann/quadtree-ts`? That library is solid and you should use it for stand-alone work. `aiquadtreejs` exists so that an ai*js stack can talk to entity IDs from `aiecsjs` without per-frame object adaptation — `insert({ id: eid, x, y, width, height })` lines up with the SoA columns you already maintain.
42
-
43
- > `aiquadtreejs` is one of the four 0.3-cycle siblings joining the family — alongside [aipooljs](https://github.com/yshengliao/aipooljs) (object pool), `aieventjs` (typed events; self-built, not a `mitt` fork), and `aiaudiojs` (Web Audio shell over a Howler.js `peerDependency`).
44
-
45
- ---
46
-
47
- ## Quick Start
20
+ ## Install
48
21
 
49
22
  ```bash
50
23
  pnpm add aiquadtreejs
51
24
  ```
52
25
 
53
- ```typescript
26
+ ```ts
54
27
  import { createQuadtree, type AABB } from "aiquadtreejs";
28
+ ```
29
+
30
+ ## Quick Start
55
31
 
56
- type Body = { id: number } & AABB;
32
+ ```ts
33
+ interface Body extends AABB {
34
+ id: number;
35
+ }
57
36
 
58
- // 1. Build the tree once.
59
- const qt = createQuadtree<Body>({
37
+ const tree = createQuadtree<Body>({
60
38
  bounds: { x: 0, y: 0, width: 800, height: 600 },
61
39
  maxObjects: 10,
62
40
  maxLevels: 4,
63
41
  });
64
42
 
65
- // 2. Per frame: clear and re-insert.
66
- function rebuild(entities: Body[]) {
67
- qt.clear();
68
- for (const e of entities) qt.insert(e);
69
- }
43
+ const bodies: Body[] = [
44
+ { id: 1, x: 100, y: 100, width: 32, height: 32 },
45
+ { id: 2, x: 400, y: 250, width: 32, height: 32 },
46
+ ];
70
47
 
71
- // 3. Per query: broadphase, then precise hit-test.
72
- function nearbyEnemies(player: Body, enemies: Body[]): Body[] {
73
- const region: AABB = { x: player.x - 50, y: player.y - 50, width: 100, height: 100 };
74
- const candidates = qt.retrieve(region);
75
- // Caller filters with precise AABB / pixel test:
76
- return candidates.filter((c) => aabbOverlap(c, region));
77
- }
78
- ```
48
+ tree.clear();
49
+ for (const body of bodies) tree.insert(body);
79
50
 
80
- Right-open coordinate semantics: `x + width` and `y + height` are exclusive (renderer-neutral; matches common conventions such as PixiJS `getBounds()`).
51
+ const candidates = tree.retrieve({ x: 80, y: 80, width: 120, height: 120 });
52
+ ```
81
53
 
82
- ---
54
+ ## Core API
83
55
 
84
- ## Capabilities / Limitations
56
+ - `createQuadtree<T extends AABB>({ bounds, maxObjects?, maxLevels? })` creates a tree.
57
+ - `insert(obj)` stores an object reference in overlapping nodes.
58
+ - `retrieve(region)` returns a deduplicated broadphase candidate array.
59
+ - `retrieveInto(region, target)` reuses a caller-owned result array.
60
+ - `clear()` empties the tree for the next frame and clears scratch buffers.
61
+ - `dispose()` is idempotent permanent teardown.
62
+ - Errors: `QuadtreeError`, `QuadtreeDisposedError`.
85
63
 
86
- | Will do (v1) | Won't do |
87
- | --------------------------------------------------------- | ----------------------------------------------------- |
88
- | 2D rectangle quadtree | 3D octree / R-tree / KD-tree |
89
- | `insert()` / `retrieve()` / `clear()` / `dispose()` | Move-tracking (use `clear()` + re-`insert()`) |
90
- | Set-based dedup on `retrieve` (each candidate once) | Precise hit-test (broadphase only) |
91
- | `maxObjects` + `maxLevels` knobs | Auto-rebalance / dynamic depth growth |
92
- | Reuse the root node across frames; resubdivide cheaply | Circle / Line / polygon primitives |
93
- | `dispose()` idempotent; post-dispose calls throw | Persistence / snapshot / serialise (out of scope) |
64
+ ## Model
94
65
 
95
- ---
66
+ - Coordinates are right-open: `{ x, y, width, height }` covers `[x, x + width)` and `[y, y + height)`.
67
+ - This is a broadphase only. Returned candidates may not actually overlap the query region.
68
+ - Expected usage is per-frame rebuild: `clear()`, insert active bodies, query.
69
+ - Objects spanning quadrant boundaries can be stored in multiple child nodes; results are deduplicated.
70
+ - `maxLevels` has no hard cap. Very high values plus spanning objects can create huge node counts.
96
71
 
97
- ## API sketch
72
+ ## Sharp Edges
98
73
 
99
- ```typescript
100
- interface AABB {
101
- x: number;
102
- y: number;
103
- width: number; // x + width is exclusive
104
- height: number; // y + height is exclusive
105
- }
74
+ - Known bug: a zero-size point exactly on the root `left/top` boundary, such as `{ x: bounds.x, y: bounds.y, width: 0, height: 0 }`, is currently ignored by the root overlap check. Zero-size objects away from that root minimum edge are covered by tests. Next code pass should fix the root containment helper and add boundary tests.
75
+ - Fully outside objects are ignored by retrieval.
76
+ - Negative width/height and non-finite coordinates throw.
77
+ - `retrieveInto()` clears the target array before writing results.
78
+ - After `dispose()`, all methods except `dispose()` throw `QuadtreeDisposedError`.
106
79
 
107
- interface QuadtreeOptions {
108
- bounds: AABB;
109
- maxObjects?: number; // default 10
110
- maxLevels?: number; // default 4
111
- }
80
+ ## AI Context
112
81
 
113
- interface Quadtree<T extends AABB> {
114
- insert(obj: T): void;
115
- retrieve(region: AABB): T[];
116
- retrieveInto(region: AABB, target: T[]): T[]; // ← new in 0.3.0
117
- clear(): void;
118
- dispose(): void;
119
- readonly disposed: boolean;
120
- }
82
+ - Short index: [`llms.txt`](llms.txt)
83
+ - Full generated context: [`llms-full.txt`](llms-full.txt)
84
+ - Stability contract: [`STABILITY.md`](STABILITY.md)
85
+ - Current review backlog: [`REVIEW.md`](REVIEW.md)
86
+ - Release history: [`CHANGELOG.md`](CHANGELOG.md)
121
87
 
122
- class QuadtreeError extends Error {}
123
- class QuadtreeDisposedError extends Error {}
124
-
125
- function createQuadtree<T extends AABB>(opts: QuadtreeOptions): Quadtree<T>;
126
- ```
88
+ ## License
127
89
 
128
- Full JSDoc lives in [`src/index.ts`](src/index.ts).
90
+ MIT
129
91
 
130
92
  ---
131
93
 
132
- ## Roadmap
94
+ <!-- ===== CHANGELOG.md ===== -->
133
95
 
134
- | Version | Adds |
135
- | ---------- | ------------------------------------------------------------------------------------------------------------------------------------- |
136
- | **0.1.0** | `createQuadtree`, `insert` / `retrieve` / `clear` / `dispose`, Set-based dedup, ≥95% coverage, ≤2 KB gzip. |
137
- | **0.3.0** | `retrieveInto(region, target)` zero-alloc API; property-based tests (`fast-check`); STABILITY.md tracking. |
138
- | **0.4.0** | Dependency hygiene (removed unused `tsx`, aligned `fast-check`); 0.3.x public surface frozen for the 1.x track. No runtime API change. |
139
- | **0.5.1** | `insert()` input validation: throws `QuadtreeError` for non-finite coords or negative dimensions; 22 new tests (J1–J15, K1–K7). |
140
- | **0.6+** | Evaluate 3D octree variant (`createOctree<T extends AABB3>`); see `STABILITY.md` for current draft. |
96
+ # Changelog
141
97
 
142
- ---
98
+ All notable changes to aiquadtreejs are summarized here.
143
99
 
144
- ## License
145
-
146
- [MIT](LICENSE).
100
+ ## [Unreleased]
147
101
 
148
- ---
102
+ ## [0.5.8] - 2026-06-14
149
103
 
150
- <!-- ===== CHANGELOG.md ===== -->
104
+ - Fixed: a zero-size point on the root left/top minimum boundary (`{ x: bounds.x, y: bounds.y, width: 0, height: 0 }`) is now inserted and retrievable. The root insert gate's right-open overlap test dropped it; a new `rootContains` check is inclusive on the minimum edge and exclusive on the maximum edge, preserving right-open `[x, x+width)` semantics. Boundary regression tests added.
105
+ - Documentation-only slimming pass across README, stability notes, review backlog, and LLM context.
151
106
 
152
- # Changelog
107
+ ## [0.5.6] - 2026-06-10
153
108
 
154
- All notable changes to this project are documented here. The format follows
155
- [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project
156
- adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
109
+ - Hardened retrieve validation, scratch cleanup, and size-budget docs.
110
+ - Kept root quadtree API stable and regenerated generated LLM context.
157
111
 
158
- ## [Unreleased]
112
+ ## Older releases
159
113
 
160
- ## [0.5.5] - 2026-06-08
161
-
162
- ### Changed
163
-
164
- - Project home migrated to the [`islumina`](https://github.com/islumina) GitHub org; the package is now published from there via npm trusted publisher (OIDC + SLSA provenance). Family-wide version alignment at `0.5.5` — no runtime or API changes.
114
+ - `0.5.5` through `0.5.1` focused on release hygiene, docs accuracy, and validation/retrieve regressions.
115
+ - `0.4.0` declared the stable ai*js quadtree surface.
116
+ - `0.3.x` added `retrieveInto()` and zero-allocation query paths.
117
+ - `0.1.x` introduced `createQuadtree`, `AABB`, `Quadtree`, and error classes.
165
118
 
166
- ## [0.5.2] - 2026-06-05
119
+ ---
167
120
 
168
- ### Docs
121
+ <!-- ===== STABILITY.md ===== -->
169
122
 
170
- - Review-driven documentation fixes (`README.md`, `README_ZHTW.md`, `llms-full.txt`) and corrected a stale version reference in the `src/index.ts` header comment. No functional change; `dist` byte-identical to 0.5.1.
123
+ # aiquadtreejs Stability
171
124
 
172
- ## [0.5.1] - 2026-06-02
125
+ ## Stable Surface
173
126
 
174
- ### Fixed
127
+ | Surface | Status | Notes |
128
+ | --- | --- | --- |
129
+ | `createQuadtree()` | Stable | Root factory. |
130
+ | `AABB`, `QuadtreeOptions`, `Quadtree<T>` | Stable | Public types. |
131
+ | `insert`, `retrieve`, `retrieveInto`, `clear`, `dispose` | Stable | Main methods. |
132
+ | Error classes | Stable | `QuadtreeError`, `QuadtreeDisposedError`. |
175
133
 
176
- - **`insert()` input validation** — `insert()` now throws `QuadtreeError`
177
- when the inserted object contains a non-finite coordinate (`NaN`,
178
- `Infinity`, `-Infinity` in any of `x`, `y`, `width`, `height`) or a
179
- negative dimension (`width < 0` or `height < 0`). Previously, such
180
- objects were silently mishandled (kept before subdivide, silently dropped
181
- after). Zero-extent objects (points / lines with `width=0` and/or
182
- `height=0`) remain valid and are not rejected. The `QuadtreeError`
183
- JSDoc already noted this use was reserved; the behaviour is now
184
- implemented and documented in `STABILITY.md`.
185
-
186
- ### Tests
187
-
188
- - Added J-group (J1–J15): `insert()` throws `QuadtreeError` for
189
- `width<0`, `height<0`, `NaN`/`Infinity` in any of `x/y/width/height`, and
190
- for `null`/`undefined` objects (J14/J15); valid zero-extent objects
191
- (width=0, height=0, mixed) are accepted.
192
- - Added K-group (K1–K7): oversized object appears exactly once in
193
- full-region and per-quadrant sub-queries after subdivide; `retrieveInto`
194
- buffer identity preserved across 60 clear+insert+retrieveInto frames;
195
- negative-origin bounds with negative-coord objects and queries; zero-
196
- extent point at a non-midpoint survives deep subdivision (maxLevels=4)
197
- and is retrievable with a tight region; maxLevels=1 with many same-
198
- quadrant objects — all retrievable, zero duplicates; non-origin bounds
199
- insert+retrieve correctness.
200
-
201
- ## [0.4.0] - 2026-05-29
202
-
203
- Dependency hygiene + stability freeze. **No runtime API addition or behaviour
204
- change** — `dist/index.js` is byte-identical to 0.3.1; consumers see no
205
- difference. This release unifies the ai*js family version line at 0.4.0 and
206
- formally freezes the public surface for the 1.x track.
207
-
208
- ### Changed
209
-
210
- - **devDependencies** — removed unused `tsx` (no script, config, or example in
211
- this package invoked it) and aligned `fast-check` `^3.23.0` → `^4.8.0` to
212
- match the rest of the ai*js family. Both are dev-only and absent from the
213
- published tarball (`files` ships `dist` + docs only), so consumers are
214
- unaffected.
134
+ ## Behavioral Contract
215
135
 
216
- ### Stability
136
+ - Bounds use right-open coordinates.
137
+ - Inserted object references are not cloned.
138
+ - Retrieval is broadphase and deduplicated.
139
+ - `retrieveInto()` preserves target array identity and clears it first.
140
+ - `clear()` drains node contents and scratch references.
141
+ - `dispose()` is idempotent and permanent.
217
142
 
218
- - The 0.3.x public surface — `createQuadtree`, the `Quadtree<T>` interface and
219
- all its members (`insert` / `retrieve` / `retrieveInto` / `clear` /
220
- `dispose` / `disposed`), `AABB`, `QuadtreeOptions`, `QuadtreeError`,
221
- `QuadtreeDisposedError` — is declared **frozen for the 1.x track**: it will
222
- not break before a 1.0.0+ major. The 3D octree variant remains a draft
223
- (target v0.6+).
224
-
225
- ### Internal (not shipped to npm)
226
-
227
- - `pnpm audit` reports no known vulnerabilities; `pnpm-lock.yaml` regenerated
228
- after the devDependency changes. Property tests re-run green under
229
- fast-check v4.
143
+ ## Current Caveat
230
144
 
231
- ## [0.3.1] - 2026-05-29
145
+ A zero-size point on the root minimum `x/y` boundary is known to be ignored by the current root overlap check. Treat this as a documented bug, not a stable behavior.
232
146
 
233
- ### Changed
234
-
235
- - **`retrieveInto` is now genuinely zero-allocation in steady state.** The
236
- internal dedup `Set` and DFS stack are hoisted to the tree instance and
237
- reused across calls (cleared, not re-created) instead of being allocated
238
- per query. Combined with the caller-owned `target` buffer, a per-frame
239
- broadphase loop issuing thousands of `retrieveInto` queries now allocates
240
- nothing once result sizes stabilise — the design goal stated in 0.3.0.
241
- Purely internal: no API, signature, or observable-behaviour change.
242
- `retrieve` still returns a fresh array each call.
243
- - **`dispose()`** now also clears the internal scratch, preserving the
244
- "drops references so the GC can reclaim everything" guarantee.
245
- - **Docs** — `AABB` JSDoc leads with a renderer-neutral right-open
246
- definition (PixiJS `getBounds()` demoted to a compatibility note);
247
- `dispose()` JSDoc now lists `retrieveInto` among the post-dispose
248
- throwers; the 0.3.0 changelog note reworded ("observationally identical"
249
- rather than "byte-for-byte"); `STABILITY.md` exports list now includes
250
- the `Quadtree<T>` interface.
251
-
252
- ### Internal (not shipped to npm)
253
-
254
- - Property test `prop2` uses `fc.uniqueArray` keyed on `id` instead of an
255
- early-return guard that skipped ~39% of runs on id collisions; the
256
- id-uniqueness invariant now runs on every case. Property generators mix
257
- in zero-extent midpoint points (`fc.oneof`) so the dedup invariants
258
- exercise the G4 regression shape, not just deterministic fixtures.
259
- - Tightened `I4` (`toBe(1)`); added `I13` (retrieve fresh-array vs
260
- retrieveInto buffer-reuse contrast — backward-compat lock) and `I14`
261
- (interleaved retrieve / retrieveInto correctness — shared-scratch guard).
262
-
263
- ### Notes
264
-
265
- - `dist/index.js` runtime differs from 0.3.0 only by the scratch-hoist
266
- optimisation; the public API and all observable behaviour are unchanged.
267
-
268
- ## [0.3.0] - 2026-05-29
269
-
270
- ### Added
271
-
272
- - **`retrieveInto(region: AABB, target: T[]): T[]`** — zero-allocation
273
- variant of `retrieve` for hot-path callers. Clears `target`, walks
274
- the same iterative DFS + Set dedup as `retrieve`, writes results
275
- into `target`, returns `target`. The returned reference equals the
276
- argument — callers can hold a permanent buffer and pass it every
277
- frame to eliminate the result-array allocation churn (5,000+ calls
278
- per frame in typical bullet-hell broadphase loops).
279
- - **`STABILITY.md`** — explicit stable vs experimental API tracking.
280
- Includes a v0.6+ 3D octree draft (no source code in this release).
281
- - **Property-based tests** via `fast-check` — 4 invariants covering
282
- `retrieve` dedup and `retrieveInto` identity / length / content
283
- equivalence. Adds `fast-check` to `devDependencies`.
284
-
285
- ### Changed
286
-
287
- - **`Quadtree.clear` JSDoc** — corrected the claim that "internal
288
- node objects are reused across frames"; only the root node is
289
- reused, child nodes are released on `clear()` and re-created when
290
- subdivision next triggers. No runtime behaviour change.
291
- - **README Roadmap / Status / API sketch** — synced to v0.3.0,
292
- including the `retrieveInto(region, target)` signature (the
293
- pre-0.2 Roadmap entry was a single-argument draft).
294
-
295
- ### Notes
296
-
297
- - `retrieve` behaviour is observationally identical to 0.1.1: the
298
- internal refactor extracts a shared `retrieveSet` helper that both
299
- `retrieve` and `retrieveInto` call, but `Set` insertion order →
300
- `Array.from` order is preserved by spec.
301
- - Bundle size: ≤ 2 KB gzip budget still ~50% headroom after this
302
- release (expected ~1050-1090 B gzip).
303
-
304
- ## [0.1.1] - 2026-05-28
305
-
306
- ### Changed (CI)
307
-
308
- - **`publish.yml` now triggers on `push: tags: ["v*"]`** (was `workflow_dispatch` only). Aligns with the trigger used by `aifsmjs` / `aiecsjs` / `aibridgejs`. Tag push now automatically runs the OIDC trusted publish.
309
- - **`npm publish --provenance --access public`** — the workflow now emits a [sigstore provenance attestation](https://docs.npmjs.com/generating-provenance-statements) so consumers can verify the tarball was built by this workflow on this commit.
310
-
311
- No runtime / source / API changes from 0.1.0. **0.1.1 is also the first version to actually land on npm — 0.1.0 was tagged in git but never published to npm.** Production bundles are byte-identical to the 0.1.0 git tag.
312
-
313
- ## [0.1.0] - 2026-05-28
314
-
315
- ### Added
316
-
317
- - `createQuadtree({ bounds, maxObjects, maxLevels })` factory — 2D AABB broadphase.
318
- - `insert(obj)` / `retrieve(region)` / `clear()` / `dispose()` lifecycle.
319
- - Set-based dedup on `retrieve()` so objects spanning multiple quadrants are returned once.
320
- - Per-frame rebuild model — `clear()` reuses internal node objects (zero GC churn frame-to-frame).
321
- - `disposed` read-only flag; post-dispose calls throw `QuadtreeDisposedError`.
322
- - Test coverage ≥95% statements / lines / functions / ≥90% branches (~30 it() blocks, groups A–H).
323
- - Size budget: ≤2 KB gzip.
324
- - Dual ESM + CJS build via `tsup` with `minify: true`; `sideEffects: false`; zero runtime dependencies.
325
-
326
- ## [0.0.1] - 2026-05-28
327
-
328
- ### Added (scaffold)
329
-
330
- - Full package scaffold landed (`package.json`, `tsconfig.json`,
331
- `tsconfig.test.json`, `tsup.config.ts`, `vitest.config.ts`, `biome.json`,
332
- `scripts/{verify-exports,check-size,build-llms-full}.mjs`,
333
- `test/scaffold.test.ts`, `examples/.gitkeep`, `.github/workflows/{ci,publish}.yml`,
334
- `llms.txt`, `llms-full.txt`).
335
- - `src/index.ts` remains a `throw` stub exposing the frozen 0.1.0 API surface
336
- (`createQuadtree`, `Quadtree<T>`, `QuadtreeOptions`, `AABB`,
337
- `QuadtreeError`, `QuadtreeDisposedError`).
338
- - `pnpm typecheck && pnpm lint && pnpm coverage && pnpm build &&
339
- pnpm verify:exports && pnpm verify:llms && pnpm check:size` walks clean
340
- against a single placeholder test.
341
- - Coverage thresholds temporarily set to `0/0/0/0`; tightened to
342
- `95/90/100/100` in 0.1.0 with real tests.
343
- - Size budget temporarily set to 3 KB gzip; tightened to the 2 KB README
344
- target in 0.1.0.
345
- - Publish workflow exists but trigger is `workflow_dispatch` only — no
346
- accidental npm release on tag push until 0.1.0.
147
+ ## Out of Scope
347
148
 
149
+ Precise collision checks, physics integration, spatial hashing, and 3D octrees are outside the current package.
348
150
 
349
151
  ---
350
152
 
@@ -352,80 +154,31 @@ No runtime / source / API changes from 0.1.0. **0.1.1 is also the first version
352
154
 
353
155
  # Contributing to aiquadtreejs
354
156
 
355
- Thanks for taking the time to look. aiquadtreejs is a deliberately small
356
- library (target ≤ 2 KB gzip); contributions that keep the surface narrow
357
- are easier to accept than ones that expand it.
157
+ Keep the tree small, allocation-aware, and explicit about broadphase semantics.
358
158
 
359
- ## Quick start
159
+ ## Local workflow
360
160
 
361
161
  ```bash
362
162
  pnpm install
363
- pnpm test # vitest
364
- pnpm coverage # vitest with v0.1.0 thresholds (95/90/100/100)
365
- pnpm typecheck # tsc --noEmit on strict mode
366
- pnpm lint # biome check
367
- pnpm build # tsup; dual ESM/CJS + .d.ts
368
- pnpm verify:exports # ensures package.json#exports matches dist/
369
- pnpm verify:llms # ensures llms-full.txt is in sync with README + CHANGELOG
370
- pnpm check:size # gzip per subpath against the size budget
163
+ pnpm typecheck
164
+ pnpm test
165
+ pnpm verify:docs
166
+ pnpm build:llms
167
+ pnpm verify:llms
168
+ pnpm check:size
371
169
  ```
372
170
 
373
- The full pre-publish gate is `pnpm prepublishOnly`, which runs typecheck,
374
- lint, coverage (with thresholds), build, exports verification, llms drift
375
- check, and size budget check — in that order.
376
-
377
- ## What gets in easily
378
-
379
- - Bug fixes with a failing test added first
380
- - README / typing corrections
381
- - Tests that lock down existing behaviour (especially the Set-dedup
382
- invariant on `retrieve`)
383
- - Performance work that keeps per-frame `clear()` + bulk `insert()` zero-GC
384
-
385
- ## What needs discussion first
386
-
387
- - Anything that changes the public surface (`createQuadtree`, `Quadtree<T>`,
388
- `AABB`, `QuadtreeOptions`, error classes)
389
- - Move-tracking / dynamic update (explicit non-goal — `clear()` + re-insert
390
- is faster in practice for ≤ 10k entities)
391
- - Circle / Line / Polygon shape primitives (out of 2D AABB broadphase
392
- scope; bring your own user-land wrapper)
393
- - 3D octree / R-tree / KD-tree (different size class; out of scope)
394
- - Anything that pushes the core gzip past 2 KB
395
-
396
- ## Design principles
397
-
398
- aiquadtreejs follows the ai*js library-core priority order:
399
-
400
- > Security > Correctness > Simplicity > YAGNI > Performance
401
-
402
- Key invariants:
403
-
404
- - `retrieve()` deduplicates with a `Set` so each candidate appears once
405
- regardless of how many quadrants it spans.
406
- - `clear()` reuses internal node objects across frames; no per-frame node
407
- allocation.
408
- - `x + width` and `y + height` are **right-open** (exclusive), matching
409
- PixiJS `getBounds()` semantics.
410
- - `dispose()` is idempotent.
411
-
412
- ## Commit & PR style
413
-
414
- - Commit messages: imperative subject under 70 chars; body explains *why*.
415
- - PRs: keep scope to one topic. Link the issue if any.
416
- - Tests required for any behaviour change. Property-based tests welcome
417
- for invariants (especially the Set-dedup property).
171
+ Run `pnpm lint` before PRs. If docs change, regenerate `llms-full.txt`.
418
172
 
419
- ## Reporting issues
173
+ ## Rules
420
174
 
421
- - Minimal reproduction welcome (paste the smallest insert / retrieve
422
- sequence that shows the bug).
423
- - For security issues, please email the maintainer rather than filing
424
- publicly.
175
+ - Preserve right-open coordinate semantics.
176
+ - Add tests for root edges, quadrant boundaries, zero-size objects, `retrieveInto()`, `clear()`, and dispose.
177
+ - Do not turn broadphase results into precise collision promises.
178
+ - Keep allocation behavior visible in docs and tests.
425
179
 
426
180
  ## License
427
181
 
428
- By contributing, you agree your changes will be licensed under the MIT
429
- license that covers this project.
182
+ MIT
430
183
 
431
184
  ---
package/llms.txt CHANGED
@@ -1,5 +1,9 @@
1
1
  # aiquadtreejs
2
2
 
3
- > A tiny 2D quadtree for per-frame rebuild collision broadphase. Insert AABBs, retrieve candidates with Set-based dedup, clear, dispose. Caller does precise hit-testing. Designed for PixiJS games with 500–10,000 active entities. Zero runtime dependencies. Part of the ai*js micro-runtime ecosystem.
3
+ Small 2D quadtree broadphase with insert, retrieve, retrieveInto, clear, and dispose.
4
4
 
5
- For the full LLM context (README + CHANGELOG + CONTRIBUTING concatenated), fetch [llms-full.txt](llms-full.txt).
5
+ - Start: README.md
6
+ - Stability: STABILITY.md
7
+ - Current backlog: REVIEW.md
8
+ - Changelog: CHANGELOG.md
9
+ - Full generated context: llms-full.txt
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "aiquadtreejs",
3
- "version": "0.5.5",
3
+ "version": "0.5.8",
4
4
  "description": "Tiny 2D quadtree for per-frame rebuild collision broadphase. Insert AABBs, retrieve candidates, clear. Caller does precise hit-testing. Designed for PixiJS games with 500–10,000 active entities.",
5
5
  "keywords": [
6
6
  "quadtree",
@@ -50,13 +50,14 @@
50
50
  "test:watch": "vitest",
51
51
  "lint": "biome check src test",
52
52
  "format": "biome format --write src test",
53
- "typecheck": "tsc --noEmit",
53
+ "typecheck": "tsc --noEmit && tsc -p tsconfig.test.json --noEmit",
54
+ "verify:docs": "node scripts/verify-docs.mjs",
54
55
  "verify:exports": "node scripts/verify-exports.mjs",
55
56
  "check:size": "node scripts/check-size.mjs",
56
57
  "build:llms": "node scripts/build-llms-full.mjs",
57
58
  "verify:llms": "node scripts/build-llms-full.mjs --check",
58
59
  "coverage": "vitest run --coverage",
59
- "prepublishOnly": "pnpm typecheck && pnpm lint && pnpm coverage && pnpm build && pnpm verify:exports && pnpm verify:llms && pnpm check:size"
60
+ "prepublishOnly": "pnpm typecheck && pnpm lint && pnpm verify:docs && pnpm coverage && pnpm build && pnpm verify:exports && pnpm verify:llms && pnpm check:size"
60
61
  },
61
62
  "devDependencies": {
62
63
  "@biomejs/biome": "^1.9.0",