Skip to content

Parse obstruction strand continuations - #128

Merged
flyingrobots merged 5 commits into
mainfrom
syntax/obstruction-strand-source
Jul 4, 2026
Merged

Parse obstruction strand continuations#128
flyingrobots merged 5 commits into
mainfrom
syntax/obstruction-strand-source

Conversation

@flyingrobots

Copy link
Copy Markdown
Owner

Summary

This PR lands PR 1 of the obstruction-strands plan: source parser support only.

It adds first-class parsing for:

require jim.basisFresh(input.basis)
  else continue obstructed {
    reason: jim.EditObstruction.StaleBase,
  };

The new form is represented as RequireElseArm::ContinueObstructed, requires exactly one reason field, rejects duplicate reason fields, and is contextual to a require ... else arm. Existing terminal require ... else SomeObstruction; behavior remains terminal, and helper-shaped constructors such as continueInObstructedStrand(...) do not acquire hidden control-flow semantics.

Closes #118
Refs #116

Claim Delta

New in this PR:

  • Source syntax parses for else continue obstructed { reason: ... }.
  • Parser exposes a distinct source AST arm.
  • Missing or duplicate reason fields reject with stable parser error kinds.
  • The stale-basis corridor source fixture parses.

Still not claimed:

  • Core obstruction semantics.
  • Target IR obstruction lowering.
  • Echo acceptance or execution.
  • Canonical Echo receipt bytes or receipt digests.
  • Graft/jedit projection lanes.
  • Scheduler counterfactual semantics.
  • Continuum/XYPH settlement.

Claims Checklist

  • Source syntax parses.
  • Core semantics implemented.
  • Echo Target IR lowering implemented.
  • Echo runtime execution implemented.
  • Graft/jedit projection implemented.
  • Scheduler admission/counterfactual semantics implemented.
  • Continuum settlement implemented.

RED/GREEN Evidence

RED:

cargo test -p edict-syntax --test parse_review_regressions continue_obstructed

Observed failure before implementation: missing RequireElseArm, missing Stmt::Require { arm }, and missing ParseErrorKind::{MissingRequiredField, DuplicateField}.

GREEN:

cargo test -p edict-syntax --test parse_review_regressions
cargo test -p edict-syntax
cargo xtask contract-check
cargo xtask verify

Notes

  • Topic README wording is deliberately narrow: parser source syntax exists; Core/Target/Echo behavior remains deferred.
  • The design note records the cross-layer ladder but is not a topic shelf contract for unlanded behavior.
  • The corridor fixture directory includes only PR 1 source material and a manifest; later Core, Target IR, and receipt artifacts must be added by their owning PRs.

@coderabbitai

coderabbitai Bot commented Jul 4, 2026

Copy link
Copy Markdown

Review Change Stack

Summary by CodeRabbit

  • New Features

    • Added parser support for first-class obstruction-strand syntax in require ... else continue obstructed { reason: ... }.
    • The require ... else AST now models this as a dedicated continuation arm (with strict reason semantics).
  • Bug Fixes

    • Improved validation with explicit missing/duplicate reason detection and stable parse error codes.
    • Rejects continue obstructed { ... } outside the contextual require ... else form.
  • Tests & Docs

    • Added regression tests and a new stale-basis fixture covering the ContinueObstructed parse path.
    • Updated obstruction-strands design, syntax test-plan, and README to clarify current parser-only support and remaining gaps.

Walkthrough

Adds parser-first support for require ... else continue obstructed { reason: ... } with a new AST arm, parsing and validation for a single required reason, regression coverage, fixture data, and documentation updates. Lowering, Target IR, and runtime behavior remain deferred.

Changes

Obstruction-strand parsing support

Layer / File(s) Summary
AST shape for RequireElseArm
crates/edict-syntax/src/ast.rs
Stmt::Require now carries arm: RequireElseArm, and the AST adds RequireElseArm::{Terminal, ContinueObstructed} plus ContinueObstructedArm { reason, payload, span }.
Parser support and error kinds
crates/edict-syntax/src/parser.rs
Adds MissingRequiredField and DuplicateField, a keyword lookahead helper, and require_else_arm parsing that enforces exactly one reason field and falls back to terminal obstruction parsing otherwise.
Semantic validation of RequireElseArm
crates/edict-syntax/src/semantic.rs
Updates Stmt::Require validation for the new arm shape and centralizes record-entry validation in a shared helper.
Regression tests and stale-basis fixture
crates/edict-syntax/tests/parse_review_regressions.rs, fixtures/obstruction-strands/v0/stale-basis/*
Updates terminal-require assertions, adds continuation parsing and rejection tests, and validates the new stale-basis fixture.
Documentation and test-plan updates
CHANGELOG.md, docs/design/obstruction-strands-v0.md, docs/topics/obstruction-strands/*, docs/topics/syntax/test-plan.md
Describes the new syntax, marks related requirements and test cases implemented, and keeps Core/Target/runtime work out of scope.

Estimated code review effort: 3 (Moderate) | ~30 minutes

Possibly related issues

Possibly related PRs

  • flyingrobots/edict#9: Extends the same edict-syntax path by changing Stmt::Require to carry RequireElseArm and teaching the parser to accept the contextual continuation arm.

Poem

A require met a winding else,
And learned one reason for itself.
Two reasons? No — that path is barred.
Missing one? The parser’s hard.
Syntax blooms; the rest can wait,
In careful steps, not all-at-once fate.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 inconclusive)

Check name Status Explanation Resolution
Linked Issues check ❓ Inconclusive Most acceptance criteria are covered, but the provided summary does not show a stable lowering-failure diagnostic path. Add or cite the lowering-stage change or test that returns a stable not-yet-lowered/unsupported diagnostic for Stmt::Require.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title is concise and matches the main change: parsing obstruction-strand continuations.
Description check ✅ Passed The description directly describes the parser-only obstruction continuation work and its limits.
Out of Scope Changes check ✅ Passed The changes stay within parser support, tests, docs, and fixture coverage for obstruction-strand continuations.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

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

Self-audit findings before repair:

ID Severity Source File:Lines Issue Mitigation
CL-1 P4 Self docs/topics/syntax/test-plan.md:42 Syntax requirement says “Resumable obstruction preservation has first-class source syntax,” which can read as a semantic preservation claim even though this PR is parser-only. Narrow the requirement to first-class obstruction-strand source syntax and explicitly keep Core/runtime behavior deferred.
CL-2 P4 Self docs/topics/obstruction-strands/README.md:9-10, crates/edict-syntax/src/ast.rs:261-267 README/API comments use “preserving” phrasing on source AST shape, which risks implying landed preservation semantics. Reword to “source syntax reserved for future preservation” / “parser-supported source arm” without claiming Core/Target/Echo behavior.
CL-3 P5 Self fixtures/obstruction-strands/v0/stale-basis/README.md:13-16 Corridor manifest labels source.parse.review as PR 1 expected layer even though this slice only adds source.edict; it can look like a missing artifact. Rename table column to “First eligible layer” and clarify absent artifacts appear only when explicitly added by their owning PR.

I will repair these narrowly, rerun the relevant docs/parser gate, commit once, and update the PR.

@flyingrobots

Copy link
Copy Markdown
Owner Author

Activity Summary

Item Severity Source File Commit Outcome
CL-1 P4 Self docs/topics/syntax/test-plan.md 3c764c5 Narrowed syntax shelf wording from semantic “preservation” to parser-owned source spelling.
CL-2 P4 Self docs/topics/obstruction-strands/README.md, crates/edict-syntax/src/ast.rs 054a4ac Reworded README/API comments so this PR claims parser syntax only, not landed preservation semantics.
CL-3 P5 Self fixtures/obstruction-strands/v0/stale-basis/README.md 2931e40 Clarified corridor artifact table as first eligible layer, not missing expected files.

Verification after repairs:

cargo xtask verify

Result: green locally.

Review state: GraphQL reviewThreads returned zero unresolved threads. CodeRabbit is rate-limited on this PR, so alternate review has been requested with @codex review please per repo policy.

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. You're on a roll.

Reviewed commit: 663f8ebe36

ℹ️ 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".

@coderabbitai coderabbitai 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.

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
docs/topics/obstruction-strands/test-plan.md (1)

8-20: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Scope section reads as self-contradictory.

"future Core and Target IR disposition for obstruction preservation" is listed under In scope, immediately followed by "Core semantics for the first-class source syntax" / "Target IR lowering for the first-class source syntax" under Out of scope. Without a qualifier (e.g. "tracked as planned rows only"), this looks like exactly the kind of overclaim ambiguity the PR's own self-audit (CL-1) already flagged and fixed elsewhere.

As per coding guidelines, "Topic README.md files must not describe intended behavior before it lands" and shelves should avoid ceremonial ambiguity about contract status.

✏️ Suggested wording fix
-- first-class source syntax for preserved repairable obstruction attempts;
-- future Core and Target IR disposition for obstruction preservation;
+- first-class source syntax for preserved repairable obstruction attempts;
+- ledger tracking (planned rows only) of future Core and Target IR
+  disposition for obstruction preservation;
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/topics/obstruction-strands/test-plan.md` around lines 8 - 20, The Scope
section in the test-plan README is internally inconsistent because it lists
future Core/Target IR disposition as in scope while also marking the
corresponding Core semantics and Target IR lowering as out of scope. Update the
wording in this document so the in-scope items only describe what is actually
covered today, and move any future disposition language into a clearly labeled
tracking/planned note or remove it entirely. Use the existing section headings
and phrases around obstruction preservation, Core IR, and Target IR to make the
scope status unambiguous.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@crates/edict-syntax/src/parser.rs`:
- Around line 1096-1126: The duplicate `reason` diagnostic in
`require_obstructed_reason` is too broad and should point at the second
offending entry instead of the whole payload. Update the `DuplicateField` path
to use the span from the current `RecordEntry`/`Expr` candidate when the second
`reason` is seen, while keeping the existing `MissingRequiredField` behavior on
`payload_span`.

In `@docs/design/obstruction-strands-v0.md`:
- Around line 153-168: The “Future Verification” checklist in this design doc is
stale because several items are already covered by executable tests in this PR.
Update the checklist in obstruction-strands-v0.md to separate the
already-verified behaviors from the genuinely future work: mark the source AST
node, helper-shaped negative guard, missing/duplicate reason rejection, and
contextual-only rejection as implemented/verified, and leave only the
Core/Target IR, digest/mutation evidence, and receipt fixture items as future
verification. Use the existing test names like
continue_obstructed_source_arm_parses,
continue_obstructed_requires_reason_field,
continue_obstructed_rejects_duplicate_reason_field,
continue_obstructed_is_contextual_to_require_else, and
helper_shaped_continue_in_obstructed_strand_is_terminal to anchor the “verified
in PR” section.

---

Outside diff comments:
In `@docs/topics/obstruction-strands/test-plan.md`:
- Around line 8-20: The Scope section in the test-plan README is internally
inconsistent because it lists future Core/Target IR disposition as in scope
while also marking the corresponding Core semantics and Target IR lowering as
out of scope. Update the wording in this document so the in-scope items only
describe what is actually covered today, and move any future disposition
language into a clearly labeled tracking/planned note or remove it entirely. Use
the existing section headings and phrases around obstruction preservation, Core
IR, and Target IR to make the scope status unambiguous.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: e60df0ee-5969-4cbc-bf82-7b6ed4c9dc14

📥 Commits

Reviewing files that changed from the base of the PR and between eadc06a and 2931e40.

📒 Files selected for processing (11)
  • CHANGELOG.md
  • crates/edict-syntax/src/ast.rs
  • crates/edict-syntax/src/parser.rs
  • crates/edict-syntax/src/semantic.rs
  • crates/edict-syntax/tests/parse_review_regressions.rs
  • docs/design/obstruction-strands-v0.md
  • docs/topics/obstruction-strands/README.md
  • docs/topics/obstruction-strands/test-plan.md
  • docs/topics/syntax/test-plan.md
  • fixtures/obstruction-strands/v0/stale-basis/README.md
  • fixtures/obstruction-strands/v0/stale-basis/source.edict
📜 Review details
⏰ Context from checks skipped due to timeout. (1)
  • GitHub Check: supply-chain (cargo-deny)
🧰 Additional context used
📓 Path-based instructions (3)
**

⚙️ CodeRabbit configuration file

**: # AGENTS

Git Rules

NEVER amend git commits. Make a new commit instead.

NEVER use git rebase unless the user explicitly approves a rare exception.
Use regular merge commits.

NEVER force any git operation. If a force operation appears necessary, stop and
explain what happened and what options remain.

NEVER create draft pull requests.

NEVER use a codex prefix in branch names, PR titles, or commit messages.

Pull request bodies for issue work MUST include GitHub auto-close text such as
Closes #123`` for every issue the PR is intended to close.

Think

Think is durable memory for cross-session coordination.

  • Use codex-think --remember --json when starting a new session, changing into
    this repository, or regaining context after a context shift.
  • Use codex-think "..." --json when a cycle closes or a significant event
    should survive across turns.
  • Treat Think as memory, not repo truth. Anchor strong claims back to files,
    commits, commands, issues, or pull requests.
  • Claude memories are read-only. Use claude-think --remember --json only for
    additional context.

Topic Shelves

docs/topics/ contains the living contract graph for landed behavior. Topic
shelves are not proposals, retrospectives, or design archaeology.

Each shelf may contain:

  • README.md: what is true in HEAD.
  • test-plan.md: how those truths are verified, including requirements, cases,
    fixtures, oracles, implemented evidence, planned cases, and known gaps.
  • architecture.md: optional structure or dataflow notes when the machinery
    earns a separate page.
  • rationale.md: optional still-relevant tradeoffs and rejected approaches.

When To Update Topic Shelves

For every nontrivial behavior, contract, workflow, release, schema, validation,
or public-surface change:

  1. Identify the owning topic shelf before editing code.
  2. If no shelf owns durable behavior, create one.
  3. Update test-plan.md before or alongside tests with requirement IDs, case
    IDs,...

Files:

  • fixtures/obstruction-strands/v0/stale-basis/source.edict
  • fixtures/obstruction-strands/v0/stale-basis/README.md
  • CHANGELOG.md
  • docs/topics/obstruction-strands/README.md
  • docs/topics/syntax/test-plan.md
  • crates/edict-syntax/tests/parse_review_regressions.rs
  • docs/topics/obstruction-strands/test-plan.md
  • crates/edict-syntax/src/ast.rs
  • docs/design/obstruction-strands-v0.md
  • crates/edict-syntax/src/semantic.rs
  • crates/edict-syntax/src/parser.rs
docs/topics/**/README.md

📄 CodeRabbit inference engine (AGENTS.md)

docs/topics/**/README.md: Topic shelf README.md files must describe only what is true in HEAD.
Update the topic shelf README.md only after the behavior exists in the branch; do not describe intended future behavior there.
Do not churn topic-shelf README files for purely mechanical edits that do not change a contract.

Files:

  • docs/topics/obstruction-strands/README.md
docs/topics/**/test-plan.md

📄 CodeRabbit inference engine (AGENTS.md)

docs/topics/**/test-plan.md: Update a topic shelf test-plan.md before or alongside tests with requirement IDs, case IDs, fixtures, oracles, implemented evidence, planned cases, and known gaps.
Mark planned cases as implemented only when executable evidence exists.
Do not use policy rows in topic-shelf test plans to avoid writing behavior tests for software behavior.
Negative tests in topic-shelf test plans should assert stable error kinds or structured artifacts, not merely is_err() or diagnostic text.
For nontrivial behavior, contract, workflow, release, schema, validation, or public-surface changes, update the owning topic test-plan.md with planned requirement and case rows before or alongside the first test.
Mark planned rows as implemented only after executable evidence exists.

Files:

  • docs/topics/syntax/test-plan.md
  • docs/topics/obstruction-strands/test-plan.md
🔇 Additional comments (18)
crates/edict-syntax/src/parser.rs (1)

7-10: LGTM!

Also applies to: 31-32, 63-64, 225-230, 906-910, 1597-1598

crates/edict-syntax/src/semantic.rs (1)

8-8: LGTM!

Also applies to: 365-368, 416-428, 459-473, 503-503

docs/topics/obstruction-strands/README.md (1)

3-16: LGTM!

Also applies to: 30-60

docs/topics/obstruction-strands/test-plan.md (2)

30-34: LGTM!

Also applies to: 68-70


44-56: 📐 Maintainability & Code Quality

Drop this concern. crates/edict-syntax/tests/parse_review_regressions.rs already contains continue_obstructed_is_contextual_to_require_else, helper_shaped_continue_in_obstructed_strand_is_terminal, and stale_basis_obstruction_strand_fixture_parses, and fixtures/obstruction-strands/v0/stale-basis/{README.md,source.edict} are present.

			> Likely an incorrect or invalid review comment.
docs/topics/syntax/test-plan.md (1)

42-42: LGTM!

Also applies to: 79-79, 105-107

crates/edict-syntax/src/ast.rs (1)

208-211: 🎯 Functional Correctness

No downstream exhaustiveness issue Stmt::Require { .. } matches are unaffected by the obstructionarm rename, and RequireElseArm is already handled explicitly for both variants.

			> Likely an incorrect or invalid review comment.
crates/edict-syntax/tests/parse_review_regressions.rs (4)

8-14: LGTM!


249-262: LGTM!


264-355: LGTM!


309-317: 🎯 Functional Correctness

No change needed: continue is a bare identifier here, so ParseErrorKind::ExpectedToken is the right contract.

			> Likely an incorrect or invalid review comment.
fixtures/obstruction-strands/v0/stale-basis/README.md (1)

1-34: LGTM!

fixtures/obstruction-strands/v0/stale-basis/source.edict (1)

1-17: LGTM!

CHANGELOG.md (1)

13-20: LGTM!

docs/design/obstruction-strands-v0.md (4)

3-9: LGTM!


27-81: LGTM!


101-131: LGTM!


141-147: LGTM!

Comment thread crates/edict-syntax/src/parser.rs
Comment thread docs/design/obstruction-strands-v0.md
@flyingrobots

Copy link
Copy Markdown
Owner Author

Review Fix Summary

Addressed CodeRabbit CHANGES_REQUESTED feedback in commit ec898dc.

Source File Outcome
CodeRabbit crates/edict-syntax/src/parser.rs Duplicate reason diagnostics now use the second offending entry/value span instead of the whole payload span.
CodeRabbit crates/edict-syntax/tests/parse_review_regressions.rs Added regression assertion that the duplicate reason error points at jim.EditObstruction.Other.
CodeRabbit docs/design/obstruction-strands-v0.md Split verification into already verified PR #128 parser tests vs future Core/Target/receipt work.
CodeRabbit docs/topics/obstruction-strands/test-plan.md Clarified that future Core/Target IR disposition is tracked only as planned-row ledger work, while Core semantics and Target lowering remain out of scope.

Verification:

cargo test -p edict-syntax --test parse_review_regressions continue_obstructed
cargo xtask contract-check
cargo xtask verify

All green locally.

@flyingrobots
flyingrobots merged commit c6ddc48 into main Jul 4, 2026
3 of 4 checks passed
@flyingrobots
flyingrobots deleted the syntax/obstruction-strand-source branch July 4, 2026 19:04

@coderabbitai coderabbitai 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.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@crates/edict-syntax/src/parser.rs`:
- Around line 1581-1599: The expr_span helper currently duplicates the Expr
variant list and must stay exhaustive; keep its match arms aligned with Expr in
parser.rs so any new variant is handled here too. If you add or rename an Expr
variant, update expr_span alongside the enum to preserve the compile-time
exhaustiveness check and avoid a stale second source of truth for spans.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: c38b0175-b30f-4e70-afba-d45522accc27

📥 Commits

Reviewing files that changed from the base of the PR and between 2931e40 and ec898dc.

📒 Files selected for processing (4)
  • crates/edict-syntax/src/parser.rs
  • crates/edict-syntax/tests/parse_review_regressions.rs
  • docs/design/obstruction-strands-v0.md
  • docs/topics/obstruction-strands/test-plan.md
📜 Review details
⏰ Context from checks skipped due to timeout. (1)
  • GitHub Check: supply-chain (cargo-deny)
🧰 Additional context used
📓 Path-based instructions (2)
docs/topics/**/test-plan.md

📄 CodeRabbit inference engine (AGENTS.md)

docs/topics/**/test-plan.md: Update a topic shelf test-plan.md before or alongside tests with requirement IDs, case IDs, fixtures, oracles, implemented evidence, planned cases, and known gaps.
Mark planned cases as implemented only when executable evidence exists.
Do not use policy rows in topic-shelf test plans to avoid writing behavior tests for software behavior.
Negative tests in topic-shelf test plans should assert stable error kinds or structured artifacts, not merely is_err() or diagnostic text.
For nontrivial behavior, contract, workflow, release, schema, validation, or public-surface changes, update the owning topic test-plan.md with planned requirement and case rows before or alongside the first test.
Mark planned rows as implemented only after executable evidence exists.

Files:

  • docs/topics/obstruction-strands/test-plan.md
**

⚙️ CodeRabbit configuration file

**: # AGENTS

Git Rules

NEVER amend git commits. Make a new commit instead.

NEVER use git rebase unless the user explicitly approves a rare exception.
Use regular merge commits.

NEVER force any git operation. If a force operation appears necessary, stop and
explain what happened and what options remain.

NEVER create draft pull requests.

NEVER use a codex prefix in branch names, PR titles, or commit messages.

Pull request bodies for issue work MUST include GitHub auto-close text such as
Closes #123`` for every issue the PR is intended to close.

Think

Think is durable memory for cross-session coordination.

  • Use codex-think --remember --json when starting a new session, changing into
    this repository, or regaining context after a context shift.
  • Use codex-think "..." --json when a cycle closes or a significant event
    should survive across turns.
  • Treat Think as memory, not repo truth. Anchor strong claims back to files,
    commits, commands, issues, or pull requests.
  • Claude memories are read-only. Use claude-think --remember --json only for
    additional context.

Topic Shelves

docs/topics/ contains the living contract graph for landed behavior. Topic
shelves are not proposals, retrospectives, or design archaeology.

Each shelf may contain:

  • README.md: what is true in HEAD.
  • test-plan.md: how those truths are verified, including requirements, cases,
    fixtures, oracles, implemented evidence, planned cases, and known gaps.
  • architecture.md: optional structure or dataflow notes when the machinery
    earns a separate page.
  • rationale.md: optional still-relevant tradeoffs and rejected approaches.

When To Update Topic Shelves

For every nontrivial behavior, contract, workflow, release, schema, validation,
or public-surface change:

  1. Identify the owning topic shelf before editing code.
  2. If no shelf owns durable behavior, create one.
  3. Update test-plan.md before or alongside tests with requirement IDs, case
    IDs,...

Files:

  • docs/topics/obstruction-strands/test-plan.md
  • crates/edict-syntax/tests/parse_review_regressions.rs
  • docs/design/obstruction-strands-v0.md
  • crates/edict-syntax/src/parser.rs
🔇 Additional comments (11)
crates/edict-syntax/src/parser.rs (3)

1096-1131: 🎯 Functional Correctness

Duplicate-reason span fix looks correct — resolves prior CodeRabbit feedback.

The previous review asked for the DuplicateField diagnostic to point at the second offending reason entry instead of the whole payload span. The current implementation computes expr_span(value) for Field entries and uses the shorthand's own span for Shorthand entries, then returns Self::err_at(ParseErrorKind::DuplicateField, ..., span) using the second candidate's span while MissingRequiredField still correctly uses payload_span. This matches the updated regression test (continue_obstructed_rejects_duplicate_reason_field) asserting err.span.start equals the position of the second reason value.


225-230: LGTM!

Also applies to: 1072-1094


7-10: LGTM!

Also applies to: 31-32, 63-64, 906-912, 1133-1148, 1605-1625

docs/design/obstruction-strands-v0.md (2)

149-176: "Verification" split now correctly separates PR-1 evidence from future work — prior feedback addressed.

The earlier review flagged that the "Future Verification" checklist understated already-landed evidence. This revision now cleanly splits "Already verified in PR #128" (anchored to concrete test names: continue_obstructed_source_arm_parses, helper_shaped_continue_in_obstructed_strand_is_terminal, continue_obstructed_requires_reason_field, continue_obstructed_rejects_duplicate_reason_field, continue_obstructed_is_contextual_to_require_else) from genuinely future Core/Target IR/receipt work. This matches the coding guideline that test-plan/evidence claims should only be made once executable evidence exists.

Source: Coding guidelines


3-5: LGTM!

Also applies to: 27-81, 101-131, 141-148

crates/edict-syntax/tests/parse_review_regressions.rs (4)

243-262: LGTM!


265-297: LGTM!


300-311: 🎯 Functional Correctness

Updated duplicate-field test correctly asserts the tightened span — matches parser fix.

Switching from reject_kind to direct parse_module + expect_err lets the test assert err.span.start against src.find("jim.EditObstruction.Other"), which is exactly the evidence the guidelines require ("Negative tests ... should assert stable error kinds or structured artifacts, not merely is_err() or diagnostic text"). This is a solid regression addition.

Source: Coding guidelines


313-359: LGTM!

docs/topics/obstruction-strands/test-plan.md (2)

12-16: 📐 Maintainability & Code Quality | 💤 Low value

"planned-row ledger entries" is an unusual scope item — double-check wording intent.

Line 13 lists "planned-row ledger entries for future Core and Target IR disposition work" as in scope. That's fine if it means "this shelf tracks the planned rows," but the guidelines specifically warn against policy rows being used "to avoid writing behavior tests for software behavior." Worth a quick sanity check that this bullet isn't read as license to defer real test coverage indefinitely rather than as a documentation-tracking statement.

Source: Coding guidelines


27-56: LGTM!

Also applies to: 68-68

Comment on lines +1581 to +1599
fn expr_span(expr: &Expr) -> Span {
match expr {
Expr::Ident { span, .. }
| Expr::Int { span, .. }
| Expr::Str { span, .. }
| Expr::Bool { span, .. }
| Expr::Digest { span, .. }
| Expr::Field { span, .. }
| Expr::Call { span, .. }
| Expr::Unary { span, .. }
| Expr::Binary { span, .. }
| Expr::Record { span, .. }
| Expr::If { span, .. }
| Expr::IfYield { span, .. }
| Expr::VariantLit { span, .. }
| Expr::Match { span, .. } => *span,
}
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Exhaustive expr_span match — verify it stays in sync with Expr.

The match arms cover all 14 current Expr variants with no wildcard, so this will fail to compile (good) if Expr grows a new variant without updating this helper — that's a reasonable non-silent-failure design. Just flagging for awareness since it's a second source of truth for spans alongside whatever span access already exists on Expr variants individually.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@crates/edict-syntax/src/parser.rs` around lines 1581 - 1599, The expr_span
helper currently duplicates the Expr variant list and must stay exhaustive; keep
its match arms aligned with Expr in parser.rs so any new variant is handled here
too. If you add or rename an Expr variant, update expr_span alongside the enum
to preserve the compile-time exhaustiveness check and avoid a stale second
source of truth for spans.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Parse obstruction strand continuation source syntax

1 participant