Result: done Files: crates/nikaia-std/src/tools/text_tiers.nika crates/nikaia-std/src/tools/lowered/text_tiers.rs crates/nikaia-std/src/tools/view_changes.nika crates/nikaia-std/src/tools/lowered/view_changes.rs crates/nikaia-std/src/tools/buffers.nika crates/nikaia-std/src/tools/lowered/buffers.rs crates/nikaia-std/src/tools/lowered.rs crates/nikaia/src/parser/mod.rs crates/nikaia/src/text_tiers.rs crates/nikaia/src/view_changes.rs crates/nikaia/src/contracts/keep.rs crates/nikaia-std/src/lib.rs tests/compiler/tests/a_viewed_text_moved_into_a_literal_is_kept.nika tests/compiler/tests/a_viewed_text_moved_into_a_literal_is_kept.stdout tests/compiler/tests/a_struct_result_with_a_moved_text_lives_in_the_callers_keep.nika tests/compiler/tests/a_struct_result_with_a_moved_text_lives_in_the_callers_keep.stdout tests/compiler/tests/a_viewed_text_moved_into_a_field_that_owns_is_refused.nika tests/compiler/tests/a_viewed_text_moved_into_a_field_that_owns_is_refused.stderr tests/compiler/tests/a_text_moved_into_a_field_that_owns_with_no_view_left_runs.nika tests/compiler/tests/a_text_moved_into_a_field_that_owns_with_no_view_left_runs.stdout tests/compiler/tests/a_view_stored_in_a_field_changed_in_place_is_refused.nika tests/compiler/tests/a_view_stored_in_a_field_changed_in_place_is_refused.stderr tests/compiler/tests/text_moved_into_a_field_is_watched_while_a_view_is_used.stderr docs/briefs/b942-moved-text-tiers.md.report.md Commit: text tiers: a viewed text moved into a literal is kept, or refused at the move where the field owns Body: ADR-353 D8-D10 for moved text. The late tier walk records each text moved into a struct, tuple, list or variant literal while a view of it is still read later (TierLate.moved, views/viewers per body) and makes that position a view of the kept text (viewed_arms); where the position must own (a field changed in place anywhere, TierWalk records the forcing place in Flows.forced), the move is taken out of viewed_arms and recorded in TextTiers.refused_moves, and view_changes refuses it with NK2305 at the move, labelling the forcing change and naming .clone() or building the value first and viewing its field. buffers: a moved viewed text counts as an origin of a struct or list literal, so a returned struct takes the caller’s keep (BufferAsk.viewed). #944 was already fixed in 8fd0a56; its tests (view_of_a_field_leaves_another_field_free, view_of_a_field_is_watched_when_that_field_changes) still pass. text_moved_into_a_field_is_watched_while_a_view_is_used now refuses at the move (D9) instead of at the push_str. Fixes: #942 Tests: 5 new tests/compiler programs; kept, caller’s-keep and refused fail on the unfixed compiler (rustc E0505 use of moved value / E0308, Cannot move out of text); no-view-left and F8 NK1106 are guards and pass on both compilers by design; tests/compiler –both-settings 261 of 261 ok; it guard set 23 ok; nikaia –lib contracts:: 36 ok; clippy clean (after allowing map_identity on tools); fmt and pre-push-check ok Gate: green Deviation: one commit for steps 2-4 (one code change serves all); lowered.rs committed with only this run’s hunk (TierRefusal, TierForced re-export) by git apply –cached and a manual commit with the script’s message, because the working copy also holds another agent’s project_settings hunk and commit.nika adds whole files; step 1 (#944) a noop, the brief’s two tests exist under other names Found: .map(fn(w) { w.to_string() }).collect() into a list the tiers decide holds views lowers to .map(|w| { w }), clippy map_identity; allowed on the tools module in lib.rs like map_clone Needs: none Changelog: A text that a live view still reads can be moved into a struct, tuple, list or variant literal: the literal views the kept text, and where the field must own its text the move is refused with NK2305 naming the change that forces it (ADR-353 D8-D10). Owner: none Disk freed: none (cache 2.5G, 3.1G free; new entries over 100 MB: run-bundle/194302eb 345 MB, build-time-parsers/768d2772 566 MB) Rs2nika: none