markharness

日本語版 / Japanese version: README.ja.md

A Git-native management CLI (Rust) for test knowledge (Feature / Behavior / Scenario) that uses Git itself as the backend. It deterministically generates TestCases from test knowledge hand-written as YAML under .markharness/knowledge/, and automatically computes ChangeEvents (a diff log of each Feature’s version history — not a persistently queryable graph) by comparing Git tree SHAs between milestone tags. This main-lineage computation (changes compute) only looks at the tree diff between two milestones, so it does not depend on branching workflow (merge/squash/rebase); however, the secondary feature that audits the branching itself (changes lineage, true_divergences) assumes merge commits are preserved, so it does not work under a squash/rebase workflow (see docs/en/cli-manual.md §1.9/1.16 for details).

All files markharness manages live under the single .markharness/ namespace (knowledge/, axes/, generated/, executions/, changes/, schema/), so they don’t collide with a pre-existing top-level knowledge/ or schema/ in the host project. Everything under .markharness/ is meant to be committed — including generated/ and executions/, which serve as an audit trail in this Git-native model — except .markharness-cache/ (the id-resolution cache), which markharness init adds to .gitignore.

For the design background, see docs/en/git-native-model-for-test-knowledge-management.md; for product details, see docs/en/product-operation.md. For how to contribute, see CONTRIBUTING.md.

Every persistent Knowledge element (Requirement / Feature / Behavior / Scenario) also carries an immutable uid (a ULID) alongside its human-editable id (ADR 0013). id is what you type and edit; uid is what ChangeEvent, lineage, verify, execution, and TestCase tracking actually key off internally, so renaming an element’s id (pass markharness knowledge reconcile a Knowledge Intent naming the element’s uid and its new id) collapses into a single ChangeEvent instead of severing its version history into an add+delete pair. See docs/en/cli-manual.md §1.21–1.24 for the full identity command set.

Minimal tutorial

All commands in this section refer to target/release/markharness (.exe on Windows) after cargo build --release. It is written as markharness below.

A complete set of sample knowledge data is at examples/todo-minimal/. It has no dependency on any external repository and is fully self-contained within this repository.

# 1. Prepare an empty repository for a new project
mkdir my-todo-project && cd my-todo-project
git init

# 2. markharness init — creates .markharness/{knowledge,axes,generated,executions,changes,schema}/
markharness init

# 3. Register knowledge — use the axis registry and Knowledge Intent from examples/todo-minimal/
cp -r <path to your markharness clone>/examples/todo-minimal/axes .markharness/
markharness knowledge reconcile <path to your markharness clone>/examples/todo-minimal/intent-v1.yml

# 4. Generate — deterministically generate TestCase from .markharness/knowledge/
markharness generate

# 5. Milestone (git tag) — tag the first release point
git add -A && git commit -m "add todo-management/add-todo knowledge"
git tag v1
markharness milestone init v1

# --- Now suppose the spec changes (examples/todo-minimal/intent-v2.yml is
#     the same Intent with one new Scenario added under the same Behavior;
#     restated elements whose content still matches report `unchanged`,
#     so only the addition is created) ---
markharness knowledge reconcile <path to your markharness clone>/examples/todo-minimal/intent-v2.yml
markharness generate
git add -A && git commit -m "add max-length scenario"
git tag v2
markharness milestone init v2

# 6. changes compute — automatically compute the ChangeEvent between v1..v2
markharness changes compute v1 v2
cat .markharness/changes/v2.yaml

# 7. Declare how each TestCase is verified (ADR 0020 / ADR 0025)
markharness binding set --case-uid <case-uid> --mode automated --reference tests/empty-title.spec.ts
markharness binding set --case-uid <case-uid> --mode manual
markharness binding list

The case_ids follow the generator’s tc-{feature.id}-{behavior.id}-{scenario.id} rule; if you’re unsure of the exact id after generate, read it from the generated file directly (e.g. .markharness/generated/testcases/add-todo/add-task/empty-title.yml). A binding is keyed by the file’s case_uid, not that display case_id.

A binding declares how a TestCase is verified and where that verification lives. It is deliberately not a record of an execution: it holds no result, timestamp, build, or environment, and its presence must never be read as “executed” or “passed” (ADR 0025).

See docs/en/cli-manual.md for the detailed options and output format of each command.

Operational constraints

Unaddressed items

See docs/en/git-native-model-for-test-knowledge-management.md §3.6 Summary of Implementation Status. Highlights:

Development

Implemented in Rust (edition 2024). See CONTRIBUTING.md for the build/test/lint process and the pre-PR checklist.

cargo build
cargo test
cargo clippy --all-targets -- -D warnings
cargo fmt --check

Document index