Files
ARCADIA-Studio/harness/release-contextual-source-creation-review-20260911.md

31 KiB
Raw Permalink Blame History

Contextual source creation: independent preimplementation review

Codex-9e8r6t /root/behavior_audit, 2026-09-11. Reviewed the proposed release-contextual-source-creation-plan-20260911.md against committed 4bb4aaf3dc47b9738625b4d3f23ef8c74f286395 desktop contracts and current unchanged core. Read AGENTS, revised PROJECT_GOAL, Gitea issue1 through #138, empty open PR inventory and LocalBehaviorCreation20260911 Wiki. No evolving implementation was read; no production edits, Cargo, direct rustc or native input. These are source-derived integration traps and exact acceptance expectations, not findings against the new implementation. Urgent items were sent directly to its author.

The proposed staged-source transaction is coherent for Lifeline, process Work and new machine owner. Keep qualified Action allocation, new ScenarioUse targets and the external chooser implementation outside this slice. The following existing contracts require explicit handling; a generic wrapper is insufficient.

Ranked material traps

  1. P1 — New first-action routes can implicitly commit another editor. In committed app.rs:2326, non-creation starts_form() invokes self.apply(). A new first-lifeline/contribution button routed to the existing Start event, arriving while a valid raw property draft exists, commits that property before opening its form. The explicit Canvas Choose guard does not protect this route. Reject source/property/pending conflicts in the actual new App event path before generic Apply; a disabled button alone cannot guard stale dispatch. Assert accepted snapshot/history and all raw strings unchanged.

  2. P1 — Stale scenario owners can panic before transaction validation. scenario.rs's parents() always includes the supplied owner ID, even if that element is absent. A recovered Lifeline draft therefore passes the first destination check in Draft::command, then sources() at line 941 indexes p.elements[&d.owner]. A removed owner can panic before execute_batch gets a chance to reject it. Validate owner existence/kind/layer/viewpoint before candidate rendering and parent planning. Show repair/cancel with both raw drafts retained. Do not interpret a same UUID with changed kind or viewpoint as the unchanged invocation merely because a new source still exists.

  3. P2 — Nesting the old process batch loses consumer selection. topology/direct.rs:209 scans only immediate Batch children for a newly created contribution. Batch[CreateSource, Batch(parent_commands)] therefore returns no contribution selection. Core session.rs:386 uses the last selected operation and SetSteps at line 703 selects the process owner. Flatten with preserved command order, or carry the exact prepared command's consumer target through success. Test the actual App selection, including rejection of changed/trailing commands borrowing that target.

  4. P2 — Stable source identity does not make the combined plan stable. scenario.rs:1274 still creates a fresh Lifeline via make_element each prepare; topology.rs:476–508 creates fresh occurrence and link UUIDs. Reserve/cache the complete created identity set, including repaired links. With a blank consumer label, source and consumer share a display name: the source already owns its alias in the private preview, so the consumer alias includes its UUID suffix. Replacing only the temporary consumer ID leaves an alias derived from a discarded UUID. All aliases, endpoints, SetSteps, parent references and optional machine/view IDs must use the reserved set. Require full prepared-Command equality across preview/retry/recovery, not merely equality of the source UUID or final object count.

  5. P2 — A fresh Work source cannot satisfy every captured insertion. topology.rs:438–449 requires a Work target next to an Exchange contribution to equal that exchange's exact source/target UUID. A newly created Function cannot equal an existing endpoint. The plan's successful “between two contributions” case should use Action→Action. An Exchange-adjacent case must refuse and retain both names and the exact slot; it must not retarget the shared exchange, change a reusable definition, choose a different source or silently append. Keep the existing full compatibility check on the preview.

Semantic constraints that the new source form must expose accurately

validation.rs:92 separates source containment from its use. Activity may be root-owned or owned by Activity; Function by Function; OA Entity/Actor/Role may be roots or children of Entity. Current SA System and SystemActor admit no semantic parent, so a new SA owner is a root even when its machine is nested under it. Neither process, scenario nor lifeline owns new work. A new Lifeline belongs directly to its scenario, never an operand, and does not enter its ordered steps (session.rs:336 attaches Occurrences only).

viewpoint_represents at validation.rs:1262 admits Activity, Function, Entity/Actor/Role, and System/SystemActor for the four explicit viewpoints respectively. Role is valid for an OA participant lifeline but not a machine owner: Kind::is_performer at model.rs:153 excludes Role. SA System uniqueness is a hard project-wide error at validation.rs:238. A second System must refuse, even if named differently; an Actor requires a separate explicit choice.

Do not turn completeness warnings into new blockers. Unallocated leaf work and a missing SA System are warnings. Adding a lifeline to an already reused callee can also be accepted while existing uses gain missing_lifeline_binding warnings (validation.rs:2112); keep all caller bindings unchanged. By contrast, an explicitly incompatible binding is an error. Compatibility uses represented identities or explicit RoleRealization/RoleAssignment, never equal names (validation.rs:1283, :2073). A new same-named Role does not impersonate an existing referenced role, and staging it creates no realization or allocation.

Persist authored state and reserve identities, but separate it from runtime canvas generations. Existing behavior recovery deliberately drops viewport and revision tokens (behavior.rs:789); App reset gives a fresh canvas_document. A recovered valid draft must be rebound to that runtime document without reusing stale event invocations. A child invocation token must still reject late Use/Name/Back events after that child was cancelled/reopened. Passive scroll/viewport epoch changes must neither discard input nor count as a semantic context change. New optional recovery fields must preserve older pending forms.

Compact exact acceptance matrix

Use separate fixed symbols for source S, consumer C, child invocation I, new link L, and optional machine/view/placement M/V/N. Only a new cancelled- then-reopened invocation may reserve a new set. Every accepted row compares the complete Project and SourceBundle against the explicit delta; every refused or cancelled row requires exact accepted baseline and raw-draft preservation.

Case Exact expected result
OA activity lifeline OperationalActivity scenario; source Assess distress, consumer Assessment role. Exactly Activity S at selected valid work parent/root and Lifeline C under the original scenario with represented=S. Names remain separate, description/body defaults empty, scenario steps unchanged. No allocation, capability involvement, actor, view or placement. Blank consumer label uses the source name; explicit label follows the existing consumer trimming policy, while raw text remains exact during staging.
SA function lifeline Functional scenario, no existing Function/System. Exactly Function S at root or selected Function parent plus Lifeline C, with fixed represented identity. Missing allocation/System warnings do not cause fallback or automatic participant creation. Wrong-viewpoint source kind refuses.
OA Role and reuse mapping ParticipantInteraction scenario can create Role S plus Lifeline C; no relationship is inferred. An existing local Actor maps to an existing referenced Role only through its explicit realization. A new same-named Role without that relationship cannot satisfy the old binding. While editing a reused callee, adding C leaves both existing caller-use records byte-for-byte unchanged; missing-binding warnings are expected, not auto-binding or rejection.
SA boundary and new owner kinds BoundaryInterface permits explicit System/SystemActor, not Function/Role. Empty SA permits one new System; existing System makes another System refuse unchanged. Explicit SystemActor remains valid. Role cannot own a machine. Illegal source-parent choices refuse; source-parent change must not become machine-parent change.
Work at exact Action→Action link For captured A —(R, guard g)→ B, source S, contribution C: add root/valid-parent work S; C is Action { action:S, lifeline:None } owned by that process. Preserve R's ID/name/alias/guard and change only its target to C; add L: C→B with empty guard; insert C in the captured order. All sibling paths and referenced definitions unchanged. Select C. Repeat preparation/recovery with exactly the same new IDs/aliases.
Work next to Exchange / stale slot A new UUID cannot equal the captured existing exchange endpoint; refuse without changing it. Also remove/change the captured link or presentation-before ID between staging and Apply: retain both drafts and require an explicit position repair. Never fall back to current selection or append.
Machine before participant Name machine Rescue modes, opt into first view, stage explicit valid participant Rescue team. Commit exactly participant S + machine M with parent=S; optional view V named Rescue modes · states, StateMachine projection, one placement N, no regions/states/routes. Select/open M/V. Child Back restores prior owner; parent Cancel creates nothing. Re-selecting an existing owner commits no abandoned staged source.
Invocation, recovery and Escape Parent label, source raw name, search, original reference, viewpoint, slot and IDs survive child opening/Back/recovery. Old invocation I cannot affect a reopened child I2, even with identical names and owner IDs. Restored valid drafts survive the fresh runtime canvas ID; missing owner refuses without panic. Overlay Escape closes the overlay first, then child Back, then parent Cancel. The focused captured-Escape path must follow the same ordering.
Semantic first action and history With no semantic contributions, first-work action is directly visible; with no lifelines/occurrences, first-lifeline action is visible. An unresolved lifeline (represented=None), offscreen content, ScenarioUse or fragment prevents a false “empty” claim. A lifeline-only scenario gets applicable guidance without inventing an exchange/action allocation. CTA appearance/resize and rejected stale Start leave model/source/history/raw properties unchanged.

For committed names with leading/trailing whitespace, pin source and consumer policies explicitly: current scenario/topology planners trim an explicit consumer label; they do not overwrite it with the selected source's label. Do not claim all committed names remain byte-exact by inspecting only raw recovery.

One Undo must restore the prior Project and reachable SourceBundle, while disk Save may retain newly detached source files. Use the corrected oracle's explicit history origin: disk equals the first committed checkpoint's file map overlaid with expected reachable files; unknown/changed retained bytes fail. Redo/reopen uses original committed role IDs, not newly borrowed replacement UUIDs.

This matrix deliberately excludes qualified Action allocation and new reuse definitions. Those require further explicit semantic intent; they are not required to validate this staged-source slice. The external chooser remains owned separately. Implementation review and native evidence follow only after the author freezes the new source.

Independent implementation review, 2026-09-11

Codex-9e8r6t /root/behavior_audit. Resumed after the author froze the first production candidate. Read issue #1 through #151 and traced the actual App, behavior dispatch, nested draft, recovery, view, and command-selection paths. The author made explicitly identified corrections between the first and second compile windows. This reviewer edited only this report and ran no Cargo, rustc, native input, or implementation tests. The author's first compilation exposed missing Clone derives; no passing runtime result is inferred from that compile.

Five independently derived counterexamples were sent directly to the author and root. All five have corresponding corrections in the second frozen source inspected here. The following is source verification, pending the author's 19-case focused gate and root's native acceptance.

Priority / finding in first candidate Concrete counterexample and consequence Correction inspected in second frozen source
P1: missing pending owner can panic while rendering another owner Recover source draft for scenario A after A is absent, with another same-layer scenario B present. behavior::selected_owner returns pending A, while behavior::view falls back to B. B's workspace calls scenario_context().expect(...), but the context still resolves absent A and is None. Process fallback has the same mismatch. With no other owner, the pending form is hidden behind New instead. Safe sources() and prepare_pending() do not protect this render path. behavior::view now checks the pending owner's presence/kind/layer before choosing a fallback. It shows the retained consumer name plus current child form or explicit parent Cancel. The child Back remains reachable; it never silently opens B as the pending consumer. New orphan-view tests construct both no-choice and remaining-B cases.
P1: staged recovery completeness was assumed by presentation Recover selected staged source with source.staged.kind = null, a valid value for its serialized Option<Kind>. Deserialization accepts it; State::label then calls unwrap() and panics in parent view/selection before command validation can return its existing missing-kind error. source_draft::State::label is now total and displays a missing-kind label. Planning still refuses; raw recovery remains intact. A malformed-kind regression exercises both planning and the label.
P2: owner-first machine creation cannot leave its valid child New → Machine, leave machine name blank, Create new owner, choose valid kind/name, Use. The source is valid, but the parent handler calls next.command(p) and refuses the blank machine name. Parent edits are locked while the child is open; Back drops the entered owner before the machine can be named. Machine Use stages the valid prerequisite and checks the actual eligible-owner predicate on its private preview. It does not require an already complete machine. Final Submit still validates the complete batch. The owner-first regression keeps the same source/name while the machine is subsequently named.
P2: footer Back disagrees with Escape on retained stale/dirty recovery After recovering unrelated dirty source/property text, App rejects every source event, including Back. After deleting/changing the owner, scenario/topology validate the origin before dispatching Back; the helper also compares scope first. The visible Back button refuses although global Escape succeeds through source_back(). Token-only source.dismiss runs before semantic context checks. App exempts only Source(Edit::Back) from other-editor admission. Wrong/old tokens still refuse; Open and Use keep their guards. Added dirty-editor and deleted-owner Back regressions preserve parent/property state.
P2: new empty actions accept a previous owner's event Capture A's new first-action message, navigate to clean B or another layer, then deliver A's bare Start(owner, tool). That route checks dirtiness and owner existence but carries no context. It can open A; selected_owner prioritizes the resulting pending owner. Scenario CTAs now use CanvasEvent::First(Context, Tool) through the existing context and dirty guards, with a fresh semantic emptiness check. Process first Work uses its existing context-bound Begin with the explicit default insertion. A new owner/layer-stale CTA regression rejects old context and admits the current one.

The source changes address the reported mechanisms. Their tests are authored regressions, not independently executed evidence in this review. In particular, constructing an orphan view prevents the identified expect panic but does not by itself prove its footer can be clicked at the minimum native window size.

The unchanged core contracts are used correctly in the inspected paths:

  • App form start/source admission checks raw source and property dirtiness without calling generic Apply. Source/parent submission retains the existing dirty guard. Model-menu and modal Escape precedence is resolved before child Back, then parent cancellation. Raw edits and form rendering create no accepted model/history operation.
  • Source commands keep source name, semantic parent, kind, layer, document, and exact captured consumer/parent identity distinct from the consumer. Existing validation admits Role only where appropriate, enforces System uniqueness, and preserves allowed completeness warnings. No allocation, role realization, reuse binding, or shared exchange retargeting is inferred.
  • For an actively selected staged source, the helper previews the source, prepares the original consumer, remaps every new element/relation identity and typed reference plus SetSteps to the reserved set, then forms one flat validated batch. Recomputed aliases use the reserved IDs rather than an abandoned temporary UUID. Machine/view/placement identities remain reserved by the existing creation planner. This review does not claim that the older non-staged planners reserve their IDs across separate preparations.
  • App compares the complete prepared staged command before assigning its consumer selection, and assigns it only after Document::execute succeeds. Parent acknowledgement follows success. Choosing an existing reference makes the staged source inactive: preview/combine omit it, so it is not published. Parent Cancel drops the entire pending state.
  • Captured process link identity/endpoints and presentation-before slot remain validated. Work insertion preserves the existing guarded link and adds the new successor link; a fresh source next to an existing Exchange still cannot impersonate the required endpoint and refuses with raw input retained.
  • New empty guidance counts semantic Lifeline/Occurrence/contribution records, rather than rendered positions. An unresolved lifeline is still a lifeline; ScenarioUse, fragment, and offscreen content do not become empty merely because of presentation. Existing scenario canvas/scroll slots remain in the surrounding workspace tree while the explicit child form occupies its form pane.

The author deliberately made explicit staged-consumer names exact, including leading/trailing whitespace; source names are also exact, and a blank consumer continues to default to its chosen source name. This supersedes the earlier matrix's inherited trimming expectation for active staged-source consumers. The older existing-reference consumer path still has its pre-existing trim policy. Native/oracle expectations must distinguish those paths and must not borrow an observed output name to define the expected model.

Second frozen source fingerprints captured at approximately 11:39 UTC:

File SHA-256
crates/oa-desktop/src/app.rs 81E0AA21A93126D716E628B3EBD440201AB19D6B578E2585F5E500072244D58B
crates/oa-desktop/src/behavior.rs A0E595F17F254002F1FBD7984EEB679320DAB042CA310C38D8916F0055713780
crates/oa-desktop/src/behavior/source_draft.rs 32057E30C0526FA674D463F47C4EAC7C0F391B1F4C5060757981A3CBED16C6AE
crates/oa-desktop/src/behavior/scenario.rs 759805631BE9E8526DACFB959D91C76CA1A2A40F47F8645BCEB0E0C15B77E326
crates/oa-desktop/src/behavior/topology.rs 8E1C65AFE4C7C097F683B33A6DF237219F48AFD1E81F81329B07612F4D6994CC
crates/oa-desktop/src/behavior/creation.rs BE75840293E84FCAE90DC6D17CCD6630A586B389FB189ADF73D1E9B046CE3DE2
crates/oa-desktop/src/behavior/contextual_source_tests.rs 242B68E0DFF14E57E1F510EA3DEA95ED1B2ADCDABFD24C9F493FC871CB50F049

No additional implementation blocker was found in this bounded review. Required evidence still includes terminal focused checks and native minimum/wide form authoring, plus independent complete model/source comparison for actual source/consumer creation and Undo/Redo/reopen. The earlier explicit detached-file retention rule remains unchanged. No native result, full-suite result, or release completion is claimed here.

Final staged-source delta review, 2026-09-11

Codex-9e8r6t /root/behavior_audit. Reviewed only the changes after the recorded second freeze: compact consumer captions, explicit creation summaries, recovered typed-scope validation, nested semantic-parent and callee/caller regressions, guide correction, and App Undo/Redo result handling. Read the final author gate and current Gitea decisions through #178. No production edits, Cargo, rustc or native input; root retains the immutable full-suite run and native acceptance.

The source inspected in this pass matched all ten corresponding entries in .local/contextual-source-20260911/focused4-inputs.json: App, behavior, source draft, scenario, scenario workspace, topology, topology view, creation, contextual-source tests and guide. This identifies the precise compiled source without presenting the earlier second-freeze fingerprints as current.

Concrete corrections identified at the final boundary

  1. P2 — The State machine guide still directs the user out of the new flow. At guide.rs:547, the first step says to cancel and create a missing owner in Architecture; the immediately following new step describes Create new owner with the retained machine draft. The old sentence would unnecessarily lose the user's pending setup and hides the new supported route. Sent directly to the author/root; the author removed it after the Clippy source freeze and this reviewer confirmed the source readback. The guide's previously rejected explain argument count is already corrected in the passing focused4 source.

  2. P2 — The source origin must survive inactive dependency planning. The author identified this additional case before review closure, and this reviewer independently confirmed its actual code path. Start a Lifeline or Work form with a valid existing target, open Create new source, then Back. source.engaged remains true, but there is no editing/active staged source. check_scope and preview therefore pass without a source-side document check. Parent Draft::command at scenario.rs:1350/topology.rs:582 then reaches its ordinary consumer planner against a different Project.id with the same owner and target UUIDs. The captured source_origin is checked only while handling Source events. Use followed by reselecting an existing source has the same inactive-dependency mechanism. This is a concrete preparation-boundary failure; no claim is made that ordinary file navigation preserves the form through its existing App reset.

    The narrow proposed correction checks captured document plus exact owner at final command preparation whenever source creation has been engaged, keeping token-only Back and cancellation available. Regression must begin with a valid existing target, prove baseline preparation succeeds, then refuse the other document while retaining all raw fields. A compatibility edge was sent separately: old recovered forms legitimately have source_origin=None and unengaged default source state. Their first successful source Open should bind the current origin; an already engaged missing/mismatched origin must never be silently rebound. The author implemented these document/legacy controls after the source freeze, with a valid-target Scenario/Work × Back/inactive × ordinary/legacy regression matrix. That later source is not covered by focused4 and no new execution is claimed here.

    One final owner-binding detail remains at this handoff. The initial new guard compares the captured owner with p.elements.get(&owner.id). A recovered origin can contain another valid, unchanged same-layer owner B while the parent draft still targets A. That lookup validates B against itself; the otherwise valid consumer planner still operates on A. Compare the captured owner record with p.elements.get(&self.owner) in final planning and p.elements.get(&d.owner) in Source-event admission, or explicitly require the two IDs to agree. The simplest negative control replaces only the serialized origin's owner record with B, leaving the valid target/slot and actual draft owner A unchanged. This avoids a false rejection caused by an unrelated invalid Scenario parent slot. This reviewer sent that independently derived detail to author/root; final strengthened source readback is pending.

Confirmed scope of the other deltas

  • New outer consumer captions call views::short with 60 characters, or 80 in the orphan card. That helper collapses whitespace and truncates presentation; it does not rewrite raw draft names. The source fields still have their own remaining-height scroller and a separate Back/Use footer. Active-source summaries describe the actual source+lifeline/work/machine transaction, with the first machine view explicitly conditional. No view call adopts a model command. Native minimum-window readability is not inferred from this trace.
  • source.check_scope is called before preview in all three parent planners. A selected staged source or current child with the wrong typed consumer scope is rejected; an inactive staged source remains excluded. The malformed-kind regression now also falsifies a Machine scope inside a Lifeline draft.
  • The nested-parent test uses a real OA Activity parent, refuses an Entity as work ownership, stages exactly one child Activity, then changes the captured parent's kind and proves private preview refuses without changing the raw source state. The implementation validates both the exact parent snapshot and current can_parent predicate. This is not a test of every parent family.
  • The callee regression has one existing ScenarioUse with an empty binding list. Adding a new Activity-backed callee lifeline preserves every original element, relation and diagram and produces the expected missing_lifeline_binding warning on that use. Its shared history helper checks model/source Undo, Redo and fresh source reconstruction. This is useful evidence for allowing an incomplete caller; it is not a claim of independently testing multiple callers with nonempty Role mappings.
  • App Undo/Redo now uses the actual boolean returned by Document, calls sync only for a history step, and reports Nothing to undo/redo when appropriate. Its test exercises both an empty history and a real rename through the public Message::Command path. Existing apply() guards for pending behavior/source remain in front; the existing property-Apply behavior is unchanged. No claim that all Undo/Redo requests are inherently free of property application is introduced.

CLI documentation cross-check

docs/source-cli.md and README's explicit cargo run --locked -p oa-cli --bin arcadia -- check examples/text-first/project.arcadia example match the final CLI adapter. The example's execution was already verified by root and was not repeated here. The page correctly separates aliases from display names, previews from explicit per-invocation writes, changed-file reports from unchanged captured dependencies, pending recovery from automatic recovery, and source3–7 migration from canonical formatting or detached-file deletion. Root accepted and applied two precision additions during this review: Unicode scalar columns, and written:false not implying guaranteed rollback. Readback confirmed both. No new CLI implementation issue or saved-plan/digest requirement was raised.

Evidence status

Read the author's terminal focused4.log/status: 22 passed, 0 failed, 653 filtered, 2.04 seconds test execution, exit 0 at 11:59:25 UTC. The matched immutable test executable is SHA-256 6E677F58458B6122EA1886AAC98882640CD9CF260651FE3ECE62BDDA4BE38CC0, inventory 675. The full suite was running under root at review time; it is not reported passed here. Guide/source-origin corrections above are later deltas and require their own coherent source/test evidence, including the final owner-binding detail. Current source-input manifest, focused logs, and author's revised implementation report remain the build evidence authority; this reviewer executed no desktop tests or native workflow.

Final source readback closure

The author froze the strengthened source and root requested a short final readback. No remaining material source finding in this bounded delta review. This closes the pending owner-binding detail above; it does not assert that the new source has completed its later compiled/native gates.

All four guards now compare the captured owner record against the actual parent draft's d.owner/self.owner, in addition to the document identity. The 23rd regression includes ordinary/legacy × Back/inactive-existing variants for both Scenario and Work. Each has a valid existing-target control, wrong-document and null-origin refusal, and a borrowed full record from another valid same-layer owner. The latter must fail both final preparation and Source Open while the entire raw recovery snapshot remains unchanged. This is the exact falsifier requested in the preceding handoff, not an unrelated invalid-parent failure.

For an old unengaged draft, first Source Open creates its missing origin only in a private clone; the clone replaces the parent only after source admission succeeds. It cannot rebind an already engaged missing/mismatched origin. Back is still dismissed by its token before those semantic guards, and parent Cancel remains available. The old guide sentence is absent and the retained-owner creation instruction is present.

Readback hashes match the author's final freeze:

File SHA-256
behavior/scenario.rs D12A4B1CAA61C08F69C4D2A64BD15568C4B7158DEA91AAC5A52A58A35ADB863C
behavior/topology.rs D06B2F0FC39B4814E94200297E148F1D4D97E04CB167766030AC9DF18689E3B0
behavior/contextual_source_tests.rs 5F05318A6533503B9D6FEBF1EC4DD7256F192394BC1B952A7904C8175BD8DDAE
guide.rs 47EEB3CC0A48D5712720096015A08387CD354FB91559B0BD6FA106B5CAC6292C

Paths in this last table are under crates/oa-desktop/src/. Root subsequently reported the earlier immutable 675-test artifact passed 675/675 in 448.33 seconds (Gitea #185). That artifact predates these final corrections. The author's focused5, matching GUI/lint and root's native/source oracle remain the appropriate next evidence; no Cargo, rustc, native input or production change was performed by this reviewer during closure.