Skip to content

Editor E4 park: review-verdict fixes, sweep-lead verification, gen2 policy default - #3601

Merged
borisbat merged 16 commits into
masterfrom
codex/e4-park
Aug 1, 2026
Merged

Editor E4 park: review-verdict fixes, sweep-lead verification, gen2 policy default#3601
borisbat merged 16 commits into
masterfrom
codex/e4-park

Conversation

@borisbat

Copy link
Copy Markdown
Collaborator

Follow-up to #3596: executes Boris's verdicts on the landing review's deferred questions and parks E4 for good.

Review-question verdicts executed

  • Viewer tests move in-suite (20ae2dce6) — examples/text/tests/test_viewer.das ran in no CI lane; now modules/dasImgui/tests/test_text_viewer.das per modules/dasImgui/CODEREVIEW.md, riding nightly_imgui + preflight --only imgui.
  • Dead keymap removed (4ce3d70ca) — route_editor_keys (the pre-registry "interim hardwired keymap", zero callers, drifted bindings) and its nav_pressed helper are gone. The no-registry text_source_edit overload now lazily owns a private default-keymap registry, so both overloads route through the one imgui_commands keymap.
  • Fold collection single-parse (022fdb234) — new _tree_sitter_highlight_and_structure extern parses once and feeds both the highlight flattener and the multi-line structure walk; tree_sitter_source_document uses it whenever the language profile folds. The standalone syntax_structure / tree_sitter_collect_folds entry points stay for the markdown-lexical path and external callers.
  • Honest unknown retire tier (5e5e68f77) — an unmeasured unmerged count (no origin/master|main, rev-list failure, unparsable PTY output) used to fall through to the green delete verdict with a check-marked "count unknown" row. New WORKTREE_TIER_UNKNOWN between warn and green: help-glyph checklist row, honest tooltip and session-retire reason; delete stays advisory like warn.
  • CodeOfPolicies.version_2_syntax defaults to true (8bef48c7e) — gen2 has long been the CLI default, but every embedder or das tool constructing a fresh cop still parsed options-less buffers as gen1 (the editor's das provider shipped with exactly that bug). Per-file options gen2 = false still opts out both ways (probe-proven); tests-cpp-small passes 78/78 (1,103,732 assertions) under the flip.

Sweep-lead verification (adversarial, fixes test-first)

  • CONFIRMED — markdown code-blocks rail OOB (026f9cf1b): the rail indexed the view's layout cache with document-node indices, but that cache is empty until the first render — a plain-text-mode file containing a fence panicked (array index out of range, 3 of 0, reproduced). markdown_view_code_blocks now owns the walk and reports undrawn blocks as laid_out = false; the same unguarded pattern in rich_live.das fixed too. New test_markdown_view_code_blocks (3), watched red first.
  • CONFIRMED — destructive-confirm hijack (2dc2d5caf): the retire-dialog lead was refuted as located (identity held by path, not index), but the shared destructive-confirm modal re-derived its terminate target from the live selection, which the network re-points on its own (launch, herd-create, pruned-session auto-attach) — a confirm could silently act on nothing. New destructive_confirm.das model derives the action from the captured identity and refuses a repository-less delete. New test_destructive_confirm (5), watched red first.
  • REFUTED — named-key sentinel walk: doubly guarded, no bad key escapes. The walk did trip IM_ASSERT(IsNamedKeyOrMod) on ImGuiKey's range markers in assert-enabled builds (9b0fb8c9f) — imgui_key_is_nameable() now gates by value. New test_imgui_key_nameable (3).

Nolint hygiene (STYLE037/038 on new code)

Stripping all suppressions and re-linting showed 12 of 16 were stale — the code had already shrunk under the caps; they are simply removed (c1fa17f4e). The 4 that still fire carry measured reasons in the — why format (keymap registration table, command-verb ladder, ordered capture-prefix ladder, one-pass lexer). The 8 test_text_viewer scenarios and the viewer state snapshot carry theirs too (123a8ea8d).

Gates

  • changed-set lint: 22 files, 0 issues; formatter: all already_formatted
  • watcher suite 132/132; dasImgui full suite green (CODEREVIEW.md recipe + Windows high-POST excludes); editor model 45/45, complete model 20/20, fold model 2/2, viewer 8/8, tests-cpp-small 78/78
  • preflight run before push

🤖 Generated with Claude Code

https://claude.ai/code/session_01Kv2yQu558ryra5WS1AFASZ

borisbat and others added 12 commits July 31, 2026 13:37
… self-owns a default registry

The hardwired pre-E2 keymap had zero in-tree callers and had diverged from
the registry bindings. text_source_edit without a registry now lazily
registers the default keymap into a private CommandRegistry, so both
overloads route through the one imgui_commands keymap.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Kv2yQu558ryra5WS1AFASZ
examples/text/tests ran in no CI lane or gate; test_viewer.das becomes
tests/test_text_viewer.das and rides nightly_imgui + preflight --only imgui.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Kv2yQu558ryra5WS1AFASZ
WORKTREE_TIER_UNKNOWN between warn and green: an unresolved base ref
(no origin/master|main, rev-list failure, unparsable PTY output) used to
fall through to the green delete verdict with a check-marked 'count
unknown' row. Now the tier, the retire-dialog help glyph, the row
tooltip, and the session-retire reason all say unknown honestly; delete
stays advisory like warn.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Kv2yQu558ryra5WS1AFASZ
The two code-block rails walked the document's node list and indexed the
view's node cache with it. The cache is sized on the first render, so a
document in plain-text mode -- or one reparsed larger than the retained
cache -- panicked with "array index out of range" instead of answering.

markdown_view_code_blocks() owns the walk now and reports an undrawn block
with laid_out = false and zero geometry.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Kv2yQu558ryra5WS1AFASZ
…d one

New extern _tree_sitter_highlight_and_structure parses once and feeds both
the capture flattener and the multi-line structure walk (collectHighlights
grew a keep_tree handoff; the walk and the token emitter are shared
helpers). tree_sitter_source_document uses it whenever the language
profile folds; the standalone syntax_structure/tree_sitter_collect_folds
entry points stay for the markdown-lexical path and external callers.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Kv2yQu558ryra5WS1AFASZ
The shared confirmation modal re-derived its terminate target from the live
selection and only fired when it still matched the captured one. The network
re-points that selection on its own -- every launch and relaunch attaches the
new session, and a pruned session hands it to the first running one -- so a
confirmation the user read and accepted silently terminated nothing.

The captured worktree_delete repository was worse: the slot was read at
confirm time and written nowhere, so wiring that kind up would have sent a
delete with a blank repository for the watcher to aim.

destructive_confirm.das owns the decision now: everything comes from the
capture, and a confirmation that cannot name its target sends nothing.
terminate_session() replaces terminate_selected().

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Kv2yQu558ryra5WS1AFASZ
Iterating type<ImGuiKey> hands GetKeyName three values that are not keys:
NamedKey_END (667), NamedKey_COUNT (155) and ImGuiMod_Mask_ (61440). Release
ImGui answers "Unknown" and the lookup already rejects that, so no sentinel
was ever passed on -- but IM_ASSERT(IsNamedKeyOrMod) fires on all three in an
assert-enabled build, aborting on the unsupported-key path.

imgui_key_is_nameable() gates the walk by value.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Kv2yQu558ryra5WS1AFASZ
gen2 has been the CLI default for a long time, but every embedder or
das-side tool constructing a fresh CodeOfPolicies still parsed
options-less buffers as gen1 (the editor's das provider shipped with
exactly that bug). The struct default now matches the language default;
per-file 'options gen2 = false' still opts out both ways (probe-proven),
and tests-cpp-small passes 78/78 under the flip.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Kv2yQu558ryra5WS1AFASZ
`var block = ...` is error[30151], which reads as nothing in particular
until you know the lexer claims the word.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Kv2yQu558ryra5WS1AFASZ
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Kv2yQu558ryra5WS1AFASZ
The eight event-gated playwright scenarios and the JV state snapshot are
suppressed by design, not by omission - say why on each line.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Kv2yQu558ryra5WS1AFASZ
Stripping every STYLE037/038 suppression in the E4 editor files showed that
twelve of the sixteen no longer tripped anything - the code had shrunk under
the caps since they were added. Those are gone. The four that still fire are
a keymap registration table, a command-id ladder, an order-sensitive
capture-prefix ladder, and a one-pass lexer; each now names why splitting it
would cost more than it buys.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Kv2yQu558ryra5WS1AFASZ
Copilot AI review requested due to automatic review settings July 31, 2026 21:25

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR follows up on #3596 by landing a set of targeted fixes and verifications in the dasHerd watcher + dasImgui text stack, including safer destructive confirmations, a new “unknown” worktree delete tier for unmeasured unmerged counts, a single-parse Tree-sitter path for highlight+structure, and flipping the default CodeOfPolicies.version_2_syntax to gen2.

Changes:

  • Introduce WORKTREE_TIER_UNKNOWN and propagate it through watcher UI/messaging/tests so “unmerged count unknown” never reads as “safe/green”.
  • Replace ad-hoc destructive-confirm globals with a small destructive_confirm model + tests; update termination to always target an explicit session id.
  • Add _tree_sitter_highlight_and_structure (C++ + AOT header + das wrapper) and use it to avoid double-parsing when folds are needed.

Reviewed changes

Copilot reviewed 28 out of 28 changed files in this pull request and generated no comments.

Show a summary per file
File Description
utils/dasHerd/watcher/tests/test_repository_core.das Extends coverage for the new unknown delete tier and adds failure-explanation tests.
utils/dasHerd/watcher/tests/test_destructive_confirm.das New tests ensuring confirm actions remain bound to captured identity and reject repo-less deletes.
utils/dasHerd/watcher/rich_sessions_ui.das Integrates shared destructive-confirm model and adds unknown-tier retire reason messaging.
utils/dasHerd/watcher/rich_net.das Changes termination API to target a specific session id (not “selected”).
utils/dasHerd/watcher/rich_live.das Updates live-command tier docs and switches markdown code-block inspection to the new safe enumerator.
utils/dasHerd/watcher/rich_git_ui.das Updates retire hint text to reflect the new unknown tier semantics.
utils/dasHerd/watcher/rich_client.das Adds “help” glyph row support and surfaces the unknown tier as a third checklist state.
utils/dasHerd/watcher/repository_core.das Defines WORKTREE_TIER_UNKNOWN and ensures unmeasured counts do not map to green.
utils/dasHerd/watcher/destructive_confirm.das New pure-logic module that captures destructive-confirm intent and derives a safe dispatch action.
modules/dasTreeSitter/src/dasTreeSitter.cpp Adds a combined highlight+structure extern, refactors structure walk, and supports tree reuse.
modules/dasTreeSitter/src/aot_builtin_tree_sitter.h Declares the new combined extern for AOT builds.
modules/dasTreeSitter/daslib/tree_sitter.das Adds syntax_highlight_and_structure wrapper for one-parse token+span collection.
modules/dasImgui/widgets/imgui_live_core.das Adds imgui_key_is_nameable and uses it to avoid asserting ImGui key markers.
modules/dasImgui/text/imgui_text_tree_sitter.das Refactors fold extraction and introduces the “wants_folds” single-parse path.
modules/dasImgui/text/imgui_text_source_edit.das Removes dead hardwired key routing and makes the no-registry overload use a private registry.
modules/dasImgui/text/imgui_text_edit_syntax.das Removes stale nolint from a small helper.
modules/dasImgui/text/imgui_text_edit_provider_das.das Updates comment to reflect gen2 flip motivation (still explicitly sets gen2 for compatibility).
modules/dasImgui/text/imgui_text_edit_provider_cpp.das Removes stale nolint from clang output parsing entry point.
modules/dasImgui/tests/test_text_viewer.das Updates nolint annotations to include rationale for long scenario tests.
modules/dasImgui/tests/test_markdown_view_code_blocks.das New regression tests for code-block enumeration when view cache is empty/short.
modules/dasImgui/tests/test_imgui_key_nameable.das New tests asserting marker keys are excluded from GetKeyName probing.
modules/dasImgui/markdown/imgui_markdown_view.das Adds markdown_view_code_blocks API that safely reports code blocks even before first layout.
modules/dasImgui/examples/features/text_edit.das Removes stale nolint on the example update loop.
modules/dasImgui/CLAUDE.md Updates the approximate test-file count in docs.
include/daScript/ast/ast.h Flips CodeOfPolicies.version_2_syntax default to true and documents the opt-out.
examples/text/main.das Switches code-block inspection to markdown_view_code_blocks and updates nolint rationale.
CLAUDE.md Adds/records a lexer-reserved-words note (type-token identifiers).
.github/workflows/nightly_imgui.yml Updates comment test-file count estimate in workflow header.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

test_compile_sample compiles its embedded sample under a DEFAULT
CodeOfPolicies, so the gen1 sample stopped parsing when
version_2_syntax flipped to true. The sample is now gen2, making the
test the in-tree witness of the flipped default.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Kv2yQu558ryra5WS1AFASZ
Copilot AI review requested due to automatic review settings July 31, 2026 21:39

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 29 out of 29 changed files in this pull request and generated no new comments.

Suppressed comments (2)

modules/dasImgui/markdown/imgui_markdown_view.das:543

  • markdown_view_code_blocks treats a node as laid_out purely based on index < length(state.nodes). After prepare_view_state() calls markdown_view_invalidate(), state.nodes can already be sized to the document while every entry has screen_revision = -1 (never rendered yet). In that case this function incorrectly reports laid_out = true for undrawn blocks, which reintroduces the same class of inspection OOB/incorrect telemetry the helper is meant to avoid.
    for (index in range(length(doc.nodes))) {
        continue if (doc.nodes[index].kind != RichNodeKind.code_block)
        var code = MarkdownViewCodeBlock(node = index,
            collapsed = markdown_view_code_collapsed(state, index))
        if (index < length(state.nodes)) {

modules/dasImgui/tests/test_markdown_view_code_blocks.das:62

  • test_markdown_code_blocks_report_layout manually populates screen_origin/icon rects but leaves entry.screen_revision at its default (-1). In real rendering paths, screen_revision is set when a node is actually placed, so the test should set it too to represent a laid-out cache entry (and to stay correct if laid_out is keyed off screen_revision).
    var entry & = unsafe(state.nodes[node])
    entry.icon_rects_valid = true
    entry.screen_origin = float2(12.0f, 34.0f)
    entry.fold_icon_rect = float4(10.0f, 20.0f, 30.0f, 40.0f)
    entry.copy_icon_rect = float4(50.0f, 60.0f, 70.0f, 80.0f)

borisbat and others added 3 commits July 31, 2026 15:51
The subtool compiles its require-stub under a fresh CodeOfPolicies -
the second consumer the version_2_syntax flip exposed (10 darwin
extended_checks failures). Self-marking with options gen2 keeps it
correct under any default. write_module_api's section ladder carries
its reason.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Kv2yQu558ryra5WS1AFASZ
imgui_key_is_nameable(key : ImGuiKey) was the first documented signature
naming a raw-binding type; das2rst emitted a :ref: to the nonexistent
label enum-imgui-imguikey and sphinx -W died on it. mark_module_pageless
declares a binding has no generated pages; handle/struct/enum mentions
from it render as plain text. imgui2rst registers 'imgui'. Legacy
describe_type-family offenders dragged into the changed set carry
reasons.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Kv2yQu558ryra5WS1AFASZ
MSVC path::string() throws system_error on filenames outside the ANSI
codepage, killing the whole process mid-walk (crashed the mcp test run
locally). Treat an unconvertible name like an ec entry and skip it.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Kv2yQu558ryra5WS1AFASZ
Copilot AI review requested due to automatic review settings July 31, 2026 22:51

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 35 out of 35 changed files in this pull request and generated no new comments.

Suppressed comments (3)

modules/dasImgui/tests/test_markdown_view_code_blocks.das:58

  • After initializing the node cache without a real render, the cache entries need to be explicitly constructed (avoid unsafe resize). Also, if MarkdownViewCodeBlock.laid_out is based on screen_revision, the test should set entry.screen_revision to a non-negative value when faking layout telemetry.
    var state = MarkdownViewState()
    unsafe(state.nodes |> resize(length(doc.nodes)))
    let node = code_block_nodes(doc)[0]
    var entry & = unsafe(state.nodes[node])

modules/dasImgui/markdown/imgui_markdown_view.das:536

  • MarkdownViewCodeBlock.laid_out is set to true whenever index < length(state.nodes), but state.nodes can be pre-sized/retained (e.g. after markdown_view_invalidate) before any render pass sets geometry. This contradicts the docstring (“False until the view has laid this node out”) and can mis-report undrawn blocks as laid out.
        if (index < length(state.nodes)) {
            let entry & = unsafe(state.nodes[index])
            code.laid_out = true
            code.icons_valid = entry.icon_rects_valid
            code.screen_origin = entry.screen_origin

modules/dasImgui/tests/test_markdown_view_code_blocks.das:41

  • This test uses unsafe(state.nodes |> resize(2)), which leaves MarkdownNodeViewCache elements uninitialized. Since markdown_view_code_blocks may read cache fields for nodes within the resized range, this can make the test nondeterministic (and can mask real issues). Prefer constructing initialized cache entries.

This issue also appears on line 55 of the same file.

    var state = MarkdownViewState()
    unsafe(state.nodes |> resize(2))
    let expected <- code_block_nodes(doc)

@borisbat
borisbat merged commit 7efab48 into master Aug 1, 2026
40 checks passed
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