Skip to content

Add Jedit-owned Edict flat-text replacement reference - #302

Merged
flyingrobots merged 31 commits into
mainfrom
feature/replace-range-edict-source
Oct 19, 2026
Merged

flyingrobots merged 31 commits into
mainfrom
feature/replace-range-edict-source

Conversation

@flyingrobots

@flyingrobots flyingrobots commented Aug 23, 2026 •

Copy link
Copy Markdown
Owner

Add Jedit-owned Edict source that computes flat-text replacement as prefix + replacement + suffix, with ordered range, UTF-8, offset-boundary and no-op refusals. The public compiler build, independent verification, vendor closure, artifact locks and runtime consume one exact pinned basis: Edict 2b4832efe62de75e1f204cec72f9fe7d00ef9551 and Echo b314f7fd071985edad1f9876df383a85fb491205.

The executable package identity is sha256:4c2b7859f291e97b6b38fb265086e6cb0581ed030d54d38152b0585152120397. Clean macOS and Linux builds emit byte-identical package and verifier-report files. Runtime tests cover nine literal replacements, thirteen semantic refusals and five host-resource refusals. The invalid-original-UTF-8 witness failed against the previous package before passing with the corrected source. The clean pinned Docker package chain, both locked runtime targets and all twelve proof-harness regressions pass.

The branch also retains explicitly classified capability probes and noncompiling persistent-rope drafts outside the application gate, plus the proposed application representation. These are design and evidence artifacts, not executable authority. Canonical ownership, bearing and application documentation describe the boundaries.

This lands the completed flat-text reference and public build foundation. It does not close #296. The full campaign still requires the generic authored effect bridge, persistent AVL implementation, domain-typed outcomes, structural sharing, corpus agreement, atomic admission, Tick/WAL/receipt/readings and fresh-engine recovery. The schema and independent oracle remain separate from executable input. Existing editor integration and production rope behavior are unchanged.

Related: #296, flyingrobots/echo#889, flyingrobots/echo#917.

@flyingrobots flyingrobots added the work-in-progress Cycle or PR is intentionally in progress and not ready to merge label Aug 23, 2026
@flyingrobots flyingrobots self-assigned this Aug 23, 2026
@coderabbitai

coderabbitai Bot commented Aug 23, 2026 •

Copy link
Copy Markdown

Important

Review skipped

Too many files!

This PR contains 160 files, which is 60 over the limit of 100.

To get a review, reduce the PR to 100 files or fewer by splitting it into smaller PRs or changing its base branch.

Upgrade to a paid plan to raise the limit.

This review couldn't start because sufficient usage credits or metered capacity aren't available. Add credits or update usage-based reviews in the billing tab, then retry.

⚙️ Run configuration
  • Configuration used: Organization UI
  • Review profile: ASSERTIVE
  • Plan: Advanced
  • Run ID: 36f96c98-c3f5-42b6-ac91-c01739de22a2
📥 Commits

Reviewing files that changed from the base of the PR and between ecefbbb and 6155218.

⛔ Files ignored due to path filters: 8
  • edict/replace-range-probes/buffer-decoder/control/vendor/.atom-read.edict-lawpack-build.lock is excluded by !**/*.lock
  • edict/replace-range-probes/buffer-decoder/evidence/original/guard.log is excluded by !**/*.log
  • edict/replace-range-probes/buffer-decoder/evidence/reproduction196/guard.log is excluded by !**/*.log
  • edict/replace-range-probes/buffer-decoder/evidence/resource-stop/guard.log is excluded by !**/*.log
  • edict/replace-range-probes/range-assembly/evidence/candidate/guard.log is excluded by !**/*.log
  • edict/replace-range-probes/range-assembly/evidence/candidate/portable-guard.log is excluded by !**/*.log
  • edict/replace-range/tests/runtime/Cargo.lock is excluded by !**/*.lock
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing: 160
  • .github/workflows/ci.yml
  • .gitignore
  • CHANGELOG.md
  • docs/BEARING.md
  • docs/design/0159-edict-rope-representation.md
  • edict/replace-range-probes/basis-identity/Dockerfile
  • edict/replace-range-probes/basis-identity/Dockerfile.dockerignore
  • edict/replace-range-probes/basis-identity/PayloadEquality.edict
  • edict/replace-range-probes/basis-identity/README.md
  • edict/replace-range-probes/basis-identity/ReplaceRange.edict
  • edict/replace-range-probes/basis-identity/build.sh
  • edict/replace-range-probes/buffer-decoder/.gitattributes
  • edict/replace-range-probes/buffer-decoder/Decimal.edict
  • edict/replace-range-probes/buffer-decoder/README.md
  • edict/replace-range-probes/buffer-decoder/cases.json
  • edict/replace-range-probes/buffer-decoder/control/edict.application.json
  • edict/replace-range-probes/buffer-decoder/control/src/ReplaceRange.edict
  • edict/replace-range-probes/buffer-decoder/control/vendor/atom-read/adapter.cbor
  • edict/replace-range-probes/buffer-decoder/control/vendor/atom-read/adapter.sha256
  • edict/replace-range-probes/buffer-decoder/control/vendor/atom-read/echo-operation-configuration.cbor
  • edict/replace-range-probes/buffer-decoder/control/vendor/atom-read/echo-operation-configuration.sha256
  • edict/replace-range-probes/buffer-decoder/control/vendor/atom-read/edict.lawpack-output.json
  • edict/replace-range-probes/buffer-decoder/control/vendor/atom-read/exports.cbor
  • edict/replace-range-probes/buffer-decoder/control/vendor/atom-read/exports.sha256
  • edict/replace-range-probes/buffer-decoder/control/vendor/atom-read/manifest.cbor
  • edict/replace-range-probes/buffer-decoder/control/vendor/atom-read/manifest.sha256
  • edict/replace-range-probes/buffer-decoder/control/vendor/atom-read/verifier-rules.cbor
  • edict/replace-range-probes/buffer-decoder/control/vendor/atom-read/verifier-rules.sha256
  • edict/replace-range-probes/buffer-decoder/evidence/compiler-source.json
  • edict/replace-range-probes/buffer-decoder/evidence/original/decimal/ReplaceRange.edict
  • edict/replace-range-probes/buffer-decoder/evidence/original/decimal/stderr.jsonl
  • edict/replace-range-probes/buffer-decoder/evidence/original/decimal/stdout.jsonl
  • edict/replace-range-probes/buffer-decoder/evidence/original/fn-control/ReplaceRange.edict
  • edict/replace-range-probes/buffer-decoder/evidence/original/fn-control/stderr.jsonl
  • edict/replace-range-probes/buffer-decoder/evidence/original/fn-control/stdout.jsonl
  • edict/replace-range-probes/buffer-decoder/evidence/original/git-locks-receipt.jsonl
  • edict/replace-range-probes/buffer-decoder/evidence/original/guard.launch.json
  • edict/replace-range-probes/buffer-decoder/evidence/original/guard.result.json
  • edict/replace-range-probes/buffer-decoder/evidence/original/public-build.json
  • edict/replace-range-probes/buffer-decoder/evidence/original/read-control/ReplaceRange.edict
  • edict/replace-range-probes/buffer-decoder/evidence/original/read-control/application/executable-operation-package.cbor
  • edict/replace-range-probes/buffer-decoder/evidence/original/read-control/application/verification-report.cbor
  • edict/replace-range-probes/buffer-decoder/evidence/original/read-control/stderr.jsonl
  • edict/replace-range-probes/buffer-decoder/evidence/original/read-control/stdout.jsonl
  • edict/replace-range-probes/buffer-decoder/evidence/original/run.py
  • edict/replace-range-probes/buffer-decoder/evidence/provider-manifest.echo.json
  • edict/replace-range-probes/buffer-decoder/evidence/reproduction196/decimal/ReplaceRange.edict
  • edict/replace-range-probes/buffer-decoder/evidence/reproduction196/decimal/stderr.jsonl
  • edict/replace-range-probes/buffer-decoder/evidence/reproduction196/decimal/stdout.jsonl
  • edict/replace-range-probes/buffer-decoder/evidence/reproduction196/fn-control/ReplaceRange.edict
  • edict/replace-range-probes/buffer-decoder/evidence/reproduction196/fn-control/stderr.jsonl
  • edict/replace-range-probes/buffer-decoder/evidence/reproduction196/fn-control/stdout.jsonl
  • edict/replace-range-probes/buffer-decoder/evidence/reproduction196/guard.launch.json
  • edict/replace-range-probes/buffer-decoder/evidence/reproduction196/guard.result.json
  • edict/replace-range-probes/buffer-decoder/evidence/reproduction196/public-build.json
  • edict/replace-range-probes/buffer-decoder/evidence/reproduction196/read-control/ReplaceRange.edict
  • edict/replace-range-probes/buffer-decoder/evidence/reproduction196/read-control/application/executable-operation-package.cbor
  • edict/replace-range-probes/buffer-decoder/evidence/reproduction196/read-control/application/verification-report.cbor
  • edict/replace-range-probes/buffer-decoder/evidence/reproduction196/read-control/stderr.jsonl
  • edict/replace-range-probes/buffer-decoder/evidence/reproduction196/read-control/stdout.jsonl
  • edict/replace-range-probes/buffer-decoder/evidence/resource-stop/after-cleanup-usage.json
  • edict/replace-range-probes/buffer-decoder/evidence/resource-stop/guard.launch.json
  • edict/replace-range-probes/buffer-decoder/evidence/resource-stop/observer-record.json
  • edict/replace-range-probes/buffer-decoder/evidence/resource-stop/partial-toolchain-cleanup.txt
  • edict/replace-range-probes/buffer-decoder/run.py
  • edict/replace-range-probes/leaf-slice/LeafSlice.edict
  • edict/replace-range-probes/leaf-slice/README.md
  • edict/replace-range-probes/leaf-slice/cases.json
  • edict/replace-range-probes/leaf-slice/evidence/candidate-artifacts/executable-operation-package.cbor
  • edict/replace-range-probes/leaf-slice/evidence/candidate-artifacts/verification-report.cbor
  • edict/replace-range-probes/leaf-slice/evidence/candidate-compiler-source.json
  • edict/replace-range-probes/leaf-slice/evidence/candidate-report-inspection.json
  • edict/replace-range-probes/leaf-slice/evidence/compiler-source.json
  • edict/replace-range-probes/leaf-slice/evidence/public-build-candidate.json
  • edict/replace-range-probes/leaf-slice/evidence/public-build-red.json
  • edict/replace-range-probes/leaf-slice/run.py
  • edict/replace-range-probes/node-atom-read/Dockerfile
  • edict/replace-range-probes/node-atom-read/Dockerfile.dockerignore
  • edict/replace-range-probes/node-atom-read/README.md
  • edict/replace-range-probes/node-atom-read/edict.application.json
  • edict/replace-range-probes/node-atom-read/edict.lawpack.json
  • edict/replace-range-probes/node-atom-read/run.py
  • edict/replace-range-probes/node-atom-read/src/ReplaceRange.edict
  • edict/replace-range-probes/range-assembly/README.md
  • edict/replace-range-probes/range-assembly/RangeAssembly.edict
  • edict/replace-range-probes/range-assembly/cases.json
  • edict/replace-range-probes/range-assembly/evidence/assembly-stderr.jsonl
  • edict/replace-range-probes/range-assembly/evidence/assembly-stdout.jsonl
  • edict/replace-range-probes/range-assembly/evidence/baseline-stderr.jsonl
  • edict/replace-range-probes/range-assembly/evidence/baseline-stdout.jsonl
  • edict/replace-range-probes/range-assembly/evidence/candidate/assembly/application/executable-operation-package.cbor
  • edict/replace-range-probes/range-assembly/evidence/candidate/assembly/application/verification-report.cbor
  • edict/replace-range-probes/range-assembly/evidence/candidate/assembly/stderr.jsonl
  • edict/replace-range-probes/range-assembly/evidence/candidate/assembly/stdout.jsonl
  • edict/replace-range-probes/range-assembly/evidence/candidate/baseline/application/executable-operation-package.cbor
  • edict/replace-range-probes/range-assembly/evidence/candidate/baseline/application/verification-report.cbor
  • edict/replace-range-probes/range-assembly/evidence/candidate/baseline/stderr.jsonl
  • edict/replace-range-probes/range-assembly/evidence/candidate/baseline/stdout.jsonl
  • edict/replace-range-probes/range-assembly/evidence/candidate/compiler-source-sha256.json
  • edict/replace-range-probes/range-assembly/evidence/candidate/compiler-source.json
  • edict/replace-range-probes/range-assembly/evidence/candidate/first-control/application/executable-operation-package.cbor
  • edict/replace-range-probes/range-assembly/evidence/candidate/first-control/application/verification-report.cbor
  • edict/replace-range-probes/range-assembly/evidence/candidate/first-control/stderr.jsonl
  • edict/replace-range-probes/range-assembly/evidence/candidate/first-control/stdout.jsonl
  • edict/replace-range-probes/range-assembly/evidence/candidate/git-locks-receipt.jsonl
  • edict/replace-range-probes/range-assembly/evidence/candidate/guard.result.json
  • edict/replace-range-probes/range-assembly/evidence/candidate/portable-git-locks-receipt.jsonl
  • edict/replace-range-probes/range-assembly/evidence/candidate/portable-guard.result.json
  • edict/replace-range-probes/range-assembly/evidence/candidate/portable-public-build.json
  • edict/replace-range-probes/range-assembly/evidence/candidate/public-build.json
  • edict/replace-range-probes/range-assembly/evidence/candidate/second-control/application/executable-operation-package.cbor
  • edict/replace-range-probes/range-assembly/evidence/candidate/second-control/application/verification-report.cbor
  • edict/replace-range-probes/range-assembly/evidence/candidate/second-control/stderr.jsonl
  • edict/replace-range-probes/range-assembly/evidence/candidate/second-control/stdout.jsonl
  • edict/replace-range-probes/range-assembly/evidence/compiler-source.json
  • edict/replace-range-probes/range-assembly/evidence/first-control-stderr.jsonl
  • edict/replace-range-probes/range-assembly/evidence/first-control-stdout.jsonl
  • edict/replace-range-probes/range-assembly/evidence/public-build-red.json
  • edict/replace-range-probes/range-assembly/evidence/second-control-stderr.jsonl
  • edict/replace-range-probes/range-assembly/evidence/second-control-stdout.jsonl
  • edict/replace-range-probes/range-assembly/run.py
  • edict/replace-range-probes/state-read/Dockerfile
  • edict/replace-range-probes/state-read/Dockerfile.dockerignore
  • edict/replace-range-probes/state-read/README.md
  • edict/replace-range-probes/state-read/edict.application.json
  • edict/replace-range-probes/state-read/edict.lawpack.json
  • edict/replace-range-probes/state-read/run.py
  • edict/replace-range-probes/state-read/src/ReplaceRange.edict
  • edict/replace-range/README.md
  • edict/replace-range/draft/README.md
  • edict/replace-range/draft/Reference.edict
  • edict/replace-range/draft/ReplaceRange.edict
  • edict/replace-range/draft/Rope.edict
  • edict/replace-range/draft/Text.edict
  • edict/replace-range/edict.application.json
  • edict/replace-range/edict.build-lock.json
  • edict/replace-range/edict.executable-subject-lock.json
  • edict/replace-range/edict.lawpack.json
  • edict/replace-range/edict.toolchain-lock.json
  • edict/replace-range/src/ReplaceRange.edict
  • edict/replace-range/tests/assert-build-output.mjs
  • edict/replace-range/tests/build.sh
  • edict/replace-range/tests/package-chain.mjs
  • edict/replace-range/tests/proof-harness.spec.mjs
  • edict/replace-range/tests/runtime/Cargo.toml
  • edict/replace-range/tests/runtime/compiled_boundary.rs
  • edict/replace-range/tests/runtime/flat_text.rs
  • edict/replace-range/tests/verification-evidence.mjs
  • edict/replace-range/vendor/jedit-text/adapter.cbor
  • edict/replace-range/vendor/jedit-text/adapter.sha256
  • edict/replace-range/vendor/jedit-text/echo-operation-configuration.cbor
  • edict/replace-range/vendor/jedit-text/echo-operation-configuration.sha256
  • edict/replace-range/vendor/jedit-text/edict.lawpack-output.json
  • edict/replace-range/vendor/jedit-text/exports.cbor
  • edict/replace-range/vendor/jedit-text/exports.sha256
  • edict/replace-range/vendor/jedit-text/manifest.cbor
  • edict/replace-range/vendor/jedit-text/manifest.sha256
  • edict/replace-range/vendor/jedit-text/verifier-rules.cbor
  • edict/replace-range/vendor/jedit-text/verifier-rules.sha256
  • package.json

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@flyingrobots

Copy link
Copy Markdown
Owner Author

@codex review please, focus on the three unmet plan items and whether they are reachable at these exact heads.

Requesting the fresh independent exact-head operational audit that is item 11 of this PR's plan. Please state the exact commits you audited rather than accepting the ones quoted below.

Heads as I read them right now

repo commit
jedit (PR head) a894c7c4c6d150c0fb210d2e0ca4c27bf518b4c7
edict (PR body pin) 3f81f759e921a69b04fe8cf8e62e62f8f3dc7b7e
echo (PR body pin) 49e9efb68001dfd78563d18bac9359a87671e431
edict (my local main) e4fa81dd772a88fa50b5272da627716e7ea56214
echo (my local main) 490134c0753a3df6a74da366cc71c1248764dc5a

The pins in the PR body are behind both upstreams, so part of what I need is whether the closure still reproduces byte-identically at current heads or only at the pinned ones.

Findings I want checked, not trusted. These are my reads from source this session and I would rather you contradict them than confirm them politely:

  1. No loop-carried result in Edict. crates/edict-syntax/src/compiler.rs builds every bounded for with result: CoreExpr::Const(CoreValue::Null) (~line 1815), and return is rejected inside a bounded-for body (~line 1798). If that is right, a rope traversal that accumulates cannot be expressed in Edict source today, which blocks the "application-owned rope algorithm" half of item 12 on an Edict language change rather than on authoring effort.

  2. No generic pure evaluator in Echo. crates/warp-core/src/edict_target_ir.rs::execute_accepted_edict_echo_target_ir evaluates no program: it checks a single BasisFresh predicate and returns a receipt, never touching the intent body. If that is right, item 12's evaluator half is a new warp-core component, not a wiring task, and item 13 cannot start until it exists.

  3. The current source is a boundary record, not an algorithm. edict/replace-range/src/ReplaceRange.edict is 41 lines: one maxCreatedLeafCount() call, one rangeIsEmpty conditional, one returned record. No traversal.

What would help most

  • Confirm or refute 1 and 2 with file and line, at the heads you actually audited.
  • If 1 is right: the smallest Edict language capability that unblocks the algorithm — general loop-carried result, or something narrower that still expresses replace-range.
  • Whether the maintainer position that Echo must not learn ropes is satisfiable with a generic evaluator, or whether it forces a different split.
  • Anything in items 1-10 that has silently regressed since they were ticked.

Not asking you to implement anything. James has asked me to finish this PR and I want an independent read on what finishing actually requires before I touch three repos.

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 8, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-19T05:06:01.413483Z 6155218 Draft marked ready
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Breezy!

Reviewed commit: a894c7c4c6

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@flyingrobots

Copy link
Copy Markdown
Owner Author

Resumed this work in a separate worktree at 83ab52a3744babb63c8ce15cd94d917012e364a2. Its checked-in compiler/provider/evaluator pins remain unchanged; historical recovery branches are separate.

The source-compiler prerequisite now has an implementation and review PR: flyingrobots/edict#211 (closes flyingrobots/edict#210). Docker validation passed the focused RED/GREEN, the syntax suite, strict Clippy, and cargo xtask verify.

A public-build witness using an isolated copy of this PR's source adds deletedByteCount: U64 = input.endByte - input.startByte and returns it in the boundary record. With the original compiler it returns ApplicationCompilationFailed / UnsupportedSourceShape. With the patched compiler it reaches TargetLoweringFailed / InvalidCoreIdentity (Core expression authorization). Both exit 2: this proves advancement past source compilation, not executable graph mutation.

Next: establish generic target expression authorization and independent totality validation for the new Core subtraction before advancing executable artifact pins. No rope semantics will be added to Echo, and this observation does not mark the full ReplaceRange algorithm, Tick/WAL/recovery, or production cutover complete.

@flyingrobots

Copy link
Copy Markdown
Owner Author

Progress at de77085 on feature/target-unsigned-subtraction (separate worktree, stacked on the compiler slice):

  • Observed RED: the public Core-to-Target test rejected valid guarded subtraction with InvalidCoreIdentity.
  • Initial GREEN: valid subtraction lowers; stripped, reversed, and disjunctive evidence each rejects. The syntax suite and strict Rust 1.94 Clippy pass in Docker.
  • The isolated Jim Add Jedit-owned Edict flat-text replacement reference #302 source copy with returned deletedByteCount now completes the public JSONL application build with status: ok, checked: 1, exit 0, using the existing provider artifact at 49e9efb68001dfd78563d18bac9359a87671e431.

This does not yet establish runtime execution of the new package, the full rope algorithm, or production cutover. Broader malformed-Core/scope coverage, full gates, and runtime evidence remain. Existing Jim source and producer locks are unchanged. No PR is marked ready from these initial witnesses.

@flyingrobots

Copy link
Copy Markdown
Owner Author

Subtraction prerequisite update:

The isolated authored source adds deletedByteCount = input.endByte - input.startByte under the existing ordered-range constraint. The public compiler emits an accepted package; the unchanged evaluator previously returned UnsupportedProgram. The candidate evaluator now passes Jim's standalone consumer test with JEDIT_EDICT_PURE_RUNTIME_OK. All execution was in copied-source Docker, with no host repository mounts.

Echo's pinned Rust 1.90 gate also passes the nine new subtraction tests, seven unchanged pure-evaluation tests, two meter tests, and strict focused Clippy. U64 coverage uses the real compiler artifact; deliberate matching-pin mutations exercise U32 bounds, wrong arity/types, and underflow without claiming verifier approval for those mutations.

The checked-in #302 source, compiler/provider/evaluator pins, and proof locks remain unchanged at 83ab52a3744babb63c8ce15cd94d917012e364a2. Candidate dependency substitution happened only in a disposable consumer copy. No historical WIP branch was modified.

This is prerequisite progress, not completion: authored persistent-rope semantics, generic stateful execution, oracle agreement, and admitted Tick/WAL/receipt/reading/recovery evidence remain required by #296. Review and hosted CI are pending for the new PRs; nothing was merged.

Preserve the original parser/lexer refusals and failed witness, then reproduce those distinct boundaries with a controlled Rust 1.96 build. Retain raw artifacts, resource-stop qualifications, and source/compiler/provider identities. The decoder remains unexecuted; Edict #226 and Echo #752 own the function prerequisites for Jim #296.
Move the toolchain lock from the Edict 3f81f759 and Echo #724/#726
candidate pins to Edict main e60411fc and Echo main 9b3b9396, and the
Rust toolchain to 1.96.0 as Edict main requires. Regenerate the build
lock through the harness's --write-locks path. The executable-subject
lock is byte-identical, so the verified package did not change.

The full proof harness passes 12/12 under Node 22.23.1 and npm 10.9.8 in
a container, against isolated clones of both pinned commits.

Refs #296, #302
Add DL-0159, a draft representation for the rope that Jim's Edict source
reads and writes: every structural relation is a typed Echo edge, facts
use canonical CBOR, immutable nodes are content-addressed over their facts
and children, each head links to its basis so every version stays inside
Echo's state root, and an import head is anchored to its file coordinate
and host digest.

Add complete drafts of ReplaceRange in Edict source against that
representation: a deliberately inefficient flat-text semantic reference
and the persistent AVL rope (pure split, join, balance, build, and
collect, plus the effectful intent). They do not compile on Edict main;
the README classifies every blocker as language, primitive, runtime,
resource, or defect, separates confirmed refusals from code reading, and
states the evidence plan. Nothing here enters the application gate.

Refs #296, #302, #350
@flyingrobots

Copy link
Copy Markdown
Owner Author

Route C: supersession proposal and implementation plan

Direction (approved by @flyingrobots, pending design review): Jim's rope law is authored in Jim-owned Edict source using generic, independently justified primitives. No native causal.sequence.splice@1, no rope-specific Echo primitive, no opaque patch authority.

Supersession (proposal, not merged): flyingrobots/echo#889

  • Supersedes only ADR 0023's "Jedit rope-law closure" and its selection under "Alternatives for Expressing the Rope Law"; every other ADR 0023 provision still governs. ADR 0023's rationale is preserved and the supersession is linked both ways.
  • New evidence: the declarative resource route was never implemented; Edict and Echo grew since 2026-07-18; and every route is gated by the same generic gap, no admitted path from an evaluated Edict operation to graph writes.
  • Includes the proposed design Authored Operation Effects: evaluation proposes typed node/edge effects; Echo witnesses reads, validates writes against a declared footprint law, basis, budget, authority, and identity; the proposal commits atomically in one decided Tick (existing WAL) or obstructs with no patch.

Done on this branch

  1. Repin (a7bcff6b): Edict main e60411fc, Echo main 9b3b9396 (provider + evaluator), Rust 1.96.0. Proof harness 12/12 under the pinned Node/npm in a container; the executable-subject lock is byte-identical to the old candidate pins. The leaf-slice and range-assembly probes now build on Edict main.
  2. Representation DL-0159 (draft): schema 2 with every structural relation as a typed Echo edge (Echo's two-plane law; id-in-atom children are outside the state root), canonical CBOR facts, content-addressed immutable nodes, a basis edge chain that keeps every version inside the state root, and an anchored-refinement import anchor (file coordinate + host digest). UTF-16 length dropped (no consumer outside the native rope).
  3. Complete Edict drafts edict/replace-range/draft/ (783db531), outside the application gate and not compiling yet:
    • target 1, semantic reference: flat text, slice + concat + head retarget;
    • target 2, persistent rope: pure AVL split/join/balance/build/collect plus the effectful intent with one bounded closure read and ensure effects.
      The README classifies every blocker (language / generic primitive / Echo runtime / resource / defect), separates confirmed refusals (built against Edict main) from code reading, and states the evidence plan.
  4. Bugs filed: Reopening a file silently reuses a stale rope and discards the file's current bytes #350 (reopen silently reuses a stale rope; a correctness defect and prerequisite for durable file integration), Lexer: support \r and explicit byte escapes in string and bytes literals edict#249 (bytes literals are not lexed at all, plus missing escapes).

Plan (stages; nothing major starts until the designs are reviewed)

Stage Gate
A. Review echo#889 decision + bridge design, DL-0159 review
B. Echo: implement the effect bridge test-first (atomicity, ensure identity, witnessed footprint, stale basis, budget, determinism, recovery, composition) design accepted
C. Edict: smallest features target 1 needs: bytes literals (#249), U64 + with overflow proof, hash, edge read/ensure/retarget and ensure effects, source-module import B's contract settled
D. Target 1 end to end: Reference ReplaceRange through Echo, checked against the oracle's logical outcomes, with roots, footprints, budgets, receipts, replay, typed negatives C
E. Edict features target 2 demonstrably needs: depth-bounded recursive variants + match, structural recursion, Option/List, typed pure failure, guided closure read D
F. Target 2: persistent rope; differential against target 1 plus the property suite (persistence, sharing, canonicalization, Unicode, atomicity, conflict, commutation, closure sufficiency) E
G. #297 → #301 (active Jim Kitten) → #298 F

#350 (reopen) and save/export must land before any durable or end-to-end editor claim. UI PRs stay untouched.

Decisions still open

  • The closure selector's expansion rule (argued, not proven; must be shown never to fail).
  • Footprint law per invocation vs per package; how edict_read exposes edges and a guided closure read.
  • Which domain-separated hash Edict source can call for ids.
  • Echo's 128-op Tick cap vs a 1 MiB replacement (needs measurement), and the state root's full-graph walk as retained history grows (an existing open decision in Echo's Sliced Readings design).

Remove the head-to-predecessor basis edge from DL-0159 and the drafts.
It made every version of every buffer permanently reachable, so the
state root and retention grew with editing history, and it duplicated
the causal history Echo's ticks and receipts already own. The graph now
holds the current Buffer, Head, Import, and rope; superseded nodes leave
the reachable graph, and their retention and any reconstruction of past
states are Echo's retention and replay contract. Every new head copies
the anchor edge instead of reaching its Import through a chain, and head
identity no longer includes the predecessor. Undo and redo are forward
operations.

Replace 'UTF-16 length is dropped' with an explicit coordinate contract:
byte offsets are authoritative, and whether UTF-16 offsets are derived,
cached, or retained is an open decision driven by the interoperability
surfaces Jim commits to, not by today's consumers.

Refs #296, #302
@flyingrobots

Copy link
Copy Markdown
Owner Author

Correction to the plan above (22376d6a): DL-0159 no longer links each head to its predecessor. That chain made every version of every buffer permanently reachable, so the state root and retention grew with editing history, and it duplicated the causal history that Echo's ticks and receipts already own.

  • The graph now holds the current Buffer, Head, Import, and rope only. Superseded nodes leave the reachable graph. Whether they stay retained, and how far back a past state can be rebuilt, is Echo's retention and replay contract. A tick witnessing a transition does not by itself promise the bytes are still retained.
  • Every new head copies the anchor edge to its Import, and head identity no longer includes the predecessor.
  • Undo and redo are forward operations from a past witnessed state, subject to retained evidence and admission.
  • UTF-16 is no longer "dropped": byte offsets are authoritative, and whether UTF-16 offsets are derived, cached, or retained is an open decision driven by the interoperability surfaces Jim commits to.

Route C is unchanged.

Copying the import anchor to every head preserves where the text came
from; it must not imply the rope still matches the file. DL-0159 now
keeps three facts apart: import provenance (Import, anchor edge), the
current logical content (digest computed over the rope at a crossing,
not on every edit), and host synchronization (an Export node with the
logical and resulting host digests, reached by a lastExport edge that
each save retargets). Save requires the file's host digest to equal the
last exported digest, or the import digest if never exported; a mismatch
is a typed conflict that needs explicit reconciliation. Reopen compares
host digests against the last export, so it never materializes the rope.

Refs #296, #302, #350
flyingrobots added a commit to flyingrobots/echo that referenced this pull request Oct 16, 2026
Add invariant 4: no committed coordinate contains an edge to an absent
node, so a retargeted head is never observable before everything it
reaches. Validation rejects dangling endpoints with DanglingReference,
because GraphStore::upsert_edge_record does not check them, and commit
makes partial visibility impossible by binding all effects to one Tick
published only after its decided WAL record.

State that reads are witnessed through a recording view over a bounded
slice rather than declared, and that today's edict_read only counts
reads, so this is new instrumentation. State the composition rule for
shared structure: an Ensure of an identical existing node is a read, and
two Actions creating the same new node conflict under the existing set
test, with no new merge rule; a retry sees the node and reads it.

Add three concrete execution traces for Jim's reference ReplaceRange:
committed, obstructed by a stale basis at evaluation, and rejected at
composition. Extend the required tests accordingly.

Refs flyingrobots/jedit#302
DL-0159 drops the Export -> Head edge: an Export is evidence of one
crossing (file, logical digest, resulting host digest, and the causal
event that witnessed it), not a reason to keep a historical rope
reachable, and never file authority. A pinned saved snapshot would be an
explicit retention lease.

Save is now spelled out as a foreign crossing: export intent, host write,
read-back observation as witnessed ingress, export outcome, and recovery
by re-observation under the same occurrence key. The design no longer
claims a digest check prevents a concurrent writer; without a host-side
concurrency protocol the guarantee is detection at observation.

Add third-party file changes: a buffer's synchronization basis, detection
only through witnessed observation, an external change admitted as a new
Import, adoption for a clean buffer, and for a dirty buffer an explicit,
witnessed keep-mine, take-theirs, merge, or defer. Merge needs the base
bytes; when retention no longer has them it refuses with
MergeBaseUnavailable.

Refs #296, #302, #350
Replace the third-party change notes with an explicit reconciliation
contract between Base (last agreed host contents), Local (the current
rope), and Host (the latest validated observation), with a decision
table. Watchers are hints; decisions use a validated, stable re-read.
ObserveExternalFileChange is separate from adoption. Divergence preserves
both sides: Reload keeps Local recoverable, Keep local does not grant an
overwrite, Overwrite is its own explicit choice against a specific Host,
and Reconcile is a forward edit that never invents the external editor's
history. Offering Reconcile requires B's bytes, not just its digest.
Classify modification, atomic-save rename, deletion, replacement,
symlinks, permission changes, and unstable reads; support ordinary files
first and refuse ambiguous crossings. Save revalidates and claims
detection, not prevention, until a host concurrency protocol exists.

Refs #296, #302, #350
flyingrobots added a commit to flyingrobots/echo that referenced this pull request Oct 16, 2026
Record observed absence as a dependency (missing node or atom, empty or
specific outgoing-edge set) against the basis, so a co-scheduled Action
that creates the slot invalidates the reader. Align dependency kinds
with the Action validity across ticks decision (#837): value and
single-key absence are supported; reading edges by type is a topology
dependency that keeps the whole-frontier rule until sound edge-set
tracking exists there.

Make retry identity explicit: a decided outcome, receipt, and
attribution never change; a retry is a new submission with its own
identity; Echo does not retry on its own; and a never-decided Action
recovered after a crash is the same submission, not a retry. Update the
composition trace and the required tests accordingly.

Refs flyingrobots/jedit#302
An external write is testimony from another authority, not an editor
event. DL-0159 now routes it through Echo's existing contracts instead of
a filesystem-specific model: a filesystem adapter turns a validated
observation into an import proposal under the Continuum Transport import
law, and the observation is held, judged, and applied as Participant
History as a Braid describes. Jim's Edict-authored law judges B, L, and H
into Derived, Plural, Conflict, or Obstruction; divergence is a Conflict
that bars dependent operations until settled; only a witnessed forward
commit changes the buffer.

Each observation carries Echo's Continuum occurrence identity and an
explicit receiving context. Re-delivery is idempotent; distinct
observations stay distinct; and a digest identifies observed content,
not the write that produced it, so the adapter never invents distinct
external writes. Filesystem-specific work stays at the adapter boundary.

Refs #296, #302, #350
Cite Paper VII directly, checked against the paper: transport precedes
judgment, so an observed file version is re-expressed at Jim's receiving
frontier, with B as the comparable basis the adapter can actually support
(section 4.3); a braid is a comparison carrier, not a merge, and
observing, braiding, judging, and admitting are separate acts (Definition
2.4, Remark 2.6), with plurality a lawful outcome (section 4.2); and the
optic Psi = (Omega, chi, rho, Pi, Lambda) is Jim's (Definition 3.1).
Commitment, folding, and revelation stay separate (section 3.3), the
section 6.2 hot-text optic matches the draft's closure read and single
head retarget, and section 8 names app-authored optic compilation and
export semantics as open seams, which is what this document attempts.
The paper is cited as foundation, not as evidence of implementation.

Refs #296, #302
The slice chi in Jim's reconciliation optic is the smallest lawful
comparison closure within the file site. A whole-file comparison is
acceptable at first and is not a permanent requirement.

Refs #296, #302
flyingrobots added a commit to flyingrobots/echo that referenced this pull request Oct 16, 2026
…contracts

Add an identity chain: submission (Submission Attribution and canonical
inbox sequencing), Action (ADR 0023/0025), proposal (new, evidence only,
deterministic per Action and basis), and decision (recorded once by
submission_id). The bridge removes no admission check, adds no identity
root, and persists nothing outside the decided-Tick WAL record.

Retries now rest on Echo's existing intake idempotence: identical content
returns the existing submission as Duplicate with its original outcome;
a real new attempt must differ, which makes it a new submission.

The new receipt-entry fields change an encoding that commit hash v3
binds, so they need a new entry format version under Submission
Attribution's format rules. Recovery replays decided Ticks and checks the
patch digest and commit hash without re-evaluating; scoped-validity
Actions follow #837's recomputation; undecided Actions re-evaluate as the
same submission. Extend the required tests accordingly.

Refs flyingrobots/jedit#302
@flyingrobots flyingrobots changed the title Author ReplaceRange as Jedit-owned Edict source Add Jedit-owned Edict flat-text replacement reference Oct 19, 2026
@flyingrobots
flyingrobots marked this pull request as ready for review October 19, 2026 05:03
@flyingrobots
flyingrobots merged commit a1fd5d2 into main Oct 19, 2026
14 checks passed
@flyingrobots
flyingrobots deleted the feature/replace-range-edict-source branch October 19, 2026 05:05

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 6155218f98

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +5 to +8

- `edict.lawpack.json` is the reviewable `jedit.text@1` authoring input;
- `vendor/jedit-text/` is Edict's canonical published lawpack closure;
- `src/ReplaceRange.edict` is the application-owned source;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Update the canonical ownership document for the new package boundary

This change introduces authored ReplaceRange.edict, its published lawpack closure, and an executable package chain, but docs/jim-component-ownership.md:700–706 still explicitly states that the source and complete application-owned lawpack closure do not exist in Jedit. That document is the registered canonical owner of the Jim/Jedit/Edict/Echo ownership model, so the new README and bearing entries leave authoritative current-versus-target guidance contradictory. Update the canonical owner in this change, distinguishing the now-working pure reference from the still-unimplemented stateful rope and installed release. The root AGENTS.md explicitly requires same-change canonical-owner updates for these decisions.

AGENTS.md reference: AGENTS.md:L79-L87

Useful? React with 👍 / 👎.

Comment on lines +13 to +15
COPY edict/replace-range /application-source
COPY edict/replace-range-probes/basis-identity/ReplaceRange.edict /comparison-sources/ReplaceRange.edict
COPY edict/replace-range-probes/basis-identity/PayloadEquality.edict /comparison-sources/PayloadEquality.edict

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Supply a matching lawpack closure to the basis-identity probe

Following this probe's documented Docker recipe copies the current application closure, whose vendor/jedit-text/manifest.sha256 is sha256:f385072314ea57af5b66cad9eb4119b51e456df2050ea0c9a6302c7693212dc1, while both comparison sources import sha256:95758c1605894672cc9069fde01bb8b6e11842b053102660c9cd4f4d6f34d64e. build.sh copies that closure and replaces only the source, so the probe cannot build its advertised comparison packages: the imported release does not match the supplied manifest. Preserve a matching historical closure for this pinned witness, or migrate the compiler, provider, closure, and imports together.

Useful? React with 👍 / 👎.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

work-in-progress Cycle or PR is intentionally in progress and not ready to merge

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Slice: Author and prove Jim's first Edict operation ReplaceRange

1 participant