Download arche-lang

The VS Code extension and the command line, archec.

Looking for the latest release…

VS Code extension

arche-lang-0.10.0.vsix

Download the extension

  1. Install it from a terminal:
    code --install-extension arche-lang-0.10.0.vsix
  2. Or in VS Code: Extensions › … › Install from VSIX…, then pick the file.
  3. Open a folder with .arche files: highlighting, diagnostics, quick fixes, the diagram and the simulator are there. What the extension does.

Command line

arche-lang-0.10.0.tgz · Node 18 or newer

Download archec

  1. Install it with npm (Node ≥ 18):
    npm i -g https://arche-lang.xyz/downloads/arche-lang-0.10.0.tgz
  2. Start a project that checks clean:
    archec new my-robot
  3. Use the Arche Store for architectures, drivers and boards:
    archec store use https://store.arche-lang.xyz
  4. archec alone lists the everyday commands; all of them.

What changed

0.11.0 (unreleased): a complete language

  • The extension, tested in VS Code: npm run test:vscode opens a VS Code window per example (the car, the TypeScript handlers, the living model, the board bench, a beginner's first model), with its own settings and no other extension, and runs every contributed command, the views, the diagram's webview and its ▶ run, Live on a replayed trace, a board dragged into a file, the regeneration round trip, completion and hover. Fixed on the way: Open TypeScript Block as File types self and msg from arche.d.ts (they were any, so nothing completed); the hover of a TypeScript handler shows TypeScript, not Python; Reveal in Source with nothing to reveal no longer throws; the diagram's script errors go to the Arche output. Start Live takes { deployment, replay } and Filter Boards… a text, for keybindings; Open TypeScript Block as File is in the editor's menu.
  • ```arche bodies you can read and follow: a body was raw text in one colour, and Ctrl+click did nothing in it. The body checker now links every name to what it is — a variable, a function, a port, an operation through a port, a message and its fields, a constant, an enum value, a state, a watchdog; a parameter and a local to where they are declared — so Ctrl+click, hover, Find References and Rename work in bodies, and rename follows the links instead of the text (a message field in a record follows; a parameter of the same name does not). The grammar colours bodies as the action language and the semantic tokens by meaning; arche.bodies.highlight adds a faint background. Models written in JavaScript and TypeScript as archeSrc`…` (the tests' helper) are coloured as arche with Ctrl+click and hover on their names; arche.embedded.problems shows their errors.
  • archec in a terminal: Arche: Open archec Terminal (also archec in the terminal's + menu) opens a terminal in the model's folder where archec runs the compiler the extension uses — arche.paths.compiler, else its bundled copy on VS Code's own Node: no install, no PATH to set.
  • A rename keeps your code: the code of a USER CODE region follows its element when it is renamed. The editor's Rename and the new archec refactor rename record the rename (arche.renames.json, committed), and archec gen applies it once per output folder, into the new file when a component is renamed. A clear rename by hand is recognised (one region gone, one new, the same stub). Anything else stops archec gen (nothing written, exit 1) until --move a=b or --orphans ok. Preview Generated Changes asks where the code goes, and archec check warns first (gen-stranded).
  • Regenerating code: generated C, Rust and Go mark where your code goes — USER CODE BEGIN <id> / END <id> around a function the model gives no body, the init, the includes, an on-receive, a send — and archec gen puts it back each time it writes the file again, by an id made of model paths; a region the model no longer gives goes to <file>.orphans, not away. Each function or type from a model element carries @arche <path> <file>:<line>, mapped in generated/.archec/genmap.json: archec where puts a gcc, clang, rustc or go error back on its .arche line, Go to Model Element (a lens above each tag, Go to Definition) does it in a generated file, Show Generated Code the other way. archec gen --diff and Arche: Preview Generated Changes… (VS Code's diff editor, then a question) show a write before it happens. Templates write {{#region "id"}}, scripts ctx.region() (docs/regeneration.md).
  • Integration targets: archec gen --target canopen (a CiA 306 EDS per node on a CAN bus: its PDOs from the routes, the messages as objects) --target j1939 (the parameter groups of the 29-bit routes, their PGN read from the id, an SPN per signal) --target mavlink (the catalog as a MAVLink 2 dialect, checked by mavgen), --target someip (the services of the interfaces provided, their methods, events and instances, as JSON), --target openapi (OpenAPI 3.1 from the HTTP handlers) --target asyncapi (AsyncAPI 3.0 from the links that carry messages, at their topics); build systems around the generated C — --target cmake (a project per binary, toolchain files from the cores, everything built on the host), --target west (a Zephyr application with its pinned manifest per binary on a Zephyr board), --target platformio — --target ci (GitHub Actions and GitLab CI: check, ci, gen --check, the builds); and for the lab, --target flash (per microcontroller binary, a flash script with its chip's tools — probe-rs, OpenOCD, nrfjprog, picotool, espflash — and a monitor that reads its trace off the board into archec timing and archec live --replay) and --target bench (the test rack as YAML — buses, nodes, frames, devices under test, power — and per CAN bus a SocketCAN setup and a python-can script that checks the frames against their periods or stands in for a missing node); what the model has no word for comes from attr and is otherwise noted, not made up (docs/integration-targets.md).
  • The editor for a newcomer: arche.level is auto by default — beginner (plain-words diagnostics, the core of the language in completion) until the project says level full or uses declarations beyond the simple set; archec new's templates say their level (level simple, level full for those with a deployment, and a deployment added by --target sets it). The empty Navigation view has New Project…, Get Started and Open Example… buttons. Lenses: ▶ Simulate | Open Diagram above a system, ▶ Run Test above a test plan and a case. Signature help in bodies for MSG(field=…) and send(port, message), and in ```arche bodies for MSG { field: … } and send port MSG: the fields with their types, units and ranges. The Documentation, Live and Animations views show when the model has a deliverable, a deployment, an animation (always for an expert); Boards and Store start collapsed. A beginner's status bar says the next step (3 requirements unverified · no test plan), a click lists where and offers the quick action. Settings by purpose: arche.paths.app, arche.paths.appCli, arche.paths.compiler (the old names still read). Command titles shortened, in Title Case (Generate Code…, Run Tests, Simulate in Diagram).
  • Learning it: docs/concepts.md (the model before the syntax, five ideas, a picture and a model that compiles for each) and docs/cheatsheet.md (the core declarations on one page); the walkthrough starts with them, and arche-lang: Show Cheat Sheet opens the sheet. The README, the tutorial, the examples' simple bodies and the reference teach arche bodies first. A simple python body is a hint (arche-body, archec vet) whose quick fix, Convert to arche body, rewrites it — also archec fix --only arche-body, and the MCP fix tool. The README is short now: each area's notes are a page of docs/ (verification, safety, deployment, code generation, robots, physics, importing, Python, design notes, the editor).
  • Generators of your own: generator rte "…" { templates "folder" | script "gen.js" | command "python3 gen.py" }, run as archec gen --target rte beside the built-in targets. They read the generator model — the project as JSON, version 1 (schemas/generator-model.v1.json): names resolved, values worked out, each message's layout on the wire, a bus's CAN frames, each element's file and line — and return files. Templates fill {{ }} (loops with where, #if, a #file per element, partials, filters such as snake and ctype, keep); a script runs in a sandbox (no require, no file system but its folder); a command in any language reads the model on stdin and writes the files on stdout. from another generator with other options; --option; a generator's problems at the elements' lines. archec generator new|model|test|approve. A library's or Store package's script or command runs only once approved in arche.lock, at its fingerprint. In VS Code a ▶ Generate lens, Generate code… lists them, completion and hover in template files. examples/generators writes a C header, a DBC (the built-in one byte for byte, from the model alone) and an ICD in Python (docs/generators.md).
  • More for generators of your own: a script calls ctx.builtin("c") for a built-in target's files ({ path: text }), and a template or a command reads them in the model's builtins (builtins c, dbc). A hook — generator license { script "license.js"; after c } — changes a target's files before they are written: archec gen --target c runs the project's hooks on it in the order written, each returning only what it changes (null takes a file away; a keep file stays one); --no-hooks leaves them out. Each body in the generator model has c, rust and go beside its python, through the built-in translators. Options are declared with their type, default and values (option prefix "…" { type string; default "kc_" }): archec check holds what a generator from it sets and --option to them, archec gen --list lists them, and in options { } completion offers their names and values and hover says what each is. script "gen.ts": TypeScript, its types stripped (node's own, else esbuild or typescript); archec generator new --script --ts and archec generator types write generator-model.v1.d.ts for it.
  • Animations: animation v-x "…" from <template> { … } — one of Arche's 72 animation templates (flows, timelines, state machines, signals, hardware, mission, comms…), its content written in the model and bound to it: a component is written as its name, a constant or a formula as ${…} the app works out on the slide, machine kria.ps.app draws a state machine's states, transitions and a walk through them, scenario boot plays a scenario's lifelines and arrows; a list of names where the template wants records gets the rest from its sample. Checked against what each template reads (unknown data, wrong shapes, paths that name nothing). Written as Arche's animation editor writes it. A story step animates one and stays its dwell. archec animation list|show|new|preview|render (a GIF, recorded in headless Chrome as the .pptx export records one), archec story export (a story as one HTML file, its animations running, played by itself); in VS Code an Animations view, a preview beside the editor that follows the model, completion of the templates and of their data (docs/animations.md).
  • Views as queries, diagrams anywhere: a viewpoint with include/exclude lines (include * -> adcu, exclude kind sensor, depth 2) is a diagram of its own in the Model view, the blocks it picks at any depth with the links between them, laid out by ELK; a term that matches nothing is a warning (view-empty), its names follow a rename. The places dragged in a view go to main.layout.json, out of the model (arche.diagram.positions: file does the same for every diagram); a rename renames their keys. archec diagram writes any diagram as Mermaid (GitHub draws it), D2 or SVG, and --play a scenario as an SVG that plays it step by step on its system's blocks.
  • The simulator, live: archec sim --html runs the model in the page as MuJoCo's viewer runs a scene — Play/Pause, Step (the next event) and Step by (a fixed time), a speed from 0.1× to 10×, a time scrubber back over what has run (the run replayed, with what was sent), Reset; a form per input port that sends one of its messages now, its fields with their type, range, unit and enum values; a physical network integrated in the page with a push (a step or a pulse) on its sources; live plots (inline SVG) of states, variables, message fields and physical quantities; keys listed on the page (docs/sim.md). The diagram panel's ▶ does the same in VS Code: the run is live in the extension, driven from the panel's bar (pause, step, step by, reset, speed, scrubber, the same keys) and its ☰ controls (send, push, plots).
  • See the model work, nothing installed: the browser simulator runs a model's state machines (on a message, on "after 500ms"), ```arche bodies and simple Python, links and a deployment's periodic threads on a virtual clock. The diagram panel's ▶ (Arche: Run the Model in the Diagram) plays it on the diagram — dots along the links, each block's state, Pause/Step/Stop; archec sim prints the trace, --html writes one page that runs it in any browser; the store's package pages get a Try it link. What it does not simulate is said (docs/sim.md).
  • Errors that fix themselves: the common diagnostics carry their fixes — the closest name, property, value or unit, a link's ends swapped, a port's direction, a duplicate renamed, the file an include names created — as quick fixes, the best one preferred; archec fix <main.arche> applies them and checks again (--dry-run shows the diff); the MCP server's fix tool gives them to an assistant. Every diagnostic has Explain [code], the explanation beside the editor. A beginner level: the setting arche.level (beginner) or archec check --beginner says the messages in plain words with what exists, and a project's level simple keeps completion to the core of the language (fixes (docs/fixes.md)).
  • Draw instead of type: a palette beside the diagram — the core elements, the board store, the Arche Store, searched — whose items drop onto the canvas as source edits (a board with its include and uses, a store package after the question about its code, then placed); property forms generated from the language's description (dropdowns, checkboxes, number + unit, the documentation as help, checked before writing); and a Get started with arche-lang walkthrough whose steps complete as the model grows. Generate code… offers C and Go.
  • The living model: Arche: Start Live runs archec live on a deployment (running, or replaying trace files): a Live view of its requirements, chains, threads and containers passing, failing or pending, a status bar count (Live: 2 ✗ 14 ✓), a dot in the gutter of each one's line with a hover (why, the last evidence) and the measured p99 against its budget after a chain or thread, and the deployment diagram's threads tinted. Explain & Fix with Claude on a failing one runs archec live-fix — Claude's explanation, its edits to the model previewed as a refactoring, live restarted once they are applied. archec is bundled (arche.archecPath for another).
  • Boards: a store of known boards ships with archec (arche-hw-store: ESP32-C3/S3/DevKitC, NUCLEO-G474RE/F446RE/H743ZI2, Raspberry Pi Pico/Pico W/4/5, nRF52840 DK, Jetson Orin Nano, Kria KR260), and your own go in collections (arche.boardCollections, ARCHE_BOARDS, a project's libraries). archec board list|show|add|new|check|extract; a Boards view in the side bar (add to the model, details, duplicate, new board, check). A board is kind board with product { vendor; part-number; url }, its processors and its connectors' pins { tx PA12; rx PA11 }; binary … on <board> runs on its processor, a route over a bus on its connector reaches it, and the Embassy CAN drivers (TWAI, bxCAN, FDCAN, MCP2515) use its pins. A record also reads { key value; … }. Checked with cargo check on the nRF52840 DK, NUCLEO-G474RE and ESP32-C3 boards.
  • Boards in the editor: completion after part x: offers the boards of the store and of your collections, with vendor and part number (one not included yet brings its include and uses); in pins { … } the roles, then the board's pins and what each is wired to; in a part of a board, its connectors with their pins. Hover on a board shows its product, URL, processors, memory and pins; on a pin, what the board wires to it. A pin the board's chip does not name so, or a role archec does not read, is a warning (board-pin) with the nearest as a quick fix. A board dragged from the Boards view into an editor becomes a part where it is dropped (in a new hardware system outside any block), with its include and uses.
  • The action language: a body written in a arche block instead of python is typed and checked by archec (names, types, ports and what they send, states) and translated: to the Python Arche runs, to Rust in the Embassy crates (no TODO left in app.rs), to C. var, if/else if, while, for i in a..b, send port MSG { … }, goto, wait 10ms, return, log; state == S, now(), min/max/clamp/abs/sqrt, int/float.
  • C++: archec gen --target cpp — C++17: enum class, std::variant unions, std::optional fields, messages as structs with encode/decode on the C's bytes (checked byte for byte against the C), a class per component with its state machine as an enum class and a switch (on-exit/on-enter, guards, actions, after timers, watchdogs, deadlines; door.arche runs as the C runs it), ```arche bodies and the Python the action language can say translated, sends as std::function members; with a deployment a program per language cpp binary, a std::thread per thread of the model, and a CMakeLists.txt. Built with -Wall -Wextra -Werror on examples/autonomous-car (docs/cpp.md). The C target's union fields now compile.
  • Register maps: archec gen --target regmap — each part's addressed memory blocks as one map for every side: a C header (offsets, field shifts and masks, access macros on a base, static asserts that a struct of the map puts each block at its offset), an AXI4-Lite register bank in VHDL-93 and SystemVerilog (byte strobes, reset values, r blocks as inputs, a write strobe per element, large blocks as RAM ports, SLVERR elsewhere), IP-XACT 2014, SystemRDL 2.0 and a Markdown memory map; count and whole-byte record fields read as the block lays them out. archec check warns of a block off its alignment (memory-misaligned), a field past its element or wider than its type (memory-field-width) and fields sharing bits (memory-field-overlap) (docs/regmap.md).
  • The quality of the generated code: archec gen --target c|embassy --build --lint builds what it writes (-Wall -Wextra -Werror -pedantic; cargo) and runs cppcheck's MISRA C:2012 addon, clang-tidy and cargo clippy when installed, each finding said at the model element its line comes from (main.arche:57 error [cc-unused-variable] … — c/controller_ports.c:6 in controller_send_cmd (port cmd of Controller)), --sarif for code scanning; --target c-tests turns the test plans into C unit tests of the generated C (make test, --run, gcov coverage read back as states, transitions and functions); --defensive checks ranges, stale inputs and E2E checksums and counters on receive; --target trace-matrix writes requirement → element → generated function → test case → last result (docs/codegen-quality.md).
  • C code generation: archec gen --target c — C99, no heap: messages, structs and enums with little-endian encode/decode on the model's wire layout (the bytes the DBC and the Rust codecs use); a module per component with its variables and state, its functions (a ```arche body translated, Python left as a TODO), goto with on-exit/on-enter, fire taking its transitions innermost state first, guards in the action language translated; the send functions written once for you to wire; a POSIX runtime; with a deployment, a FreeRTOS task per thread (priority, stack, period). Compiled with -Wall -Wextra -Werror -pedantic and run in the tests.
  • Generic structs: struct Ring<T, N: int> { items: T[N] }, used as Ring<Sample, 64> — each use is a struct of its own (Ring_Sample_64, the fields made concrete), for Arche, the codecs, Rust and C; nested uses too. Wrong arguments (their count, a type for a number) are errors where they are written.
  • archec verify: a requirement's formal property — never brakes in Fault, always …, eventually …, adcu in Ready leads to adcu in Autonomous — checked by NuSMV (or nuXmv) on the state machines, with each state's reachability; a property that fails comes back with its counterexample as a Mermaid sequence diagram. A formal text archec cannot read is an error in the editor. archec ci has a verify gate.
  • EARS requirements: ears "when brakes receives BRAKE_CMD, brakes shall be in Braking within 50ms" — ubiquitous, state-driven (while), event-driven (when), unwanted (if … then), complex — checked against the parts, states and messages; the sentence is the text when there is none, it gives the formal property archec verify proves, and archec gen --target ears-tests writes a test case per requirement.
  • Generated tests: archec gen --target tests — a case per transition a message triggers (the shortest way to its source state by messages, sent by the part wired to send them, then its trigger and the state after) and a case per received message at its fields' limits (a written range, else the type's) and at zero; the cases with a TODO (a guard, an event no message brings) go in tests/generated.allow, which archec test --allow passes on as known failures.
  • Interface definitions for other toolchains: archec gen --target proto | ros2 | dds — the model's messages, structs, enums and unions for protobuf (proto3: enums with their zero value, a union as a oneof, a service per interface; checked with protoc in the tests), ROS 2 (a .msg per message, an enum as constants, a .srv per operation) and DDS (OMG IDL 4: @value, unions on their case byte, @optional, sequence<T>).
  • Certification: asil (ISO 26262) and dal (DO-178C) on requirements and components; a requirement keeps the level of the safety goal or requirement it derives from (derives SG-01 now resolves, traced to safety.yaml), or decomposes it — asil "B(D)", the decomposed requirements adding up to the parent (D = C+A = B+B = D+QM …) on independent elements — and an element is at the level of what it satisfies. archec cert --standard iso26262|do178c writes the trace matrix and its gaps. A requirement's level and what proves it may be written as groups: integrity { asil D; dal A }, proof { ears "…"; formal "…" }.
  • SBOM: archec gen --target sbom writes a CycloneDX 1.5 bill of materials — the hardware of the BOM with its vendor, part number and quantity, the libraries at the version arche.lock names (with their fingerprint), a firmware per binary depending on its processor; the same model gives the same file (valid against the CycloneDX 1.5 schema).
  • Merging by declaration: archec merge is a git merge driver for .arche (archec merge --install): what one branch changed is taken, a declaration both changed is merged inside, and only an item both changed differently is a conflict, named (<<<<<<< ours: Brake.pressure) — two branches that touch neighbouring lines of one component no longer conflict.
  • Libraries from git: uses can-parts "^1.2" from "https://…/can-parts.git" — archec lib <main> fetch checks out the version its tags give (the locked one, else the newest in range) into .arche/libs, which the build reads; arche.lock records the repository and the commit, and a tag that moved is reported.
  • Language editions: edition "0.12" on the project, as go.mod names a Go version — in edition 0.12 an old keyword spelling is an error, without an edition the project is read as before; archec fmt --edition 0.12 --write migrates a project (the standard spellings, and the edition); an edition newer than archec knows is an error.
  • The parser and formatter under stress: the tests run archec fmt twice on every example (a second pass changes nothing) and check the project built is the same (archec diff); 400 seeded random damages to real files (spans cut, tokens inserted, lines doubled, files cut short) never make the parser, the formatter or the checker throw or hang.
  • C that runs: with a deployment, archec gen --target c wires each binary (c/<binary>/wiring.c): its parts, a queue per thread that receives, each send routed to the thread of the part the link goes to or, over a route, to a bus hook per port type (arche_can_send, arche_can_fd_send… in drivers.c, yours), a message that arrives fires the machine and the port's on-receive, a function per thread (periodic or waiting on its queue) and <binary>_start. arche_rt.h adds queues and threads (POSIX in arche_rt_posix.c, FreeRTOS in arche_rt_freertos.c); main.c and a Makefile build it on a host, where ./<binary> 1000 runs it a second. The car's three binaries build with -Wall -Wextra -Werror -pedantic.
  • The model's Python, translated: a Python body that is the action language in other words (self.x = …, if/elif/else, while True, for i in range(…), await wait(ms(2)), await goto("Run"), send(self.p, MSG(k=v)), x ** 2, log(…)) is translated for C and Rust instead of left under a TODO — when it type-checks and has no integer division. Every body of the car now is.
  • The extension under test: test/lsp.test.js drives the language server as VS Code does (stdio, JSON-RPC): diagnostics on their line and gone once fixed, hover, go to definition, rename, inlay hints, formatting and the declare-it quick fix; a diagram drag writes the block's at and nothing else. npm run test:vscode runs test/vscode/suite.js in a real VS Code on a copy of the car: activation, the Model and Boards views, Problems, F2, inlay hints, formatting and the diagram.
  • Shipping: archec is a package now (no longer private): npm pack gives one bundled dist/cli.js with dist/index.js, dist/arche.js, the standard library and the board store — install the tarball and run npx archec, no build. npm run package gives the .vsix. test/dist.test.js checks what the package holds.
  • Translations for every text: an entry of translations en { … } may name a text by what it says, "initialisation du CFF" "CFF initialisation", for the texts no path reaches (sequence steps, branches, procedures); an entry whose text is no longer in the model is pointed out. archec translations --extract en moves them too, grouped by file: on KaCAO 3908 texts move (2595 before) and 43 stay, and the model's files read in French only. In the editor, inline translations are dimmed (Arche: Dim Translations, arche.translations.dim), and hovering a text shows the translation its translations file gives. archec fmt lines a translation up under its text only when that text starts within 40 columns; otherwise it goes two levels in.
  • examples/arche-lang: arche-lang itself as a model — the compiler stages, generators, editor, commands, decisions, and the test behind each promise; test/selfmodel.test.js keeps it in step with the code.
  • Edition 0.12 in the examples: the car, the patterns and KaCAO say edition "0.12" (archec fmt --edition 0.12; each builds the same project); completion no longer offers the old spellings.

0.10.0 (unreleased): as readable as Go

  • One spelling: an old spelling of a keyword is a warning (read until 0.12); archec fmt writes the short, standard forms by default (--no-simplify for the layout only), like gofmt -s.
  • One layout: properties in one order in every file (what it is, how it is classified, its type, the rest, its traces, its place on the canvas); one item per line, ; only inside a one-line block.
  • A small core: the 100 declarations come in sets — the core (35), deployment, functional analysis & scenarios, safety/security/design space, the Arche app (in app/*.arche), project tooling; the reference says each one's set.
  • Property groups: timing { … }, delivery { … }, compute { … }, physical { … }, the same as the lines; fmt writes a group for three or more.
  • One guard spelling: […] on transitions and operating modes (when "…" stays for a sentence an apostrophe or an accent would break).
  • Nothing silent, nothing hidden: an undeclared kind, layer or tag is a warning whose quick fix declares it (the kinds archec interprets — processor, device, bus… — are built in); the editor shows what a link carries when its ports say it, and what a defaults block gives.
  • archec vet: style apart from errors, as go vet — long forms, property order and groups, declarations out of their set, names in their case (PascalCase defined, snake_case inside, SCREAMING_CASE messages and constants), long Python in a model file; archec check leaves style out, archec ci has a vet gate.
  • Packages as in Go: package chassis on its own line puts the file in it; chassis.BRAKE_CMD.
  • Documents: docs/spec.md (the specification, with the grammar in EBNF), docs/style.md (Effective Arche); archec explain <code>, every diagnostic code described; long messages cut after their first sentence in the terminal (--long).
  • The size tracked: ceilings on keywords, the core, property names and properties per declaration (test/surface.test.js).

0.10.0 (unreleased): Arche fields as syntax

  • Interfaces from port types: archec import writes a port type with operations, a base or sources as an interface (fn op(arg: "T") -> "R" "comment", extends, source); an interface also takes handling and timing. missing-operation is one warning per port, listing every operation it lacks.
  • Structures in place: var TRACKING: struct { gain: float32; phase: float32 }[0], for a variable, a field or a message; a field may hold a message (records: RFIC_CONFIG); message PING: struct is a structure with no field; a memory record's field may say only its size (field phase { size 1 }).
  • Entries of records as declarations: a panel's widget az "Azimut" { type slider; at [0, 1, 4, 1] } and columns 12; row-height 52; an app's page and tab; a story's step; a benchmark's run; a function chain's step s1 function SF-A and edge s1 -> s2 : fl-1; a table's column a { min 0; max 15 } and unique b, c.
  • Smaller fields: var mode initial "BOOT" (Arche's value as text), port handler MSG with no function, note-at x, y, state do/entry-activity/exit-activity as text, kind color, menu entry section, deliverable covers by address, unit symbol/logarithmic, visual comment/data-file, project pptx-template, file "x.yaml" { version nil }, simulation horizon/seed and stimulus at, operating modes' components/requirements by address, ports and variables named out, on…
  • Embassy CAN on nRF and RP2040: they have no CAN controller, so src/can.rs drives an MCP2515 on SPI (its INT on a pin): the bit timing for an 8 or 16 MHz crystal, standard and extended ids, frames over 8 bytes counted in DROPPED; up to 1 Mbit/s. RP2040 projects now build: no rp2040 feature on embassy-rp 0.2, its critical section rather than cortex-m's single-core one, portable-atomic for the Cortex-M0+. Both checked with cargo check.
  • data "file.yaml" = { … }: a file Arche does not define, written from a value instead of verbatim text.
  • The last escapes: a link's icd m1 "Pointing" { Azimuth: float64 }; a component's hardware { … } sheet and implementation { language: "rust", … }; port p: T with no direction (Arche writes none); an Arche id that is not a name, tag-group lot "Lot" as "Lot Projet", which a tag's group lot follows; a template's catalog summary (no longer a copy of its description); a message field's size 0 (out of band).
  • kacao: 347 attr lines to none, and no file written verbatim. Data fixes on both sides: the missing glt component, a requirement id used twice, three undeclared units, three requirements that said TBD, an expectation YAML read as an object.

0.10.0 (unreleased): main features

  • Simpler to write — traces where they start: verifies REQ-1 as t-7 (a trace property keeps its id), trace satisfies A -> R1 as s-1, R2 (several targets), verifies on a scenario, and the traces of a requirement written inside a component. archec move-traces moves each trace written apart to where it starts, writing out positional ids and address strings as paths, only if the same traces come out — kacao: 721 traces moved. archec diff compares traces.yaml by id.

  • Simpler to write — attr escapes as syntax: function-flow A -> B "item" as fl-1 { name "…" }, port-type latency/jitter/bitrate and memory-mapped, link bus; a part that shows another model (ref) is walked into by paths, so a scenario's attr participants/attr sequences become participant/sequence (fmt --simplify) — kacao: 72 escapes gone, scenarios.arche 5,748 → 2,650 lines.

  • Simpler to write — readable names: component flash_memory "FLASH_MEMORY" as c-1793752253957: paths say the name, Arche keeps the id. archec name-components names imported ids from their labels — kacao: 11 components, 527 → 39 ids left (the as ids and Arche address strings).

  • Simpler to write — translations apart: translations en { REQ-1 "Start"; REQ-1.text "…" }, the same as en "…" after each text; archec translations --extract en moves the inline ones into one file, only if the project builds the same.

  • Simpler to write — cases as a table: cases "Speed {v}" { body; rows { id | v; TC-1 | 10 } }, a case per row (- leaves out the lines that use a cell) — kacao's PBIT decision table: 32 cases, 512 → 52 lines.

  • Simpler to write — quick fixes that declare: an unknown message, type, port type, requirement, component… is declared at the end of the file; a link to a missing port adds it (direction from the end, type from the other end).

  • Documentation: a tutorial (docs/tutorial.md) that builds a water pump from model to firmware, and is compiled by the tests; every command in docs/commands.md; an index, docs/README.md.

  • archec ci: lint (with the project's rules and suspect links), format, timing, TARA, build, tests and coverage (--coverage-min) in one command, one line per gate, a JUnit report (--junit), exit 1 when a gate fails.

  • Versioned libraries: a library is a folder with a library.arche (library kria-parts { version "1.4.0"; archec ">=0.10" }), side by side as <name>@<version>/; uses kria-parts "^1.4" takes the newest in range and include "kria-parts/…" reads that version; archec lib lists, archec lib lock writes arche.lock. Missing, out-of-range, too-new-for-archec, conflicting, unlocked and changed-under-lock libraries are pointed out.

  • Embassy state machines: a part's state machine in Rust (states, events, the transitions innermost first, * -> X, guards as methods to implement, goto_name), fired by its task when a trigger message arrives, with on_transition for the action; a new app.rs has the part's variables at their initial values and the model's Python under each TODO.

  • Works without ../arche: the Arche code archec runs (RTOS generator, rule engine, study evaluation) is one minified bundle committed as vendor/arche.js (1.4 MB, for 6.9 MB before).

  • One version: archec --version, package.json and the extension all say 0.10.0.

  • Inside: checker.ts and emit.ts split by topic (src/checker/, src/emit/), the compiler tests by area; the same diagnostics and byte-for-byte the same builds.

  • Debugger variable values: arche-cli --trace also writes the trace records (PLAN__CASE.trace.json), so a debug session over a run shows each component's variables. An older arche-cli still works, without values.

  • ARXML system description: ECU instances (one per processor, with CAN connectors and frame, PDU and signal ports), PDU and signal triggerings, the SYSTEM with its root composition, the SWC-to-ECU mapping, and the data-element-to-signal mapping (signal groups, field by field).

  • Embassy CAN FD on STM32: a chip with FDCAN (stm32g4, h7, h5, l5, u5, g0b…) gets an FDCAN driver in src/can.rs: CAN FD frames up to 64 bytes with bit-rate switching, so the car's 15-byte BRAKE_CMD goes out (padded to 16); these chips build with embassy-stm32 0.2, executor 0.7, time 0.4. On a bxCAN chip, the note names each message longer than 8 bytes, and can::DROPPED counts the frames not sent, instead of losing them silently.

  • Embassy CAN on ESP32: hal esp32 gets a TWAI driver in src/can.rs (TWAI0, the nearest preset rate). nRF and RP2040 get a note that they have no CAN controller.

  • Guards in UPPAAL and NuSMV: a guard on the component's own variables is translated. A variable that the machine's transitions set to written values becomes a small integer. Of one state's transitions on one trigger, the first that can fire wins. NuSMV uses a TRANS relation.

  • Cybersecurity (TARA, ISO/SAE 21434): asset, damage-scenario, threat, attack-path, security-goal; feasibility, risk and CAL derived; checks; archec tara; a LaTeX section; goals as Arche requirements of category security.

  • Error propagation (the idea of AADL's error model): a port says the errors its part makes there (produces omission, value), stops (contains late) or changes (turns value into omission), and which inputs feed an output (from, from-all for redundancy); hazard … { error omission on Car.brakes.cmd }. archec derives each hazard's fault tree, its minimal cut sets and rate, and an FMEA row per error source, checks them against the written ones (fta-mismatch, fmea-mismatch) and shows them, marked derived, in archec safety, the LaTeX and HTML specification and the Safety group of the model tree.

  • STPA: control-action CA-… { from Car.adcu; to Car.brakes; feedback …; uca UCA-… { type not-provided; causes HZ-…; constraint REQ-…; loss-scenario LS-… { … } } } — the architecture is the control structure. Checked: each control action considered for the four types or said not-applicable (stpa-incomplete), each UCA traced to a hazard and a constraint (uca-untraced), a link that carries the action and its feedback (stpa-no-path); the tables in archec safety, the LaTeX and HTML specification, and the model tree (Control actions (STPA), a UCA under its type).

  • FMUs in the simulation: archec import plant.fmu, a component's fmu "plant.fmu", copied into the project and co-simulated by arche-cli (FMI 2.0 CS, Real, Integer, Enumeration and Boolean variables, a native host; sources built with cc when no binary).

  • Test coverage: archec test --coverage, Run with Coverage in the Test Explorer — states, transitions, messages per link, functions and requirements the runs exercised, marked at their lines (arche-cli test --coverage).

  • Fault injection in tests: at 20ms fault drop a.p / delay / stuck a.p f=0 / freeze part / thaw / clear, or a failure mode's id (its new inject), run by Arche's simulation (new engine fault helpers).

  • Timing analysis: handler-blocking — a message handler on a periodic thread that can hold the step past its deadline (counted as blocking in the response time, shown in the thread's hover).

  • Exporters for the tools around the model (archec gen --target …): aadl, an AADL v2 package of the deployment for OSATE (processors with a virtual processor per core, the bus, processes and threads with Dispatch_Protocol, Period, Deadline, Compute_Execution_Time, Priority and Stack_Size, ports typed by Data_Model data, connections bound to the bus and processes bound to their core); arxml, AUTOSAR Classic R4 (implementation data types, a sender-receiver interface per message, a software component per part with runnables on timing, data-received and init events, the composition, and per routed message on a CAN bus the I-signals, I-PDU, frame and CAN id); bom, a bill of materials as CSV and Markdown, grouped by definition with quantity, mass, power, cost, ram and every budgeted number, with totals and a roll-up per subsystem; icd, an interface control document per port type, interface and bus: the messages with their fields, units, ranges and byte layout, the links that provide and consume them, their timing and CAN ids, and the requirements traced to them.

  • One way to write each thing. Each declaration has one standard keyword, and multi-word ones take a hyphen: port-type, test-plan, use-case, joining failure-mode and safety-goal. The other spellings are still read and build the same project. Each gets an alias-keyword hint with a quick fix, and fmt --simplify rewrites it. That covers msg, req, let, regs, ivv, adr, contract, namespace, record, block, connect, statemachine, function, task, interrupt, firmware, param and the rest. A word now means one thing:

    • bus X declared a port type, but a route's bus is a component with kind bus: write port-type X.
    • process is an OS process in a deployment; a workflow is a workflow.
    • mode is an operating-mode, not a state; view and model are properties, not keywords.
    • A pseudo-state is pseudo choice, since kind names a catalog kind.
    • A requirement's provenance is origin, since source is where code lives.
    • A processor/device with a kind is a component: the kind makes it hardware.
  • Same thing, one form. attr key = value, like prop key = value (the = may still be left out). private fn f instead of visibility private. struct D extends Base and interface I extends J in the header. lanes "a.*", "b.*" without brackets. complexity medium in lower case (Arche still gets Medium). A parameter takes range 1..8 for its min/max, and a safety goal's ftti is checked as a time. The importer writes the standard forms. The four examples are converted, and they build byte-identical projects.

  • unit m/s², unit °C, unit km/h: a unit is written as it is, to the next space, and reaches Arche unchanged. The quoted form is still read; it's needed only for a unit with a space, and fmt --simplify drops the quotes. The examples are converted and build the same projects.

  • processor and device are just component. The keyword alone no longer makes a block hardware for the deployment checks: its kind (processor, device, sensor…), cores or nature hardware does. fmt --simplify writes component Soc { kind processor; … }, adding the kind the keyword implied. This is the one rewrite that changes the generated project, which gains that kind:. A device x: Lidar instance becomes part x: Lidar.

  • component LidarFront extends Lidar { … } builds a definition on another. It has the base's kind, ports, functions, variables, parameters and state machine; what it writes adds to them or replaces them by id, and its states { … } adds states and transitions to the base's (the base's initial state stays unless it names one). Arche has no inheritance, so templates.yaml and every part carry the whole of it. extends on a part, and a definition that extends itself, are errors. component A : B at top level used to drop B's members silently; it now means the same and gets a hint with a quick fix to write extends.

  • The project's rules are checked in the editor. rule sw-on-cpu "…" { applies component; when kind == "software"; check parentKind in ["processor", "software"]; severity error; message "…" } was already written to rules.yaml for Arche's Problems view. Now archec runs it with Arche's own rule engine (bundled from the app, so the verdicts are the same) and reports each breach on the element where it is written, with the rule's severity. A breach doesn't stop the build. A condition that doesn't parse is an error on the rule. when and check are written without quotes, applies is a name, and severity and disabled are properties, so attr severity is no longer needed. The quoted form is still read, and fmt --simplify unquotes it. kacao's rules report 240 infos, mostly requirements with no test.

  • fix: optional GpsFix is a field that may be absent: it is written to Arche as multiplicity: 0..1, and archec gen embassy makes it an Option<GpsFix>. fmt --simplify rewrites { multiplicity 0..1 } to this form. optional on a variable or an argument is an error.

  • union Command { stop; move: MoveArgs; speed: float32 } holds one of its cases. A bare name is a case with no payload; name: Type is a case that carries a value. Arche has no union type, so it gets the enum CommandCase of the cases and a struct Command with a case field plus one 0..1 field per payload. Messages built from it show and simulate as usual. archec gen embassy writes a Rust enum Command { Stop, Move(MoveArgs), Speed(f32) }, whose default is its first case. On a bus, an optional field is a presence byte plus its value, and a union a case byte plus room for its largest case, so the Embassy codec encodes and decodes them and the DBC frame multiplexes on the case.

  • System operating modes, written as the model names things. An operating-mode now names its components and requirements as the rest of the model does: components kria.ps, imu (from the top of the one system that has them, or KaCAO.terminal) and requirements REQ-KAC-010. Arche gets the same addresses as before. Transitions are to STANDBY on PBIT_RESULT_OK when "every PBIT passed", replacing attr transitions [...]. An unknown target mode is an error, and a second initial mode is a warning. budget power 60W in a mode adds up the components active in it (all of them when it names none) and says when they draw more; archec checks this, since Arche has no per-mode budget. fmt --simplify rewrites the quoted addresses and attr transitions; kacao's 7 modes now read this way, with the same built project.

  • Tolerances. parameter VBUS { value 12; unit V; tolerance 5% } (also tolerance 0.5, tolerance 20us, tolerance -2%, +10%) is written to Arche as the parameter's min/max, so its slider and sweeps keep to the band. distribution normal makes the tolerance 3σ (the default is uniform). A study with worst-case sweeps both ends of every toleranced parameter its outputs read (or those it names), and Arche evaluates each corner. archec study main.arche <id> runs a study with Arche's own evaluator, bundled from the app: a worst-case study gives each output's lowest and highest value and the corner where it occurs; monte-carlo 2000 (with seed) gives the mean, σ, the 5/50/95 % percentiles and the range of 2000 random designs. Arche has no random-sampling study, so it shows a Monte Carlo study at the nominal values. Studies now write their seed to Arche.

  • ReqIF, both ways. archec reqif main.arche -o reqs.reqif writes the requirements as ReqIF 1.2, the format DOORS, Polarion, Jama and codebeamer exchange. Each requirement carries ReqIF.ForeignID, ReqIF.Name and ReqIF.Text (as XHTML), plus status, priority, verification method, rationale, source, owner, tags and TBC, with translations as Name (en) / Text (en). There is one specification per document, and derives links become relations; --document SRS exports one document. archec reqif reqs.reqif -o reqs.arche reads one back: attributes are matched by name (a tool's "Object Text" or "Description" is the statement, "Object Heading" the title, enumerations by value name). The documents become deliverable declarations, and what has no place in the language is kept as a comment. kacao's 513 requirements go out and come back in with no errors.

  • SysML v2. archec sysml main.arche -o model.sysml writes the architecture in SysML v2 textual notation:

    • definitions as part def (extends as :>) and parts as part;
    • ports typed by a port def per port type, with ~T for in ports;
    • links as connect, variables as attribute, state machines as exhibit state;
    • structs and unions as attribute def, enums as enum def, messages as item def;
    • requirements as requirement <'R-1'> with their text as doc, and satisfies as satisfy … by part.

    Deployment, the canvas and Python behaviour are left out.

  • SysML v2, in. archec import model.sysml -o model.arche reads a SysML v2 textual model into arche-lang, then builds the result and reports its errors. Part defs and parts (with [4] and :>), ports with ~ and the items of their port defs, item, attribute and enum defs, attributes with = 1200 [kg], interface defs, connect, connection and flow, state machines (with the short accept … then form and entry/exit/do), actions as fns, and requirements with <'id'>, doc, satisfy and verify are all mapped. The rest stays in the file as // sysml: … comments, with a note for each. The car, exported to SysML and imported back, gives back the same SysML text.

  • FMI 2.0. archec fmi main.arche Plant -o plant --build makes a co-simulation FMU of a system's (or a definition's) equations, for Simulink, Dymola, OpenModelica or any FMI 2.0 tool:

    • each part's variables and ports go in, with links summed into the input they feed, and constants and parameters inlined;
    • an unlinked in port is an FMU input, out ports and integrated variables are outputs, and a variable no equation gives is a tunable parameter;
    • the solver is RK4 at the solver step;
    • --build compiles it with cc and zips Plant.fmu.

    The C source declares the FMI types itself, so it needs no SDK. The two-tank example's FMU passes fmpy's validation, and its simulation matches the example's own test (0.7225 m at 600 ms). Python behaviour does not go in.

  • Baselines and suspect links. archec baseline main.arche --name v1.0 freezes the requirements into baselines/v1.0.json beside the model, to commit with it. The baseline holds what each requirement says (title, statement, translations, metric, limit) and the traces pointing at it. Once a project has one, the linter compares against the newest. When a requirement's wording has changed, each test plan, case or element that verified or satisfied it gets a suspect warning where it is written, until it is re-checked and a new baseline is taken. A change of status, priority or owner is listed, not flagged. archec changes main.arche [--since v1.0] lists the requirements added, removed and changed (showing the part of a long text that differs) and the suspect links.

  • The specification as a web page or Markdown. archec doc main.arche -o spec.html (or --html) writes the specification as one self-contained page, and -o spec.md (or --md) as Markdown. The chapters are the LaTeX export's, plus operating modes:

    • requirements as cards grouped by document, with status and priority, rationale, and what satisfies and verifies each one (marked when nothing does);
    • data types and messages, and the architecture part by part (ports, variables, state machine, links);
    • scenarios and test plans;
    • a traceability matrix that counts the gaps, and the changes since the last baseline with their suspect links.

    Requirement ids and [REQ-1] references are links. The page has a table of contents, light and dark themes, and prints cleanly. LaTeX math is typeset by KaTeX when the page can load it.

  • Inlay hints. After the value or declaration they are about, they show what archec computed:

    • a sum of quantities as one value (2 * TICK + 500us = 2.5ms), a rate as its period (2.5kHz = 400us period), a constant's value where it is used;
    • the ports a definition inherits (extends Lidar inherits ports cloud, power);
    • a budget's roll-up against its limit (= 8.5W of 10W, ⚠ 12W of 10W), the same sum the checker makes;
    • a deployment thread's worst-case response time and deadline (R=200us/D=1ms), from the timing analysis;
    • the copies of a part array whose size is a constant (= 4 parts).

    A plain quantity gets none. arche.inlayHints.enabled turns them off.

  • Semantic highlighting. The language server colours each name by what it resolves to. A definition is a class, a part a read-only variable, a port a property, a message a type, a requirement a requirement, a state an enum member, a function a function, a constant a read-only variable, a deployment a namespace, a thread an event. A quantity's unit is a unit token. The TextMate grammar still colours keywords, strings and numbers.

  • A simulation debugger. A test case runs in simulation with arche-cli (test --case … --trace), and you step through its run event by event. Start it with "type": "arche" in launch.json (program, case), F5 on an .arche file, or Debug Test on a case in the Testing view.

    • The stack frame is the event, at its line in the model: a message at the function it ran on arrival (or the transition it fires, or the case line that sent it), a state change at the state, an expectation at its expect line.
    • Variables shows the time, the event, each component's state, the expectations checked so far and the messages sent. Watches and hovers read time, adcu.state and sent("X").
    • Breakpoints go on .arche lines, and a failed expectation or an error stops the run.
    • Step over goes to the next event and step out to the next instant. Step back and reverse continue work too.

    arche-cli's trace has no variable values; "trace" replays one exported from the Arche app, which has them. arche-cli keeps the run of a failing case only, so the debugger builds a copy of the project and adds a last step that fails on purpose. That step is hidden, and the case's verdict is reported as it is.

0.9.0 (unreleased): readability, round 3

  • A translation on its own line. description "…" followed by en "…" on the next line, indented deeper, is the same as both on one line. fmt lines the translation up under the text, and fmt --simplify splits a line over 100 characters when both texts are long. The grammar colours the language code.
  • defaults requirement { status draft; method test; document SRS }, and defaults verify { … }, set what the requirements of a file share, once. At the top of a file a block covers the file; inside a component or system, that block in this file. The nearest block wins, an element's own value always does, and the generated project is unchanged. fmt --simplify writes these blocks for a value every requirement of the file sets, when most of them share it. Completion and hover inside a block offer the target's properties.
  • out tx: requires panel-device gives the type and says that the port requires it (or provides), replacing out tx: panel-device { requires panel-device }, with the same port emitted. fmt --simplify and a quick fix rewrite the long form; kacao has 74 such ports. A title that repeats the type stays, because it is the port's name in Arche.
  • References in text: [REQ-KAC-037], [kria.ps.app.tracking], [KaCAO.modem]. A name in brackets in a description, a requirement's text, a procedure or the like refers to something in the model. The linter checks it and suggests the right name; in VS Code it is a link, a hover and part of rename. Arche gets it written the way it writes references itself: an id as itself, a block as KRIA260.yaml#kria.ps.app.tracking. The LaTeX spec links to the requirement. Other brackets ([1], [devices.host] in a TOML snippet) stay ordinary text, and code is never touched. fmt --simplify turns kacao's File.yaml#path and bare requirement ids into references, with the same built project. fmt --simplify now reads every file of a project in that project, not just body files.
  • fmt --simplify moves the parts' at/size into a canvas block at the end of the file (one per system or definition with two or more placed blocks), so a component's body says what it is, not where it sits. The project is unchanged. Files that hold part of a body (an include inside a system) keep theirs, since canvas is a top-level declaration.
  • Fewer attr lines from imports. var armed = 0 is a variable of any type, the same as var armed: any = 0 { attr type nil }. A -> B as t-tx on e gives a transition its Arche id, replacing { attr id "t-tx" }. fmt --simplify and quick fixes write both forms; kacao loses 135 attr lines with the same built project. attr value "…" stays, because it writes the value without quotes.
  • means bench "Banc d'intégration" en "Integration bench" names a verification means once. verify { means bench }, and defaults verify { means bench }, then say it by name, and Arche gets the text and its translations as before. An unknown name is an error. fmt --simplify replaces a written-out means with the name of a declared one that has the same text and translations.

0.8.0 (unreleased): model any system

  • A faster language server. An edit rebuilds only the projects that hold the edited file: checked at once, fully compiled (emit, schema, cross-file references) when typing pauses or on save. Only diagnostics that changed are sent, and the workspace is rescanned only when files come and go. An error in a small project now shows in about 0.2 s, whatever else the workspace holds.
  • Simulated timing. A thread's wcet now takes CPU time on its core in the simulator (shared by priority), so the response times and deadline misses archec analyze predicts show in a run. overflow block is simulated: a full queue keeps the message and the trace marks where the sender would wait (the sender itself goes on, as send is not awaited). A step with no body is the thread's wcet only.
  • Deployments, seen. A deployment opens as a diagram: its processors and the buses its routes take, each processor opening on its threads (priority, period, C/T/D/R from the timing analysis, red when a deadline can be missed) and the links between them. Hovering a thread, a processor, a bus or a chain shows what the analysis says of it.
  • Tests, closer to the model. A case alone runs only that case (archec test --case PLAN/CASE, arche-cli --case). After a run, each requirement verified by a failing case gets a warning naming the case, and archec test prints the requirements' status and writes .archec/test-results.json. A failed case links to Show the run as a sequence diagram: the simulation trace (arche-cli --trace), drawn in the Diagram panel with the model's folding.
  • Code generation (archec gen, Arche: Generate code…): Rust / Embassy crates from a deployment (channels per link, a task per thread, CAN codec and frames per route, hal/chip on the processor, RP2040 dual-core, thread priorities enforced with one executor per level — an InterruptExecutor on a spare interrupt on a chip, an OS thread at that priority on a host, esp32 too), a CAN driver (src/can.rs: SocketCAN on a host, bxCAN on stm32), optional and union fields on a bus (presence and case bytes, DBC multiplexing), CAN DBC per bus, and the Arche app's FreeRTOS / Zephyr / POSIX skeletons. Your files are written once and kept.
  • Parity with the Arche app's checks: quoted references ("KRIA260.yaml#kria.ps.app", {file, component}) are resolved as Arche does (dangling-ref), requirements with unverifiable words get vague-word, and alias ports that contradict the port they stand for get delegate-conflict. A test compares archec with arche-cli check on every example.
  • Test plans in the Testing view. Every testplan and case of the workspace's projects is listed, read from the sources as you type (no build needed). Run a case, a plan or a whole project from the Testing view or the editor gutter: the project is built, arche-cli runs the plans, and each case is marked passed or failed. Each failed expectation is shown at its expect line. Cancelling stops arche-cli.
  • package chassis { … } groups declarations. A name can be written qualified (chassis.BrakeEcu) or bare. Arche ids are global, so a name is still declared once per project: two packages declaring the same name is an error that names both.
  • interface BrakeApi { messages A, B; extends Device; fn apply(force: float32) -> bool } is written to types.yaml the way Arche holds interfaces: a port type with messages, operations and extends. The linter reports a link where one end requires what the other does not provides, and a provider that has no function for an operation. Interfaces that are named but not declared (kacao's) are only a hint.
  • Repeated parts and parameters. part wheels: Wheel[4] gives wheels_0 … wheels_3; wheels[2].can and wheels[*].can -> ecu.can link one copy or all of them. component Adc(channels: uint8 = 8) with part adc: Adc(channels = 16) gives each instance its values: they size arrays and repeated parts, and Python reads them as self.channels. An out-of-range index or an unknown parameter is an error.
  • Design space, as Arche reads it: parameter, variant (with variants a, b on components and links), study (sweep P = 1, 2, 4; across a, b; output x = expr) and viewpoint (by kind, layer, tag), written to parameters.yaml, variants.yaml, studies.yaml and viewpoints.yaml. The built menu gets Parameters and Studies pages.
  • Budgets. budget power 150W (or budget temperature max 85°C) on a component sums the same-named numbers of everything beneath it, copies counted. A block beneath that has its own budget counts as its allowance. The budget is written as Arche rollup variables, and archec reports an overrun with who draws what, or a draw in another unit (nothing is converted).
  • Units. A unit's quantity comes from unit declarations or a built-in table. The linter reports adding unlike quantities (5ms + 2m), a value that contradicts its declared unit, a property given the wrong quantity (power 2kg), and a unit missing from the project's catalog.
  • Safety. hazard (S/E/C ratings, with the ASIL derived) and safety-goal are written to safety.yaml, which is Arche's own safety model, and the menu gets a Safety page. failure-mode (FMEA: RPN from severity × occurrence × detection) and gate (all / any) make fault trees: a hazard's probability is computed from them and checked against its target. All of it is typeset in the LaTeX specification.
  • decision ADR-7 "…" { status; context; option; chosen; because; answers; affects; supersedes } is written as an Arche requirement of category decision, with its traces. An accepted decision that doesn't say what it chose or why is reported.
  • process onboarding "…" in Shop { lanes sales, ops; sales: qualify "…"; sales -> ops : provision; alt { when "…" { … } } } is a workflow, written as an Arche scenario. lane: activity is a step within one lane, in any sequence.
  • Continuous behaviour (simulated). equation der(level) = (inlet - drain) / AREA and equation drain = K * sqrt(level) on a component, with solver 1ms. Arche's simulator integrates them with RK4 between events. An out port's flow arrives at the in ports it is linked to, and flows into one port add up. Python reads and sets the same variables. The linter checks the names in equations, keywords used as names, log (use ln), and links whose ends measure different quantities. examples/physics has two tanks, a valve and a timeline test.
  • Standard library: include "std/units", "std/buses", "std/interfaces", "std/parts" (SI units, CAN FD / LIN / automotive Ethernet / RS-485 / QSPI / I3C with their wires, Device / Sampler / PowerSupply, parametrised Mcu / Adc / Regulator). project { libraries "../shared" } adds folders where include also looks.
  • Formal checks of behaviour.
    • State machines are walked as graphs, bases included. unreachable-state now follows composite entry and ignores transitions that never fire. New checks: deadlock-state (a state with no way out that is not pseudo final), dead-transition (a message no input port receives, a false guard), shadowed-transition (beaten by an earlier unguarded one on the same trigger), and nondeterministic (a hint for two guards that may both hold).
    • contract { assume cmd.force in 0..1000N; guarantee status.applied within 20ms after cmd } on a component, an interface or a port type. At each link the sender's guarantees must imply the receiver's assumptions: ranges and equalities on the same field, and deadlines. The checks report contract-unmet and contract-unknown. Contracts stay in the model (Arche has no place for them), and archec sysml writes them as assume / require constraints.
    • archec gen --target uppaal writes UPPAAL timed automata and queries (no deadlock, each state reachable, each within kept). --target nusmv writes untimed SMV modules.
  • Readability, round 2.
    • Message fields take their default when a message is built without them, and a struct field is built from its fields' defaults (BRAKE_CMD(force=1.0) carries a whole header).
    • Test cases can be a timeline (at 5ms do …, at 10ms expect …, within 40ms expect …). Each moment starts at its time from the start of the case.
    • fmt --simplify puts kind, layer, tags and color on one line.
    • duplicate-trace reports the same link written twice.
    • duration-math suggests to_s(X) for X / sec(1).
    • Test-step linting finds a block by its id at any depth, as Arche does.
  • Deleting a component from the diagram asks first. This covers the Delete button and the Del key, with several selected items too. It uses the same modal dialog the side bar already had.
  • Model view and diagram. The Model view puts each package's declarations under Packages, in the same sections, with sub-packages nested. It gains sections for Interfaces, Decisions, Design space (variants, parameters, studies), Safety (hazards, safety goals, failure modes, fault trees) and Processes (with their sequence diagram), and in Catalogs for Units, Viewpoints and Canvases. A repeated part is drawn as one stacked box marked ×4; its links fan out from it, and its properties show the copies wheels_0 … wheels_3.
  • Changes in Arche's simulator (arche/frontend/src/sim) for the above: MessageField.default is filled into payloads, a test step's at starts it at that time, and physics.ts is the equation solver. Each has its own tests.

0.7.0 (unreleased): any Arche project in the language, several projects at once

  • archec import <arche-project> -o <dir> rewrites an Arche project in arche-lang. It builds the result, compares it with the project (archec diff, as data), and fixes every difference on the declaration that made it, until the build gives the project back exactly. It then rewrites the long forms (--simplify), keeping them only if the project is still the same, and copies the files the project refers to (assets). examples/kacao is the KaCAO project imported this way: 7 model files, 211 components, 206 requirements, 54 scenarios, 1280 traces, French with English translations, exact.
  • archec diff <a> <b>: two projects (folders, or a .arche entry) compared as data — key order, quoting and empty values do not count; list order does.
  • Translations: "Libellé" en "Label" after any text gives Arche's name.en / description.en; project { languages fr, en }.
  • attr key value on any declaration writes an Arche field the language has no word for (attr key nil drops one archec would write); file "x.yaml" { attr … } for a file's own fields; project { omit "x.yaml"; auto-catalogs false; infer-links false; assets "code", "visuals"; logo; source-root }.
  • New declarations: verify { level means procedure tests } (IVV) on requirements, components and links; usecase, system-function, function-flow A -> B "item", function-chain, operating-mode, story, benchmark, panel, app, visual, rule, table, unit, tag-group, plugin, menu { entry … }; sequence fragments alt/loop/opt/par { when "…" { steps } }.
  • More of Arche said directly: requirement source, owner, tbc and requirements inside links; as <id> for traces, variables, constants and memory; trace and link ends given as Arche addresses ("tile.yaml#tile"); foreign types (fn read -> "Result<Vec<u8>>"); system { file "KRIA260.yaml"; listed false }; test plans in other files; case setup; transitions on "free text"; ports provides/requires/side; memory size/count/reset; source "path" on functions and components; ref Sys.comp; scenario steps write the names Arche shows (name, funcName).
  • Several projects in one workspace: the Model and Files views show one root per project (an .arche file with a project declaration that no other file includes), each built when it is expanded; using an item of another project makes it the active one; each builds into its own arche-out/<folder>.
  • Enums as code imports write them: literal-form object (every literal as {name: …}), values that are names (DIFF = "REG_SD_DIFF"); arguments take a description (fn f(dev: "struct dev *" "The device.")); components their nature.
  • requirement-wording accepts the modal verb in French, German, Spanish… (doit, muss, debe), and in a requirement's translations.

0.6.0 (unreleased): readability

  • Test steps take Python as it is. do send(hmi.bus, ENGAGE_REQ(True)), expect within 200ms: adcu.state == "Manual": no quotes, no \" escapes, one assertion per expect. The same goes for stimuli (do …), a test plan's setup and a transition's / action. The Python runs to the end of the line, with brackets balanced, so f({'a': 1}) is whole; a ; or the block's } ends it. It is highlighted as Python. The linter now reads these lines: an unknown message (GOO(True), sent("BRAKE_CMDS")) or state (adcu.state == "Autonomus") is reported with a did-you-mean, and do f() wait 5ms without a ; gets a quick fix.
  • purpose replaces main. purpose "Fuses the sensors" says what a component is for, so it can no longer be read as fn main. main is still read.
  • The type comes right after the name. out cloud: auto-eth "Ethernet" sends POINT_CLOUD, and the same for part cam: Camera "Front" and message M: T "Name".
  • canvas System { part at x, y; … } holds canvas positions apart from the structure. Dragging a block in the diagram, or adding a part, writes there when the system has one. A block placed in both places is flagged, and the canvas line wins.
  • One spelling. Every long form archec fmt --simplify rewrites is now a long-form hint with a quick fix, and two properties on one line without ; give a same-line hint. Old files still parse and build the same project.
  • MAX-1 is caught. When a hyphenated name names nothing but its pieces are constants and numbers, hyphen-minus is reported with the fix MAX - 1.
  • Code bodies are nested. The formatter indents the body of a block opened at the end of a header (`fn fpython`) one level under that header. The code itself is the same: a block's common indentation is removed when it is read.
  • Diagnostics can carry their own quick fix (Diagnostic.fix), and rewrites() is exported next to simplify().

0.5.2

  • The built project has a menu. Build writes menu.yaml — Models (one canvas per system), Specification, Architecture, Verification and Documents, each entry only when the project has its file — and a layout.yaml whose left pane shows it. Until now the Arche app opened a built project on an empty menu. A layout in the model, or a raw "menu.yaml", still wins.
  • Edits made in Arche are kept. Once menu.yaml or layout.yaml is changed in the app ("+ Page", a renamed entry, the content languages) — or was written by hand — the build leaves it alone; it replaces only what it wrote itself (kept in .archec/).
  • Open in Arche opens the document. From the Documentation view, a document's menu or its panel's title bar, Arche opens on that document's page (/view/documentation?tab=SRS), not on its start page.

0.5.1

  • Code edited in the Arche app comes back. When the Arche app saves the generated project, the extension offers to pull the code changed there into the .py def or the ``` block it came from, as one undoable edit (arche.pullOnChange: ask, always, never; or Arche: Pull code changes from the Arche project). Changes on both sides are reported as conflicts. A build no longer silently overwrites code edited in Arche: it offers to pull first. archec pull does the same from the command line.
  • Simulator errors at their source line. Builds write .archec/sourcemap.json. Arche: Run test plans / Run the simulation run arche-cli and put each Python error on its line of the .py or .arche file (Problems view), instead of "line 4" of Arche's copy; Arche: Go to a simulator error… takes an error pasted from the Arche app. archec test, archec run and archec where do it on the command line.

0.5.0

  • Documentation view. The Arche side bar lists the project's documents, as the Arche app's Documentation page does: grouped, with their status and progress, and how many requirements each one holds. Click one to read it beside the editor: its fields, the requirements written in it, what it covers, its coverage. Export as Word writes the same document as a .docx. The documents follow the model as you edit it.
  • deliverable in the language: deliverable SRS "Software Requirements" { group "Software" kind specification status draft version "0.3" covers REQ-1 }, emitted to deliverables.yaml. A requirement names the document it is written in with document SRS (an unknown name is an error, with a suggestion). Deliverables have their own section in the Model tree.
  • The extension ships the Arche command line (dist/arche-cli.mjs), which assembles the documents with the app's own code. arche.cliPath points at another one.

0.4.0

  • Python in .py files. code "ctrl.py" on a component, a system or the project. A fn with no ``` block takes the def of the same name; every code property (on-enter, on-exit, on-receive, on-write, body, a transition's action) takes the def it names; on_enter_<State>, on_exit_<State>, on_receive_<port>, on_write_<MEMORY> bind by themselves. Bodies are copied into the Arche project, with the imports, constants and helpers they use; a docstring becomes the description.
  • Checks: missing file or def (with a quick fix that creates it), parameters that are not what Arche passes, the same def in two files, unused defs, a block that hides a def, top-level state changed by a function (lost between calls).
  • Editor: go to definition / hover / references / rename between the model and the .py file (renaming fn main or state On renames def main / def on_enter_On); completion of def names and .py files; arche.py stubs written beside the .py files (arche.python.stubs) so Pylance knows Arche's helpers and the model's messages and constants.
  • Diagram and tree: the Inside card tags each function with ctrl.py:12 (click to open it), and the Model tree lists a component's .py files.
  • archec fmt --extract-code[=file.py] --write moves ```python blocks into .py files without changing the generated project; archec stubs writes arche.py.
  • The patterns example keeps ctrl's Python in ctrl.py.

0.3.1

  • Double-click opens a component, as on the Arche canvas. Double-clicks on blocks were lost (the canvas held the pointer for dragging) and only fitted the view.
  • The diagram could open off-screen when the panel was created at another size (e.g. beside the editor): a fitted view now refits whenever the panel is resized. A view you panned or zoomed is kept.
  • Narrow panels: a slimmer properties panel, and a toolbar that no longer wraps.
  • Every component can be opened, not only those with parts. Inside a component without parts, a card lists its functions, variables and registers (click one to go to its source) and links to its state machine.

0.3.0

  • Arche theme: the diagram is drawn as the Arche canvas draws it — dotted canvas, white (or dark) rounded cards with soft shadows, kind icons, ports as coloured dots with their names inside, grey links with pill labels, Arche's selection (blue halo, unrelated elements fade), the palette resolved per theme from colors.yaml. arche.diagram.theme: auto, light, dark.
  • Arche actions: click to select and edit in a properties panel (rename everywhere, name, description, kind, layer, colour, tags; port direction, type, sends, receives; link messages, flip); drag a block to move it (at); drag from port to port to link; drag from state to state to add a transition; double-click to go inside or name a link; Del to delete; + to add a part or a state. Side-bar context menu: add part / port / function / state, rename, set name, set kind, delete. Every action is a source edit, undoable in the editor.
  • Simpler language (the long forms still work): direction-first ports (out tx: can sends A, B), a code fence right after fn is its body, lists without brackets, the first state is the initial one, links take their type and messages from their ports. archec fmt --simplify rewrites a file in the short forms without changing the generated project.
  • Pointers: *T, T*, **T, *void, *T[4] in every type position; pointer-size project property; pointer-value, pointer-on-wire, void-value checks; emitted as ptr_T address entries in data-types.yaml.
  • Delegated boundary ports are drawn as dashed lines to the part that implements them.

0.2.0

  • Diagram beside the editor (Arche: Open diagram to the side, ⌘K V, or the editor-title button): block diagrams of systems and components (ports, links coloured by port type, carried messages), state machines and scenario sequence diagrams. Uses the at canvas positions when every part has one, else an automatic layout (toggle). Click selects and reveals the source; double-click or open › drills into a composite; the diagram follows the editor cursor; live as you type; export to SVG.
  • Arche side bar (activity-bar icon): a Model tree laid out like the Arche app — systems and their component hierarchy (ports, functions, variables, memory, state machines, requirements), component definitions, messages, data types, constants, requirements, actors, missions, scenarios, test plans, traces and catalogs — and a Files tree of the include graph. Click to jump to the source; the diagram button opens the element in the diagram.

0.1.0

  • First release: grammar, language server (diagnostics, completion, hover, navigation, rename, formatting, quick fixes), build / LaTeX export / open-in-Arche commands.