feat(v3): D4 Milestone 2 — staging buffer + commit pipeline (v0.15)#84
Open
mbreiser wants to merge 1 commit into
Open
feat(v3): D4 Milestone 2 — staging buffer + commit pipeline (v0.15)#84mbreiser wants to merge 1 commit into
mbreiser wants to merge 1 commit into
Conversation
Second D4 milestone: the full add → plan → commit substrate, in Node, no UI (UI is Milestone 3). This is where most of D4's risk lives, and it's now fully test-covered. js/v3-import.js (staging API, dual-export): - createStagingBuffer(srcExperiment, filename, opts) — duplicate-anchor preflight (#6); filename-derived prefix - addToStaging(staging, condIdx, yours) — plan walk: visited-set transitive anchor closure (#5) into a per-batch registry (#4); plugin merge-vs-namespace decision (broadened identity = all fields but name, + rig guard when config-less); alias-bound plugin_name detection (#7); built-in `log` left alone; unknown-command-type notes; walks imported plugin config aliases - removeFromStaging / setStagingPrefix / setItemTargetName / setAnchorPlannedName / setPluginPlannedName — explicit name overrides persist across prefix changes (#4-defaults) - validateStaging — pre-commit blocking pass: condition-name collisions (with suggestions), planned anchor validity + collisions (incl. empty prefix, #2), plugin namespace collisions (#10), alias-bound plugin_name (#7), real anchor cycles (self-edges OK) - commitStaging — one shared aliasRewriteMap (#2); topological anchor insert (#3, self-edges ignored); name: rewrite (#1); plugin_name rewrite; plugin merge-by-default; comment-stamp provenance on imported conditions/anchors/ plugins (user request); atomic — validates first, snapshots, rolls back on any mid-commit throw Tests: suites N7–N10 (+66 checks) — dry-run build/add/adjust/commit, every conflict + built-in (collision, merge, merge false-positive guard, alias-bound, log, empty-prefix anchor collision, unknown command, transitive closure), edge cases (no variables:/plugins:, zero-alias, depth-3 chain topo order, self-edge vs genuine cycle, rollback), and preflight rejection (duplicate-anchor source, broken-alias parse). npm test: arena 10/10, v2 137/137, v3 576/576 (was 510). Footer v0.14 -> v0.15. Design doc notes the truly-circular-anchor mirror limitation (pre-existing, fails safe via rollback). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What this is
Milestone 2 of D4 (cross-library import). The full add → plan → commit
substrate that copies conditions (plus their anchors and plugin declarations)
from a second YAML into yours. Node-only, no UI (UI is Milestone 3). The
handoff calls M2 "most of D4's risk" — it's now fully test-covered without a
browser.
Decisions from review (confirmed by repo owner)
all plugin fields except
name, plus samerigwhen both are config-less(closes the empty-config false-positive both Codex passes flagged). No explicit
per-plugin mapping wizard for v1.
# imported from <source>onimported conditions, anchors, and added plugins) — pulled in from v1.1.
js/v3-import.js— staging API (dual-export)createStagingBuffer— duplicate-anchor preflight; filename-derived prefix.addToStaging— plan walk: visited-set transitive anchor closure into aper-batch registry (anchor referenced by two conditions imports once); plugin
merge-vs-namespace; alias-bound
plugin_namedetection; built-inlogleftalone; unknown-command notes; walks imported plugin
configaliases.removeFromStaging/setStagingPrefix/setItemTargetName/setAnchorPlannedName/setPluginPlannedName— explicit overrides persistacross prefix changes.
validateStaging— pre-commit blocking pass (condition-name collisions withsuggestions, planned-anchor validity + collisions incl. empty prefix, plugin
namespace collisions, alias-bound
plugin_name, real anchor cycles — self-edgesOK).
commitStaging— one sharedaliasRewriteMap; topological anchor insert(self-edges ignored);
name:rewrite;plugin_namerewrite; pluginmerge-by-default; provenance stamps; atomic (validate → snapshot → roll back
on any mid-commit throw). Does not call
pushUndo(the M3 UI wrapper will, once).Tests — Milestone 2 gate
Suites N7–N10 (+66 checks):
on
toString(), provenance stamp,addBareRefs:false.merge when class+config match; merge false-positive guard (config-less +
different rig → namespace); cross-buffer plugin collision → bump; alias-bound
plugin_nameblocks;plugin_name: logpreserved; empty-prefix anchor collisionblocks; unknown command type warns (non-blocking) + raw card preserved;
transitive closure.
variables:/plugins:, zero-alias, depth-3 chain topoorder, self-edge vs genuine cycle, failed-commit rollback restores doc+mirror.
at parse;
derivePrefix/suggestUniqueName.Footer v0.14 → v0.15. Design doc notes the truly-circular-anchor mirror limit
(pre-existing; D4 fails safe via rollback).
Not in scope
M3 three-pane UI + locking; M4 polish/docs.
🤖 Generated with Claude Code