v0.4.0-prerelease — Phase 3: Source-Edit Engine
Pre-releaseMarker-bounded source-file splice with byte-equivalence contract, atomic
writes, JSONL undo log, 8-rule safety guard, brace+quote+comment-aware
@scope CSS carbonizer. Lead-fixed one blocking marker-regex bug
live-debugged via tester pins.
Built by a 4-agent team (architect / coder / security / tester) with
disjoint file ownership.
What landed
Contracts (src/contracts/source.ts, 463 lines)
MARKER_SYNTAXtable per filetype (tsx/jsx/html/vue/svelte/css)- 6 marker kinds collapsed to 3 groups (inject/variants/style)
InjectMarker,VariantBlockMarker,MarkerBlock,AcceptOperation,
DiscardOperationzod schemasSafetyErrorCodeenum,SafetyResultdiscriminated unionUndoEntryKindenum,UndoEntryschema (JSONL append-only)- 7 module interfaces, all constants
Modules (src/source/, 2700 lines / 7 files)
_helpers.ts(244) - shareddetectEol, sha256, atomicWrite, findMarkerBlocksafety.ts(403) - 8-rule pipeline; single 512-byte head-read serves
binary + magic-comment + EOL-detect (1 syscall round trip)inject.ts(387) -injectLiveScript/removeLiveScript; JSX/TSX
refused withagent-drivenfallback; SHA256 hash-mismatch detectionwrap.ts(499) -wrapVariantBlock/discardVariantBlock; heuristic
selector-to-anchor; brace-balanced tag-end walkeraccept.ts(338) -findMarkerBlock,extractVariant,expandReplaceRange,
acceptVariantwithop.variantCssfallbackcarbonize.ts(429) - pure CSS-in/CSS-out; recursive-descent parser;
:scope-var merge with paramOverrides;var(--x, fallback)resolution;
@media/@supportspreservedundo-stack.ts(201) - JSONL append, rotation at 10 MB, malformed-line
warn-skip on read
Tests (tests/source/, 99 new tests in 6 files)
safety.test.ts(22) - all 8 rules + EOL detection + happy pathinject-roundtrip.test.ts(13) - byte-equivalence roundtrip across
HTML/Vue/Svelte, CRLF preservation, double-inject refusal, hash-mismatchwrap-discard.test.ts(15) - selector heuristics, ambiguity, self-closing
tags, case-insensitive matchingaccept-splice.test.ts(17) - findMarkerBlock filtering, extractVariant
with @media nesting, expandReplaceRange indentation, paramOverrides bakecarbonize.test.ts(19) - worked example, var fallbacks, dead-var
elimination, @supports preservation, malformed throwsundo-stack.test.ts(13) - append/read/rotate, malformed resilience
Cumulative: 270/270 tests green (99 source + 94 browser + 77 bridge + 2 smoke).
Live-debugged bug fix
Initial marker regex used [^-]*? for HTML/Vue/Svelte (and [^*]*? for
JSX/CSS). The HTML body class forbade hyphens, but UUID injectIds, ISO
timestamps, dashed hashes and URL-safe base64 all contain hyphens.
Consequence: findMarkerBlock returned null for HTML-family,
removeLiveScript always threw, double-inject refusal silently failed open,
byte-equivalence contract could not be verified.
Fix: all 5 patterns switched to [\s\S]*? - the trailing terminator
(--> for HTML, */ for JSX/CSS) is unique by spec, no inner-char
exclusion needed. Tester's 6 [BUG]-pinned tests rewrote to assert correct
post-fix behavior.
Known limitations (deferred to Phase 6 component-detect.ts)
wrapselectorToAnchoris heuristic -.btndoes not match
className="btn primary"(multi-class); pinned as[FINDING]testwrapthendiscardnot full-file byte-equivalent for JSX (engine
consumes trailing newline);restoredByteEquivalentreports honestly
false; tests assert structural recovery insteadinjectthenremovehas collapseDoubleBlank artifact at splice site
(one byte difference); engine reports honestly; markers gone + content
structurally intact
Quality gates
typecheck: clean
test: 270/270 in 3.82s (19 files)
build: index.js 9.74 kB + live.js 31.30 kB
doctor: 7/7 OK
Next
Phase 4 - Agent-Loop + Skill-Korpus (src/agent/poll-loop.ts, skills/).
Long-poll loop with 270s slicing, variant-generation prompts encoding
Samuel's vault anti-slop checklist + UI-UX-Pro-Max corpus (MIT fork) +
Huashu directions + 4 Narrative Questions Pre-Code-Gate. AgentDB+HNSW
index over skills/data/corpus.