Modern fuzzy multi-criteria decision analysis for software architecture, shipped as three concurrent implementations sharing one spec.
GuideArch helps software architects pick between competing technology stacks by modeling a decision space — decisions, alternatives, quality properties with priority weights, and three families of constraints — and ranking the resulting candidate architectures using fuzzy TOPSIS. It also reports which decisions matter most (sensitivity analysis) and which constraints are most binding (elimination counting).
v1.0.0 released — M5 complete — release artifacts wired. All three implementations (TypeScript, C#, Python) are feature-complete: full domain + TOPSIS engine, editors, results, analysis charts, and release-ready build configs. Tauri installers, Avalonia self-contained binaries, Python wheel + Docker image, and a SvelteKit static web bundle are all produced by the GitHub Actions release workflow on every v*.*.* tag push.
Milestone tags: v0.0.0-bootstrap (M0), v0.1.0-m1 (M1 — domain + TOPSIS), v0.2.0-m2 (M2 — ViewModels + skeleton UI), v0.3.0-m3 (M3 — full editors), v0.4.0-m4 (M4 — analysis + charts), v1.0.0 (M5 — release artifacts).
Three implementations of the same application, kept in conformance by a shared spec and a cross-impl test corpus. All three render against a shared design system (spec/design-system.md): two first-class themes — an elevated dark default and a fully-retinted light theme, toggled from the toolbar — plus a unified toolbar, tab strip, Solve action, dialogs, and results charts, so the apps read as one product.
| # | Language | UI framework | Desktop | Web |
|---|---|---|---|---|
| 2.1 | TypeScript | Svelte 5 + Tauri 2 | ✓ | ✓ |
| 2.2 | C# | Avalonia 12 | ✓ | deferred to v1.1 (see spec/release.md §1.2) |
| 2.3 | Python | NiceGUI 3.x | ✓ (pywebview) | ✓ |
All three are built on the VMx MVVM framework. The Python impl consumes VMx from its published PyPI package; the TypeScript and C# impls build VMx from the git submodule at vendor/vmx/ (their npm/NuGet packages are not yet published). See ADR-0001.
Read most-to-least essential. Each link includes when to use it.
spec/— the language-neutral source of truth that every implementation must satisfy. Contents:spec/algorithms/topsis.md— the canonical TOPSIS pipeline with magic-number table and tie-break rule. (M1)spec/algorithms/critical-decisions.md,spec/algorithms/critical-constraints.md— reference cards. (M1)spec/domain/scenario.schema.json— JSON Schema 2020-12 for the input format. (M1)spec/domain/glossary.md,spec/domain/invariants.md— vocabulary and load-time validation rules. (M1)spec/viewmodels.md— shared ViewModel tree shape: command names, observable property names, dirty-tracking, and re-solve trigger lists every impl mirrors. (M2)spec/editors.md— editor semantics: cascade rules for Delete (decision → alternatives → coefficients → constraints), add-with-defaults behavior, validation timing. (M3)spec/charts.md— chart contracts: fuzzy-decomposition triangle layout, axis/series conventions, color tokens. (M4)spec/design-system.md— the visual language (color tokens, type scale, spacing, component specs) that all three impls render against. (v1.0)spec/release.md— release process, versioning policy, monorepo tag scheme. (v1.0)spec/conformance/— the seed corpus:scenarios/sas.json(10 decisions, 25 alternatives, 7 properties),scenarios/eds.json(same shape), and the matchingexpected/*.jsonoutputs the three impls must reproduce withintolerances.json(1e-9 absolute on scalars; ranking exact). (M1, expanded M2-M4)
Numbered rationale for each non-obvious design choice. Read when questioning why something is the way it is.
- ADR-0001 — Three implementations sharing one spec; VMx as submodule
- ADR-0002 — JSON Schema for scenario files (not legacy XML)
- ADR-0003 — TOPSIS as in-repo code; no Microsoft Solver Foundation
- ADR-0004 — MIT License
- ADR-0005 — Single monorepo version; all three impls release together
- ADR-0006 — NiceGUI 3.x as the Python view layer (not Shiny, not Streamlit)
- CHANGELOG.md — Keep-a-Changelog–style history of every release plus the running
[Unreleased]section for post-v1.0 maintenance. Start here when answering "what shipped?" — more reliable than scanninggit log. - CONTRIBUTING.md — feature workflow (spec-first, all three impls in lockstep), local development, test layout, code style per language. Read before opening a PR.
- CODE_OF_CONDUCT.md — Contributor Covenant 2.1. Report violations to kaveh.razavi@gmail.com.
- SECURITY.md — private vulnerability reporting.
- docs/contract-ledger.md — consumed external-contract ledger for VMx, framework packages, Docker images, CI actions, and invoked toolchains. Update it when a lockfile, submodule pin, Docker digest, or workflow action changes.
- VMx 3.1 refactor audit report — summary of the VMx 3.1 upgrade/refactor investigation across Python, TypeScript, and C#.
- VMx 3.1 audit design and execution plan — planning context for the VMx audit branch.
- VMx capability notes, current usage, replacement ledger, test impact, baseline, and LOC baseline — detailed evidence behind the VMx audit report.
spec/ language-neutral spec (schema, algorithms, conformance corpus, ADRs)
vendor/vmx/ VMx submodule for the TS + C# builds, and optional Python co-dev (do not edit directly; PR upstream)
langs/typescript/ TS + Tauri 2 + Svelte 5 implementation
langs/csharp/ C# + Avalonia 12 implementation
langs/python/ Python + NiceGUI 3.x implementation
tools/ cross-cutting scripts (VMx mode switch, legacy XML import)
.github/ CI workflows, issue/PR templates, dependabot config
Each implementation has its own README with language-specific setup, run, and test detail: TypeScript · C# · Python.
The TypeScript and C# impls build VMx from the submodule at vendor/vmx/; without it initialized, those two fail because VMx imports won't resolve. The Python impl pulls VMx from PyPI and works from a plain clone — initialize the submodule only if you also build TS/C# or co-develop VMx's Python port via tools/use-vmx-local.sh.
git clone --recurse-submodules https://github.com/thekaveh/GuideArch.git
# or, if already cloned without --recurse-submodules:
cd GuideArch
git submodule update --init| Tool | Used by | Check | Install |
|---|---|---|---|
| Node 22+ | TypeScript | node --version |
brew install node@22 |
| pnpm 11+ | TypeScript | pnpm --version |
npm install -g pnpm@latest |
| Rust + cargo | TypeScript (Tauri desktop only) | cargo --version |
https://rustup.rs |
| .NET 8 or 9 SDK | C# | dotnet --list-sdks |
brew install --cask dotnet-sdk |
| Python 3.11+ | Python | python3 --version |
brew install python@3.12 |
| uv | Python | uv --version |
curl -LsSf https://astral.sh/uv/install.sh | sh |
cd langs/typescript
pnpm install
pnpm dev # Vite dev server — browser at http://localhost:1420 (also used by `pnpm tauri dev`)
pnpm tauri dev # desktop mode — native Tauri window attaches to the same dev server (first build is slow)Ctrl-C (or close the window) to stop.
cd langs/csharp
dotnet build
dotnet run --project src/GuideArch.View # desktop Avalonia windowClose the window to stop. The Avalonia WebAssembly target is deferred to v1.1 (see spec/release.md §1.2); v1.0 C# ships desktop-only.
cd langs/python
uv sync
uv run guidearch # web mode — browser at http://localhost:8080
uv run guidearch --native # desktop mode — native pywebview window
uv run python -m guidearch.main --native # equivalent module-form invocationCtrl-C (or close the window) to stop.
The two --native forms behave identically. The console-script form
(uv run guidearch --native) detects the flag and re-execs itself as
python -m guidearch.main before booting NiceGUI, so the multiprocessing
spawn child that drives pywebview has a stable package-qualified __main__
to import — without that handoff, on some platforms the parent's HTTP
server starts (you see NiceGUI ready to go on http://127.0.0.1:8080) but
the pywebview window never surfaces.
What native mode actually is: a borderless desktop window backed by
pywebview's WebKit (macOS) / WebView2 (Windows) / GTK-WebKit (Linux). The
UI inside is the same Svelte-style NiceGUI view you'd see in the browser —
only the chrome differs. The 127.0.0.1:8080 line is still printed in
native mode because pywebview talks to NiceGUI's local HTTP server; you
don't need to open it manually.
Each app ships SAS (Service-Oriented Architecture, 10 decisions / 25 alternatives / 7 properties) and EDS (Enterprise Decision Space, similar shape) as bundled samples. After launching any flavor, click the toolbar button Sample SAS (or Sample EDS) — or the Open Sample SAS CTA on the first-launch hero — and the candidates table populates immediately. The JSON form of each scenario lives under spec/conformance/scenarios/; the original legacy XML files are not committed to this repository, but tools/import-legacy-xml.py is the converter that produced the bundled JSON from them.
The recommended exploration flow:
- Click Sample SAS in the toolbar.
- Results tab — top candidate's score should be
0.031180695179944085. The bar chart on the right shows the top 30; click any bar to jump to that candidate. - Properties tab — change one property's weight (e.g., bump Reliability to 9). Watch the candidates table refresh instantly (v1.0 re-solves synchronously — see the v1.0 status note at the top of
spec/editors.md; at SAS/EDS scale a single solve is under 10 ms). - Critical Decisions tab — see which architectural choices drive the result most.
- Critical Constraints tab — see which constraints eliminate the most candidates.
- Save As… to a temp file; New; then Open… the file you just saved — the edit should round-trip.
Each impl ships a runner that solves every scenario in spec/conformance/scenarios/ and compares against spec/conformance/expected/ within 1e-9 absolute. CI fails on divergence.
# Python
cd langs/python && uv run python -m guidearch.conformance.runner
# C#
cd langs/csharp && dotnet run --project src/GuideArch.Conformance
# TypeScript
cd langs/typescript && pnpm conformanceEach impl ships VM-layer integration tests (load scenario → exercise ViewModel → assert results — no UI mounted) that prove MVVM separation works.
cd langs/python && uv sync --all-extras && uv run pytest tests/ -q
cd langs/csharp && dotnet test --nologo
cd langs/typescript && pnpm testThe Python --all-extras flag installs the dev group (pytest, mypy, ruff); the bare uv sync used in §5.4 is the runtime-only path.
| Symptom | Likely cause | Fix |
|---|---|---|
| TS web shows blank page | Stale build with module-init filesystem access | Pull latest; re-run pnpm dev |
pnpm tauri dev fails with cargo errors |
Rust toolchain too old or missing Linux deps | Re-run rustup; on Ubuntu install libwebkit2gtk-4.1-dev libsoup-3.0-dev |
dotnet run says "must install .NET 8" |
No .NET 8 runtime installed | Install .NET 8 runtime or rely on RollForward=Major (already set in Directory.Build.props) |
uv run guidearch fails on import vmx |
venv out of sync with the lockfile | Re-run uv sync (vmx installs from PyPI); if you switched to the editable submodule via tools/use-vmx-local.sh, ensure vendor/vmx/ is initialised (git submodule update --init) |
| OS file picker never appears | macOS file permissions for the terminal app | System Settings → Privacy → Files & Folders |
MIT — see LICENSE.