Minimal Enter Dispatch Verification #
Result #
A proven final root bullet/task continuation is now a local text-and-identity operation. It does not rewrite the old line, invalidate/rebuild the writer's full projection, or reparse the full attachment topology before returning from dispatch.
The expensive work was removed from this operation, not cached after being done once and not moved into a microtask that would still block the same paint. Full Record/search/metadata derivation remains in the existing asynchronous shared pipeline. No new worker, scheduler, or undo stack was added.
Dispatch Contract #
The supported operation:
- Inserts only the newline and continuation prefix at the caret.
- Inserts one fresh native block before that prefix, in the same Automerge change.
- Retains the original text characters, native marker, identity, and facts.
- Updates the existing writer coordinate state from the known insertion.
- Returns proven local geometry so the controller does not call
getTextFirstDocumentState()to rebuild the result immediately. - Updates the affected CM attachment geometry without the generic full-document
collectMarkdownStructures()pass or an immediate projection redispatch.
The writer independently validates the current frontier, prepared cache, source line and native marker, continuation syntax, UTF-16 boundaries, fresh identity, and insertion coordinates. It is not an arbitrary mutation callback with a flag to skip validation. Mutation hooks are rejected by this dedicated operation.
Manager validation also requires the structural delta to describe exactly the append. Combined metadata/structural operations use the existing general path. Input scalars and the prepared cache are captured before mutation, so synchronous observers cannot corrupt the result by mutating the caller's objects or requesting a prepared state. An actual observer write that advances the frontier is treated as a committed failure: the writer stops, records progress, and the controller recovers canonical state without replaying the insertion.
This is not a general incremental Markdown parser or a claim of constant work for every command. The fast path is limited to a nonempty, final root bullet/task item with a proven bullet-list native marker and no following/conflicting marker. Ordered/nested/quoted lists, selection replacement, legacy non-bullet native markers, ambiguous literal-sentinel cases, and other structural changes retain the general path. Undo/redo remains correct through the existing generic inverse and may still rebuild synchronously. A complete local index is published only for the proven topology; no partial AST is labeled complete.
Baseline And Method #
- Baseline runtime: commit
90f74c9bc7151aa929326b52668fde884620e38e. - Frozen runtime source:
/tmp/opencode/enter-dispatch-baseline/source. - Baseline Git tree:
acaba6b32c1b8335ccf723ffe8ada92e67410efb. - The measurement harness was updated identically for both lanes; its instrumentation is not part of the frozen baseline runtime.
- Final candidate
srcfingerprint:6c8200f83e863b1cb0d30beec5b78a2442a2f33e78f4f3f0a9eaa25a8f726535. - Fingerprint command:
git ls-files --cached --others --exclude-standard -z src | sort -zu | xargs -0 sha256sum | sha256sum. - Nix Chromium 136; isolated Vite-only server on 7496; WebSocket sync disabled.
- Fresh context, viewport 1280x900, 128-item plain list with trailing newline.
- One real Enter creates item 129; 80 subsequent characters are collected only after the Enter state settles. Setup is performed at 1x before any throttle.
- Final 6x candidate calibration: 6.09x; comparison baseline: 6.11x. The original 4.5-7.5 acceptance interval was not relaxed.
- Each browser command had a 180-second host timeout and exited successfully.
Final-Source Timings #
Milliseconds for one Enter per context. These are individual samples, not p95 estimates across many Enter actions.
| Metric | Desktop Baseline | Desktop Candidate | 6x Baseline | 6x Candidate |
|---|---|---|---|---|
| Editor dispatch | 132.6 | 19.1 | 791.3 | 115.3 |
| Keydown to first DOM mutation | 139.1 | 25.1 | 827.0 | 151.0 |
| Keydown to first RAF | 172.6 | 50.1 | 1033.0 | 294.2 |
| Old-line root deletions | 1 | 0 | 1 | 0 |
| Writer-cache rebuilds after Enter | 1 | 0 | 1 | 0 |
The baseline deleted and reinserted 10 characters from the unchanged last line. The candidate emitted no such deletion, and retained its existing cache rebuild count both immediately after Enter and after settling. Both lanes inserted one new native block and retained all 128 existing IDs.
Three earlier alternating 6x development pairs showed baseline dispatch 791-794 ms versus candidate 114-120 ms, and first RAF 1032-1036 ms versus 296-313 ms. Those repetitions preceded the final input-isolation/fallback guards; they corroborate the mechanism but are not pooled with the final-source sample.
This is a large reduction for the supported operation, not a full performance-gate pass. Approximately 115 ms dispatch and 294 ms first-frame latency remain in the final simulated 6x sample. Continuous typing and generic structural commands are separate performance targets; no general improvement is claimed for them.
Important measurement distinction: phases.enter.transaction measures dispatch.
The JSON elapsedMs includes derived settling and expensive independent validation
performed after the first frame. It must not be presented as dispatch or visible
input latency. The legacy input field may fall back to the DOM timestamp when
command-handled Enter emits no native input event; the table uses DOM and RAF.
Correctness #
- Full suite: 512 files passed, one skipped; 10,166 tests passed, three skipped; no type errors. The final bounded full run took 251.93 seconds.
- Production build and diff checks passed. The existing chunk-size warning remains.
- Direct tests verify the actual native marker position and old character cursors, not merely the editor's visible text.
writer.validateProjection()and independentbuildNodeIndex()comparisons validate the cached writer state and manager geometry, including trailing newlines, CRLF, immediate typing, undo/redo, and the supported task case.- Tests guard against full attachment parsing/state rereads on the supported dispatch path, malformed operations/deltas, callback mutation, synchronous observer writes, following markers, and legacy-marker fallback.
- Independent review found no blockers in the bounded operation contract.
- Final browser samples passed exact text, canonical/derived heads, retained IDs, independent native validation, 80 follow-on modify events, and zero browser errors. The known favicon 404 is recorded separately.
Reproduction #
Harness: tests/perf/file-index-roundtrip.perf.test.ts.
timeout --kill-after=5s 180s nix develop --command sh -c '
RUN_PERF_TESTS=1 FILE_INDEX_CPU_RATE=6 FILE_INDEX_EXPECTED_REDUCE_POSTS=0 \
FILE_INDEX_EXPECTED_ENTER_DELETIONS=0 FILE_INDEX_EXPECTED_CACHE_REBUILDS=0 \
FILE_INDEX_ROUNDTRIP_SOURCE=/home/anish/usr/try-reams/.worktrees/text-first-writer-spike \
FILE_INDEX_ROUNDTRIP_OUTPUT=/tmp/opencode/minimal-enter-final-source-6x.json \
VITE_DISABLE_WEBSOCKET_SYNC=1 \
PLAYWRIGHT_CHROMIUM_BIN="$(command -v chromium)" \
npx vitest run tests/perf/file-index-roundtrip.perf.test.ts \
--config vitest.config.perf.ts --maxWorkers=1
'
For baseline, select the frozen source directory and set expected deletions/cache rebuilds to 1. For desktop, set CPU rate to 1. Keep separate outputs.
Final-source comparison artifacts:
/tmp/opencode/minimal-enter-baseline-1x.json/tmp/opencode/minimal-enter-baseline-6x.json/tmp/opencode/minimal-enter-final-source-1x.json/tmp/opencode/minimal-enter-final-source-6x.json
Early artifact source.commit/source.tree labels were supplied by the runner;
use the baseline identity above and candidate fingerprint rather than interpreting
the dirty candidate as committed 90f74c9b.
Changes remain uncommitted. No merge, push, or protected app/sync process changes were performed.