refactor(NDNM): WarpRuntime decomposition + tech debt sweep#74
refactor(NDNM): WarpRuntime decomposition + tech debt sweep#74flyingrobots merged 73 commits intomainfrom
Conversation
- Retrospective: TSC zero + JoinReducer OpStrategy (docs/archive/retrospectives/2026-04-01-*.md) - CHANGELOG: TSC campaign, OpStrategy registry, dot-notation disable, EffectSinkPort widening - Design alignment audit: all points aligned or accepted drift - Playback: both hills achieved - Lessons: agent over-refactoring, worktree leakage, test-per-merge
ROADMAP: added P1b tier with 4 high-priority items from TSC campaign drift: - B171: audit 27 agent-authored files merged without review - B172: restore dot-notation via @typescript-eslint/dot-notation - B173: EffectSinkPort breaking change hygiene - B174: @git-stunts/trailer-codec type declarations Retro updated with 3 additional drift items that were initially glossed: - No design doc for TSC campaign (process skip) - dot-notation disabled globally (implementation shortcut) - 27 files merged via checkout --theirs (not aligned)
Process restructuring: - BACKLOG/ is now a flat directory of markdown files (one per B-item) - Cycles replace milestones: pull item → docs/design/cycles/<cycle>/ - The backlog file becomes the design doc for the cycle - No more ROADMAP as planning registry (kept for reference only) Migration: - 38 incomplete B-items extracted from ROADMAP into individual files - 13 completed OG-items moved to BACKLOG/done/ - 5 queued OG-items left in place - CONTRIBUTING.md rewritten for cycle-based process - CLAUDE.md updated (Task Tracking section) - docs/ROADMAP.md marked as migrated
B176: WarpRuntime + warp/ god class decomposition (XL, HIGH) B177: Cohesive WarpKernelPort — persistence union type cleanup (L, HIGH) B178: CLI __dirname path traversal fragility (S, HIGH) Origin: code quality audit findings (AUDIT_CODE_QUALITY.md, AUDIT_THE_JANK.md). Note: 161 any casts and 172 TODO(ts-cleanup) markers cited in the audit are already at zero — TSC campaign fixed those. The structural issues (god class, fragmented ports, path traversal) remain.
Replace B-number backlog system with The Method: lane-based backlog directories, legend-prefixed filenames, sequential cycle numbering, and dual-audience design docs. - METHOD.md signpost at root - docs/method/backlog/ with inbox, asap, up-next, cool-ideas, bad-code lanes - 49 B-number/OG items migrated to named files in appropriate lanes - 10 tech debt entries split from .claude/bad_code.md to bad-code/ - 13 cool ideas split from .claude/cool_ideas.md to cool-ideas/ - docs/method/process.md, release.md (moved from docs/) - docs/method/retro/, graveyard/, legends/ directories - BACKLOG/ directory removed - CLAUDE.md, CHANGELOG.md, docs/ROADMAP.md updated
Covers god object decomposition, raw error purge, type boundary cleanup, constructor hygiene, file size policy, and lint ratchets. Legend code: CC. All bad-code/ items and several asap/ items fall under this legend.
Design doc for @git-stunts/code-nav — a tree-sitter-powered tool that lets LLM agents extract named symbols, view file outlines, and find definitions without reading entire files. JS/TS + Rust. CLI + MCP server. Phased: core extraction → MCP → Rust → polish.
Five real scenarios from git-warp sessions showing 53-96% context reduction. Key insight: the compounding effect over a full session saves 20K-90K tokens — the difference between hitting compression mid-task and finishing cleanly.
Editor's Edition reframe: the product is not code-nav (a search tool). It is safe-context (a context governor). AST-aware extraction is one tooth of a policy-enforcing read layer grounded in empirical data from 1,091 sessions showing Read at 96.2 GB of context burden. Rewritten hill, 4-layer architecture (policy → structural extraction → transport → session hygiene), 7-command surface, phased delivery (governor first, precision tools second, session intelligence third).
Design cycle that started as AST-aware symbol extraction and pivoted to a full context governor after empirical data from Blacklight (96.2 GB Read burden) reframed the problem. Remaining work re-enters backlog as safe-context Phase 1.
Full design doc with command contracts, output shapes, test strategy, project structure, and technology choices. Phase 1 scope: safe_read, file_outline, read_range, run_capture, state_save/load. JS/TS only. MCP + CLI. Tree-sitter for structural extraction.
Tree-sitter is the parser. WARP graphs are the memory of structural truth over time — symbol lineage, structural deltas, observer- relative views. Not for MVP, but the ramp from ephemeral extraction to provenance-aware incremental context is clear.
Git has trees and branches. Grafting is attaching new growth onto existing rootstock. CLI: git graft, MCP: graft-mcp, npm: @git-stunts/graft.
REJECT fixes: - read_range bounded: max 250 lines, 20 KB, clipped with metadata - state_save capped at 8 KB with recommended template - safe_read uses lines + bytes (not lines alone), special-cases lockfiles and .min.js MUST fixes: - file_outline bounded: 60-char params, 200-entry cap - Project root defined: .git detection, symlink resolution, path escaping refused, logs in .graft/logs/ - Machine-stable reason codes for all policy decisions - intent documented as advisory only — never weakens policy - Build path refusal: no source-path guessing Repo: flyingrobots/graft (not git-stunts)
Two enforcement layers: MCP server (cross-LLM, voluntary) and Claude Code hooks (enforced). PreToolUse hooks on Read and Bash route through graft's policy gate — the agent never sees raw large files or full test dumps. New commands: graft doctor (diagnostic), graft stats (decision metrics). NDJSON metrics log for Blacklight validation. Agent ideas: parse cache, outline focus mode, smarter next-step hints, estimated savings in every response.
User-defined patterns for paths that should always be refused. Covers secrets (.env, credentials), large data files, project- specific generated code. Optional — built-in bans still apply without it. Reason code: graftignore.
REJECTs fixed: - action: "error" distinct from "refused" (operational vs policy) - Broken-file outline: best-effort with partial: true + parseErrors - .graftignore uses picomatch (declared dep, not transitive) - run_capture: cwd, env, timeout, max log size all specified Promoted from COULD/SHOULD/COOL to MUST: - Built-in secret file bans (.env, *.pem, *.key, id_rsa, etc.) - Outline truncation metadata (entryCount, elidedCount) - focus param on file_outline - doctor --json, stats --json, stats --since-clear - Log retention (metrics 1MB, logs 10MB, oldest pruned) - Symlink escape test, broken-syntax test, secret-file tests - Smart next-step hints with symbol names from outline - Estimated savings in every response - Parse cache (mtime-invalidated Map) - Explicit CLI binary names (graft + git-graft) - root param on safe_read, read_range, file_outline - explain field (one-sentence human-readable reason)
graft pack, graft since, graft explain, graft init, focus auto, capture handles, policy profiles (balanced/strict/feral), receipt mode, symbol heatmap, and the line where graft becomes a WARP substrate.
projection, focus, residual, receipt, witness. Not public CLI names — internal architecture doctrine. Gives coherence: policy is not arbitrary, projection is not truncation, focus is not slicing. "Derive the smallest lawful view of the code that lets the agent act without poisoning its own context."
Design cycle delivered a locked spec for Graft (context governor for coding agents) through two APPROVE/REJECT/ENHANCE review rounds. All escape hatches bounded, broken-file behavior specified, hooks enforcement defined. Implementation begins as graft cycle 0001 at flyingrobots/graft.
docs/release.md moved to docs/method/release.md during the Method bootstrap (cycle 0001) but the test path was not updated.
Each OpStrategy object now carries its own TickReceipt-compatible operation name (e.g. NodeRemove strategy has receiptName 'NodeTombstone'). This eliminates the redundant RECEIPT_OP_TYPE lookup tables that duplicated knowledge already present in the strategy registry. - Added `receiptName` property to all 8 strategy objects - Added `receiptName` to OpStrategy typedef and load-time validation - Deleted RECEIPT_OP_TYPE from JoinReducer.js - Deleted duplicate RECEIPT_OP_TYPE from ConflictAnalyzerService.js - ConflictAnalyzerService now imports OP_STRATEGIES (already imports from JoinReducer, so no new dependency direction) Closes bad-code/PROTO_receipt-op-type-redundant
SyncProtocol.loadPatchRange() was constructing a plain Error and manually attaching a code property. Now uses SyncError which provides proper error typing, context serialization, and consistent error hierarchy. Also added E_SYNC_DIVERGENCE to the SyncError error code table. Closes bad-code/PROTO_sync-protocol-raw-error
Introduced AuditError domain error class with four error codes: - E_AUDIT_INVALID: receipt field validation failures - E_AUDIT_CAS_FAILED: compare-and-swap ref update failures - E_AUDIT_DEGRADED: service degraded after exhausting retries - E_AUDIT_CHAIN_GAP: missing commit in audit chain ancestry Replaced all 16 raw Error throws in AuditReceiptService with typed AuditError instances carrying serializable context. Added AuditError to package exports, index.d.ts, and type surface contract. Closes bad-code/PROTO_audit-receipt-raw-error
Release Preflight
If you tag this commit as |
- TrustState: frozen class constructed by buildState(). Holds Maps of active/revoked keys, writer bindings, errors, and record count. - TrustRecord: remains a @typedef. It is Zod-parsed from external data and consumed as Record<string, unknown> throughout the trust chain — making it a class would break the index-signature compatibility that Zod parsing and signature verification depend on. Closes bad-code/PROTO_typedef-truststate-to-class.
Not permanently blocked — Zod parse wrapping + consumer signature widening is straightforward S-tier work, just more touch points than the XS vassals.
Release Preflight
If you tag this commit as |
…, unknown> pipeline The typedef is the symptom. The disease is 20+ function signatures across 5 trust files that accept Record<string, unknown> because nobody introduced a concrete type at the CBOR decode boundary. Effort upgraded from S to M.
Release Preflight
If you tag this commit as |
1 similar comment
Release Preflight
If you tag this commit as |
CHANGELOG updated with: - 11 typedef-to-class promotions - CBOR codec canonical key sorting fix - WarpStateV5 class as new public export Moved to ASAP for next cycle: - PROTO_typedef-trustrecord-to-class (M — Record<string, unknown> pipeline cleanup) - PROTO_typedef-orset-to-class (M — 10+ CRDT operations) - PROTO_typedef-patchv2-to-class (M — core entity, deep integration)
Release Preflight
If you tag this commit as |
Critical: - CONTRIBUTING.md: fixed broken cycle path (docs/design/cycles/ → docs/design/<NNNN-slug>/), stale BACKLOG/ refs, and retro path mismatch (docs/archive/retrospectives/ → docs/method/retro/) Major: - ROADMAP.md: updated stale BACKLOG/ references to docs/method/backlog/ - AuditReceiptService: writer mismatch now throws with explicit E_AUDIT_WRITER_MISMATCH code instead of defaulting to E_AUDIT_INVALID Minor: - TickReceipt: added @throws annotation to constructor JSDoc - METHOD.md: clarified structure diagram with <NNNN-slug> pattern - DeliveryObservation: documented that reason field is omitted (not null) when absent Nits acknowledged but deferred: - WarpRuntime delegation boilerplate (DRY) — future cleanup - WarpCore single-line JSDoc — cosmetic - Em-dash inconsistency — cosmetic - WarpStateV5 edgeBirthEvent default — intentional for old checkpoints - BTR computeHmac guard — validated upstream
- DX_warpruntime-delegation-dry (XS): extract delegation boilerplate helper - DX_warpcore-jsdoc-block-style (XS): expand single-line JSDoc to blocks
Release Preflight
If you tag this commit as |
1 similar comment
Release Preflight
If you tag this commit as |
Inline comments:
- ForkController: fork creation now rolls back ref on WarpRuntime.open
failure (was non-atomic — dangling ref on error)
- ForkController._isAncestor: replaced MAX_WALK counter with visited
Set for true cycle detection (was false-positive on deep histories)
- ForkController._validatePatchAgainstCheckpoint: backfill rejection
and divergence now throw typed ForkError with E_FORK_BACKFILL_REJECTED
and E_FORK_WRITER_DIVERGED codes (was raw Error)
- JoinReducer.cloneStateV5: restored structural fallback for plain
objects from checkpoint deserialization (was strict instanceof-only)
- JoinReducer: receiptName load-time validation now checks against
TickReceipt OP_TYPES allowlist (catches typos at module load)
Duplicate comments:
- ComparisonController: introduced ComparisonSideResolver class to
hold graph + scope + liveFrontier as instance state, with role tag
('left'/'right'/'source'/'target') preventing side swaps.
Live frontier captured once and shared across both sides.
- ComparisonController: added assertOptionsObject() validation for
compareStrand() and planStrandTransfer() options params (was leaking
raw TypeErrors on null/array/primitive input)
Release Preflight
If you tag this commit as |
…mparisonSide class ComparisonController: - NormalizedSelector is now a base class with 4 subclasses: LiveSelector, CoordinateSelector, StrandSelector, StrandBaseSelector. Each implements resolve() directly — no dispatch switch, no resolver intermediary. The selector IS the resolver. - ResolvedComparisonSide promoted from typedef to class. - ComparisonSideResolver deleted (selectors resolve themselves). - Live frontier captured once and shared via resolve() param. - assertOptionsObject() guards on compareStrand/planStrandTransfer. JoinReducer: - OpOutcomeResult is now a base class with 3 subclasses: OpApplied, OpSuperseded, OpRedundant. OpSuperseded carries the winning EventId as a structured field instead of a formatted string. - cloneStateV5 restored structural fallback for plain objects. - receiptName load-time validation checks OP_TYPES allowlist. BoundaryTransitionRecord: - VerificationResult promoted from typedef to class. - BTR.deserializeBTR returns class instance. ForkController: - _isAncestor uses visited Set for true cycle detection. - Fork ref creation rolls back on WarpRuntime.open failure. - Backfill rejection uses typed ForkError codes. Logged asap/NDNM_comparison-pipeline-class-hierarchy for remaining value object work (LamportCeiling, StrandId, WriterId, etc.).
Release Preflight
If you tag this commit as |
… ForkController hardening
Engineering standard for how JavaScript is written in git-warp. Ten rules: classes not typedefs, validation in constructors, subclasses not switches, instanceof for runtime checks, unknown means the class hasn't been built yet, factory functions are shims, serialization is the codec's problem, structured data not strings, errors are domain classes, modules are the encapsulation boundary. This is infrastructure. The code must be honest at runtime.
Release Preflight
If you tag this commit as |
1 similar comment
Release Preflight
If you tag this commit as |
Complete rewrite of the engineering standard. Not a style guide — a doctrine for writing JavaScript infrastructure that remains honest under execution, replay, migration, debugging, replication, failure, and time. Rule 0: Runtime Truth Wins. The Hierarchy of Truth. The Object Model. Seven Principles. The Anti-Shape-Soup Doctrine. The Review Checklist. Co-authored-by: James Ross <james@flyingrobots.dev>
Release Preflight
If you tag this commit as |
Refined structure, tightened language, added Hierarchy of Truth, Language Policy (JS default, TS allowed not authoritative, Rust escape hatch), Architecture section (browser-first, hexagonal mandatory), four-category Object Model, cross-realm branding note, Anti-Shape-Soup Doctrine, Review Checklist. Co-authored-by: James Ross <james@flyingrobots.dev>
|
All three findings from this review round were already addressed in commit 23fbacb (pushed before this review completed):
|
Release Preflight
If you tag this commit as |
- CONTRIBUTING.md: ../../METHOD.md → ../METHOD.md (one level up from .github/, not two) - SYSTEMS_STYLE_JAVASCRIPT.md: wrapped cross-realm branding snippet in a class body so the markdown code-sample linter can parse it
Release Preflight
If you tag this commit as |
Summary
Tech debt sweep + WarpRuntime decomposition + NDNM vassal liberation
Quick wins (6 items closed)
WarpRuntime god class decomposition (phases 1-3)
Extracted 6 of 11 mixin method groups into independent service controllers:
3,061 LOC extracted. Remaining kernel (checkpoint, patch, materialize, materializeAdvanced — 2,115 LOC) deferred.
NDNM typedef-to-class liberation (11 promoted)
AuditReceipt, WarpStateV5, Dot, EventId, EffectEmission, EffectCoordinate, DeliveryObservation, TickReceipt, PatchDiff, LWWRegister, BTR, TrustState — all promoted from phantom @typedef to real JavaScript classes with constructors, validation, and instanceof support.
CBOR codec canonical key sorting
Both CborCodec and defaultCodec now sort keys for class instances (not just plain objects). Uses instanceof checks to skip built-in CBOR types. Decouples class field declaration order from wire format.
Also includes
Zero public API surface changes — all 100+ methods remain on WarpRuntime.prototype.
Test plan
npm run lint— 0 errorsnpm run typecheck— 0 errorsnpm run test:local— 314 files, 5,157 tests passnode scripts/check-dts-surface.js— 248 exports, 0 errors