markharness gui only launches itAccepted (decided 2026-10-02). Not implemented. It keeps the policies of 0022 (no UI bundled into the core) and 0032 (the CLI’s JSON is the external contract) and decides how to build a GUI on top of them.
Test knowledge in markharness has relationships among Requirements, Features, Behaviors, Scenarios, and TestCases. When people edit YAML directly, they must understand the related elements and the effects of a change, then preserve consistency while handling UIDs and file locations. This burden can discourage even small additions, as well as larger changes, and make it harder to keep test knowledge current.
The CLI outputs these relationships, Change Impact, and Release Coverage as JSON. The GUI is intended to let people follow the relationships, select what to change, edit test knowledge in that context, and check the resulting relationships. It also lets people who do not use a terminal (including non-developers) do this work on screen. A viewing-only stage is allowed during development, but it still sends people back to YAML to make changes; the GUI is therefore bundled into the markharness distribution only once it can edit. This record decides in what form the GUI is provided.
0022 removed the dashboard that was bundled into the core because it meant “permanently bearing the maintenance cost of a UI that does not serve the MVP’s thesis.” 0032 made the JSON of traceability, impact, and coverage an external contract and left display to a separate tool.
The precedent is git gui. The official Git manual says git-gui is maintained as an independent project and that its stable releases are distributed as part of Git. It is launched by the subcommand git gui, which finds and runs a separate executable, git-gui. git-gui uses Git by calling the git CLI as a child process, and its implementation language is independent of Git itself.
The GUI is built in a separate repository (markharness-gui) as a separate executable (markharness-gui). Its implementation technology, screen design, and internal structure are decided by the GUI repository; the core does not assume them. The core holds no HTTP server, frontend assets, or browser-launching code.
The GUI calls markharness as a child process from outside and reads only its JSON output. It does not read the internal files under .markharness/ directly, and it does not call the core’s Rust library directly.
The viewing-only intermediate stage uses only the existing read outputs: traceability (with --at omitted, so the working tree), binding list, coverage, and impact. Detail fields such as axes, descriptions, and steps are not in the existing output. To show them, which editing needs, first add a read output to the CLI and have the GUI read that output (decision 10). axes list is not used in this intermediate stage. It returns only a list of axis definitions (id and label), and traceability returns no per-element axis, so the screen has nothing to attach the list to. Its output is also a bare array with neither record_kind nor schema_version, so decision 5’s check of the record kind cannot apply to it.
markharness gui only launchesmarkharness gui [--dir <path>]
project_root::resolve, like the other commands. If the project is not initialized, it fails with an error that tells the user to run markharness init.markharness-gui in the same directory as markharness itself, then on PATH, and runs it. If it is not found, it exits with an error saying the GUI is not bundled and how to get it.--dir <absolute path of the root> to the GUI and sets the environment variable MARKHARNESS_BIN to the absolute path of the markharness that launched it. The GUI calls the markharness at that path. Only when the GUI is started on its own does it use the markharness on PATH. This keeps the GUI calling only the markharness of the same distribution and avoids version mismatch.Ctrl-C ends it. Whether the GUI itself stays resident or detaches is up to the GUI.markharness <name>). It has only gui until something else is needed.So that people who use only the CLI (CI, AI) do not get a larger download for the GUI, the current CLI-only archive stays as it is. A separate GUI-bundled archive is built with markharness and markharness-gui in the same directory. The GUI artifact is the stable release published by the GUI repository, pinned and pulled in when markharness is released. The stable release pulled in is limited, as decision 10 says, to one that can edit test knowledge. Running markharness gui from a CLI-only distribution gives the “not bundled” error of decision 3.
schema_version; during 0.x it does not change, so the bundled combination is trustedThe GUI checks that the record_kind of the JSON it receives is the kind it expects and that its schema_version is a version the GUI supports, and stops displaying if not. It shows the supported version and the received version, guides the user to update, and does not show partial results. Showing wrong relations does more harm than stopping. The GUI treats a rise in schema_version as the signal of a change that requires it to read differently. Which changes raise it is decided by the core, as 0039 says.
The GUI reads only the fields it needs, and ignores unknown keys added to existing objects and unknown new arrays, because such additions do not make the relations within the range the GUI displays wrong. On the other hand, when a value the GUI does not know appears in a set of values whose meaning the GUI interprets (such as the kind of a relation, the source of a Requirement, or the mode of a binding), it does not silently drop that element but stops displaying, as an unsupported version. It stops in the same way when a field it needs is missing. This detects a case where schema_version is the same but a field that was added is absent from an older markharness, and a case where a newer markharness emits a new value. That no partial results are shown applies to these cases where the GUI stops.
However, by 0026 decision 7 and 0039, the schema_version of public JSON is fixed at 1 during 0.x and is not raised even when the shape of an output changes. During that time the schema_version check cannot detect a compatibility change (only a missing required field can be detected). So during 0.x the bundled combination is trusted: the GUI calls only the markharness of the same distribution (decision 3), and the GUI’s stable release is pinned to the markharness release it is bundled with (decision 4). As a result, when the GUI is started on its own and uses a markharness of a different version, a difference in the shape of an output cannot be detected.
The criterion for raising schema_version is decided when the criteria for 1.0 are met, as 0039 says. Once schema_version is actually raised, the GUI’s check works as a compatibility judgment without any change to the GUI.
The GUI treats a non-zero exit code as failure and shows the standard-error text as it is. Some commands report errors as JSON and others as plain text, but there is no concrete case yet where the GUI needs to branch mechanically, so it is not unified.
strictdoc export to get StrictDoc display informationFor a Requirement with source: external, traceability returns only up to source_key; it does not include the requirement’s title or hierarchy. To show them, the GUI runs strictdoc export --formats=json and reads that JSON. This is an exception for the GUI alone, which keeps the policy that the core neither holds nor duplicates external content (0023) and the decision that the core does not run strictdoc (0036 decision 2). StrictDoc stays an optional integration; where it is absent, the GUI shows only markharness’s data.
The export takes time (see the measurements below). The GUI stores the export JSON as its basis and re-exports in the background only when the StrictDoc documents or configuration files are newer than that JSON. During this, it shows markharness’s data first. The core imposes only one constraint: never keep showing stale content. The user must have a way, which does not use the cache (a forced re-export), to get out of a stale display for sure. The storage location, the details of the check, and the in-progress display are decided by the GUI repository.
The GUI does not watch files. It re-fetches the JSON when the user refreshes. After the GUI itself writes (edits), it re-fetches automatically. Changes made outside the GUI are picked up by the refresh action.
The GUI is responsible for both viewing and editing. A viewing-only version may exist as an intermediate stage of development in the GUI repository, but it is not bundled into the GUI-bundled archive. Bundling starts with a stable release that can edit test knowledge.
Editing goes only through knowledge reconcile, as §14.2 of the design document cli-read-model-design.md requires, and the GUI does not rewrite Knowledge files directly. The detail fields that an editing screen needs (axes, descriptions, steps, and so on) are, as decision 2 says, first added to the CLI as read outputs, and the GUI reads those outputs.
src/cli.rs: add a Gui subcommand. The file lookup and the assembly of arguments and environment variables for launching are split into units that can be tested. Implementation is a separate task done with TDD..github/workflows/release.yml: add the GUI-bundled archive. How to pull in the GUI is decided once the GUI repository has its first stable release.docs/ja/cli-manual.md, docs/en/cli-manual.md: add a description of markharness gui together with the implementation.CONTEXT.md: the term “GUI” (already added).docs/ja/design/cli-read-model-design.md and docs/en/design/cli-read-model-design.md: two points that conflicted with this record are updated. (1) §14.1 limited the read commands the view uses to three (traceability, impact, coverage), but the GUI also uses binding list for verification means. binding list is not one of the initial read models of §3.3 but an output of the outcome family, so that the GUI reads it is decided within this record, and whether to add it to the read models is decided separately. (2) §14.3 said markharness view is not added; it now states that this record’s markharness gui only launches a separate tool and the main tool holds no viewer implementation.record_kind and schema_version for contract tests. This is consistent with decision 5, which judges compatibility by schema_version, but it does not decide what the GUI imports for contract tests. The document also has other statements that assume a differently named viewer. These will be reconciled on a separate branch after this record is agreed.PATH, without bundling: this makes non-developers install separately and suffer version mismatch.--strictdoc-export option that takes an exported file: passing a file generated by CI, without information identifying the version, could combine an old export with new Knowledge and show a wrong diagram as a normal screen. The case that needs it is the “review snapshot” of decision 9; there is no reason now to add it as a standalone option.strictdoc, but it would bend the boundary 0023 set deliberately, that the core neither holds nor duplicates external content.traceability reads the working tree by default, so re-fetching gives the latest.strictdoc export --formats=jsonMeasured on 2026-10-02 with strictdoc 0.30.1 on Windows. One environment and one real project only; not measured on Linux or macOS.
| Target | Requirements | Default | --no-parallelization |
|---|---|---|---|
Synthetic data (simple requirements, 8 .sdoc files) |
400 | 4.1 s | 2.0 s |
StrictDoc’s own whole repository (strictdoc export .) |
358 | 20.6 s | 18.6 s |
A copy with only the same docs/ and spec/ |
358 | 6.3 s | 3.9 s |
include_source_paths in the configuration. This scan is unnecessary for the requirement titles and hierarchy the GUI needs.--no-parallelization roughly halved the time for small projects and shortened the whole-repository run by about 10%. The JSON content was identical in both modes for the two data sets checked. The StrictDoc help itself describes this option as “useful for debugging.”strictdoc export --config) is an unverified possibility. StrictDoc’s configuration is Python code, so changing a project’s configuration partially may be hard.