Complete source 6 engineering workflows and preserve release validation evidence

This commit is contained in:
Codex
2026-09-06 21:49:04 -07:00
parent 2b2d2bc18b
commit 4b6b5fc197
290 changed files with 48271 additions and 1791 deletions
+306 -23
View File
@@ -25,8 +25,10 @@ pub enum Topic {
States,
Interfaces,
Transitions,
SemanticReview,
Artifacts,
Source,
ModelChecks,
Recovery,
Files,
Server,
@@ -44,8 +46,12 @@ pub enum Event {
Topic(Topic),
}
pub(crate) const ARTICLE_SCROLL_ID: &str = "engineering-guide-article";
impl State {
pub fn update(&mut self, event: Event) {
/// Returns whether navigation selected a different article.
pub fn update(&mut self, event: Event) -> bool {
let previous = self.topic;
match event {
Event::Search(query) => {
self.query = query;
@@ -62,11 +68,12 @@ impl State {
self.query.clear();
}
}
self.topic != previous
}
}
impl Topic {
const ALL: [Self; 16] = [
const ALL: [Self; 18] = [
Self::FirstProject,
Self::Perspectives,
Self::Participants,
@@ -78,8 +85,10 @@ impl Topic {
Self::States,
Self::Interfaces,
Self::Transitions,
Self::SemanticReview,
Self::Artifacts,
Self::Source,
Self::ModelChecks,
Self::Recovery,
Self::Files,
Self::Server,
@@ -98,9 +107,11 @@ impl Topic {
Self::States => "States, modes & transitions",
Self::Interfaces => "Data types, ports & interfaces",
Self::Transitions => "Move between OA & SA",
Self::SemanticReview => "Review semantic changes",
Self::Artifacts => "Connect engineering evidence",
Self::Source => "Textual editing & Git",
Self::Recovery => "Checks & error recovery",
Self::ModelChecks => "Read model checks",
Self::Recovery => "Drafts & crash recovery",
Self::Files => "Files & keyboard shortcuts",
Self::Server => "Hosted models & REST API",
}
@@ -113,8 +124,10 @@ impl Topic {
"MODEL THE SYSTEM"
}
Self::Chains | Self::Scenarios | Self::States | Self::Interfaces => "DESCRIBE BEHAVIOR",
Self::Transitions | Self::Artifacts | Self::Source => "CONNECT YOUR WORK",
Self::Recovery | Self::Files | Self::Server => "REFERENCE",
Self::Transitions | Self::SemanticReview | Self::Artifacts | Self::Source => {
"CONNECT YOUR WORK"
}
Self::ModelChecks | Self::Recovery | Self::Files | Self::Server => "REFERENCE",
}
}
}
@@ -177,13 +190,23 @@ fn article(topic: Topic) -> Article {
"Choose Entity under Create element, then + At root. Name it Rescue coordinator and Apply changes. Use Actor for an external participant such as a Vessel in distress.",
"Select Rescue coordinator, choose Activity, then + Allocated. Name the new activity Assess incident. It appears inside its performer; an Allocation relationship records that responsibility.",
"Add a second activity for another participant. Select an activity, choose + Relationship, select Interaction and choose the compatible target. Name the exchange after what is conveyed.",
"Visit Model checks to review unfinished work. Save project writes the accepted model and applied drafts to your chosen file.",
"Visit Model checks to review unfinished work. Save all writes the accepted model and applied drafts to your chosen file.",
],
),
explain(
"Continue into system design",
"Use Create / update counterpart on an operational element to review an OA → SA mapping. In System Analysis, identify the System under study, its external Actors and the Functions for which each is responsible. The transition tutorial explains scope, reuse and review decisions.",
),
walkthrough(
"Build a reviewable OA → SA baseline",
&[
"State the mission and capability: for example, protect life at sea by coordinating a rescue. Link the mission to the capability and identify the participants that support it.",
"Describe the normal operational Process and an exception Scenario using the activities and Interactions already in the architecture. Give the scenario an explicit Context capability and connect the process with Chain involvement.",
"Review which operational work the System will support. Create or reuse its SA counterparts, then check the resulting System boundary, external actors, leaf Function allocations and exchanged payloads.",
"Refine the system Functional chain, Scenario and State machine. Specify data contracts and entry/do/exit work where they clarify responsibilities. Link requirements, analyses or tests to the particular records they support.",
"Read Model checks, review changes through counterpart traces, and inspect both perspectives. Save the complete source project and review its Git diff as one engineering milestone.",
],
),
explain(
"Explore a worked model",
"Open the coastal rescue example to inspect allocation, decomposition, repeated scenario messages, operating modes, typed interfaces and artifact references. Loading the example uses the normal unsaved-work prompt. It replaces the current project only after that workflow completes.",
@@ -194,6 +217,7 @@ fn article(topic: Topic) -> Article {
Topic::Participants,
Topic::Nesting,
Topic::Transitions,
Topic::ModelChecks,
],
destination: Some((Page::Diagram, "Open Architecture")),
}
@@ -264,7 +288,7 @@ fn article(topic: Topic) -> Article {
const {
Article {
summary: "A diagram is a view of the model. Its boxes, positions and nesting reveal selected relationships; moving a box does not redefine engineering ownership.",
keywords: "containment semantic parent hierarchy nested nesting allocation deployment diagram placement arrange fit fold hide zoom resize routing connection bend waypoint detour label reset",
keywords: "containment semantic parent hierarchy nested nesting allocation deployment diagram placement arrange fit fold hide zoom resize routing connection bend waypoint detour label reset selective visibility category categories coverage process context duplicate copy items",
sections: &[
explain(
"Three things to distinguish",
@@ -281,7 +305,7 @@ fn article(topic: Topic) -> Article {
walkthrough(
"Choose and edit the relationship you mean",
&[
"Use the diagram selector or + View to work with a focused diagram. View properties edits its name, perspective and projection.",
"Use the diagram selector or + View to work with a focused diagram. View properties edits its name, perspective, projection and Saved view visibility. Apply changes commits the view settings.",
"Choose Containment for semantic children, Architecture · allocated work for responsibilities, Functional dataflow for work and exchanges, or Missions & capabilities for outcomes. All relationships is a broader exploration view; OA ↔ SA traceability displays counterparts.",
"Select an element and edit Semantic parent to change ownership. Use an Allocation relationship to change responsibility. Apply changes validates the semantic change.",
"Drag nodes to arrange the current view, scroll to zoom and use Fit to frame its contents. Arrange changes diagram geometry. Export SVG produces a shareable view.",
@@ -292,6 +316,16 @@ fn article(topic: Topic) -> Article {
"Keep diagrams readable",
"Use separate views for responsibility, decomposition and cross-layer coverage. Place existing elements with Show in this diagram. A placement's Diagram field can relocate it while preserving its identity and artifact references. Do not duplicate a semantic element merely to show it in another view.",
),
walkthrough(
"Save a focused exchange view",
&[
"To preserve the current presentation, right-click empty diagram space and choose Duplicate view. The copy has independent placements, routes and visibility settings while representing the same model elements and relationships. View-specific artifact links stay with the original view.",
"Open View properties. Under Work exchange categories or Participant exchange categories, uncheck All, including uncategorized exchanges, then Include the categories you need. Selected categories combine by union; none selected shows none of that family. Work means OA Interactions or SA Functional exchanges; participant means OA Communication means or SA Boundary exchanges, including supported legacy records.",
"Work exchange coverage across the whole model offers All work exchanges, Used in behavior and Outside behavior. This uses explicit process, chain and scenario occurrences, including reuse. To focus on particular behavior, uncheck All work contexts and Include those processes, chains or scenarios. Context and coverage intersect with categories; no selected contexts means no work lines.",
"Choose Exchange labels: Names, Items or Names and items. In Individual lines and omission reasons, search a name or alias and check Hide to retain an explicit hide. Unchecking Hide removes only that reason; other settings or missing endpoints may still omit the line. Clear all explicit hides removes the manual hide list.",
"Apply changes and inspect the result. To restore all eligible lines, enable All relationship line kinds, both category All choices and All work contexts, choose All work exchanges, and clear explicit hides. Empty relationship-kind selection shows no lines. These settings do not remove nodes or model facts; a line still needs endpoints eligible for the projection.",
],
),
explain(
"Read allocation summaries and ports",
"A dashed parent activity/function with an italic name and SUMMARY heading groups leaves assigned to the same performer. It has no direct allocation of its own; its inspector explains the leaf performer. Small ports belong to the boundary of their visible owner and are selectable model elements. Folding a container hides its inner work and ports; summary exchange lines do not invent new ports on the container.",
@@ -341,7 +375,7 @@ fn article(topic: Topic) -> Article {
),
explain(
"Use scenarios as concrete evidence",
"A scenario illustrates one path through the behavior: normal response, degraded operation or an exception. Keep its intended capability and assumptions clear in its engineering description and available model relationships. Scenarios complement the capability definition; they do not replace the outcome.",
"A scenario illustrates normal response, degraded operation or an exception. In its Properties, choose Context to name the capability it supports in the same perspective; record assumptions and pre/postconditions too. Connect a Process or Functional chain with Chain involvement. Descriptive prose explains the intent, while these explicit references make the context inspectable.",
),
explain(
"Avoid implementation names at this stage",
@@ -362,7 +396,7 @@ fn article(topic: Topic) -> Article {
const {
Article {
summary: "An exchange says what passes between work or across a participant boundary. Its payload, endpoints and allocation make that statement precise.",
keywords: "interaction functional exchange boundary exchange flow information material energy event source target port exchange allocation",
keywords: "interaction functional exchange boundary exchange communication mean participant directed bidirectional category categories flow information material energy event source target port exchange allocation",
sections: &[
walkthrough(
"Create a typed exchange",
@@ -371,7 +405,7 @@ fn article(topic: Topic) -> Article {
"Choose Interaction or Functional exchange in the diagram palette. Click the source, then a highlighted compatible target, or drag between them. Functional exchanges connect output ports to input ports; function cards create or reuse real ports in the same transaction. Middle-button drag pans while keeping the source; arrow keys also pan when the drawing canvas has focus. Click empty space to restart, or Escape to cancel.",
"Create an Exchange item under Data & interfaces. Choose its nature (Information, Material or Energy) and its mechanism (Flow, Event, Operation or Shared data). Describe the payload independently of the connection.",
"Select the exchange in Model explorer or the diagram. Edit its properties to reference the appropriate exchange items and available ports; Apply changes validates the complete record.",
"Choose Boundary exchange and connect compatible component ports. Flow goes from Out to In; Standard is unoriented. Select / move returns to arranging. Exchange allocation associates a boundary exchange with the functional exchange it carries.",
"In System Analysis, choose Boundary exchange and connect compatible component ports. Flow goes from Out to In; Standard is unoriented. Select / move returns to arranging. Exchange allocation associates a boundary exchange with the functional exchange it carries.",
],
),
explain(
@@ -382,6 +416,14 @@ fn article(topic: Topic) -> Article {
"Use engineering payloads",
"Choose Information for data such as a distress report, Energy for delivered power and Material for a transferred substance. Mechanism separately describes how it is exchanged: an Event is a notification, an Operation has parameters, and a Flow carries values or a physical quantity. Data types and fields make payloads precise. Artifact links can point to interface-control documents.",
),
explain(
"Operational and system boundaries",
"An OA Interaction connects activities. A Communication mean connects operational Entities or Actors directly; it requires no system ports. In Operational Analysis, choose Communication means and connect its participants. Its properties hold carried items and direction; the relationship form offers Directed source → target (unchecked: bidirectional). Existing OA Boundary exchanges with Legacy ports remain editable for compatibility.",
),
explain(
"Relate operational transport and concerns",
"Use Exchange allocation to associate a Communication mean with the Interactions it carries. Allocate each activity to its actual performer and check that those performers match the communication endpoints and direction. Create an Exchange category at the perspective root, choose Work exchanges or Participant exchanges in its properties, and Include existing exchange members. Categories name reusable concerns for view filtering; they do not change endpoints, allocate work or imply execution. A category may be empty, and an exchange may belong to several categories.",
),
],
related: &[
Topic::Interfaces,
@@ -404,8 +446,9 @@ fn article(topic: Topic) -> Article {
&[
"First create the activities/functions and their exchanges. Check the source and target work for every exchange.",
"Open Behavior & scenarios. Create Process in OA or Functional chain in SA using Create element and + At root.",
"Select that behavior in the page's selector. Use + Work or + Exchange to involve an existing source. Each contribution keeps its own identity while referring to the shared engineering definition.",
"Select a contribution, then add another after it or use Connect to wire existing contributions. Branch / parallel creates a split, two paths and their merge in one undoable edit. Enter explicit alternative conditions; use Fit and zoom to inspect the topology.",
"Select that behavior in the page's selector. Choose Work or Exchange, then a highlighted path or contribution position to involve an existing source. Each contribution keeps its own identity while referring to the shared engineering definition.",
"Choose Sequence link and click or drag from the preceding contribution to the following contribution. In Select / reorder, drag a selected path endpoint to reconnect it; a contribution's ↕ handle changes its position within a column. These are local contributions and sequence links, not new architecture exchanges.",
"Select a contribution, then add another after it. Two paths… creates a split, two paths and their merge in one undoable edit. Enter explicit alternative conditions; use Fit and zoom to inspect the topology.",
"Use Chain involvement from the Process/Functional chain to the capability it supports. Read Model checks for unfinished or disconnected paths.",
],
),
@@ -415,7 +458,7 @@ fn article(topic: Topic) -> Article {
),
explain(
"Review the path as an engineer",
"Check that exchanges express meaningful handoffs and that the links and branch guards support the selected outcome. Use Reuse to involve an existing process or chain as a nested reference. Imported ordered exchange paths retain their meaning; the first topology edit explains and preserves their implied links in the same transaction.",
"Check that exchanges express meaningful handoffs and that the links and branch guards support the selected outcome. Use Reuse to involve an existing process or chain as a nested reference. For an imported ordered exchange path, Append exchange… continues that path; Convert ordered path to explicit links exposes its implied links for topology editing. Conversion preserves the original order in one undoable change.",
),
],
related: &[Topic::Exchanges, Topic::Capabilities, Topic::Scenarios],
@@ -436,7 +479,8 @@ fn article(topic: Topic) -> Article {
"Use + Lifeline and choose the participant or work it represents. Choices follow the scenario's viewpoint: operational activities, operational participants, system functions or system boundary participants.",
"Choose + Message and its style. Call + correlated reply creates both occurrences in one edit. Select the exchange and compatible sending/receiving lifelines. Reply to existing call offers valid unanswered calls.",
"Use Action, Observe state or Fragment for other behavior. A local timer has an expression and a lifeline, with no global exchange. Create and delete messages describe participant lifetime; Model checks also flag risks inside repeated loops.",
"Use the ordered list's up/down controls to change sequence order. Click a message or list entry to inspect that occurrence rather than the reusable exchange definition.",
"Choose a message style and Draw message. Start at a highlighted sequence position on a lifeline, then click or drag to the receiving lifeline. The form retains the chosen position while you select the exchange and details. Escape cancels the gesture.",
"In Select / reorder, click an occurrence and drag its ↕ handle to another position within the same sequence. The ordered list's up/down controls provide another way to reorder. Select an occurrence to inspect its particular use of the exchange, including its message values.",
],
),
walkthrough(
@@ -452,6 +496,10 @@ fn article(topic: Topic) -> Article {
"Conditions are engineering statements",
"Guards, actions and effects document behavior; a drawn scenario does not execute code or prove timing. Add evidence references when a simulation, test or analysis establishes a stronger claim.",
),
explain(
"Keep uses distinct from definitions",
"Several occurrences can refer to one exchange without duplicating it. Edit occurrence properties for this message's sender, receiver and value expressions; edit the exchange for the shared endpoints and payload. A Reply refers to a particular Call, not merely a similar name. Reordering across fragment operands or changing lifeline bindings needs an explicit structural edit, not an accidental drag across a boundary.",
),
],
related: &[
Topic::Chains,
@@ -489,7 +537,16 @@ fn article(topic: Topic) -> Article {
),
explain(
"Availability and state actions",
"Availability links a participant or behavior to a State/Mode in which it is available. State action links a State/Mode to an Activity/Function and records its entry, do or exit phase. Use these typed relationships when work depends on operating conditions.",
"Availability links a participant or behavior to a State/Mode in which it is available. State action links a State/Mode to existing Activity/Function work and records Entry, Do or Exit. The saved state view shows those named action rows above internal transitions and nested regions. Select a row to edit its actual State action relationship. The linked work remains in its own semantic owner; the row does not contain or copy it. Free-text entry/do/exit notes remain separate engineering prose.",
),
walkthrough(
"Add timing without losing an existing transition",
&[
"Select the transition and choose Edit transition. Its current endpoints, kind, existing triggers, guard and effects populate the form.",
"Choose Add a time event with this transition, select After for a delay or At for a time, then enter a time expression such as 30 s. This adds a typed Event to the trigger alternatives; it does not replace existing triggers.",
"Review the complete transition before Apply. The event and transition update are one undoable change. If the form is rejected, correct the retained values; a rejected candidate creates no orphan Event.",
"Save the entry and any included source files. On reopening, check the transition's trigger list and the Event expression. An expression documents timing intent; it is not evaluated by a simulator.",
],
),
explain(
"Keep conditions testable",
@@ -579,7 +636,7 @@ fn article(topic: Topic) -> Article {
),
explain(
"Know what reconciliation changes",
"Semantic review supports explicit structural and scalar changes, typed constructors and individual collection rows, including members, literals, annotations and bindings. Candidate validation checks the complete proposed model before applying one undoable transaction. Ordered collections, attachment/artifact and multi-source review controls remain unfinished; some structured facts are read-only. Do not assume Refresh preview automatically synchronizes arbitrary structure or every field.",
"Semantic review supports structural and scalar changes, typed constructors, individual collection rows and explicit ordered collections. Several trace rows can contribute to one combined destination proposal. Candidate validation checks the complete proposed model before one undoable transaction. The Review semantic changes topic explains included rows, mapped references and order decisions. Attached-record and artifact reconciliation remain outside this dialog's authoring controls; use their supported editing workflows.",
),
explain(
"Avoid duplicate counterparts",
@@ -591,6 +648,68 @@ fn article(topic: Topic) -> Article {
Topic::Participants,
Topic::Capabilities,
Topic::Recovery,
Topic::SemanticReview,
],
destination: Some((Page::Traces, "Open Traceability")),
}
}
}
Topic::SemanticReview => {
const {
Article {
summary: "Review what changed between corresponding OA and SA records. Choose the engineering result explicitly and retain the reasoned correspondence for later changes.",
keywords: "semantic drift review keep take final candidate previously reviewed history reset reference pairs annotation qualified field path binding lifeline membership order up down reconcile steps fragment branch direction multi-source batch",
sections: &[
walkthrough(
"Compare the right records and direction",
&[
"From an existing counterpart trace, choose Review semantics…. Confirm the OA → SA or SA → OA direction and select the intended trace / review history. Each correspondence and direction has its own retained row draft; opening another row does not discard the first row's choices.",
"In Properties, select a fact. Compare Previously reviewed with Current on both sides. Unreviewed means there is no prior observation; Both changed means both sides changed since that observation, not that one side is automatically wrong.",
"Choose Keep for the destination, Take for the source, or Set final value…. For a kind change, Set final kind and payload… reviews the complete replacement and its affected references. Leave unselected makes no decision for that fact.",
"Read Reference pairs and Additional changes before Apply reviewed changes. A missing or ambiguous correspondence must be resolved explicitly. Apply commits the validated model and the reviewed history together; Undo restores both.",
],
),
explain(
"Map references by meaning",
"Reference pairs connect exact OA and SA identities used by the proposed change. Similar names are not sufficient. Map the records that play the same engineering role, including enclosing fields in qualified message-value paths. Mapping a referenced record does not authorize creating, moving or editing that record. If it needs a counterpart, establish that correspondence first.",
),
walkthrough(
"Review one message value or lifeline binding",
&[
"Open Members / rows and choose the exact identities on both sides. For a message value, browse the enclosing record fields as well as the final field: origin.latitude and destination.latitude are distinct addresses.",
"For a binding, choose the referenced lifeline key and its compatible local lifeline. Check which scenario owns each side. Keep or Take concerns that row, not all bindings in the scenario.",
"Use Set final value… to enter the destination expression or local lifeline. Include in destination collection controls that row's presence. Unchecking removes the entry without deleting its referenced engineering object.",
"If a row key changed, review the old entry's removal and the new entry's addition separately. A missing source identity is not the same decision as an identified source entry that has been deleted. Read the proposed value before applying.",
],
),
walkthrough(
"Review membership and sequence order separately",
&[
"Review which occurrences belong to Steps, or which operands belong to Fragment branches, using Members / rows. This changes membership; it does not silently reparent or create the referenced records.",
"Choose Review final order… or the corresponding order fact in Properties. Keep retains destination positions. Take uses mapped source order when it can preserve destination-only members without an ambiguous placement.",
"For an explicit result, choose Set final value…, then use Up and Down. If you change membership afterward, choose Reconcile with selected membership: surviving positions are retained, removed members leave the list, and new members append for you to position.",
"Every surviving destination member must appear exactly once. Resolve an ambiguous insertion with an explicit final order; do not remove an engineering contribution merely to make the preview pass.",
],
),
explain(
"Preserve intentional differences and useful history",
"Keep can acknowledge a deliberate difference without overwriting the destination. Reset this exact previous observation clears only the chosen review history; it does not restore an old model value. Overlapping row addresses may require an explicit history reset. Review those messages rather than clearing unrelated observations. Pending review choices and raw values can be recovered after an unexpected exit, but the plan is recomputed against the recovered accepted model.",
),
walkthrough(
"Review several sources together",
&[
"Use Choose another trace to add or reopen, then Open row. Include this row determines whether its decisions contribute to the shared preview. The trace / review history selector switches the row you are editing; excluded rows retain their drafts.",
"Review each included source's contribution to the destination. Compatible decisions combine; contradictory Keep, Take or final-value decisions must be resolved explicitly. Read the combined conflicts, Reference pairs and Additional changes before Apply reviewed changes. One Apply commits the combined model and review histories; one Undo restores them.",
"Only one trace history per source can be included. Some reverse correspondences cannot share the core reference mapping; the preview explains the conflict. Exclude a row or choose a distinct correspondence without discarding its draft. Switching direction retains the other direction's choices for later review.",
"Recovery retains included and excluded row drafts and raw final values, then recomputes the plan against the recovered accepted model. Refresh preview is not automatic synchronization and does not authorize changes to attached records or artifacts.",
],
),
],
related: &[
Topic::Transitions,
Topic::Interfaces,
Topic::Scenarios,
Topic::Recovery,
],
destination: Some((Page::Traces, "Open Traceability")),
}
@@ -608,7 +727,7 @@ fn article(topic: Topic) -> Article {
"Select the model record the evidence concerns. This may be an element, relationship, diagram, placement or other supported persistent record.",
"Choose + Artifact reference in Properties, or + Artifact in Traceability. Name the reference so another engineer understands its purpose.",
"Enter the Artifact URI, optional external Revision and Fragment. Use a commit or document revision when a reproducible reference matters; the fragment identifies a particular part of the artifact.",
"Add a description explaining whether the artifact specifies, implements or verifies the engineering decision. Apply changes, then inspect the owner and reference in Traceability.",
"Choose the relation to the artifact: References, Satisfies, Verifies or Implements. Add a description explaining the evidence and its limits. Apply changes, then inspect the owner and reference in Traceability.",
],
),
explain(
@@ -659,6 +778,11 @@ fn article(topic: Topic) -> Article {
"Use one contract",
"The normative specification is docs/language.rst in the distribution. It defines source grammar and supported graphical semantics together. Text preserves semantic records, diagram placements, ordered occurrences, traces and artifact references. Graphical edits preserve unaffected source formatting and comments; accepted model Undo/Redo also restores the exact source files. Comments and source-file organization are not part of JSON export.",
),
example(
"Keep included files with their entry",
"An include is relative to the file that declares it. Put declarations in the included file and keep one project entry. A newly created graphical record may live in another source file; use Open source to locate it and include every affected file in your review and save.",
"// Inside the project declaration:\ninclude \"oa/operations.arcadia\";\ninclude \"sa/model.arcadia\";",
),
explain(
"Resolve source-control conflicts before applying",
"Ordinary Git conflict markers are not Arcadia syntax. Resolve the text merge, preserve intended UUIDs/references, then apply and inspect Model checks. The editor does not decide which engineer's model change is correct.",
@@ -674,6 +798,53 @@ fn article(topic: Topic) -> Article {
}
}
}
Topic::ModelChecks => {
const {
Article {
summary: "Use checks to find invalid structure and unfinished engineering work. A valid model can still need decisions, behavior evidence or allocation.",
keywords: "validation warning error completeness coverage non_leaf_work_exchange work_without_behavior_context exchange_without_behavior_context mission_without_capability capability_without_behavior_context unsupported_capability sequence_gap allocation leaf context diagnostics lint",
sections: &[
explain(
"Errors and warnings answer different questions",
"An error rejects the candidate, leaving the accepted model unchanged. A warning describes an incomplete or questionable model that can still be saved. Read the record, field and source location rather than treating the number of warnings as a quality score. Fix structural errors first: the completeness pass waits for valid structure, so its warnings may appear after those errors are corrected.",
),
walkthrough(
"Connect work to explicit behavior",
&[
"For an exchange on non-leaf work, identify the leaf Activity or Function responsible for that endpoint. In SA, keep its typed input/output port owned by that Function. Do not add a fake child just to suppress the warning.",
"For leaf work without behavior context, include a work action or one of its exchanges in an ordered Process/Functional chain or Scenario. Allocation alone states who performs the work, not how it is used.",
"For an exchange without behavior context, include that exact Interaction or Functional exchange in an exchange occurrence. A similarly named exchange or an unlisted occurrence under the container does not provide evidence.",
"Only included steps, fragment operands and valid reused behavior contribute. State actions, availability links and prose remain useful but do not stand in for an explicit process/scenario use. Coverage demonstrates inclusion, not execution or completeness of every possible path.",
],
),
walkthrough(
"Connect purpose to behavioral evidence",
&[
"For a mission without a capability, connect the mission to the capability that delivers it. Merely involving a participant in the mission does not identify that capability.",
"For a supported capability without behavior context, connect a Process/Functional chain using Chain involvement or set a Scenario's Context to that capability in the same perspective.",
"A capability used only to group child capabilities is treated differently from an isolated leaf. A directly contextualized Scenario establishes support; adding an unrelated participant link is not required merely to clear a warning.",
"Review the engineering statement after each correction. Do not invent relationships solely to achieve a warning-free list; leave an unfinished decision visible until the model can express it accurately.",
],
),
explain(
"Review sequence gaps and incomplete contracts",
"A sequence gap calls attention to disconnected handoffs; inspect the contribution endpoints and intended path. Missing allocations, unspecified exchange mechanisms and incomplete conditions need their own engineering decisions. An accepted model does not prove that guards are executable, units are converted, external artifacts exist or timing requirements are met.",
),
explain(
"The same checks are available to text and automation",
"Model checks, source lint and server validation use the shared model rules. Source-project diagnostics identify the included file and location; native JSON checks identify the model record and field. A validation request can inspect a candidate without committing it. Correct errors in the complete candidate before applying it graphically, as text or through the API.",
),
],
related: &[
Topic::Capabilities,
Topic::Chains,
Topic::Scenarios,
Topic::Recovery,
],
destination: Some((Page::Validation, "Open Model checks")),
}
}
}
Topic::Recovery => {
const {
Article {
@@ -721,7 +892,12 @@ fn article(topic: Topic) -> Article {
"New, Open, opening a recent model, loading the example, Recover and Close use the unsaved-work prompt. Save and continue, discard or cancel is your decision. Checkpoints are private recovery copies; continue saving meaningful milestones and using version control or backups.",
),
],
related: &[Topic::Source, Topic::Files, Topic::Transitions],
related: &[
Topic::ModelChecks,
Topic::Source,
Topic::Files,
Topic::SemanticReview,
],
destination: Some((Page::Validation, "Open Model checks")),
}
}
@@ -734,7 +910,7 @@ fn article(topic: Topic) -> Article {
sections: &[
explain(
"Start from Home",
"Home offers New model, Open model, the rescue example and this guide. Recent models lists local files you successfully opened or saved. A disconnected drive or moved file remains visible; use Locate to choose its new location or Refresh after reconnecting the drive. Remove forgets the recent entry without deleting its model file. Returning to Home retains the current document and uses the same draft navigation guards as other pages.",
"Home offers New model, Open model, the rescue example and this guide. Recent models lists local files you successfully opened or saved. A disconnected drive or moved file remains visible; use Locate to choose its new location or Refresh after reconnecting the drive. Remove forgets the recent entry without deleting its model file. Home retains the current document; Continue editing returns to the last workspace, including Textual model or a saved state view, with its drafts intact.",
),
explain(
"Editable formats",
@@ -743,7 +919,7 @@ fn article(topic: Topic) -> Article {
example(
"Keyboard reference",
"Shortcuts act on the current project. In Textual model, undo and redo affect the source draft.",
"Ctrl+N New project\nCtrl+O Open model\nCtrl+S Save project\nCtrl+Shift+S Save as\nCtrl+Z Undo\nCtrl+Shift+Z Redo\nCtrl+Y Redo\nEscape Cancel the active dialog",
"Ctrl+N New project\nCtrl+O Open model\nCtrl+S Save all\nCtrl+Shift+S Save as\nCtrl+Z Undo\nCtrl+Shift+Z Redo\nCtrl+Y Redo\nEscape Cancel the active dialog",
),
walkthrough(
"Save and share a model",
@@ -754,6 +930,10 @@ fn article(topic: Topic) -> Article {
"If another tool changed or deleted the open file, preserve your candidate using a new Save as destination. Compare and reconcile the versions before replacing either one.",
],
),
explain(
"Save as preserves the engineering history",
"Saving a source project under a new entry name relocates the save destination without adding a model edit or clearing Redo. Choose a name that does not collide with an included file, including one retained in Undo/Redo history. Save all includes every accepted source file; an unchanged entry file alone does not prove that an included file was saved. If a save fails, the current model and drafts remain available.",
),
explain(
"Open and migration",
"Open validates a complete candidate before replacing the project. Supported earlier versions migrate to the current schema; Model checks shows migration details such as preserved ports, supplied data defaults, generated interface allocations and unresolved message paths. Old Event items become Information notifications; unknown physical mechanisms remain Unspecified. Source upgrades retain files, includes, nested ownership and comments. Opening does not overwrite the original: use Save as if it must remain in its older format. Invalid input leaves the accepted project unchanged.",
@@ -806,11 +986,15 @@ fn article(topic: Topic) -> Article {
&[
"Create or import a project using /api/v1/projects or /api/v1/projects/import. Keep the returned service resource_id; it is distinct from the editable model UUID.",
"Read the project's envelope, source or model. Preserve its exact ETag as the precondition for your edit.",
"Submit typed commands to /transactions, or a complete candidate to /source or /model, using If-Match. Use transaction dry-run or validation before committing substantial generated changes.",
"Submit typed commands to /transactions, or a complete candidate to /source, /model or /source-project, using If-Match. Use transaction dry-run or validation before committing substantial generated changes.",
"A stale write returns 412. Keep the user's draft, reload the current head and reconcile deliberately. After an uncertain write outcome, read the server state before retrying.",
"Query /artifact-links and /traces to connect domain-tool artifacts to model records. The server stores these references; the integration is responsible for resolving its external artifacts.",
],
),
explain(
"Validate and save a source bundle",
"GET /source-project returns the entry and included files. POST /validation with format source-project and source_project containing that bundle checks a candidate without committing it; warnings can coexist with valid: true. PUT /source-project accepts the complete bundle under the current If-Match ETag. Structural errors reject the write, preserving the accepted model and revision. Compare record IDs and fields across text/JSON diagnostics; source-project results also identify the included file and source span.",
),
explain(
"Deployment and persistence",
"Non-loopback binding requires a configured bearer token. Use the documented local-disk storage and deployment configuration. The service keeps the current revision and serializes accepted updates; it does not provide retained revision history or server-side undo. Stop the service cleanly before copying its committed store for backup.",
@@ -922,6 +1106,13 @@ fn article_view(topic: Topic) -> Element<'static, Message> {
);
}
if topic == Topic::FirstProject {
content = content.push(text("For a worked model, open the water-pressure walkthrough. Copy the whole examples/release1 folder and open the copied project.arcadia before editing; read its README.md. If you use Save as, also copy evidence/ beside the new entry: Save as copies model source, not external artifact targets.").size(13));
content = content.push(
button(text("Open water-pressure walkthrough").size(13))
.padding([11, 15])
.style(style::nav)
.on_press(Message::Home(crate::home::Event::Walkthrough)),
);
content = content.push(
button(text("Open coastal rescue example").size(13))
.padding([11, 15])
@@ -938,6 +1129,7 @@ fn article_view(topic: Topic) -> Element<'static, Message> {
bottom: 24.,
..Default::default()
}))
.id(ARTICLE_SCROLL_ID)
.width(Fill)
.height(Fill)
.into()
@@ -974,7 +1166,7 @@ pub fn view(state: &State) -> Element<'_, Message> {
button(text("Clear search").size(13)).padding([10, 14]).on_press(Message::Guide(Event::Search(String::new()))),
].spacing(16).max_width(520)).padding(24).width(Fill).into()
} else {
// A different article gets a fresh scroll state and starts at its title.
// Topic changes also issue an explicit article-only scroll reset.
keyed_column([(state.topic, article_view(state.topic))])
.width(Fill)
.height(Fill)
@@ -1022,6 +1214,97 @@ pub fn view(state: &State) -> Element<'_, Message> {
mod tests {
use super::*;
#[derive(Default)]
struct ScrollProbe {
snaps: Vec<iced::advanced::widget::operation::scrollable::RelativeOffset<Option<f32>>>,
}
impl iced::advanced::widget::operation::Scrollable for ScrollProbe {
fn snap_to(
&mut self,
offset: iced::advanced::widget::operation::scrollable::RelativeOffset<Option<f32>>,
) {
self.snaps.push(offset);
}
fn scroll_to(
&mut self,
_: iced::advanced::widget::operation::scrollable::AbsoluteOffset<Option<f32>>,
) {
panic!("Guide navigation must snap to the article start");
}
fn scroll_by(
&mut self,
_: iced::advanced::widget::operation::scrollable::AbsoluteOffset,
_: iced::Rectangle,
_: iced::Rectangle,
) {
panic!("Guide navigation must not use a relative pixel scroll");
}
}
#[tokio::test]
async fn guide_topic_navigation_resets_only_article_and_same_topic_search_keeps_scroll() {
use iced::futures::StreamExt;
let mut app = crate::app::App::with_project(oa_core::Project::empty());
app.page = Page::Guide;
let accepted = app.document.snapshot();
let revision = app.document.revision();
for (event, topic, reset) in [
(Event::Topic(Topic::Scenarios), Topic::Scenarios, true),
(
Event::Search("sender lifeline".into()),
Topic::Scenarios,
false,
),
// Native reproduction: related topic after scrolling Scenarios.
(Event::Topic(Topic::Exchanges), Topic::Exchanges, true),
(Event::Search("If-Match 412".into()), Topic::Server, true),
(Event::Search("If-Match".into()), Topic::Server, false),
(
Event::Search("nonexistent-topic-987".into()),
Topic::Server,
false,
),
(Event::Search(String::new()), Topic::Server, false),
(Event::Topic(Topic::Server), Topic::Server, false),
] {
let mut article = ScrollProbe::default();
let mut navigation = ScrollProbe::default();
if let Some(mut stream) =
iced_runtime::task::into_stream(app.update(Message::Guide(event)))
{
while let Some(action) = stream.next().await {
let iced_runtime::Action::Widget(mut operation) = action else {
panic!("Guide navigation must not schedule model or external actions");
};
for (id, probe) in [
(ARTICLE_SCROLL_ID, &mut article),
("guide-topic-navigation", &mut navigation),
] {
operation.scrollable(
Some(&iced::advanced::widget::Id::new(id)),
iced::Rectangle::default(),
iced::Rectangle::default(),
iced::Vector::new(0., 900.),
probe,
);
}
}
}
assert_eq!(app.guide.topic, topic);
assert_eq!(article.snaps.len(), usize::from(reset));
for offset in article.snaps {
assert_eq!(offset.x, Some(0.));
assert_eq!(offset.y, Some(0.));
}
assert!(navigation.snaps.is_empty());
assert_eq!(app.project(), &accepted.decoded.project);
assert_eq!(app.document.bundle(), &accepted.bundle);
assert_eq!(app.document.revision(), revision);
assert!(!app.document.can_undo());
}
}
#[test]
fn search_finds_concepts_in_walkthroughs_and_api_reference() {
assert!(search(" ALLOCATED rescue ").contains(&Topic::FirstProject));