Record Text alias rename proposal and updated navigation acceptance scope

This commit is contained in:
2026-09-11 12:08:32 -07:00
parent 2dedde29e9
commit fb16c4200f
3 changed files with 145 additions and 5 deletions
+12 -5
View File
@@ -47,9 +47,12 @@ Authoritative records:
Current-draft Definition/References/Back is implemented in source checkpoint
**[36db9356](http://217.177.34.108:3000/sorokin.oleg.edu/ARCADIA-Studio/commit/36db9356cce3c7614ae37eec9fe17678ca210afe)**.
The final focused Windows gate passed 181 tests with strict all-target desktop
Clippy; a matching GUI build (`DF7126B8` prefix) passed. These do not establish
native navigation or packaged acceptance. The [integrated evaluation](release-text-navigation-integrated-20260911.md)
links exact input archives, earlier full-test scope and independent findings.
Clippy; a matching GUI build (`DF7126B8` prefix) passed. Its
[initial native trial](release-text-navigation-native-initial-20260911.md), preserved
at `2dedde2`, verified navigation and exact saved-source/model equality but found
four interaction defects. Corrected native and packaged acceptance remain required.
The [integrated evaluation](release-text-navigation-integrated-20260911.md) links
exact input archives, earlier full-test scope and independent findings.
The published contextual preview remains unchanged.
The integrated release does not yet contain newer peer canvas/chooser and
@@ -77,14 +80,18 @@ Live coordination now uses focused [behavior/canvas](http://217.177.34.108:3000/
[child work](http://217.177.34.108:3000/sorokin.oleg.edu/ARCADIA-Studio/issues/4),
[lifecycle Windows acceptance](http://217.177.34.108:3000/sorokin.oleg.edu/ARCADIA-Studio/issues/5),
[source navigation](http://217.177.34.108:3000/sorokin.oleg.edu/ARCADIA-Studio/issues/6),
[quantities/calculations](http://217.177.34.108:3000/sorokin.oleg.edu/ARCADIA-Studio/issues/7)
and [maintained libraries](http://217.177.34.108:3000/sorokin.oleg.edu/ARCADIA-Studio/issues/8).
[quantities/calculations](http://217.177.34.108:3000/sorokin.oleg.edu/ARCADIA-Studio/issues/7),
[maintained libraries](http://217.177.34.108:3000/sorokin.oleg.edu/ARCADIA-Studio/issues/8),
and [Text alias rename](http://217.177.34.108:3000/sorokin.oleg.edu/ARCADIA-Studio/issues/9).
Read current comments for ownership and execution state; this checkpoint does
not track active leases.
[Authoring Wiki](http://217.177.34.108:3000/sorokin.oleg.edu/ARCADIA-Studio/wiki/Authoring20260911)
is the shared entrypoint. Durable decisions remain in [DECISIONS.md](DECISIONS.md)
and topic reports; the [text-navigation design](release-text-navigation-design-20260911.md)
records the current bounded design and its falsifiers.
The [Text alias-rename proposal](release-source-alias-rename-design-20260911.md)
and its [critique](release-source-alias-rename-critique-20260911.md) are design
preparation, not implemented or verified Text capability.
Legacy TASK_LEDGER/PLAN live content was migrated once in
[comment 408](http://217.177.34.108:3000/sorokin.oleg.edu/ARCADIA-Studio/issues/1#issuecomment-408).
@@ -0,0 +1,63 @@
# Text-caret alias rename: independent transaction critique
Codex-9e8r6t /root/release_audit, 2026-09-11T18:34:04.889481+00:00. Read Gitea #9 and current implementation independently of the design worker. This is source-traced adversarial design analysis: no implementation change, executable experiment, test, compiler, GUI, server or Linux action. Counterexamples below falsify possible adapters; they are not claims that an unimplemented Text refactor already fails.
## Existing guarantees worth preserving
`Document::execute` prepares a typed command on a cloned Project, runs the identity-aware source updater, then commits only the completed result (`document.rs:301`). `prepare_command` carries complete surviving UUID correspondence (`session.rs:170`); SetAlias edits only the identified record header (`session.rs:607`, `816`). `Project::identities` includes project, elements, relations, diagrams, node placements, artifact links and traces (`model.rs:1726`), so element-only lookup is insufficient. Alias syntax is ASCII identifier syntax with exact reserved-word exclusion (`model.rs:1704`); do not trim, lowercase, or accept an engineering-name Unicode policy as alias validation.
The updater recompiles/rechecks public source/model/index inputs, preserves ownership and syntax trivia, edits actual reference alias tokens even across intervening comments, and recompiles the result to require exact requested Project equality (`source_project.rs:780`, `1215`, `1003`). Use it across the complete accepted bundle. Existing lexical navigation is only a locator: its result-row budget and partial/detached provenance are not an edit plan (`source_navigation/query.rs:832`, `856`, `882`, `937`).
## Concrete counterexamples and required boundaries
1. **Preview by execute-then-Undo mutates history.** Start with a real Redo branch, call the live Document execute to obtain preview bytes, then Undo. Commit clears the previous future and may evict old history for the 100-entry/32MiB budget (`document.rs:378`); Undo cannot restore discarded history. Preview must work on the captured accepted snapshot, never temporarily commit to the live Document. `Document::from_project` is also the wrong preview base because it formats a new bundle (`document.rs:116`); it loses authored file layout/comments before the alleged rename.
2. **A self-consistent preview can overwrite later engineering edits.** Preview rename A→B from accepted snapshot S. Accept another valid edit, producing S2. `apply_compiled(preview_S_B)` recompiles and accepts that old valid bundle; it checks internal consistency, not that S is still current (`document.rs:324`). The S2 edit disappears from current state. Bind the preview to the actual document instance/session, accepted Arc snapshot and revision, source workspace session/revision and full accepted/source input closure. Recheck at confirm. A project UUID alone is not a document identity: copies/reopened projects can deliberately retain it. Revision alone also does not distinguish a new Document starting at zero.
3. **Public compiled data is not proof of the reviewed command.** Alter only `decoded.project` or index: existing `apply_compiled` correctly rejects. But compile a different valid bundle that also renames an engineering name or removes an unrelated record, and it passes internal consistency. Likewise `PreparedCommand` has public mutable fields (`session.rs:103`). These are data, not a sealed rename authorization. Do not let a confirm message carry arbitrary compiled data or a general command. Keep private immutable intent `(target UUID, captured old alias, proposed exact alias)` plus the preview's complete proposed result; confirm by token owned by the current form.
4. **Unchanged accepted model does not imply unchanged editor input.** Preview from accepted S, then edit a different included file, a detached buffer, a property field or a pending behavior form. S and Document revision can remain unchanged. Generic App execution later calls `sync`/`sync_source`, replacing editor buffers and refreshing properties (`app.rs:863`, `709`, `649`). Refuse at entry and confirm when source is unapplied, any required draft is pending, scope is incomplete/detached/ambiguous, or the captured workspace/file set/text changed. Do not call generic `apply()` to make these conditions disappear. Include unchanged dependencies in stale checking: editing only an include or an unaffected module must invalidate the reviewed closure. Ordinary later Save retains existing disk conflict checks; preview/confirm is not a fresh disk read or a disk transaction.
5. **No-op must not use App's generic successful-command refresh.** SetAlias(id, same alias) returns `Some(id)` even when Document commit does nothing. App::execute interprets this as success and calls sync; Workspace::accept rebuilds Buffers (`source_workspace.rs:331`), discarding their text Undo/Redo stacks. Counterexample: make a temporary source edit, Undo it to accepted bytes (source clean, text Redo present), then confirm an unchanged alias. Model history remains unchanged but text Redo is lost. Detect exact unchanged alias/unchanged complete candidate and report no change without invoking the generic refresh. Preserve selection, caret, raw snapshots, dirty/saved markers and both histories. Existing Document no-op tests (`document.rs:696`) do not cover that App seam.
6. **Preview-to-confirm substitution and replay.** Preview A→B, edit the input to C, then deliver an old queued Confirm; recomputing from the live input applies C although B was reviewed. Alternatively Close/reopen a form on the same target, then replay an old confirm. Invalidate the prepared preview on every raw name edit; confirm carries a fresh preview token, and uses only its immutable captured intent. Consume/clear it on successful commit or no-op; a second click cannot create a second history entry. Failure/stale refusal retains the user's proposed name for repair while marking the old preview non-confirmable. An accepted edit followed by Undo back to byte-identical S should still invalidate the earlier review via revision/token policy; do not silently revive stale approval.
7. **CLI behavior cannot be copied as Text-preview admission.** CLI prepare explicitly compiles raw disk input, stabilizes missing UUIDs and upgrades legacy source; its rename preview may contain those changes and says later invocations may allocate different IDs (`oa-cli/lib.rs:287`, `306`, `355`; test `source_cli.rs:302`). Text #9 instead starts from an already accepted snapshot and refuses unapplied input. Preview must not secretly turn ID-less or old-schema editor text into an accepted model. A valid accepted Document may already contain explicit IDs or migration changes relative to disk; those are the baseline, not extra edits caused by alias rename. Its existing unsaved flag must survive cancel/no-op.
8. **Global identities and bounded lexical rows.** A declaration's alias may belong to a node, diagram, project, relation, trace or artifact, not an Element. A same-named alias in detached text or a reference with partial scope does not authorize choosing the first accepted object. Require a unique current accepted declaration and verify its UUID, alias and exact location against the accepted model/index. Independently test a target with more uses than the navigation row cap: all true source references must change, even though only 200 or fewer rows were displayed. Comments, string/prose occurrences, other aliases and historical UUID literals stay exact. Count changed files/preview changes from the complete before/after bundles, not the lexical list; do not label lexical totals as typed-reference coverage.
## Transaction alternatives
| Approach | What makes it sound | Main tradeoff / falsifier |
| --- | --- | --- |
| Recompute typed SetAlias on confirm | Private immutable intent, exact base/closure/token guards, preview produced with the same core preparation/updater, confirm calls Document::execute on that unchanged base. Stable accepted IDs and SetAlias introduce no creation identities. Verify complete preview result equals actual result in tests. | Repeats bounded compile/update work. Using live text or skipping base guards falsifies correspondence. Avoid a separate live commit merely to compare results. |
| Adopt public `apply_compiled` preview | Must additionally prove unchanged base and exact SetAlias correspondence; recompilation alone is insufficient. Keep candidate private and recheck full proposed bundle/model/index. | Convenient reuse, but general source replacement can admit a consistent unrelated change or stale old snapshot. Least attractive default for this narrow command. |
| Narrow Document-owned prepared alias | Private constructor captures base Arc/revision, exact SetAlias intent and validated complete compiled result. Read-only preview accessors; consuming confirm validates base and commits exactly that result. App separately checks source/form/session closure. | Avoids repeated updater work but adds a transaction API and lifecycle to maintain. Keep it alias-specific; do not invent a generic trusted-compiled capability. Public mutable prepared fields defeat the benefit. |
**Recommended initial implementation:** a private App-owned preview of the exact typed SetAlias intent and complete output, with recompute-on-confirm through existing Document::execute after strict unchanged-base checks. This is adequate for deterministic alias-only edits on already stabilized accepted input and adds the least new authority. Handle no-op before generic App refresh. If measured large-model preview/confirm latency makes recomputation material, move the same bounded contract into an opaque Document-owned prepared alias; do not choose an unchecked public compiled shortcut. Neither option needs a new schema, evaluator, file loader or generic capability system.
## Independent evaluator
Prepare literal expected files with explicit fixed UUIDs, mixed UTF-8 names/paths and CRLF, comments between `@` and alias, strings containing `@old`, nested declarations, multiple modules and an unchanged include dependency. Build the expected Project by changing precisely one known header alias; assert equality of every remaining field/UUID/relation/view/placement and exact before/after file inventory and bytes. Define expected changed-file membership and complete hunk contents independently of the producer updater. One changed alias token does not imply one changed file or one reference.
- Preview and cancel: exact Document snapshot/revision/saved state/model Undo/Redo, Workspace recovery bytes/cursors/text Undo/Redo, property/behavior raw drafts, filesystem bytes unchanged. Rendering/scrolling preview does nothing.
- Confirm: exactly one model/source commit; complete result equals the displayed preview. One Undo restores exact S; one Redo restores exact renamed result. Save/reopen reproduces that result, but persisted Undo history is not promised.
- No-op with both model Redo and clean-buffer text Redo available: no new revision, history entry, source rewrite, dirty change, cursor move or sync-induced loss. Invalid/reserved/duplicate/whitespace alias likewise preserves all state and exact proposed input.
- Stale: accepted unrelated edit; comment-only edit in an unchanged dependency; include/file-set change; dirty detached file; property/behavior draft; same-UUID/same-path new document; Save As; recovery; accepted change→Undo; name changed after preview; Close/reopen and old confirm. Every refusal precedes mutation; no implicit Apply.
- Counterfeit data controls: inconsistent public compiled model/index must refuse; a self-consistent unrelated compiled candidate must never enter through alias confirmation. Mutating exposed preview display data, if any, must not change the stored command or adopted bytes.
- Global record classes, UUID/alias collision and more-than-row-limit usage fixture. Refuse partial/unapplied/ambiguous/detached input; do not infer all-project coverage from a bounded result array.
- Actual Windows UI: focused Text-caret entry, exact target identity/context, keyboard and mouse name/preview/confirm/cancel, stale status, long changed-file list at minimum size, first Escape/modal priority, one Undo/Redo, ordinary save/reopen and full independent source/model oracle. Existing core/CLI evidence is supporting evidence only; no such Text UI pass exists yet.
## Inspected raw source identity
| File | SHA-256 |
| --- | --- |
| `crates/oa-desktop/src/document.rs` | `2ecc2cd496d4a83fd7a32b9dc68e49f0f1cb31a06263dfd6939b4764da5b73e2` |
| `crates/oa-desktop/src/app.rs` | `370c2ce1b58f5aad4cfbbbae4a774670a20c6f4f5f1a77305daf8ce221f80dbe` |
| `crates/oa-desktop/src/source_workspace.rs` | `388c71f63829c0c76526a1700ebf5f240c86c467a65aae4fca4cd6c6a88c468b` |
| `crates/oa-desktop/src/source_navigation/query.rs` | `aa8e8e9d446b57c30520c4b3ca1ae9fe524cecb2f4f4f4b229d930ea0377ecca` |
| `crates/oa-core/src/session.rs` | `1eb77b329b2986fc6f5dc0171e77fd860375cdfd8c769a1367b445d6c49ebe00` |
| `crates/oa-core/src/source_project.rs` | `1394370bcc5908873b830c2c11312e6e1611af41f46c4f43ca0a6bcb713bb466` |
| `crates/oa-core/src/model.rs` | `4585c895c64c4a183941c92cf047a9e52ff0cbe41971e16e78d229ea9dc101fb` |
| `crates/oa-cli/src/lib.rs` | `97bebab63b4a611a1d36ad0c20fe452cbe1985fe3a6fbd39c954603da11410fc` |
| `crates/oa-cli/tests/source_cli.rs` | `a3a1b856c7a9fd3d80bc8074150a24fbb0ef0e9ddf736c7cea036725fc3dc2b8` |
@@ -0,0 +1,70 @@
# Text-caret alias rename — proposal for critique, 2026-09-11
Codex-9e8r6t `/root/behavior_audit`; [issue 9](http://217.177.34.108:3000/sorokin.oleg.edu/ARCADIA-Studio/issues/9). Inspected production commit `36db9356cce3c7614ae37eec9fe17678ca210afe`, issue 9 and `.local/next-slice-audit-20260911.md`. This is a source-derived design, not implementation, executed tests or native acceptance. The frozen #6 GUI `DF7126B8…` remains separate; finish its acceptance before adding this slice. No source8, calculation, library, core or CLI change is proposed here.
**Recommendation:** an editor-local **Rename alias · F2** action opens a compact modal, prepares a complete source preview against the current accepted document, then explicitly adopts that exact candidate as one model/source change. Refuse pending drafts and uncertain target/source membership. Keep Save separate.
## Existing authority and concrete traps
- `Command::SetAlias` edits the header by UUID; `prepare_command` validates the complete candidate and returns identity provenance ([session.rs](../crates/oa-core/src/session.rs), lines 170–198, 607–609, 816–870). It supports the project, elements, relations, diagrams, node placements, artifacts and traces. `Project::identities` covers those same families; alias rules are ASCII letter/underscore followed by ASCII alphanumeric/underscore, case-sensitive global uniqueness and the existing reserved set ([model.rs](../crates/oa-core/src/model.rs), lines 1667–1744). Do not substitute engineering-name matching, lowercase/trim the input, or reject every lexer keyword: some highlighted words remain legal aliases.
- The updater rechecks the current compiled index/model/bytes, changes typed syntax and recompiles to exact candidate-model equality. Reference edits preserve the separate `@`, intervening comments and unrelated trivia ([source_project.rs](../crates/oa-core/src/source_project.rs), lines 780–800, 852–1027, 1133–1225). Existing exact tests include comment-separated references and CRLF/escaped text ([source_project tests](../crates/oa-core/tests/source_project.rs), lines 843–897). These support the implementation choice; they do not prove a future desktop flow.
- `Document::execute` already prepares and commits model/source together. Public `CompiledSourceProject` fields are **not** a validated capability: `apply_compiled` recompiles and compares bundle, model and index before private `commit` ([document.rs](../crates/oa-desktop/src/document.rs), lines 301–397). Keep that check; do not expose `commit` or install a worker's public DTO unchecked.
- `Message::Command` calls `App::apply()`, which can accept a dirty property form; `sync()` refreshes the property draft and accepted source ([app.rs](../crates/oa-desktop/src/app.rs), lines 709–739, 785–855, 2601–2625). A clean Text buffer is insufficient: a property/behavior draft may still exist. Rename must use its own guarded adoption route, with no implicit Apply.
- History is bounded by 100 entries and **32 MiB of estimated source plus serialized model**, not the 64 MiB source admission. `commit` may evict even the immediately preceding snapshot; the existing large-current test explicitly expects no Undo ([document.rs](../crates/oa-desktop/src/document.rs), lines 24–32, 388–394, 796–820). An unconditional one-Undo promise is false without capacity admission.
- `Workspace::accept` resets accepted files' text-history stacks; ordinary Text Ctrl+Z routes to **Undo text**, not model history ([source_workspace.rs](../crates/oa-desktop/src/source_workspace.rs), lines 334–361; [app.rs](../crates/oa-desktop/src/app.rs), lines 2640–2674). Preview/failure/no-op must not call `sync`. Successful rename uses model Undo/Redo, and the UI must say so.
## Alternatives and selected boundaries
| Alternative | Decision and reason |
| --- | --- |
| Edit the selected alias inline and replace #6 reference rows in draft buffers | Reject. Its lexical list can be partial/truncated; it is not a typed replacement plan. Per-file text history cannot establish one accepted multi-file transaction. |
| Reuse Properties, immediately apply SetAlias | Existing semantic capability, but it leaves Text context and lacks complete change review. Generic command dispatch can also accept an unrelated property draft. |
| Compact modal with explicit Preview, exact candidate, guarded Document adoption | Select. It separates identity/name, keeps a visible change boundary and prevents background actions from retargeting an open form. A persistent side inspector would further narrow the editor; repeated inline expandable diffs would displace it. |
For transaction implementation, select **recompute-on-confirm through `Document::execute(SetAlias)`**. Preview uses the same `prepare_command` plus `update_bundle_with_identity_map` on the pinned accepted snapshot, without live commit. A private form-owned value holds immutable target UUID, old/exact new alias, base and complete preview output; rendering receives read-only data and Confirm carries only its token. After exact freshness/no-op/draft checks, execute that stored typed intent directly, bypassing generic App command dispatch. Already accepted IDs plus alias-only intent make this deterministic; tests must compare the complete actual result with the reviewed output. Never execute then Undo to obtain a preview: that destroys an existing Redo branch and can evict history.
Add a narrow **read-only** Document history-capacity check, using its existing estimate/budget, before Preview becomes confirmable and again before execution. Refuse if `estimated(before) + estimated(candidate) > HISTORY_BYTES`; a no-op requires no reservation. Older history may still be trimmed normally. Do not duplicate the private byte estimator in App or introduce a general compiled-accept method for this command.
This choice incorporates the [independent critique](release-source-alias-rename-critique-20260911.md), read after the initial independent draft (SHA256 `A1B68F330EEB4ED62B31788B8EEFE2D205E5A1593686633D9C9E38BDB1775512`). The first draft preferred guarded `apply_compiled`; the critique correctly distinguishes internal consistency from exact SetAlias correspondence. A self-consistent but unrelated source replacement is not rename authority. Recompute the immutable typed intent instead. An opaque **alias-specific** Document-owned prepared result remains the alternative if measured representative valid-project preparation/confirmation latency warrants it; keep construction private and consuming adoption guarded. No public mutable `CompiledSourceProject` or `PreparedCommand` is that capability. Root will measure before choosing a more complex API; #6 lexical timings do not settle this question.
## Exact contract
**Admission and target.** Begin requires Text context with no busy file operation, model workflow, architecture draft, pending property/behavior draft or competing modal. Require `Workspace.applied`, no buffer edits, exact entry plus loaded path/text equality with `Document.bundle`, and the bounded #6 snapshot's complete/validated included scope. For the first slice, any extra loaded detached buffer refuses; explicitly close a clean detached buffer, or reattach/revert a dirty one through existing actions. Physical orphan files not loaded are outside the rename and remain unchanged. This conservative policy prevents silent omission; it does not delete or auto-close a file.
Resolve only an alias token or live `@` use under the exact caret/selection, using the existing bounded hit/query seam. Require exactly one complete definition, included/validated evidence, unique authored UUID, and agreement with the accepted project's alias and declaration path. Check the alias role lies within the accepted declaration location; do not require the outline's whole declaration extent to equal the compiler's project-header extent. Names, comments, strings, historical UUIDs, blank space, ambiguous definitions, missing IDs, partial includes or an exhausted query budget cannot authorize rename. A truncated reference list is neither needed nor consulted; all changes come from the typed updater. Never compile a raw unapplied workspace just to enable the action: compilation can allocate missing UUIDs or migrate source (source_project.rs, lines 286–300).
Accepted-but-unsaved documents are eligible. Preview compares against the **accepted source**, not the last disk baseline. Stabilization/migration already accepted by ordinary Open/Apply retains its fixed IDs; this rename must add no new ID, migration, default, file or include change. Save may later include earlier unsaved accepted edits as well as this rename; the modal says that it only previews this operation.
**Form and preview.** Capture invocation ID, document snapshot `Arc`, document revision, workspace session/revision, active path and exact origin cursor/alias span/UUID. Keep the replacement string raw. Invalid syntax, reserved/colliding aliases and same-alias input produce useful inline feedback; same alias is “No change” with Confirm unavailable and no history/reset. Duplicate engineering names are valid and never disambiguate identity.
Explicit Preview starts at most one worker. It prepares `SetAlias(target_uuid, replacement)` against the pinned accepted snapshot with the desktop limits. Require full candidate Project equality to an independently formed alias-only expectation, identity-map identity for every surviving record, identical file membership/entry and ownership, and unchanged non-alias fields. Preserve old/new source via the two snapshots, not duplicated whole-file strings in every row. Updater errors leave accepted data and all drafts intact.
Preview rows are derived from every changed file in the complete candidate. Because alias replacement cannot add/remove newlines, pair source lines by ordinal, collect every changed line and group nearby context into hunks; unexpected line-ending/line-count changes refuse rather than falling back to a lossy preview. The changed-line count is not presented as a count of semantic references. Proposed display admission is 256 changed files, 50,000 changed lines and 8 MiB of retained diff display data; exceeding a bound explains that no rename was applied. Page complete admitted hunks; never approve a truncated candidate. These are proposed editor limits, not new grammar limits. Do not use unbounded quadratic line diff or copy the CLI's single potentially huge middle hunk into one widget.
**Stale and confirmation.** Every dialog event carries its invocation ID; Preview/Confirm also identify the exact replacement generation and preview ID. Reject old widget events before canceling or changing the current form. Worker completion must match the wanted job, invocation, replacement generation, original document snapshot/revision and exact workspace readback. Close hides the form immediately but retains the occupied worker slot until its completion; late results do not reopen it. A source edit, file/membership switch, reset, recovery, model transaction, Undo/Redo or replacement edit invalidates approval, even if later bytes happen to match again. The input field survives same-form invalidation for correction. Reopen/new-session IDs cannot reuse an old approval.
After the target is pinned, typing in the rename field, scrolling the preview and focusing its buttons must remain usable: do not compare all dialog input to #6's original raw-input clock, which those legitimate interactions advance. Keep source/workspace/document freshness separate from form input generation. Passive lint/viewport receipts do not approve or cancel a current preview.
Confirm rechecks all admission predicates, exact old/new alias, target UUID and the exact approved candidate, then recomputes and executes only the stored `SetAlias` through Document once. Consume the approval before dispatch to make repeated Confirm harmless. It neither reruns name resolution from the current caret nor calls generic `Message::Command`, `App::apply`, `apply_source`, Save or migration. If command/source validation or history admission fails, show the error and retain the replacement; no accepted bytes, save baseline, revisions, selection or histories change. Successful adoption follows normal accepted-source synchronization, stays in Text, and selects the new alias at the **same origin occurrence**, using an exact before/after line/token position map. No whole-buffer search for the first new alias. Apply the existing guarded reveal mechanism so a stale focus task cannot steal focus.
**Undo, Save and reopening.** Success supplies a context-bound “Undo rename” action and identifies “Undo model” as the persistent control; Text Ctrl+Z remains Undo text. The immediate Undo action must refuse pending source/property/behavior drafts and a newer accepted revision rather than applying them or undoing some later operation. Undo restores the entire preceding Project and exact accepted SourceBundle; Redo restores the exact candidate, each as one model-history transition. A successful new rename clears the previous redo branch normally; cancel, invalid, stale and no-op paths preserve it. Successful sync has the existing accepted-buffer history behavior; do not promise older per-file draft Undo stacks survive it.
Ordinary Save uses existing observed-dependency/journal checks and retains the accepted rename on a save failure. No cross-process CAS or atomic multi-file disk visibility is claimed. Pure rename creates/deletes no file, so Save/Undo/Save must preserve the same physical file set and pre-existing orphan bytes. Reopen verifies exact saved model/IDs/source; Undo history and an unconfirmed preview are not persisted. Recovery must never serialize an executable approved rename plan; a recovered accepted document requires a fresh invocation/preview.
## Interaction at minimum width
Add F2 only while the source editor is focused, plus a visible “Rename alias” Text action. It opens on the selected declaration/use without navigating away. The modal is at most 760 px wide and bounded by available window height/width, with a compact target caption (kind, engineering name, full source path available), **Source alias** input first, then summary and one unified diff pane. Explain “Engineering name stays unchanged.” Node placements use “Placement of …” context because they have no independent engineering name. Long names/paths/aliases must not push the input or footer out of view; offer full selectable details without an unbounded header.
Keep Cancel, Preview and Rename alias outside the independently scrolling diff. Use file search/selection plus Previous/Next changed file and hunk paging, rather than mounting a long homogeneous list. All admitted files/hunks are reachable; there are no per-file checkboxes because the operation is atomic. Show `+`/`−`, line numbers and before/after labels, not color alone. Enter in the alias field requests Preview, never commits implicitly; Tab/Shift+Tab reaches controls and an explicitly focused Confirm button activates normally. Captured Escape closes the rename form once, preserving source selection/drafts; it must not fall through to a different editor. Tests/native review must verify this composition at 1100×700 and a narrow dialog host, including long Unicode engineering names and paths.
## Bounded evaluator and real workflows
Prepare expected Project and exact source bytes **before** exercising the implementation; change only the chosen family's alias field and the literal role-proven declaration/typed-reference tokens. Pin all authored UUIDs. Compare complete Project, SourceBundle, declaration file ownership, saved baseline and history transitions, not only changed-file snippets or a successful reparse.
1. **OA activity across modules:** from a comment-separated `@assess` in a process, rename to `assess_damage`; keep the Unicode engineering name, CRLF, repeated uses, prose `@assess`, escaped strings, diagram geometry and trace history unchanged. Preview, Cancel, repeat Confirm, Model Undo/Redo, Save/reopen.
2. **Non-element source identity:** rename a relation alias used by view routes/traces, then a placement alias; ensure the relation/placement UUIDs, endpoints, engineering names and routed geometry do not change. Include project, diagram, artifact and trace targets in the parameterized headless family matrix rather than assuming element coverage transfers.
3. **Repair without loss:** invoke from an invalid or unapplied include draft with another dirty property form; no preview mutation or hidden Apply. After explicit repair/Apply or cancellation outside this flow, invoke afresh and complete the rename. Include a detached duplicate and a missing include; closing/reattaching remains a separate user action.
Required falsifiers: two same-name objects; legal keyword-classified alias; invalid/reserved/colliding/identical alias; target deleted/reidentified or source moved; old Confirm after same-ID reset; source edit then Undo to identical bytes; changed replacement then back to identical text; dirty property form while Text remains in sync; corrupted public candidate/index and a self-consistent unrelated compiled replacement delivered as counterfeit preview data; admitted model exceeding immediate-Undo capacity; more than 200 real uses; diff-bound overflow; long names/paths; same-line repeated uses and a caret on the final occurrence. Assert unchanged raw drafts, model/source, save baseline, revision, both undo/redo branches and cursor on every rejected/canceled/no-op path. Use real App messages for modal/captured Escape and stale queues, not only disabled-button tests. Mounted layout tests must use real paragraph metrics and actual bounded scroll/footer geometry.
Native acceptance belongs to a new identified build after #6: inspect complete preview at minimum/wide windows, keyboard focus and Escape, change the alias from a reference, Undo/Redo, Save/reopen and compare the pre-authored whole-project/source oracle. Test preparation/confirmation timing separately on a representative accepted model; the draft-only 100-module #6 query trial is not evidence for this transaction or its UI.