Skip to content

[draft] insert before/after (overwrite)#2316

Draft
SirQuackyy wants to merge 85 commits into
devfrom
insert-before-after
Draft

[draft] insert before/after (overwrite)#2316
SirQuackyy wants to merge 85 commits into
devfrom
insert-before-after

Conversation

@SirQuackyy
Copy link
Copy Markdown

Select and insert code in different expressions/elements using a special token as a representation of the selected code for overwriting.

disconcision and others added 30 commits February 28, 2026 20:25
# Conflicts:
#	src/web/Settings.re
#	src/web/app/helpful-assistant/ChatLSP.re
Module(items) returns [] children (items are Mod.t, not Exp.t).
ModuleExp(mp, def, body) returns [def, body] as child expressions.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Covers: path system critique and extension proposals, module edit
actions design, test suite plan, read/query improvements sketch.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Major additions:
- Error feedback loop analysis (works via ToolResult, needs curated messages)
- Static context restoration plan (TyDiCtx, GetStatics action)
- Dynamic cursor integration plan (Sample.Cursor.t already built)
- Thorough path examples across 6 program structures
- Form-slot path design ("f/fun/if/then" abbreviated-syntax approach)
- Read action design (GetSyntax, GetStatics, GetDynamics, GetContext)
- Annotated views and compositional query sketches

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…selectors

Key feedback incorporated:
- Delimiter-based child naming (use actual syntax tokens)
- Definition/Pattern/etc should fold into path (not separate target type)
- Names are pattern matchers against binding patterns
- Sibling selectors for case arms by pattern
- GetStatics as curated heuristic package, not raw context
- Fix: case not match, /* */ not (* *)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…t tools

- Extend HighLevelNodeMap to discover Module items as children (via
  ExpandModule ID-preserving expansion to Let/TyAlias chains)
- Add structured path resolution with Name, Index (#n), and FinalExpr
  segments, replacing flat name-path comparison
- Add module edit action support (Update Definition/Pattern work;
  Insert/BindingClause documented as limitations due to tile format mismatch)
- Add 28 new tests across 4 groups: module node map, module edit actions,
  path extensions, and edge cases (39 total, all passing)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add ReadAction variant to CompositionActions with GetSyntax, GetStatics,
  GetContext read actions that return information without modifying the editor
- Implement read_dispatch in CompositionGo: GetSyntax returns pretty-printed
  code at path, GetStatics returns type info (ana/syn/errors), GetContext
  returns in-scope variables, type aliases, and constructors
- Add tool JSON definitions (get_syntax, get_statics, get_context) with
  descriptions and examples for LLM consumption
- Wire read actions through Agent.re: compute results in handle_tool_call,
  send actual content (not generic success msg) to LLM via mk_tool_result_message
- Add 10 read action tests covering syntax retrieval, type info, context
  inspection, module paths, index paths, and error detection
- Total: 49 tests (34 AgentTools + 15 HighLevelNodeMap), all passing

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Enables updating just the type annotation in let bindings (the T in
`let x : T = ...`) and type alias definitions without touching the
pattern or definition. Adds update_type_annotation tool, dispatch
handling, and 5 tests covering annotated/unannotated/nested bindings
and type aliases.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Bare expressions in semicolon sequences (test statements, standalone
expressions) are now addressable by #n index paths. Extends
build_children with Seq case that creates nodes for non-binding
expression lines, extends Namer for bare expressions, handles
bare-expression nodes in GeneralTreeUtils.subtree_of for static
error checking, and extends top_level_term_of for Seq recognition.
6 new tests covering siblings, indexing, $, and update_binding_clause.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Checks for unmatched delimiters (via Zipper.local_backpack) before
static error checking in all edit dispatch cases. Introduces
validate_edit helper that chains parse + static error checks,
reducing boilerplate in Update(Definition|Body|BindingClause|
TypeAnnotation) cases. Parse errors now produce clear messages
listing the unmatched delimiter tokens.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Adds expected type, synthesized type, and in-scope variables to the
context message sent to the LLM before each interaction. For pattern
positions, shows expected type and available constructors. Uses
Ctx.filter_shadowed to deduplicate and limits variable list to 10
entries. Adds cursorContext XML section to the existing context
message alongside agentEditorView, staticErrorsInfo, and
workbenchTaskInfo.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
All edit_dispatch cases now use TermEdit (term-level round-trip) instead
of segment-level Select/overwrite. Key changes:

- AutoFormat mode for ExpToSegment handles whitespace heuristically
- Fixed should_add_space to add spaces around : for type annotations
- Pattern rename at term level via rename_var_in_exp (Let and ModLet)
- TyAlias definition updates dispatched to update_type_annotation
- insert_binding strips trailing " in" from user code before parsing
- Module pattern rename handles ModLet items with variable renaming
- Removed dead segment-level helpers (overwrite_term, insert_term,
  destruct, statics_map_new_ids, format_ctx_entry)
- 68 tests pass (45 AgentTools + 23 supporting)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Implements the path selector language (v0) with tokenizer, parser,
elaborator, and resolver. Supports: let/if/case spines, binder chains
(A/B/C), descendant search (⋱), focus (*), slot (_), ellipsis (_...),
and module item navigation. 12 tests covering basic selectors.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Adds Select(selector) read action variant that uses the selector
language to query focused subtrees. Handles single and multiple match
results with breadcrumb annotations. 4 integration tests covering
read-action pipeline for selectors.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Select read action now returns just the focused subtree text,
not the breadcrumb context. The selector already tells you what
was selected.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Adds 10 more selector tests covering spec examples: if condition/then/
else via descendant search, * let f for whole binding selection, case
arm selection by constructor name, module member chains, nested binder
chains, bare name = * without let keyword, body selection via name
_... in *.

Fixes walk_let_spine to return the whole expression when just a name
matches at the terminal position (enables * let f pattern).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Counts EmptyHole nodes in expressions, patterns, and types using
Exp.map_term traversal. Reports total count with breakdown by kind.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Registers both new read actions as callable tools with JSON schema
definitions, descriptions, and examples for the coding agent.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Selector pat_name now uses Pat.is_var to handle Asc/Parens wrappers,
fixing binder resolution for type-annotated let bindings like
`let f : T -> U = ...`. Adds 10 tests covering sum types, records,
case dispatch, type alias updates, and descendant search into functions.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add sel_test, edit_test, read_test helpers for common test patterns.
Refactor selector tests from 6-12 line blocks to one-liners. Extract
shared test programs as module-level constants. Net -220 lines.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Apply the same concise helper pattern to edit action, edge case, and
type annotation test groups. Saves another ~150 lines while keeping
all 84 tests passing.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Static type errors no longer block edits. Instead, they produce
warnings that the agent sees in the success message. Parse errors
(unmatched delimiters, Invalid/MultiHole) still block. This allows
multi-step refactoring like changing a type alias and then fixing
dependent code in a follow-up edit.

- validate_edit returns (Zipper.t, option(string)) with optional warning
- Insert paths use warning instead of global error count rejection
- Agent.re includes warnings in tool call success messages
- Tests: type alias cascade now succeeds with warning (+3 tests)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Case arms are now addressable in the HighLevelNodeMap with pipe-prefixed
pattern names (e.g. "f/|A", "f/|Some(x)"). TermEdit provides the core
operations (parse_case_arm, case_delete_arm, case_insert_arm,
case_update_arm_body, case_update_arm_pattern) and CompositionGo routes
case arm paths through the standard Update/Delete/Insert dispatch.

22 new tests covering TermEdit functions, node map indexing, path
resolution, and full dispatch round-trips for all operations.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
List elements addressable as "xs/[0]", "[1]", etc. Tuple elements as
"p/(0)", "(1)" for positional, or "p/x", "p/y" for labeled tuples.
All sequence types (case arms, lists, tuples) now follow the same
Insert/Delete/Update dispatch pattern through CompositionGo.

TermEdit: list_delete_element, list_insert_element, list_update_element,
tuple_delete_element, tuple_insert_element, tuple_update_element,
is_list_element, is_tuple_element, is_sequence_element.

16 new tests (8 list + 8 tuple) covering TermEdit, node map, and dispatch.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Error messages now include:
- Which node type was detected - case arm, list element, etc.
- What operation was attempted and why it failed
- The path and code being operated on
- Explicit inapplicability errors for wrong action/node combinations

New cross-cutting tests - 8 tests, 132 total:
- Read actions on sequence element paths
- Shadowed name behavior - first binding wins, index for disambiguation
- Inapplicability error messages verified

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…UI, highlights

Selector language additions:
- fun keyword: fun _ -> *, fun x -> *, fun _... -> *
- test keyword: test * body, test _ end
- Colon delimiter: let x : _ = * skip annotation, let x : * annotation
- List spine: [ * first, [ _... * last, [ _ * second
- Tuple spine: generic walk_seq_spine unifies list and tuple matching
- ->, [, ], tokens added to tokenizer/elaborator
- Descend into Test bodies in descend_all
- Verified root-anchored behavior: \... required for nested binder search

Action Explorer UI - new:
- Developer toolbar toggled via Nut Menu > Developer > Action Explorer
- Action/target/direction/read-kind selectors
- Path text input with live highlight resolution
- Select action highlights extracted from Selector.query focused_ids
- SVG highlight CSS for action-explorer-match

Test improvements:
- sel_test/sel_test_rendered use named arguments
- 18 new selector tests
- 152 AgentTools tests total, all passing

Other:
- Descend operator ASCII form changed from \_ to \...
- ReadTools.re select description updated

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Selector changes:
- Add mpat_name helper for module pattern names
- Handle ModuleExp in find_binder_in_exp, find_let_node, descend_all
- Handle ModuleMod items inside Module blocks for nested chains
- Update module keyword handler to match both ModuleExp and Let+Module
- Fix descend_all dedup: same node reachable via body-chain walk and
  child recursion was producing duplicate matches. Now dedup by focused_id.
- 7 new module selector tests: M/x chain, module M = *, body, nested A/B/x,
  descend through module body, descend through let chain

Plan cleanup:
- Remove sections 3.2-3.5 (superseded form-slot path design, ~200 lines)
- Mark sections 9.2 and 9.4 as superseded by selector language
- Update selector language gaps: all spine coverage now implemented
- Add selector-driven edits and error diagnostics to next phases
- Update test count to 159

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Pure whitespace/formatting changes: line-breaking of long function signatures,
trailing semicolon removal from match arms, comment indentation normalization.
No functional changes.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
| _ => * now matches any arm body (MatchSlot in pattern position),
| _... Name => * skips to a specific arm (MatchEllipsis), and
both compose with descend (\...) for multi-match queries.
Deduplicates ellipsis matches by focused_id.

5 new selector tests (163 total AgentTools tests).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
disconcision and others added 28 commits March 2, 2026 12:47
SelectorUpdate now dispatches on the focused variant from the match result:
FocusExp uses parse_exp + replace_exp_by_id, FocusPat uses parse_pat +
replace_pat_by_id, FocusTyp uses parse_typ + replace_typ_by_id, FocusMod
falls back to parse_exp for now. Adds 2 tests for type annotation and
type alias definition updates via selector.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
SelectorDelete now dispatches on the focused variant to use the correct
hole type: Exp.EmptyHole for expressions, Pat.EmptyHole for patterns,
Typ.Unknown(Hole(EmptyHole)) for types. Adds test for deleting a type
annotation to a type hole.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add JSON tool definitions for selector_update, selector_delete,
selector_insert_after, selector_insert_before (EditTools.re) and
get_canonical (ReadTools.re). Wire all five into the tools list and
action_of dispatch in CompositionUtils.re so external LLM agents can
call them by name.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add selector-based action kinds (SelectorUpdate, SelectorDelete,
SelectorInsertBefore, SelectorInsertAfter) and GetCanonical read action
to the Action Explorer developer UI. Separate selector input field from
path input with live highlight resolution via Selector.query.

Also includes minor formatting cleanups in CompositionUtils dispatch.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Merge selector-examples.md as the primary reference document. Add design
philosophy section from compositionality analysis, known limitations, and
future directions. Delete 3 superseded docs (v0 spec, canonical selectors
design, compositionality analysis) — all content absorbed.

Rewrite coding-agent-actions.md from 736 to 173 lines: remove completed
checklists and resolved questions, organize remaining work into near-term
fixes, semantic edit actions, and future features.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
TermEdit: Switch from PreserveWithFallback/AutoFormat to strict
PreserveExact for round-tripping. Add leading/trailing secondary
extraction (walks left/right through compound forms like BinOp where
MakeTerm stores whitespace on leaves, not roots). Fresh nodes get
explicit secondary via helpers. Remove PreserveWithFallback from
ExpToSegment entirely.

Selector: Use find_all_binders_named (multi-match) instead of
find_binder_in_exp (first-match) for `a = *`, `a ... in *`, and
EnterBinderDef cases — shadowed bindings now return all matches.
Add Parens transparency to all three binder-finding functions.

372 AgentTools + 167 Selectors + 16 SelectorEdits + 3 GetCanonical pass.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
SelectorUpdate and SelectorDelete with FocusMod targets (whole module
items from selectors like M/x) previously used replace_exp_by_id which
silently failed since Mod item IDs dont match any Exp node. Now uses
existing find_module_containing_item + replace_item/delete_item infra.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…multi-match

Sync all plan/reference docs with current state. Remove resolved items
from Known Limitations and Remaining Work. Add shadowed binding
multi-match and FocusMod edit examples to selector reference.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The selector focus marker was `*` which conflicted with Hazel's `*`
(Times) operator. Changed to `%` which is unused in Hazel's grammar.
Updated tokenizer, deparse, tool definitions, all 376 tests, and docs.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
% in pattern positions now returns FocusPat:
- let % x, let % =, fun % x, fun % ->, | % A =>
- let % and fun % (bare) also return pattern (first child)
- let x = _ in % now correctly routes to body (was broken)

Implicit focus redesign: when last token is a name, insert %
before it instead of appending. This means `let x` -> `let % x`
-> FocusPat, `fun x` -> `fun % x` -> FocusPat, etc. Delimiter-
ending selectors unchanged (% still appended).

Type/module fallback: `type T` and `module M` still return whole
form via new [MatchFocus, MatchName] arms (no FocusTPat yet).

Constructor matching in case arms documented as convenience
(matches constructor head, not just nullary). 388 tests passing.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
… ActionExplorer redesign

- Module spine navigation: tokenize { } ;, walk_mod_spine with positional,
  ellipsis, keyword-based, and wildcard access to module items
- Atom/literal matching: string-based MatchAtom for integers, floats,
  booleans; works with descent (\... 42)
- Type path selectors: generalize find_all_binders_named return type to
  binder_def = ExpDef | TypDef so M/T = % and M/T/ work for type defs
- Focus on type/module names: type % T and module % M return FocusPat
  symmetrically with let % x
- ActionExplorer: two-tier UI (Selector default, Original), selector
  read sub-kinds (Syntax, Statics, Context, Canonical)
- SelectorGetStatics/SelectorGetContext: resolve selector then look up
  info_map/context, same data as path-based versions
- 19 new tests (12 module spine, 7 atom matching)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add bare name atom matching (pat + exp), descend_all_pat for pattern descent
- Add pat_head_matches helper, binder_def sum type for type/module chains
- Add comma token, Parens(Tuple) transparency, walk_mod_let_spine focus+name
- Add selector-calculus.md spec with Focus(option(selector)) type
- Add selector-rewrite-plan.md for form-generic resolver rewrite
- Clean up obsolete plan files (selector-examples.md, notes-for-andrew.md)
- Trim coding-agent-actions.md, redirect selector content to spec/plan

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…ix tests

Resolve merge conflicts in GeneralTreeUtils.re, HighLevelNodeMap.re,
Agent.re, and Test_AgentTools.re. Refactor UpdateContext from 4 positional
strings to a labeled context_snapshot record.

Fix 8 merge-introduced test failures:
- StaticErrorRejection: use expect_warning (static errors are now warnings)
- ToolJsonDefinitions: update tool count 25 → 36
- Recursive fn whitespace: add prefix forms to trailing_secondary_of
- Delete module M: add ModuleExp case to delete_binding
- Multi-clause update_binding_clause: new replace_innermost_body helper
- CompositionGo TypeAnn: handle new variant in ModuleExp get_inner_term_id

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
HighLevelNodeMap.Modules (3 tests): Module items were counted twice —
once from the expanded Let chain and again from the synthetic export
Tuple (a=a, b=b). Skip trivial re-export TupLabel elements.

ExpToSegment spacing (10 tests): Revert should_add_space colon rules
to match dev branch — no space before ':', conditional space after ':'
(only before $ or !). Commit 7621355 had changed these to unconditional
true, breaking ascription formatting and secondary round-tripping.

ExpToSegment Match (1 test): Update expected output to include space
before second pipe in inline case — 'case x | A => 1 | B => 2 end'.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
# Conflicts:
#	src/web/Settings.re
#	src/web/view/NutMenu.re
# Conflicts:
#	src/haz3lcore/zipper/action/Perform.re
#	src/web/Settings.re
#	src/web/app/Page.re
#	src/web/app/editors/code/CodeEditable.re
#	src/web/view/AgentCore/Agent.re
#	src/web/view/NutMenu.re
# Conflicts:
#	src/haz3lcore/CompositionCore/CompositionGo.re
#	src/haz3lcore/CompositionCore/HighLevelNodeMap.re
Selector navigation deliberately doesn't handle DrvQuote/DrvQuoteTy. Failing loudly is preferable to silently returning no children, which would mask agent code paths that try to address into derivation quotes.
@codecov
Copy link
Copy Markdown

codecov Bot commented May 20, 2026

Codecov Report

❌ Patch coverage is 62.31527% with 459 lines in your changes missing coverage. Please review.
✅ Project coverage is 51.11%. Comparing base (7063347) to head (404fdda).
⚠️ Report is 34 commits behind head on dev.

Files with missing lines Patch % Lines
src/haz3lcore/CompositionCore/TermEdit.re 70.99% 172 Missing ⚠️
src/haz3lcore/CompositionCore/CompositionGo.re 63.36% 133 Missing ⚠️
src/web/view/AgentCore/Agent.re 0.00% 66 Missing ⚠️
src/haz3lcore/CompositionCore/CompositionUtils.re 0.00% 42 Missing ⚠️
src/haz3lcore/CompositionCore/HighLevelNodeMap.re 81.65% 20 Missing ⚠️
...rc/haz3lcore/CompositionCore/CompositionActions.re 0.00% 10 Missing ⚠️
src/haz3lcore/zipper/action/Action.re 0.00% 8 Missing ⚠️
src/web/app/editors/code/CodeEditable.re 0.00% 4 Missing ⚠️
src/web/Settings.re 0.00% 3 Missing ⚠️
src/haz3lcore/CompositionCore/GeneralTreeUtils.re 75.00% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##              dev    #2316      +/-   ##
==========================================
+ Coverage   50.42%   51.11%   +0.68%     
==========================================
  Files         296      298       +2     
  Lines       39458    42021    +2563     
==========================================
+ Hits        19895    21477    +1582     
- Misses      19563    20544     +981     
Files with missing lines Coverage Δ
src/haz3lcore/CompositionCore/Selector.re 61.09% <ø> (ø)
src/haz3lcore/pretty/ExpToSegment.re 62.10% <100.00%> (+1.18%) ⬆️
src/haz3lcore/zipper/action/Perform.re 51.04% <100.00%> (+1.04%) ⬆️
src/web/view/NutMenu.re 0.00% <ø> (ø)
src/haz3lcore/CompositionCore/GeneralTreeUtils.re 40.90% <75.00%> (-17.43%) ⬇️
src/web/Settings.re 0.78% <0.00%> (-0.02%) ⬇️
src/web/app/editors/code/CodeEditable.re 0.00% <0.00%> (ø)
src/haz3lcore/zipper/action/Action.re 0.00% <0.00%> (ø)
...rc/haz3lcore/CompositionCore/CompositionActions.re 0.00% <0.00%> (ø)
src/haz3lcore/CompositionCore/HighLevelNodeMap.re 70.87% <81.65%> (+3.37%) ⬆️
... and 4 more

... and 13 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@github-actions
Copy link
Copy Markdown
Contributor

Performance Benchmarks

⏳ Running... View workflow

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.

2 participants