Skip to content

Preserve ordered effect-result guards in an explicitly selected Target IR contract #218

Description

@flyingrobots

Observable outcome

Edict can preserve a straight-line sequence of semantic effects, pure bindings, and guards when a guard depends on an earlier effect result. The selected Target IR contract must preserve source ordering and fail closed with consumers that do not support it.

This is a prerequisite of flyingrobots/jedit#296 / flyingrobots/jedit#302. It is not implementation of graph reads or an Echo rope operation.

Actual consumer RED

On Edict 77f4a91080a6c2c875fe349da6fc6a64525947a2, the public lawpack build accepts a Jim-owned readCanonicalHead(BufferId) -> HeadId semantic effect. The public application build rejects this authored body:

let canonicalHead: text.HeadId = text.readCanonicalHead(input.bufferId)
  else { missing(id) => text.FactMissing };
require canonicalHead == input.basisHeadId else text.BasisNotCanonical;
return canonicalHead;

Observed refusal: TargetLoweringFailed, UnsupportedTargetFeature, obstruction_requirement_step_output_dependency, node 1. Removing only the guard advances to the selected provider, which rejects UnsupportedSemantics. Neither variant emits a runnable package.

The source, complete lawpack, Docker reproduction, and paired control are being retained under edict/replace-range-probes/state-read/ in jedit PR #302. The proposed snapshot-read-probe intrinsic is deliberately unsupported and does not establish a runtime read ABI. The probe retains an incompatible pure provider to demonstrate the next fail-closed boundary, not to claim stateful support.

Current structural limitation

crates/edict-syntax/src/target_ir.rs stores pure bindings, requirements, and steps in separate arrays. Requirements are currently pre-step guards; lower_require_node intentionally rejects both effect-result references and guards after a target step. Existing tests explicitly protect those refusals. Deleting those checks without an ordering model is incorrect.

Scope

  • Define an explicit versioned/negotiated target artifact contract for straight-line ordered bindings, effects, and terminal or supported obstruction guards.
  • Preserve exact effect-result bindings, guard payloads, input constraints, basis, budgets, lawpack closure, and source order in canonical identity.
  • Validate availability, types, duplicate/forward/self references, and output authority independently at the Core-to-Target boundary.
  • Keep legacy artifact bytes and behavior stable unless an explicit version migration is selected.
  • Prove unsupported providers reject before executable-package publication.

Exclusions

No loops, recursion, branching expansion, graph read implementation, graph writes, native callbacks, rope or editor intrinsics, runtime admission, receipt/WAL/recovery claims, or repinning the existing jedit application. Those remain under their owning issues.

Acceptance checks

  • A public source/lawpack witness preserves read → guard → result ordering under the new selected artifact contract.
  • Include effect → pure binding → guard, two effects separated by a guard, guard payload references, and input-only guards after an effect.
  • Invalid/dangling/forward/duplicate identities fail before artifact publication.
  • Reordering a valid program changes canonical identity; decoding/schema validation independently recognizes the ordered representation.
  • Existing profiles retain their protected fail-closed behavior and byte identities.
  • Old provider consumers cannot accept or execute the new semantics silently.
  • Docker-only focused regressions and the repository verification gate pass. Topic contract, test plan, schema, fixtures, and changelog agree.

Prerequisites and safe intermediate state

The Jim witness was run on the current producer stack ending at #216 / PR #217. Preserve that compiler baseline when implementing, without merging unrelated historical WIP.

A compiler-only merge is safe if the new representation is explicitly selected and unsupported consumers reject it. It must not advertise runnable stateful Echo support. Echo #684 owns generic provider/interpreter work only after the compiler supplies real artifacts; Jim #296 still owns authored rope semantics and complete end-to-end acceptance.

Activity

  1. added
    type: featureFeature issue for a cohesive capability
    state: blockedOpen but blocked by unresolved dependencies
    domain: backendCompiler/backend implementation work
    on Oct 4, 2026
  2. flyingrobots commented on Oct 4, 2026

    @flyingrobots
    OwnerAuthor

    The public consumer RED and paired control are now committed and pushed:

    https://github.com/flyingrobots/jedit/tree/19edb6fba94a8fea2dea63aa2f05cffc3e084f97/edict/replace-range-probes/state-read

    A fresh Docker image built the pinned compiler from Git and ran the public JSONL builds. Both expected boundaries were observed, no refused application artifacts were published, and the harness emitted JEDIT_STATE_READ_BOUNDARY_CONFIRMED. The README explicitly distinguishes the proposed unsupported read intrinsic from an implemented runtime contract. No existing jedit producer pin was changed.

  3. added
    state: activeCurrently being implemented or reviewed
    and removed
    state: blockedOpen but blocked by unresolved dependencies
    on Oct 4, 2026
  4. flyingrobots commented on Oct 4, 2026

    @flyingrobots
    OwnerAuthor

    Implemented the ordered Target IR prerequisite in stacked PR #219, head 2405a550e93e1e97fff640caa44bbd0f65ffff3c, based on #217.

    Explicit echo.span-ir/v2 selection preserves effect/binding/guard order and canonical identity. Legacy v1 refusals and golden bytes remain covered. The schema validator handles the new tagged-family shape with bounded, memoized dispatch.

    Validation ran in COPY-based Docker containers: 88 Target IR tests, 15 contract-pack tests, 29 CLI tests, provider-schema regressions, strict workspace Clippy, and full cargo xtask verify passed. The final public Jim witness passed with ORDERED_PUBLIC_BUILD_REACHED_OLD_PROVIDER_GATE: v1 still rejects at Target lowering; v2 reaches the old provider's schema refusal before component execution or package publication. The full gate retains the existing non-fatal v0.1.0-alpha.1 release-policy MissingSurface warning.

    No runtime graph read is claimed, no Jim producer pin was changed, and nothing was merged. Hosted CI/review are pending on #219.

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    domain: backendCompiler/backend implementation workstate: activeCurrently being implemented or reviewedtype: featureFeature issue for a cohesive capability

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions