Skip to content

Probes III#2061

Draft
disconcision wants to merge 47 commits intodevfrom
probe-III
Draft

Probes III#2061
disconcision wants to merge 47 commits intodevfrom
probe-III

Conversation

@disconcision
Copy link
Member

@disconcision disconcision commented Jan 14, 2026

In-progress probes features for study that didn't make it into #1879. See #2058 for future features currently out-of-scope.

STUDY:

  • Select tasks
  • Retheme tasks if necessary
  • Add quickdocs to sidebar
  • Populate tutorial mode with tutorial
  • Revisit in terms of RQs

TODO:

  • Add 'Focus' sample context action. Similar to pin but works on anything (maybe only have it when not on ap). effect should be to pin the stack of the sample ie as if we pinned the call. not sure if literally do that.
  • should always show dyncursor bar in autodef mode; otherwise jumps on and off as you arrow between functions. also try to somewhat integrate auto toggle into position of the bar
  • try to see if we can replace step-into by jump to definition, but if used on a probed ap, or the fn of a probed ap i guess, it accurately sets the dyncursor
  • Consider coloring combo
  • Sidebar: Docs: Better hover descriptions on toggles
  • Sidebar: Docs: Info popup for probes list?

Tutorial System (for study)

  • Basic system
  • Nested structure
  • Actual tutorial
  • Back functionality

END:

  • Sidebar: Finalize options are actually exposed
  • Choose if exposing both auto mode and auto probe (confusing names...)

Possibly out of scope:

  • DynBar: allow pin (via dropdown?)
  • DynBar: Add/remove affordance for probes on aps in callstack
  • DynBar: show values (and maybe more?) in dropdown
  • Sidebar: Refine toggles (0/1/inf?)
  • Sidebar: Make autoprobe map collapsable (collapsed shows first and last maybe so shows params and body for fn lit)
  • Sidebar: Probe displays in sidebar should always be Single not Many
  • Sidebar: Legend: Add indet

Unknowns:

  • Autoprobe vs. Manual Probe Interaction: Prevent adding manual probe inside autoprobe, or un-autoprobe on manual add?
  • Should dyn cursor incorporate current ap in some way? example... when in single mode, when on one of the calls to cases in the probes slide, would be nice if the samples shown in the cases function body would align to the ap being indicated.

Done Tasks:

  • all debugging tasks should use model/action nominative types

DONE Features:

  • StepInto: Set manual probe, and make sure pin is preserved, especially in autodef mode
  • Printarium: word-wrap printouts
  • Printarium: better toggle
  • Add DynBar: Better dynamic cursor UI
  • DynBar: Don't filter out aps in builtins.
  • DynBar: tooltip should indicate when syntax jump will round up
  • DynBar: Allow unpin via dynamic cursor pin icon
  • DynBar (or elsewhere): a remove-all affordance for probes
  • Dyncursor: Align to new ephemerals as you type: In the context of EmojiPaint-extend writing task: consider setting the dyncursor when new autos are added or something like that. when start writing a new case, there are no live values if not already aligned.
  • DynCursor should reset when there are no probes, or maybe something more specific
  • DynCursor: Adding a probe should set dyncursor to that probe's initial sample. In particular, align dyncursor to it if no samples would be otherwise shown
  • Sample Dropdown: Show function argument values for aps. When an argument is just a variable reference, append the name as a label and remove it from the environment display
  • Auto mode for Autoprobe: Follows caret, automatically auto-probing the top level definition that the caret is in. Removes option from context menu
  • Autoprobe: For TupLabel on line, autoprobe probes TupLabel instead of just the value (nbd but suboptimal)
  • Feature: Probe all mode (refactor probe sample gathering in evaluator)
  • Printarium run button option
  • Sample legend: Explanatory hovers
  • Sample legend: (Cyrus) consistency of naming of "cursor" -> should be "dynamic cursor" whenever possible; move Dynamic Cursor box in probearium to top or some other way to make clear that the legend reference to "Cursor" is the dynamic cursor
  • Sample: Legend: (Cyrus) Include icon for samples not aligned with cursor in legend in many mode

DONE Bugs:

  • step into shouldn't show for built-in functions
  • Bug: Auto mode dyncursor is borked (try on-screen arrows, or just clicking sample)
  • Bug: Add statics to fn literal and look at ctx menu options
  • Bug: Autoprobe on go in ADTs reveals incorrect no samples for case (see screenshot on desktop)

disconcision and others added 4 commits December 22, 2025 00:56
Re-add features that were simplified for probemoar merge:

Debug/profiling (for development):
- WorkerServer.re: Eval timing logging
- ScratchMode.re: Round-trip timing
- CodeEditable.re: Probe perf profiling

UI features:
- NutMenu.re: probe_all toggle enabled
- ProbeSidebar.re: Full feature set
  - Probearium/Printarium mode toggle
  - sketch_view settings panel with all toggles
  - Full Dynamic Cursor with opacity for items after index
  - Sample displays in probe list
  - indicated-call red outline

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The fold projector's hover view was always rendering code as single-line
because simple_code hardcoded is_single_line=true. Now view_seg accepts
an optional ~single_line parameter (default false) so FoldProj gets
multiline display while ProbeProj and TypeProj explicitly use single-line.

Changes:
- ProjectorBase.re: Add ~single_line to View.seg type
- ProjectorView.re: Pass ~single_line through flex_code and mk_view
- ProbeProj.re: Create view_seg_single_line wrapper for probe displays
- TypeProj.re: Add ~single_line=true for type display
- ProbeSidebar.re: Add ~single_line=true for sidebar displays

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@disconcision disconcision mentioned this pull request Jan 14, 2026
17 tasks
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@disconcision disconcision mentioned this pull request Jan 15, 2026
91 tasks
Base automatically changed from probemoar to dev January 16, 2026 23:03
@codecov
Copy link

codecov bot commented Jan 17, 2026

Codecov Report

❌ Patch coverage is 13.28671% with 248 lines in your changes missing coverage. Please review.
✅ Project coverage is 49.79%. Comparing base (322405a) to head (f26e732).
⚠️ Report is 77 commits behind head on dev.

Files with missing lines Patch % Lines
src/haz3lcore/ProbePerform.re 4.95% 96 Missing ⚠️
.../haz3lcore/projectors/implementations/ProbeProj.re 0.00% 67 Missing ⚠️
src/web/app/editors/code/ContextMenu.re 0.00% 16 Missing ⚠️
src/haz3lcore/TyDi/TyDi.re 0.00% 15 Missing ⚠️
src/haz3lcore/zipper/action/SampleCursorPerform.re 0.00% 11 Missing ⚠️
src/language/dynamics/Sample.re 15.38% 11 Missing ⚠️
src/web/util/WorkerServer.re 0.00% 8 Missing ⚠️
src/language/dynamics/state/EvaluatorState.re 75.00% 5 Missing ⚠️
src/language/dynamics/Dynamics.re 0.00% 3 Missing ⚠️
src/language/statics/Elaborator.re 0.00% 3 Missing ⚠️
... and 6 more
Additional details and impacted files
@@            Coverage Diff             @@
##              dev    #2061      +/-   ##
==========================================
+ Coverage   49.52%   49.79%   +0.27%     
==========================================
  Files         241      231      -10     
  Lines       26676    25727     -949     
==========================================
- Hits        13210    12810     -400     
+ Misses      13466    12917     -549     
Files with missing lines Coverage Δ
src/haz3lcore/derived/AutoProbe.re 71.57% <100.00%> (+0.83%) ⬆️
src/haz3lcore/lang/Token.re 81.25% <100.00%> (ø)
src/language/dynamics/Evaluator.re 94.36% <ø> (+0.08%) ⬆️
src/language/dynamics/transition/Transition.re 64.96% <100.00%> (-0.28%) ⬇️
src/web/app/editors/code/CodeEditable.re 0.00% <ø> (ø)
src/web/view/NutMenu.re 0.00% <ø> (ø)
src/haz3lcore/zipper/action/Action.re 0.00% <0.00%> (ø)
src/haz3lcore/Editor.re 17.64% <50.00%> (+0.98%) ⬆️
src/haz3lcore/zipper/Refractors.re 48.00% <0.00%> (-2.00%) ⬇️
src/language/term/Abbreviate.re 9.82% <0.00%> (ø)
... and 12 more

... and 80 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.

disconcision and others added 12 commits January 19, 2026 19:19
Each legend item now shows an explanatory tooltip on hover,
positioned below the legend panel. Also cleans up Language
module prefixes in ProbeSidebar.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
When a sample has no environment bindings to display, the context menu
actions (Pin/Step into) now stack vertically like a traditional menu
instead of horizontally.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Merges latest dev changes and resolves conflicts:
- ZipperBase.re: Use dev's extracted Refractor module pattern
- Editor.re: Keep dev's comment, add auto_def probe handling
- Refractors.re (root): Deleted, functionality moved to ProbePerform.re

Adds auto_def field to zipper/Refractors.re for auto-probe-follows-cursor
feature, which automatically places an auto-probe on the body of whichever
top-level definition the cursor is currently inside.

Fixes data flow issue where probes would appear but show no samples until
an edit was made. The fix detects ephemeral probe changes in CodeWithStatics
and triggers statics recalculation, which updates evaluation targets.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
When the cursor is on a secondary (whitespace/comment), the indicated
piece has no statics info, causing toplevel_def_body_id to return None.

Fix: Fall back to using the parent tile's ID from the zipper's ancestors,
which is guaranteed to be a real tile with statics info.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Two new auto-probe behaviors:

1. Test forms: When cursor is inside a test, auto-probe the entire test
   body. This overrides let behavior, so `test let a = 1 in a pass` with
   cursor on `a` probes the full test body, not just the let definition.

2. Let delimiter/pattern: When cursor is on the let keyword itself or
   inside the pattern (not in body), auto-probe the definition.

Implementation:
- StaticsBase.toplevel_def_body_id: Check for Test/HintedTest as current
  term or ancestor (priority over Let). Changed Let condition from
  "cursor in def" to "cursor NOT in body".
- ProbePerform.target_subterm_ids: Don't redirect Let→definition when
  the Let is the body of a Test (so we see test result, not just def).

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Rewrote toplevel_def_body_id with a cleaner top-down algorithm:
- Walk ancestors from outermost to innermost
- For each let, check if child-toward-cursor is the body
- If child == body: skip (cursor in body, let doesn't apply)
- Otherwise: return that let's def (cursor in def/pattern/on-delimiter)

Key insight: the ONLY way to not probe a let's def is if cursor is
in its body. Being on the delimiter, pattern, or def all qualify.

Fixed edge case: when cursor is directly on a top-level let (no
containing let exists), return that let's def as the auto-probe target.

Also moved toplevel_def_body_id from StaticsBase.re to ProbePerform.re
since it's probe-specific logic, not general statics.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Brings in:
- Auto-probe for test forms and let delimiters/patterns
- Fix auto-probe disappearing on whitespace/comments
- Top-down algorithm for toplevel_def_body_id
- Move toplevel_def_body_id from StaticsBase to ProbePerform
…toprobe when active. manual run more for printarium / console log
When a probe (manual or auto) is added, the sample cursor now
automatically points to an appropriate sample from that probe once
evaluation completes. Uses pending_probe_cursor field to defer until
async worker returns results. Picks the lexically first probe with
samples and uses closest_to_cursor for conservative sample selection.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- TyDi: min 2-char prefix before showing completions; prioritize
  keywords over context vars when expected type is unknown
- AutoProbe: soft-reject function types (probe if no better alternative)
- Elaborator: elaborate first pattern in MultiHole([Pat(p1), ...])
- Abbreviate: show <function> and builtin name instead of <>

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
When moving to a function definition with auto-probe mode enabled,
the sample cursor wasn't being set correctly - samples appeared blue
until another action was performed.

Fixes:
- CellEditor: Pass ~auto_probe_mode to second pass in calculate to
  prevent clear_auto_def from removing the probe
- CellEditor: Force recalculation when pending_probe_cursor is set
  during ResultAction handling
- Editor: Call resolve_pending_probe_cursor after update_auto_def_probe
  since editor_effects runs before it

Also:
- ProbeSidebar: Shorten toggle labels ("Auto"/"Manual" -> "A"/"M")
- Test: Fix arrow syntax in recursive test case
- TODO: Commented out profiling code in CodeEditable, WorkerServer,
  ScratchMode (to be deleted later)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@cyrus-
Copy link
Member

cyrus- commented Jan 28, 2026

  • show sample selector on hover not requiring a click on a sample

disconcision and others added 6 commits January 28, 2026 21:13
- New ClosureCursorBar component shows call stack as breadcrumbs
- Appears below top bar when probes are active
- Click entries to jump to syntax location
- Add RecordStackFrame to built-in function applications
- Fix grid layout for 4-row structure with sidebars

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
After the refactor that changed projector actions from IDs to indices,
clicking on probe samples caused a List.nth failure. The issue was that
refractor indices were computed from refractor_list in the view layer,
but ProjectorPerform.go only received projector_list for index lookup.

Added refractor_list parameter to ProjectorPerform.go and use
is_refractor(kind) to select the correct list for Focus and SetModel
actions.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
disconcision and others added 16 commits February 2, 2026 21:42
- Click function names → jump to definition/body
- Click separators (⟩) → jump to application site
- Use λ instead of ⌀ for top-level entry
- Add ghost styling to separators
- Lower z-index to sit under top bar outline
- Various CSS refinements (hover states, colors, border-radius)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Change call_stack type from list(Id.t) to list(stack_frame) where
  stack_frame = (Id.t, option(string)) to carry function names
- Capture function names during evaluation before unboxing discards them
- Add SetIndex action for direct sample cursor navigation
- Update ClosureCursorBar to use names from call_stack (enables display
  of function names for calls inside built-in HOFs like map/fold)
- Wire up breadcrumb clicks: entries set cursor index + jump to
  definition, separators set cursor index + jump to call site

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Double chevron (❯❯) before first ghost entry as visual indicator
- Add above/below color coding using same pink/blue as sample display
- Extract sample position colors to CSS variables for consistency
- Ghost entries at 0.7 opacity (blue color distinguishes them)
- Fixed-width separators to prevent layout shift

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Show pin icon next to the pinned entry in the breadcrumb bar
- Clicking the pin icon removes the pin (toggles it off)
- Uses same visual style as sample pin icon (red background)
- Pin icon positioned inline before the function name

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Edit pin SVG to use white fill instead of black
- Remove filter: invert() hacks from all pin icon CSS
- Use direct background colors (var(--R1) for red, var(--T3) for grey)
- Simplifies styling and makes colors more predictable

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Adjust pin icon positioning in closure cursor bar
- Comment out call_cursor_view in sidebar (TODO: handle autos)
- Add plan/closure-cursor-bar-deferred.md with future ideas:
  - Collapsing recursive runs
  - Ghost entry toggle
  - Indicated entry highlighting
  - Dropdown menus for branching paths
  - Investigation breadcrumbs for debugging

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
After changing call_stack from list(Id.t) to list(stack_frame) where
stack_frame = (Id.t, option(string)), pin filtering broke because:
- pin_call creates frames with None for function names
- actual samples have real names like Some("map") from evaluation
- structural equality failed: (id, None) != (id, Some("map"))

Fix: Add ids_of_stack helper to extract just IDs, use for comparisons
in filter_by_pin, show_pin, toggle_pin_call, resolve_pending_focus,
and is_in.

Also includes pin icon color fix (red background).

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Arrow keys navigate between breadcrumb entries (left = shallower, right = deeper)
- Enter jumps to definition and refocuses main editor
- Red outline highlights entry when syntax cursor is on its app expression
- Top-level lambda now shows focused styling when index is -1
- Various CSS polish: disable focus outline, fix padding, add tooltips
- Update deferred ideas documentation

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Lambda now gets text-decoration: underline when focused, matching other entries
- Update deferred docs: MVP implemented, focus shortcut TODO with candidates

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Needs investigation - possible mismatch between breadcrumb indicated state
and sample indicated state when clicking separators.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
When a probe is directly on a function application (e.g., ^^probe(f(5))),
the sample dropdown now displays the argument values that were passed.

- Store argument values during RecordStackFrame in EvaluatorState
- Look up and attach args to samples in both Evaluator.re paths
- Display call with values in dropdown (e.g., "f(5)" or multiline for tuples)
- Bold parentheses, regular code font for function name
- Divider line between call display and environment section

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@disconcision disconcision changed the base branch from dev to probe-fixes February 4, 2026 07:33
Base automatically changed from probe-fixes to dev February 4, 2026 20:51
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

Comments