Record revised release requirements and native scenario oracle
This commit is contained in:
+67
-20
@@ -13,6 +13,7 @@ Deliver the product described by the repository, specification, requirements, re
|
||||
Persist until the intended outcome is genuinely achieved.
|
||||
|
||||
Do not stop at:
|
||||
|
||||
- research,
|
||||
- planning,
|
||||
- a plausible conceptual design,
|
||||
@@ -26,6 +27,7 @@ The final result must be conceptually coherent, technically sound, usable, imple
|
||||
Bias toward action and completion.
|
||||
|
||||
Resolve discoverable questions yourself through:
|
||||
|
||||
- repository exploration,
|
||||
- web and literature research,
|
||||
- primary documentation,
|
||||
@@ -76,27 +78,35 @@ Maintain a concise durable Task Ledger in `harness/TASK_LEDGER.md`, unless an eq
|
||||
It should distinguish:
|
||||
|
||||
### Goal and success criteria
|
||||
|
||||
What outcome must ultimately exist.
|
||||
|
||||
### Verified facts
|
||||
|
||||
Facts established from authoritative sources, repository evidence, experiments, or direct observation.
|
||||
|
||||
### Given facts
|
||||
|
||||
Requirements or constraints explicitly supplied by me.
|
||||
|
||||
### Assumptions
|
||||
|
||||
Things currently treated as true but not yet verified.
|
||||
|
||||
### Open questions
|
||||
|
||||
Important unknowns.
|
||||
|
||||
### Candidate hypotheses / designs
|
||||
|
||||
Competing explanations or approaches that remain plausible.
|
||||
|
||||
### Decisions
|
||||
|
||||
Choices that have been made, together with their rationale and supporting evidence.
|
||||
|
||||
### Current strategy
|
||||
|
||||
The current high-level route toward the goal.
|
||||
|
||||
Do not silently convert an assumption into a fact.
|
||||
@@ -179,6 +189,7 @@ Possible roles include:
|
||||
- integration reviewer.
|
||||
|
||||
Give every subagent:
|
||||
|
||||
- one bounded question or responsibility,
|
||||
- relevant context,
|
||||
- clear boundaries,
|
||||
@@ -215,15 +226,19 @@ For consequential, uncertain, difficult-to-reverse design problems, do not accep
|
||||
Use an idea-tournament process.
|
||||
|
||||
### Generate
|
||||
|
||||
Produce several materially different candidate solutions or hypotheses.
|
||||
|
||||
Aim for diversity rather than cosmetic variations of one idea.
|
||||
|
||||
### Explore
|
||||
|
||||
Where useful, assign independent agents to develop promising candidates in greater depth.
|
||||
|
||||
### Reflect
|
||||
|
||||
Have independent critics examine candidates for:
|
||||
|
||||
- correctness,
|
||||
- hidden assumptions,
|
||||
- internal consistency,
|
||||
@@ -238,6 +253,7 @@ Have independent critics examine candidates for:
|
||||
Critics should actively attempt to falsify proposals rather than merely improve them.
|
||||
|
||||
### Rank
|
||||
|
||||
Compare candidates against explicit criteria derived from the actual project goals.
|
||||
|
||||
Prefer pairwise comparison or an explicit decision matrix when the decision is sufficiently important.
|
||||
@@ -245,6 +261,7 @@ Prefer pairwise comparison or an explicit decision matrix when the decision is s
|
||||
Do not rank based on eloquence.
|
||||
|
||||
### Evolve
|
||||
|
||||
Improve the strongest candidates.
|
||||
|
||||
Combine complementary ideas when a hybrid is genuinely better.
|
||||
@@ -252,6 +269,7 @@ Combine complementary ideas when a hybrid is genuinely better.
|
||||
Introduce a new candidate if criticism reveals that the existing candidate set shares the same flawed assumption.
|
||||
|
||||
### Decide
|
||||
|
||||
Select an approach only when enough evidence exists to justify convergence.
|
||||
|
||||
Record the decision and why alternatives lost.
|
||||
@@ -456,6 +474,7 @@ Do not equate technical functionality with usability.
|
||||
Use independent reviewers throughout the project, but select reviewers according to the artifact being evaluated.
|
||||
|
||||
A conceptual or semantic design may need:
|
||||
|
||||
- domain review,
|
||||
- consistency review,
|
||||
- adversarial / falsification review,
|
||||
@@ -463,6 +482,7 @@ A conceptual or semantic design may need:
|
||||
- and user-workflow review.
|
||||
|
||||
A language may need:
|
||||
|
||||
- ambiguity review,
|
||||
- grammar / round-trip review,
|
||||
- human-editability review,
|
||||
@@ -470,6 +490,7 @@ A language may need:
|
||||
- and version-control review.
|
||||
|
||||
An implementation may need:
|
||||
|
||||
- correctness review,
|
||||
- architecture review,
|
||||
- requirements review,
|
||||
@@ -481,6 +502,7 @@ A final release should receive a cross-disciplinary review rather than only a co
|
||||
Require concrete findings and evidence.
|
||||
|
||||
For material findings:
|
||||
|
||||
1. verify the finding,
|
||||
2. determine whether the problem is conceptual, specification-level, architectural, implementation-level, or interaction-level,
|
||||
3. fix it at the correct layer,
|
||||
@@ -562,11 +584,11 @@ Do not automatically use maximum reasoning for every delegated task.
|
||||
|
||||
Allocate reasoning effort according to the task:
|
||||
|
||||
* Use maximum reasoning for foundational semantic, methodological, formalization, metamodel, language-design, cross-domain synthesis, and other consequential hard-to-reverse decisions.
|
||||
* Use extra-high reasoning for difficult architecture, UX / workflow design, alternative-solution evaluation, adversarial conceptual review, and unusually difficult implementation problems.
|
||||
* Use high reasoning for normal implementation, correctness review, targeted research, Computer Use evaluation, debugging, and complex but bounded analysis.
|
||||
* Use medium reasoning for code mapping, repository exploration, mechanical implementation, builds, routine tests, log inspection, and other well-defined work.
|
||||
* Use lower effort only for genuinely trivial mechanical tasks.
|
||||
- Use maximum reasoning for foundational semantic, methodological, formalization, metamodel, language-design, cross-domain synthesis, and other consequential hard-to-reverse decisions.
|
||||
- Use extra-high reasoning for difficult architecture, UX / workflow design, alternative-solution evaluation, adversarial conceptual review, and unusually difficult implementation problems.
|
||||
- Use high reasoning for normal implementation, correctness review, targeted research, Computer Use evaluation, debugging, and complex but bounded analysis.
|
||||
- Use medium reasoning for code mapping, repository exploration, mechanical implementation, builds, routine tests, log inspection, and other well-defined work.
|
||||
- Use lower effort only for genuinely trivial mechanical tasks.
|
||||
|
||||
Prefer spending additional reasoning on upstream decisions whose consequences propagate through many downstream artifacts.
|
||||
|
||||
@@ -578,12 +600,18 @@ Use GPT-6 Astra model exclusively.
|
||||
|
||||
## Application specification
|
||||
|
||||
Create a modern clone of ARCADIA Capella using Rust Iced framework. It should be cross platform (supporting Windows and Linux at least). Use Rust exclusively (wherever possible & practical). Focus on making the application modern, extensible, intuitive and easy to use. Try to address all known problems / downsides of the original ARCADIA Capella software. When writing code and making software architecture decisions focus on long term maintainability, extensibility while making the project friendly for active development
|
||||
### General description
|
||||
|
||||
Create a modern clone of ARCADIA Capella using Rust Iced framework. It should be cross platform (supporting Windows and Linux at least). Use Rust exclusively (wherever possible & practical).
|
||||
|
||||
Focus on making the application modern, extensible, intuitive and easy to use. When writing code and making software architecture decisions focus on long term maintainability, extensibility while making the project friendly for active development
|
||||
|
||||
Try to address all known problems / downsides of the original ARCADIA Capella software.
|
||||
|
||||
Version 1 MVP in the form of working Operational Analysis layer is done.
|
||||
Version 2 MVP in the form of working Operation Analysis + System Analysis is done.
|
||||
You should make the 1-st release version of the project with fully feature complete Operation Analysis + System Architecture, according to this application specification.
|
||||
And the remaining ARCADIA layers will be added in future releases.
|
||||
You should make the 1st release version of the project with fully feature complete Operation Analysis + System Architecture, according to this application specification.
|
||||
Remaining ARCADIA layers will be added in future releases.
|
||||
|
||||
Transitioning of model elements between layers (in both directions) should be easy and intuitive.
|
||||
|
||||
@@ -591,33 +619,52 @@ Keep in mind that the target audience for the application are system engineers.
|
||||
|
||||
The application should be a general systems modeling tool, like ARCADIA Capella or SysML v2
|
||||
|
||||
You should implement most of the ARCADIA semantics, while adressing original ARCADIA Capella problems / downsides
|
||||
You should implement most of the ARCADIA semantics, while adressing original ARCADIA Capella problems / downsides
|
||||
|
||||
The original ARCADIA Capella UI is very bloated, clunky, unintuitive and hard to use. In addition, it lacks a number of quality of life features. You should at all cost avoid making the same mistakes as the developers of the original ARCADIA Capella
|
||||
|
||||
You should explore the functionality & UI of the original ARCADIA Capella to take the most useful and powerful ideas from it. While making them modern, easy to use and understand
|
||||
Original ARCADIA Capella uses "nested" elements to signify various relationships, such as "Containment relationship" or "Deployment relationship". Instead of using visually noisy arrows / graph edges. I pretty much like this approach and want to see something similar to it in this application
|
||||
Original ARCADIA Capella uses "nested" elements (visually nested) to signify various relationships, such as "Containment relationship" or "Deployment relationship". Instead of using visually noisy arrows / graph edges. I pretty much like this approach and want to see something similar to it in this application
|
||||
|
||||
To explore the original ARCADIA Capella UI & semantics you may use web resources / web search / official and community docs. Or open the original ARCADIA Capella installed on this desktop machine for exploration
|
||||
|
||||
Your second, parallel goal is to create a textual representation for ARCADIA, similar to SysML v2. So a user can either edit a system model using UI (graphical representation) or text. Both graphical and textual representations should be fully equivalent and have full parity. You may take inspiration from SysML v2. Both graphical and textual representations should have one overarching, concrete, unambiguous spec in reST format, similar to SysML v2 strictness
|
||||
The application should support both forms of editing
|
||||
The textual representation should be easily editable and understandble for both humans and AI
|
||||
The textual representation should be easily handled by version control tools such as Git
|
||||
Your second, parallel, goal is to create a textual representation for ARCADIA, similar to SysML v2. So a user can either edit a system model using UI (graphical representation) or text. Both graphical and textual representations should be fully equivalent and have full parity. You may take inspiration from SysML v2. Both graphical and textual representations should have one overarching, concrete, unambiguous spec in reST format, similar to SysML v2 strictness
|
||||
The application should support both forms of editing
|
||||
The textual representation should be easily editable and understandble for both humans and AI
|
||||
The textual representation should be easily handled by version control tools such as Git
|
||||
The underlying semantics of the textual / graphical representation should support traceability of various development artifacts (for example - code, CAD files, electrical schematics, Docx files and anything in between)
|
||||
The textual representation editor should have syntax highlighting and linting
|
||||
|
||||
The project should also have a backend server / service that you can deploy. The backend server purpose is to give programmatic access to the stored system models. So, there also should be a clear REST API for querying, editing and working with models. The purpose of the REST API is to allow automation, scripting and AI-driven workflows
|
||||
An example could be - writing custom plugins for various domain specific software (version control software, CAD software etc...) to establish traceability between development artifacts and a system model
|
||||
The project should also have a backend server / service that you can deploy. The backend server purpose is to give programmatic access to stored system models. So, there also should be a clear REST API for querying, editing and working with models. The purpose of the REST API is to allow automation, scripting and AI-driven workflows
|
||||
An example could be - writing custom plugins for various domain specific software (version control software, CAD software etc...) to establish traceability between development artifacts and a system model
|
||||
|
||||
The desktop application should contain built-in guide / help / tutorial with clear and concise info on modeling concepts, underlying semantics, common modeling scenarios and application features / how to use the app. It should be easy to navigate and explore
|
||||
|
||||
@Computer
|
||||
@Computer
|
||||
|
||||
### Semantic model / metamodel
|
||||
|
||||
Requirements:
|
||||
|
||||
- Textual notation.
|
||||
- Graphical notation.
|
||||
- Constraints and calculations.
|
||||
- Quantities and units.
|
||||
- State and behavior modeling.
|
||||
- Reusable model libraries.
|
||||
- Strong, standardized specification.
|
||||
- Strong, standardized API.
|
||||
|
||||
### UI
|
||||
|
||||
The focus should be on reducing system engineer's cognitive load when creating / working with a system model. Regardless of the model size (big or small).
|
||||
|
||||
Long, homogeneous lists in the UI that require user to scroll far or search for a desired option for too long - is a bad design.
|
||||
|
||||
## Active issues / current guidance
|
||||
|
||||
Right now, the behavior & scenarios UI is hard to use. It contains static / uneditable diagrams, which is highly dubious. In addition, user workflow with the behavior & scenarios UI differ significantly from the other UIs - you can't edit diagrams and instead suppose to click on menus for model development
|
||||
Right now, the behavior & scenarios UI is hard to use. It contains static / uneditable diagrams, which is highly dubious. In addition, user workflow with the behavior & scenarios UI differ significantly from the other UIs - you can't edit diagrams and instead suppose to click on menus for model development
|
||||
|
||||
---
|
||||
---
|
||||
|
||||
The current project state is nowhere near the usability of the original ARCADIA Capella (despite its downfalls) or its functionality / semantics. You should focus on that by studying original ARCADIA Capella very closely and implementing its features in a modern, ergonomic and easy to use way
|
||||
The current project state is nowhere near the usability of the original ARCADIA Capella (despite its downfalls) or its functionality / semantics. You should focus on that by studying original ARCADIA Capella very closely and implementing its features in a modern, ergonomic and easy to use way
|
||||
@@ -7,6 +7,10 @@
|
||||
2. Independently reassess current behavior/scenario ergonomics and OA/SA semantic,
|
||||
source/API and documentation completeness. Resolve verified high-impact gaps
|
||||
with bounded changes and cross-representation acceptance criteria.
|
||||
The updated goal explicitly requires calculations, quantities/units and
|
||||
reusable model libraries. Audit actual semantics, compare coherent alternatives
|
||||
and establish observable acceptance before implementing foundational extensions.
|
||||
Correct concrete unbounded selectors without replacing existing useful search.
|
||||
3. Complete realistic graphical OA/SA teaching, transition, behavior, recovery and
|
||||
hosted workflows. Exercise minimum and wide layouts, rejected edits and history.
|
||||
4. Run current Windows/Linux automated and native acceptance, fresh independent
|
||||
|
||||
+56
-6
@@ -2,7 +2,10 @@
|
||||
|
||||
## Active continuation — 2026-09-10
|
||||
|
||||
The renewed user request is preserved in `PROJECT_GOAL.md`. Root is integrating
|
||||
The updated user goal from attachment `2f1f0002-e43c-45ba-80a8-b359f05f99d0`
|
||||
was read in full and copied exactly to `PROJECT_GOAL.md` on 2026-09-10. It now
|
||||
explicitly requires calculations, quantities/units and reusable model libraries,
|
||||
and rejects long homogeneous choice lists. Root is integrating
|
||||
the first release, prioritizing direct diagram authoring and behavior/scenario
|
||||
usability. The checkout began clean at `1797516` on `codex/release1-continuation`.
|
||||
Gitea issue #1 and Wiki Home were read; ownership and progress are coordinated there.
|
||||
@@ -14,7 +17,7 @@ Gitea issue #1 and Wiki Home were read; ownership and progress are coordinated t
|
||||
build. Earlier 584-test evidence does not cover those corrections.
|
||||
- This checkout began without the historical `.local` toolchain/cache/packages.
|
||||
Project-local Rust/Cargo 1.98.1 GNU/LLVM and verified LLVM-MinGW 20260908
|
||||
(clang 23.1.1) are installed. Locked dependencies are being fetched.
|
||||
(clang 23.1.1) are installed. Windows desktop dependencies are compiling.
|
||||
Host: four logical processors, 8 GiB RAM; builds remain serialized.
|
||||
- Computer Use initialized successfully. The renewed request authorizes native
|
||||
evaluation; old session Escape holds and process IDs are historical. No Arcadia
|
||||
@@ -48,7 +51,8 @@ Implemented locally, awaiting compilation:
|
||||
recovery and source/history. Core validation remains authoritative.
|
||||
- Normative catalogs now include ExchangeCategory, ContextualLink and both
|
||||
Exchange trace pairs. Manual trace help and scope source version corrected;
|
||||
strict Docutils 0.22.2 HTML regeneration passed.
|
||||
strict Docutils 0.22.2 HTML regeneration passed. OpenAPI `semantic_schema.py
|
||||
--check --validate` passed 72 fixtures and all 204 component schemas.
|
||||
|
||||
Reference evidence: actual Capella 7.1 scenario/lifeline/LOOP creation and saved
|
||||
XML are recorded in `release-capella-scenario-benchmark-20260910.md`; the isolated
|
||||
@@ -59,8 +63,9 @@ LLVM-MinGW 20260908 ZIP SHA256
|
||||
`1bcf74d06b724aeecaa6412ca85f5b26fb1da770e7cdcefa9263c9c5c3ad34b6`, extracted
|
||||
successfully; stable **1.98.1** GNU/LLVM, rustfmt and Clippy installed.
|
||||
`.local/toolchain/env.ps1` configures task-local Cargo/Rustup/PATH and one build
|
||||
job. Locked dependency fetch is local exec session **13108**. No build/test pass
|
||||
is established; the target cache is still cold.
|
||||
job. The original full-platform dependency fetch **13108** was stopped after
|
||||
network timeouts; Windows-only compilation fetched its remaining dependencies.
|
||||
No current Rust build/test pass is established yet.
|
||||
|
||||
The coherent candidate `01bb52a` passed `cargo fmt --all` and `git diff --check`.
|
||||
Direct push failed because this fresh host has no Git credentials. Authenticated
|
||||
@@ -73,7 +78,9 @@ transfer is not acceptance. Their broader architecture
|
||||
palette/Escape repair should be reconciled with our overlapping compile/stale
|
||||
repairs while retaining the additional invariant tests. Their measured minimum
|
||||
scenario canvas is too small; they own the subsequent layout implementation.
|
||||
Their isolated palette commit is `7d1df4f`, fetched locally for reconciliation.
|
||||
Their isolated palette commit `7d1df4f` was cherry-picked cleanly as `aed40d7`.
|
||||
Our additional authoring tests and scenario handlers are retained. External
|
||||
native/test results remain scoped to their exact source and executable.
|
||||
|
||||
Independent F1 review found a real optional-value cache collision in `01bb52a`.
|
||||
The follow-up distinguishes null/scalar/list/tagged constructor identities and
|
||||
@@ -82,6 +89,49 @@ remaining collision; execution is still pending. The original full-platform
|
||||
fetch was stopped after network timeouts; current Windows desktop test build
|
||||
is exec session **51036**, compiling dependencies. Root owns this Cargo lease.
|
||||
|
||||
Commit `eb5161b` adds the pure B4 lifecycle projection, ten admitted-fixture
|
||||
tests and current scenario/history guide wording. The module is declared only
|
||||
under `cfg(test)` pending coordinated Scene integration after the other host's
|
||||
scenario workspace refactor. Independent source reviews found no confirmed B3
|
||||
navigation or B4 projection blocker; synthetic geometry tests do not establish
|
||||
actual Scene/marker/hit-test acceptance. No new Studio binary has launched here.
|
||||
|
||||
Latest transfer: `harness/transfers/behavior-eb5161b.bundle.b64` on the transfer
|
||||
branch, decoded 91,268 bytes, SHA256
|
||||
`87F3FBA862AE3751E60E18B39C7BB02B147E4E66079F501050A709D8ADDADE6D`.
|
||||
Full MCP readback matched local bytes. It contains all four local commits from
|
||||
`1797516`; the other host can cherry-pick `b6b76ef` and `eb5161b` onto its existing
|
||||
integration. Gitea #65 records exact handoff and the Wiki title-encoding problem.
|
||||
Root is preparing an independent native scenario fixture/oracle through the
|
||||
release auditor; only harness/scenario-authoring-contract.rs and its README are
|
||||
owned by that worker. Generated fixtures require a later direct-rustc lease.
|
||||
|
||||
Actual cross-host test evidence supersedes source-only confidence: the other
|
||||
host's immutable pre-`b6b76ef` integrated artifact ran 618 tests, with 615 passing
|
||||
and three failures (Gitea #68). One B3 deleted/changed-caller regression is being
|
||||
diagnosed by their scenario/layout owner. Two F1 failures came from seeding
|
||||
optional UUID/text as `NotApplicable` via broad string-shape matching. Local
|
||||
`4ecad78` now recognizes only an explicit enum constructor and adds the nullable
|
||||
UUID/text regression; independent descriptor review clears it for execution.
|
||||
No assertion was weakened. Thirteen history tests now await local execution.
|
||||
Incremental transfer `behavior-4ecad78.bundle.b64` requires `eb5161b`, decoded
|
||||
1,464 bytes, SHA256
|
||||
`3A93A99AB9C727A4B685D7436C9E23FB262144580E8524623B75D2D676FDF033`.
|
||||
Exact local and MCP readback checks pass; Gitea #76 requests warm-host reruns.
|
||||
|
||||
The native scenario oracle now requires both independently predicted semantic
|
||||
checkpoint equality and exact saved/restored Project+SourceBundle identity.
|
||||
Independent review caught that rediscovering fresh role IDs at each checkpoint
|
||||
alone could falsely accept recreated IDs on Redo; `same` and its adversarial
|
||||
self-check close that evaluator gap. It remains uncompiled/unexecuted.
|
||||
|
||||
Fresh `requirements_delta` owns only its new audit report. Early source evidence
|
||||
shows constraints are explicitly unexecuted expressions and units are strings
|
||||
without dimensional conversion; the newly explicit calculation/quantity goals
|
||||
must not be declared complete from this metadata. Reusable library contracts
|
||||
and concrete unbounded selectors are under domain/requirements review before
|
||||
foundational design decisions. Current behavior/native work remains useful.
|
||||
|
||||
Next: focused `architecture_authoring_tests`,
|
||||
`behavior::topology`, `direct_clicked`, caller-navigation and `history_fields::tests`,
|
||||
then full relevant gates and a fresh native binary. Root owns all Cargo on this
|
||||
|
||||
@@ -8,6 +8,12 @@ Graphical/source/REST parity, explicit reST semantics, traceability, offline
|
||||
guidance, Windows/Linux acceptance and independent review remain required.
|
||||
Older scope deferrals must be checked against this request.
|
||||
|
||||
Updated given requirements (2026-09-10 goal edit): calculations, quantities and
|
||||
units, reusable model libraries, and avoiding long homogeneous selection lists
|
||||
are explicit. `PROJECT_GOAL.md` preserves the exact new attachment. A fresh
|
||||
independent domain audit maps them to actual behavior before design convergence;
|
||||
unexecuted constraints and unit strings alone are not assumed to satisfy them.
|
||||
|
||||
Verified: the checkout began clean at `1797516`; Gitea contains one active
|
||||
continuation issue and no open PR. Current code includes direct behavior editors,
|
||||
so old blanket descriptions of static diagrams need workflow-level reassessment.
|
||||
|
||||
@@ -0,0 +1,96 @@
|
||||
# Scenario authoring native contract
|
||||
|
||||
Prepared by Codex-956atf /root/release_audit on 2026-09-10. **Source candidate only: compilation, self-check, generation and native execution have not run.** This fixture/oracle is preparation for B2 clicked-slot authoring and B3 caller return, not acceptance evidence.
|
||||
|
||||
`harness/scenario-authoring-contract.rs` generates deterministic OA and SA versions of the same small scenario tree. Each has Activity/Function choices, a Ready state, explicit lifelines, two nested ALT fragments, and fixed root/operand insertion anchors. A caller contains two distinct uses of B verification; B uses C detail. Each use explicitly maps both referenced lifelines to distinct local lifelines representing the same work. No native action/state/reuse/fragment role exists in the baseline.
|
||||
|
||||
Only this new Rust source and this README belong to the preparation slice. Generate fixture files after root grants the direct-rustc lease and the checker self-check passes.
|
||||
|
||||
## Compile and generate
|
||||
|
||||
Use the current matching `oa_core` and `serde_json` rlibs from root's accepted Cargo output. Do not build another Cargo tree or select an arbitrary stale rlib. With root's configured Rust environment and clang linker, substitute the exact recorded paths below:
|
||||
|
||||
```powershell
|
||||
. .local/toolchain/env.ps1
|
||||
$scenarioCore = 'ABSOLUTE_PATH_TO_CURRENT_liboa_core-HASH.rlib'
|
||||
$scenarioJson = 'ABSOLUTE_PATH_TO_MATCHING_libserde_json-HASH.rlib'
|
||||
$scenarioDeps = Split-Path -LiteralPath $scenarioCore -Parent
|
||||
$scenarioLinker = 'ABSOLUTE_PATH_TO_TOOLCHAIN_clang.exe'
|
||||
New-Item -ItemType Directory -Force -Path .local/native-qa | Out-Null
|
||||
rustc --edition 2024 -D warnings harness/scenario-authoring-contract.rs --extern "oa_core=$scenarioCore" --extern "serde_json=$scenarioJson" -L "dependency=$scenarioDeps" -C "linker=$scenarioLinker" -o .local/native-qa/scenario-authoring-contract.exe
|
||||
.local/native-qa/scenario-authoring-contract.exe self-check
|
||||
.local/native-qa/scenario-authoring-contract.exe generate harness/fixtures/scenario-authoring/base
|
||||
.local/native-qa/scenario-authoring-contract.exe check baseline harness/fixtures/scenario-authoring/base/project.arcadia
|
||||
```
|
||||
|
||||
The compiler target must match those rlibs; include root's explicit `--target` if its toolchain setup requires one. Record the exact command, compiler/rlib identities, checker hash and result. Generation refuses any existing output directory. It writes `project.arcadia`, an included Unicode/CRLF `rationale.arcadia`, and `expected-baseline.json`. The JSON is a reference artifact, not an additional source document.
|
||||
|
||||
Copy the **whole** generated base into separate fresh OA and SA native working directories. Preserve the base. Each layer's four checkpoints start from that same baseline; `sa-action` does not include the OA creations. Preserve the whole working directory after each declared Save/Undo/Redo checkpoint. Do not modify fixture sources or adjust expected fields to match observed output.
|
||||
|
||||
## Fixed locations and choices
|
||||
|
||||
The UUID namespace is `5ceaa100-0000-4000-8000-000000000000` plus a deterministic integer. Stable aliases make the intended records easy to confirm in the inspector/source. All labels below have `OA ` or `SA ` prepended.
|
||||
|
||||
| Role | OA alias / UUID suffix | SA alias / UUID suffix |
|
||||
| --- | --- | --- |
|
||||
| A caller | `scenario_oa_30` / `000000000082` | `scenario_sa_30` / `0000000000e6` |
|
||||
| B verification | `scenario_oa_31` / `000000000083` | `scenario_sa_31` / `0000000000e7` |
|
||||
| C detail | `scenario_oa_32` / `000000000084` | `scenario_sa_32` / `0000000000e8` |
|
||||
| Inner chosen operand | `scenario_oa_55` / `00000000009b` | `scenario_sa_55` / `0000000000ff` |
|
||||
| Inner anchor | `scenario_oa_57` / `00000000009d` | `scenario_sa_57` / `000000000101` |
|
||||
| Root entry / Root exit | `scenario_oa_50` / `scenario_oa_62` | `scenario_sa_50` / `scenario_sa_62` |
|
||||
| First use of B / Second use of B | `scenario_oa_60` / `scenario_oa_61` | `scenario_sa_60` / `scenario_sa_61` |
|
||||
| B use of C | `scenario_oa_64` | `scenario_sa_64` |
|
||||
|
||||
The target operand is **Outer ALT → Outer chosen operand → Inner ALT → Inner chosen operand**. The other inner operand and outer fallback are deliberate nearby decoys. Every sibling's records and order must remain unchanged.
|
||||
|
||||
## B3 navigation before editing
|
||||
|
||||
Open `project.arcadia`, select **OA A caller**, and open **Behavior**. At normal size and at 1100 × 700, record the actual diagram visibility, selected occurrence, selected tool, canvas scroll and outer page scroll. Native screenshots and observations must establish these UI properties; the source checker cannot observe them.
|
||||
|
||||
1. Select **OA Second use of B**, then **Open definition**. In **OA B verification**, select **OA B use of C** and open its definition. **Back to caller** must return first to the exact B use, then to the exact **Second use of B** in A, retaining the caller's tool and canvas/page offsets subject to viewport clamping. The first use is a distinct occurrence, not an interchangeable return address.
|
||||
2. Repeat through **OA First use of B**. Also exercise the detailed-list **Open OA B verification →** action for one of those uses; it must retain that initiating occurrence. After Back, ordinary scrolling must continue naturally rather than snapping repeatedly to the restored offset.
|
||||
3. Save without edits and run `check baseline ENTRY`. There must be no new model Undo entry from navigation. Repeat the two-use return once in **SA A caller**. No new model or source checkpoint is needed: both layers still equal baseline.
|
||||
|
||||
For one blocked navigation case, arm Add action, click a valid slot and type `unfinished native action` without creating it. Attempt Open/Back only if those controls are reachable in that pending state. The draft must remain visible/recoverable or the navigation control must be unavailable. Cancel, Save, and check baseline. Record the actual control availability; do not count an unperformed attempt as a pass.
|
||||
|
||||
## B2 four creations per layer
|
||||
|
||||
Run the same four steps on the separate OA and SA copies. Replace `XX` below with the literal `OA` or `SA`, and lowercase `xx` in checker modes. Select **XX A caller → Behavior**. The compact selector's currently authored labels are **Add action**, **Observe state**, **Reuse scenario**, and **Add fragment**. Choose the tool and click the prescribed visible insertion slot; do not substitute a Tools append action or repair the destination afterward through the inspector.
|
||||
|
||||
Before pressing Create, record the form's destination/before-slot label and selected lifeline. This observation proves which native gesture was performed. Full model/source equality then checks the resulting semantics independently.
|
||||
|
||||
| Step / checkpoint | Prescribed click and literal form values | Expected insertion |
|
||||
| --- | --- | --- |
|
||||
| 1. `xx-action` | **Add action**; click on **XX A inspector** at the root slot before **XX Root entry**. Name `XX native action`; work **XX Inspect ticket**; observed lifeline **XX A inspector**. Create. | New Action is the first A root step, before the original root entry. |
|
||||
| 2. `xx-state` | **Observe state**; click in **Inner chosen operand** before **XX Inner anchor**, on **XX A inspector**. Name `XX native state`; state **XX Ready**; observed lifeline **XX A inspector**. Create. | The inner chosen operand becomes `[native state, Inner anchor]`. Both enclosing ALT structures retain their original identities/guards. |
|
||||
| 3. `xx-reuse` | **Reuse scenario**; click in that same inner operand before **XX Inner anchor**. Name `XX native reuse`; definition **XX B verification**. Explicitly bind **XX B inspector → XX A inspector** and **XX B recorder → XX A recorder**. Create. | Inner operand becomes `[native state, native reuse, Inner anchor]`. No scenario/lifeline definition is cloned. |
|
||||
| 4. `xx-fragment` | **Add fragment**; click the root slot before **XX Root exit**. Name `XX native alternative`; operator **ALT · alternatives**; first guard `ticket.priority > 2`; second guard `ticket.priority <= 2`. Create. | One new root Fragment followed by the original Root exit. Its two new operands are empty and named `XX native alternative · operand 1` and `XX native alternative · operand 2`. Existing occurrences are not wrapped or moved into them. |
|
||||
|
||||
Before each Create, retain the previously verified stage's whole-directory snapshot (the generated baseline for step 1). After Create: Save, preserve a new whole-directory snapshot and check the declared checkpoint. Undo once, Save and preserve another copy: check the preceding checkpoint **and require `same PREVIOUS_VERIFIED_ENTRY UNDO_ENTRY`**. Redo once, Save and preserve another copy: check the current checkpoint **and require `same CURRENT_VERIFIED_ENTRY REDO_ENTRY`**. The `same` mode compares every Project identity/field and every SourceBundle byte; rerunning a semantic checkpoint alone permits a new set of fresh UUIDs and cannot prove exact history restoration. Never replace the preserved verified snapshots with their restored copies.
|
||||
|
||||
In particular, a fragment's creation and both operands must disappear/reappear in one Undo/Redo step with their original IDs. Reopen the final saved entry, Save and preserve the reopened copy, check `xx-fragment`, and require `same FINAL_VERIFIED_ENTRY REOPENED_ENTRY`. Use the normal Save operation in the working directory; save copies by preserving the whole directory so the included source stays attached.
|
||||
|
||||
Example checks for an OA run:
|
||||
|
||||
```powershell
|
||||
.local/native-qa/scenario-authoring-contract.exe check oa-action PATH_TO_SAVED_project.arcadia
|
||||
.local/native-qa/scenario-authoring-contract.exe check baseline PATH_TO_ACTION_UNDO_project.arcadia
|
||||
.local/native-qa/scenario-authoring-contract.exe same PATH_TO_VERIFIED_BASELINE_project.arcadia PATH_TO_ACTION_UNDO_project.arcadia
|
||||
.local/native-qa/scenario-authoring-contract.exe check oa-action PATH_TO_ACTION_REDO_project.arcadia
|
||||
.local/native-qa/scenario-authoring-contract.exe same PATH_TO_VERIFIED_ACTION_project.arcadia PATH_TO_ACTION_REDO_project.arcadia
|
||||
.local/native-qa/scenario-authoring-contract.exe check oa-state PATH_TO_SAVED_project.arcadia
|
||||
.local/native-qa/scenario-authoring-contract.exe check oa-reuse PATH_TO_SAVED_project.arcadia
|
||||
.local/native-qa/scenario-authoring-contract.exe check oa-fragment PATH_TO_REOPENED_project.arcadia
|
||||
.local/native-qa/scenario-authoring-contract.exe same PATH_TO_VERIFIED_FRAGMENT_project.arcadia PATH_TO_REOPENED_project.arcadia
|
||||
```
|
||||
|
||||
One cancellation can be inserted before step 1: arm Observe state and click away from a lifeline. The form must require an explicit observed lifeline; it must not silently choose an unrelated lane. Enter an incomplete name, use the form's **Cancel** control, Save, and check baseline. Exercise Escape separately: current behavior cancels the gesture while preserving the pending scenario form/raw draft; it is not form cancellation. Focus, pending-marker visibility, stable canvas origin, Escape delivery, minimum-size reachability and clicked-slot geometry require separate native observations. Do not infer those from a passing file check.
|
||||
|
||||
## Independence and limits
|
||||
|
||||
The checker uses only unique **Kind::Occurrence + layer + predetermined literal name** roles to discover fresh UUIDv4 IDs. IDs must be distinct and absent from the deterministic baseline. It independently constructs every other field: body, parent, reference targets, binding order and identities, guards, empty operands, pre/postconditions, description, alias and insertion order. It does not read observed fields into the prediction. Any unclaimed object, sibling edit, wrong destination, binding, name/value or source byte causes full equality to fail.
|
||||
|
||||
Expected transactions use core typed commands and source writeback, independently of the desktop planners, then compare the whole Project and the complete reachable two-file SourceBundle. The source oracle deliberately shares the core language engine; this fixture validates native GUI-to-model/source parity rather than supplying an independent language implementation. Semantic checkpoint checks plus required exact saved/restored snapshot comparisons prove state and identity restoration only for the captured Undo/Redo/reopen sequence, not arbitrary history internals.
|
||||
|
||||
The self-check covers deterministic seeds, all eight OA/SA checkpoint fixed points, carriers with deliberately false parent/body/alias/description, rejected unrelated edits, wrong insertion order/parent/bindings, and a model-neutral change to the retained note. It also constructs two equivalent valid checkpoints with different fresh action IDs: each passes semantic prediction, while exact `same` snapshot comparison rejects their identity difference. It is not a native UI test. Current compile, self-check, generation, native action/return/scroll/recovery, screenshot and release evidence remain pending until recorded by root.
|
||||
@@ -0,0 +1,672 @@
|
||||
//! Independent B2/B3 native fixture; no desktop implementation is linked.
|
||||
//! generate DIR | check CHECKPOINT ENTRY | same VERIFIED_ENTRY RESTORED_ENTRY | self-check
|
||||
use oa_core::{source_project::*, *};
|
||||
use std::{
|
||||
collections::{BTreeMap, BTreeSet},
|
||||
fs,
|
||||
path::Path,
|
||||
};
|
||||
|
||||
fn id(n: u128) -> Id {
|
||||
Id::from_u128(0x5ceaa100000040008000000000000000 + n)
|
||||
}
|
||||
#[derive(Clone, Copy)]
|
||||
struct Side {
|
||||
layer: Layer,
|
||||
word: &'static str,
|
||||
base: u128,
|
||||
}
|
||||
const SIDES: [Side; 2] = [
|
||||
Side {
|
||||
layer: Layer::Oa,
|
||||
word: "OA",
|
||||
base: 100,
|
||||
},
|
||||
Side {
|
||||
layer: Layer::Sa,
|
||||
word: "SA",
|
||||
base: 200,
|
||||
},
|
||||
];
|
||||
impl Side {
|
||||
fn id(self, n: u128) -> Id {
|
||||
id(self.base + n)
|
||||
}
|
||||
fn name(self, text: &str) -> String {
|
||||
format!("{} {text}", self.word)
|
||||
}
|
||||
}
|
||||
fn seed(p: &mut Project, side: Side, n: u128, kind: Kind, text: &str, parent: Option<Id>) {
|
||||
let mut element = p
|
||||
.make_element(kind, side.layer, &side.name(text), parent)
|
||||
.unwrap();
|
||||
element.id = side.id(n);
|
||||
element.alias = format!("scenario_{}_{}", side.word.to_lowercase(), n);
|
||||
p.elements.insert(element.id, element);
|
||||
}
|
||||
fn seed_occurrence(
|
||||
p: &mut Project,
|
||||
side: Side,
|
||||
n: u128,
|
||||
text: &str,
|
||||
parent: u128,
|
||||
body: OccurrenceBody,
|
||||
) {
|
||||
seed(p, side, n, Kind::Occurrence, text, Some(side.id(parent)));
|
||||
*p.elements
|
||||
.get_mut(&side.id(n))
|
||||
.unwrap()
|
||||
.shared_mut()
|
||||
.unwrap() = SharedBody::Occurrence {
|
||||
body,
|
||||
precondition: String::new(),
|
||||
postcondition: String::new(),
|
||||
};
|
||||
}
|
||||
fn action(side: Side, work: u128, line: u128) -> OccurrenceBody {
|
||||
OccurrenceBody::Action {
|
||||
action: Some(side.id(work)),
|
||||
lifeline: Some(side.id(line)),
|
||||
}
|
||||
}
|
||||
fn reuse(side: Side, target: u128, remote: [u128; 2], local: [u128; 2]) -> OccurrenceBody {
|
||||
OccurrenceBody::ScenarioUse {
|
||||
scenario: Some(side.id(target)),
|
||||
bindings: remote
|
||||
.into_iter()
|
||||
.zip(local)
|
||||
.map(|(referenced, local)| LifelineBinding {
|
||||
referenced: side.id(referenced),
|
||||
local: side.id(local),
|
||||
})
|
||||
.collect(),
|
||||
}
|
||||
}
|
||||
fn fixture() -> Project {
|
||||
let mut p = Project::empty();
|
||||
p.id = id(1);
|
||||
p.alias = "scenario_authoring".into();
|
||||
p.name = "Scenario authoring contract".into();
|
||||
p.description = "Native clicked-slot and caller-return contract.".into();
|
||||
for side in SIDES {
|
||||
let work = if side.layer == Layer::Oa {
|
||||
Kind::Activity
|
||||
} else {
|
||||
Kind::Function
|
||||
};
|
||||
seed(&mut p, side, 10, work, "Inspect ticket", None);
|
||||
seed(&mut p, side, 11, work, "Record result", None);
|
||||
seed(&mut p, side, 20, Kind::StateMachine, "Ticket modes", None);
|
||||
seed(
|
||||
&mut p,
|
||||
side,
|
||||
21,
|
||||
Kind::Region,
|
||||
"Ticket region",
|
||||
Some(side.id(20)),
|
||||
);
|
||||
seed(&mut p, side, 22, Kind::State, "Ready", Some(side.id(21)));
|
||||
for (n, text) in [(30, "A caller"), (31, "B verification"), (32, "C detail")] {
|
||||
seed(&mut p, side, n, Kind::Scenario, text, None);
|
||||
}
|
||||
for (n, owner, represented, text) in [
|
||||
(40, 30, 10, "A inspector"),
|
||||
(41, 30, 11, "A recorder"),
|
||||
(42, 31, 10, "B inspector"),
|
||||
(43, 31, 11, "B recorder"),
|
||||
(44, 32, 10, "C inspector"),
|
||||
(45, 32, 11, "C recorder"),
|
||||
] {
|
||||
seed(&mut p, side, n, Kind::Lifeline, text, Some(side.id(owner)));
|
||||
*p.elements
|
||||
.get_mut(&side.id(n))
|
||||
.unwrap()
|
||||
.shared_mut()
|
||||
.unwrap() = SharedBody::Lifeline {
|
||||
represented: Some(side.id(represented)),
|
||||
};
|
||||
}
|
||||
seed_occurrence(&mut p, side, 50, "Root entry", 30, action(side, 10, 40));
|
||||
seed_occurrence(
|
||||
&mut p,
|
||||
side,
|
||||
51,
|
||||
"Outer ALT",
|
||||
30,
|
||||
OccurrenceBody::Fragment {
|
||||
operator: FragmentOperator::Alternative,
|
||||
branches: vec![side.id(52), side.id(53)],
|
||||
},
|
||||
);
|
||||
seed_occurrence(
|
||||
&mut p,
|
||||
side,
|
||||
52,
|
||||
"Outer chosen operand",
|
||||
51,
|
||||
OccurrenceBody::Branch {
|
||||
guard: "ticket.present".into(),
|
||||
occurrences: vec![side.id(54)],
|
||||
},
|
||||
);
|
||||
seed_occurrence(
|
||||
&mut p,
|
||||
side,
|
||||
53,
|
||||
"Outer fallback operand",
|
||||
51,
|
||||
OccurrenceBody::Branch {
|
||||
guard: "else".into(),
|
||||
occurrences: vec![side.id(59)],
|
||||
},
|
||||
);
|
||||
seed_occurrence(
|
||||
&mut p,
|
||||
side,
|
||||
54,
|
||||
"Inner ALT",
|
||||
52,
|
||||
OccurrenceBody::Fragment {
|
||||
operator: FragmentOperator::Alternative,
|
||||
branches: vec![side.id(55), side.id(56)],
|
||||
},
|
||||
);
|
||||
seed_occurrence(
|
||||
&mut p,
|
||||
side,
|
||||
55,
|
||||
"Inner chosen operand",
|
||||
54,
|
||||
OccurrenceBody::Branch {
|
||||
guard: "ticket.ready".into(),
|
||||
occurrences: vec![side.id(57)],
|
||||
},
|
||||
);
|
||||
seed_occurrence(
|
||||
&mut p,
|
||||
side,
|
||||
56,
|
||||
"Inner other operand",
|
||||
54,
|
||||
OccurrenceBody::Branch {
|
||||
guard: "else".into(),
|
||||
occurrences: vec![side.id(58)],
|
||||
},
|
||||
);
|
||||
for (n, text, parent, line) in [
|
||||
(57, "Inner anchor", 55, 40),
|
||||
(58, "Inner other anchor", 56, 40),
|
||||
(59, "Fallback anchor", 53, 41),
|
||||
(62, "Root exit", 30, 41),
|
||||
(63, "B entry", 31, 42),
|
||||
(65, "B exit", 31, 43),
|
||||
(66, "C entry", 32, 44),
|
||||
] {
|
||||
seed_occurrence(
|
||||
&mut p,
|
||||
side,
|
||||
n,
|
||||
text,
|
||||
parent,
|
||||
action(side, if line % 2 == 0 { 10 } else { 11 }, line),
|
||||
);
|
||||
}
|
||||
seed_occurrence(
|
||||
&mut p,
|
||||
side,
|
||||
60,
|
||||
"First use of B",
|
||||
30,
|
||||
reuse(side, 31, [42, 43], [40, 41]),
|
||||
);
|
||||
seed_occurrence(
|
||||
&mut p,
|
||||
side,
|
||||
61,
|
||||
"Second use of B",
|
||||
30,
|
||||
reuse(side, 31, [42, 43], [40, 41]),
|
||||
);
|
||||
seed_occurrence(
|
||||
&mut p,
|
||||
side,
|
||||
64,
|
||||
"B use of C",
|
||||
31,
|
||||
reuse(side, 32, [44, 45], [42, 43]),
|
||||
);
|
||||
for (owner, steps) in [
|
||||
(30, vec![50, 51, 60, 61, 62]),
|
||||
(31, vec![63, 64, 65]),
|
||||
(32, vec![66]),
|
||||
] {
|
||||
*p.elements
|
||||
.get_mut(&side.id(owner))
|
||||
.unwrap()
|
||||
.steps_mut()
|
||||
.unwrap() = steps.into_iter().map(|n| side.id(n)).collect();
|
||||
}
|
||||
}
|
||||
execute_batch(&p, &[]).expect("deterministic fixture must satisfy core admission")
|
||||
}
|
||||
fn bundle(p: &Project) -> CompiledSourceProject {
|
||||
let entry = language::format(p).replacen("{\n", "{\n include \"rationale.arcadia\";\n", 1);
|
||||
let raw = SourceBundle {
|
||||
entry: "project.arcadia".into(),
|
||||
files: BTreeMap::from([
|
||||
("project.arcadia".into(), entry),
|
||||
("rationale.arcadia".into(), "// Retain caller/operand evidence: ticket 雨.\r\n// Navigation never edits this note.\r\n".into()),
|
||||
]),
|
||||
};
|
||||
let compiled = compile_bundle(&raw, ProjectLimits::default()).unwrap();
|
||||
assert_eq!(compiled.decoded.project, *p);
|
||||
assert_eq!(compiled.bundle, raw);
|
||||
compiled
|
||||
}
|
||||
fn load(entry: &Path) -> CompiledSourceProject {
|
||||
let files = source_files::load_project(entry, ProjectLimits::default()).unwrap();
|
||||
let raw = files.reachable_bundle();
|
||||
let compiled = compile_bundle(&raw, ProjectLimits::default()).unwrap();
|
||||
assert_eq!(
|
||||
compiled.bundle, raw,
|
||||
"No migration or source normalization permitted"
|
||||
);
|
||||
execute_batch(&compiled.decoded.project, &[]).unwrap();
|
||||
compiled
|
||||
}
|
||||
fn advance(base: &mut CompiledSourceProject, commands: Vec<Command>) {
|
||||
let expected = execute_batch(&base.decoded.project, &[Command::Batch(commands)]).unwrap();
|
||||
*base = update_bundle(base, &expected, ProjectLimits::default()).unwrap();
|
||||
}
|
||||
struct Roles<'a> {
|
||||
actual: &'a Project,
|
||||
baseline: Project,
|
||||
used: BTreeSet<Id>,
|
||||
}
|
||||
impl Roles<'_> {
|
||||
fn occurrence(&mut self, side: Side, text: &str) -> Id {
|
||||
let name = side.name(text);
|
||||
let found: Vec<_> = self
|
||||
.actual
|
||||
.elements
|
||||
.values()
|
||||
.filter(|e| e.kind() == Kind::Occurrence && e.layer() == side.layer && e.name == name)
|
||||
.map(|e| e.id)
|
||||
.collect();
|
||||
assert_eq!(
|
||||
found.len(),
|
||||
1,
|
||||
"Exactly one fresh occurrence for role {name}"
|
||||
);
|
||||
let id = found[0];
|
||||
assert_eq!(
|
||||
id.get_version_num(),
|
||||
4,
|
||||
"Native occurrence needs UUIDv4: {name}"
|
||||
);
|
||||
assert!(!self.baseline.contains(id), "Role reused a seed: {name}");
|
||||
assert!(
|
||||
self.used.insert(id),
|
||||
"Role identities must be distinct: {name}"
|
||||
);
|
||||
id
|
||||
}
|
||||
}
|
||||
fn authored(
|
||||
p: &Project,
|
||||
side: Side,
|
||||
id: Id,
|
||||
text: &str,
|
||||
parent: Id,
|
||||
body: OccurrenceBody,
|
||||
) -> Element {
|
||||
let name = side.name(text);
|
||||
Element {
|
||||
id,
|
||||
alias: p.fresh_alias(&name, "element", id),
|
||||
name,
|
||||
description: String::new(),
|
||||
parent: Some(parent),
|
||||
body: ElementBody::shared_in(
|
||||
side.layer,
|
||||
SharedBody::Occurrence {
|
||||
body,
|
||||
precondition: String::new(),
|
||||
postcondition: String::new(),
|
||||
},
|
||||
),
|
||||
}
|
||||
}
|
||||
fn insert_before(base: &mut CompiledSourceProject, parent: Id, anchor: Id, elements: Vec<Element>) {
|
||||
let mut steps = base.decoded.project.elements[&parent]
|
||||
.steps()
|
||||
.unwrap()
|
||||
.clone();
|
||||
let position = steps
|
||||
.iter()
|
||||
.position(|id| *id == anchor)
|
||||
.expect("declared insertion anchor");
|
||||
let inserted: Vec<_> = elements
|
||||
.iter()
|
||||
.filter(|e| e.parent == Some(parent))
|
||||
.map(|e| e.id)
|
||||
.collect();
|
||||
steps.splice(position..position, inserted);
|
||||
let mut commands: Vec<_> = elements.into_iter().map(Command::CreateElement).collect();
|
||||
commands.push(Command::SetSteps(parent, steps));
|
||||
advance(base, commands);
|
||||
}
|
||||
fn checkpoint(mode: &str) -> Option<(Side, usize)> {
|
||||
if mode == "baseline" {
|
||||
return None;
|
||||
}
|
||||
let (prefix, stage) = mode
|
||||
.split_once('-')
|
||||
.expect("checkpoint is baseline or oa/sa-stage");
|
||||
let side = match prefix {
|
||||
"oa" => SIDES[0],
|
||||
"sa" => SIDES[1],
|
||||
_ => panic!("Unknown layer"),
|
||||
};
|
||||
let count = match stage {
|
||||
"action" => 1,
|
||||
"state" => 2,
|
||||
"reuse" => 3,
|
||||
"fragment" => 4,
|
||||
_ => panic!("Unknown checkpoint"),
|
||||
};
|
||||
Some((side, count))
|
||||
}
|
||||
fn expected(mode: &str, actual: &Project) -> CompiledSourceProject {
|
||||
let baseline = fixture();
|
||||
let mut base = bundle(&baseline);
|
||||
let Some((side, count)) = checkpoint(mode) else {
|
||||
return base;
|
||||
};
|
||||
let mut roles = Roles {
|
||||
actual,
|
||||
baseline,
|
||||
used: BTreeSet::new(),
|
||||
};
|
||||
let key = roles.occurrence(side, "native action");
|
||||
let e = authored(
|
||||
&base.decoded.project,
|
||||
side,
|
||||
key,
|
||||
"native action",
|
||||
side.id(30),
|
||||
action(side, 10, 40),
|
||||
);
|
||||
insert_before(&mut base, side.id(30), side.id(50), vec![e]);
|
||||
if count == 1 {
|
||||
return base;
|
||||
}
|
||||
let key = roles.occurrence(side, "native state");
|
||||
let e = authored(
|
||||
&base.decoded.project,
|
||||
side,
|
||||
key,
|
||||
"native state",
|
||||
side.id(55),
|
||||
OccurrenceBody::State {
|
||||
state: Some(side.id(22)),
|
||||
lifeline: Some(side.id(40)),
|
||||
},
|
||||
);
|
||||
insert_before(&mut base, side.id(55), side.id(57), vec![e]);
|
||||
if count == 2 {
|
||||
return base;
|
||||
}
|
||||
let key = roles.occurrence(side, "native reuse");
|
||||
let e = authored(
|
||||
&base.decoded.project,
|
||||
side,
|
||||
key,
|
||||
"native reuse",
|
||||
side.id(55),
|
||||
reuse(side, 31, [42, 43], [40, 41]),
|
||||
);
|
||||
insert_before(&mut base, side.id(55), side.id(57), vec![e]);
|
||||
if count == 3 {
|
||||
return base;
|
||||
}
|
||||
let fragment = roles.occurrence(side, "native alternative");
|
||||
let branch1 = roles.occurrence(side, "native alternative · operand 1");
|
||||
let branch2 = roles.occurrence(side, "native alternative · operand 2");
|
||||
let p = &base.decoded.project;
|
||||
let elements = vec![
|
||||
authored(
|
||||
p,
|
||||
side,
|
||||
fragment,
|
||||
"native alternative",
|
||||
side.id(30),
|
||||
OccurrenceBody::Fragment {
|
||||
operator: FragmentOperator::Alternative,
|
||||
branches: vec![],
|
||||
},
|
||||
),
|
||||
authored(
|
||||
p,
|
||||
side,
|
||||
branch1,
|
||||
"native alternative · operand 1",
|
||||
fragment,
|
||||
OccurrenceBody::Branch {
|
||||
guard: "ticket.priority > 2".into(),
|
||||
occurrences: vec![],
|
||||
},
|
||||
),
|
||||
authored(
|
||||
p,
|
||||
side,
|
||||
branch2,
|
||||
"native alternative · operand 2",
|
||||
fragment,
|
||||
OccurrenceBody::Branch {
|
||||
guard: "ticket.priority <= 2".into(),
|
||||
occurrences: vec![],
|
||||
},
|
||||
),
|
||||
];
|
||||
insert_before(&mut base, side.id(30), side.id(62), elements);
|
||||
base
|
||||
}
|
||||
fn same_snapshot(verified: &CompiledSourceProject, restored: &CompiledSourceProject) -> bool {
|
||||
verified.decoded.project == restored.decoded.project && verified.bundle == restored.bundle
|
||||
}
|
||||
fn self_check() {
|
||||
let baseline = fixture();
|
||||
assert_eq!(
|
||||
baseline,
|
||||
fixture(),
|
||||
"seed identities and fields must be deterministic"
|
||||
);
|
||||
let base = bundle(&baseline);
|
||||
assert_eq!(expected("baseline", &baseline).bundle, base.bundle);
|
||||
for side in SIDES {
|
||||
// Role carrier intentionally has wrong parent, alias and occurrence body.
|
||||
// Only its fresh IDs may survive in any prediction.
|
||||
let mut carrier = baseline.clone();
|
||||
for text in [
|
||||
"native action",
|
||||
"native state",
|
||||
"native reuse",
|
||||
"native alternative",
|
||||
"native alternative · operand 1",
|
||||
"native alternative · operand 2",
|
||||
] {
|
||||
let mut e = carrier
|
||||
.make_element(Kind::Occurrence, side.layer, &side.name(text), None)
|
||||
.unwrap();
|
||||
e.alias = "wrong_carrier_alias".into();
|
||||
e.description = "must never enter the prediction".into();
|
||||
carrier.elements.insert(e.id, e);
|
||||
}
|
||||
for stage in ["action", "state", "reuse", "fragment"] {
|
||||
let mode = format!("{}-{stage}", side.word.to_lowercase());
|
||||
let correct = expected(&mode, &carrier);
|
||||
assert_ne!(correct.decoded.project, carrier);
|
||||
let again = expected(&mode, &correct.decoded.project);
|
||||
assert_eq!(again.decoded.project, correct.decoded.project);
|
||||
assert_eq!(
|
||||
again.bundle, correct.bundle,
|
||||
"full source checkpoint fixed point"
|
||||
);
|
||||
let mut wrong = correct.decoded.project.clone();
|
||||
wrong.elements.get_mut(&side.id(10)).unwrap().description =
|
||||
"unrequested seed edit".into();
|
||||
assert_ne!(expected(&mode, &wrong).decoded.project, wrong);
|
||||
let native = wrong
|
||||
.elements
|
||||
.values()
|
||||
.find(|e| e.name == side.name("native action"))
|
||||
.unwrap()
|
||||
.id;
|
||||
let mut wrong = correct.decoded.project.clone();
|
||||
wrong.elements.get_mut(&native).unwrap().parent = Some(side.id(55));
|
||||
assert_ne!(
|
||||
expected(&mode, &wrong).decoded.project,
|
||||
wrong,
|
||||
"parent is predicted, not read back"
|
||||
);
|
||||
let mut wrong = correct.decoded.project.clone();
|
||||
wrong
|
||||
.elements
|
||||
.get_mut(&side.id(30))
|
||||
.unwrap()
|
||||
.steps_mut()
|
||||
.unwrap()
|
||||
.swap(0, 1);
|
||||
assert_ne!(
|
||||
expected(&mode, &wrong).decoded.project,
|
||||
wrong,
|
||||
"clicked order is independently fixed"
|
||||
);
|
||||
}
|
||||
let mode = format!("{}-fragment", side.word.to_lowercase());
|
||||
let correct = expected(&mode, &carrier);
|
||||
// Both semantic checks may legitimately discover fresh native IDs. An
|
||||
// Undo/Redo check must additionally pin them to the earlier snapshot.
|
||||
let mut other_carrier = carrier.clone();
|
||||
let old = other_carrier
|
||||
.elements
|
||||
.values()
|
||||
.find(|e| e.name == side.name("native action"))
|
||||
.unwrap()
|
||||
.id;
|
||||
let mut replaced = other_carrier.elements.remove(&old).unwrap();
|
||||
replaced.id = Id::new_v4();
|
||||
other_carrier.elements.insert(replaced.id, replaced);
|
||||
let recreated = expected(&mode, &other_carrier);
|
||||
let correct_prediction = expected(&mode, &correct.decoded.project);
|
||||
let recreated_prediction = expected(&mode, &recreated.decoded.project);
|
||||
assert!(same_snapshot(&correct_prediction, &correct));
|
||||
assert!(same_snapshot(&recreated_prediction, &recreated));
|
||||
assert!(
|
||||
!same_snapshot(&correct, &recreated),
|
||||
"recreated native IDs pass semantic roles but must fail exact history restoration"
|
||||
);
|
||||
let mut wrong = correct.decoded.project.clone();
|
||||
let e = wrong
|
||||
.elements
|
||||
.values_mut()
|
||||
.find(|e| e.name == side.name("native reuse"))
|
||||
.unwrap();
|
||||
let Some(SharedBody::Occurrence {
|
||||
body: OccurrenceBody::ScenarioUse { bindings, .. },
|
||||
..
|
||||
}) = e.shared_mut()
|
||||
else {
|
||||
unreachable!()
|
||||
};
|
||||
bindings[0].local = side.id(41);
|
||||
assert_ne!(
|
||||
expected(&mode, &wrong).decoded.project,
|
||||
wrong,
|
||||
"bindings are never copied from actual"
|
||||
);
|
||||
let mut changed_source = correct.bundle.clone();
|
||||
changed_source
|
||||
.files
|
||||
.get_mut("rationale.arcadia")
|
||||
.unwrap()
|
||||
.push_str("// unrequested note\n");
|
||||
let changed = compile_bundle(&changed_source, ProjectLimits::default()).unwrap();
|
||||
assert_eq!(changed.decoded.project, correct.decoded.project);
|
||||
assert_ne!(
|
||||
changed.bundle,
|
||||
expected(&mode, &changed.decoded.project).bundle
|
||||
);
|
||||
}
|
||||
println!(
|
||||
"PASS self-check: deterministic OA/SA baseline, eight semantic checkpoints, independent fields/source bytes and exact history identity discrimination"
|
||||
);
|
||||
}
|
||||
fn main() {
|
||||
assert_eq!(SCHEMA_VERSION, 7);
|
||||
let args: Vec<_> = std::env::args().collect();
|
||||
if args.get(1).is_some_and(|s| s == "self-check") {
|
||||
assert_eq!(args.len(), 2);
|
||||
self_check();
|
||||
return;
|
||||
}
|
||||
if args.get(1).is_some_and(|s| s == "generate") {
|
||||
assert_eq!(args.len(), 3);
|
||||
let dir = Path::new(&args[2]);
|
||||
assert!(
|
||||
!dir.exists(),
|
||||
"Generate only into a fresh directory; preserve existing evidence"
|
||||
);
|
||||
let p = fixture();
|
||||
let base = bundle(&p);
|
||||
fs::create_dir_all(dir).unwrap();
|
||||
for (name, bytes) in base.bundle.files {
|
||||
fs::write(dir.join(name), bytes).unwrap();
|
||||
}
|
||||
fs::write(
|
||||
dir.join("expected-baseline.json"),
|
||||
serde_json::to_vec_pretty(&p).unwrap(),
|
||||
)
|
||||
.unwrap();
|
||||
println!(
|
||||
"PASS generated deterministic OA/SA fixture: {} elements, 2 sources; native roles absent",
|
||||
p.elements.len()
|
||||
);
|
||||
return;
|
||||
}
|
||||
if args.get(1).is_some_and(|s| s == "same") {
|
||||
assert_eq!(args.len(), 4, "same VERIFIED_SAVED_ENTRY RESTORED_ENTRY");
|
||||
let verified = load(Path::new(&args[2]));
|
||||
let restored = load(Path::new(&args[3]));
|
||||
assert!(
|
||||
same_snapshot(&verified, &restored),
|
||||
"Restored snapshot must preserve every Project identity/field and every SourceBundle byte"
|
||||
);
|
||||
println!(
|
||||
"PASS same: exact saved/restored Project and SourceBundle, including all native identities"
|
||||
);
|
||||
return;
|
||||
}
|
||||
assert_eq!(
|
||||
args.len(),
|
||||
4,
|
||||
"check baseline|oa-action|oa-state|oa-reuse|oa-fragment|sa-action|sa-state|sa-reuse|sa-fragment ENTRY"
|
||||
);
|
||||
assert_eq!(args[1], "check");
|
||||
let actual = load(Path::new(&args[3]));
|
||||
let prediction = expected(&args[2], &actual.decoded.project);
|
||||
assert_eq!(
|
||||
actual.decoded.project, prediction.decoded.project,
|
||||
"Complete Project differs from independent checkpoint"
|
||||
);
|
||||
assert_eq!(
|
||||
actual.bundle, prediction.bundle,
|
||||
"Complete source bundle differs, including retained note bytes"
|
||||
);
|
||||
println!(
|
||||
"PASS {}: whole model and {} exact reachable sources; only unique fresh role IDs borrowed",
|
||||
args[2],
|
||||
actual.bundle.files.len()
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user