Skip to content

qmstrace ledger

TL;DR

The project side's verbs, run in the ledger repo — where qmstrace.schema.toml is. check judges every repo of the project together — coverage met across repos, each repo's own violations, suspects across repos — from their working trees; --strict is the ledger's gate. thread and impact walk across every repo. table emits the traceability matrix, the requirements register or the coverage summary as JSON. copy-schema writes the project's trace schema into each product repo as a generated, verified copy.

The group

Usage: qmstrace ledger [OPTIONS] COMMAND [ARGS]...

  The project side's verbs — run them in the ledger repo, where
  qmstrace.schema.toml is.

Options:
  --help  Show this message and exit.

Commands:
  copy-schema  Copy the project's trace schema into its product repos.
  check        Judge every repo of the project together — the gate with
               --strict.
  thread       Trace one item across every repo: what it derives from, what
               hangs off it.
  impact       What changing several items affects across every repo of the
               project.
  table        The traceability matrix, requirements register or coverage
               summary, as JSON.

The ledger's verbs are kept apart from the product-repo loop: an agent reading the help in a product repo does not see verbs it must not use. Run one in a product repo and it names the ledger; run a product verb in the ledger and it names the product repos.

qmstrace ledger check

Usage: qmstrace ledger check [OPTIONS]

  Read every repo the schema lists under [repos] — the ledger itself too, when
  it holds documents — and judge them as one project.

  A coverage rule is met by a link in any repo; each repo's own violations are
  reported; a change to a frozen item makes what hangs off it suspect in every
  repo. Each repo is read from its working tree, not at a pin, and the output
  says so. A repo that cannot be read, or holds rules other than the ledger's
  schema, stops the check: exit 2.

Options:
  --strict  The gate: gaps fail too; suspects never fail.
  --quiet   Findings only — what could not be verified still shows.
  -C PATH   Run as if qmstrace had been started in PATH, as with git -C. Before
            or after the command.
  --help    Show this message and exit.

Every repo the schema lists under [repos] is read from its working tree, with its own qmstrace.toml, and the ledger too when it lists itself as "." — the layout where the ledger holds the requirements and the design (Around the repo). Then they are judged as one project:

read — each repo's working tree, not pinned:
  client   ../client   1 component · 2 automated tests
  ledger   .           3 requirements · 3 design elements
  service  ../service  2 components · 2 automated tests
  external AGR-*: verified against agreement.md (3 declared)
  controlled document items: 0 frozen · 0 changed · 0 new · 0 removed · 0 withdrawn
  baselines: judged from each repo's reachable local tags — remote-tag completeness NOT VERIFIED; qmstrace never fetches
  baselines in ledger: no matching reachable local tag — nothing frozen
  change requests: change-requests (1 readable; 0 malformed) — working tree, not pinned

result: 0 violations, 0 gaps in 13 items across 3 repos · 0 suspects (informational) · exit 0 · authoring: gaps do not fail — the gate is qmstrace ledger check --strict · working trees, not pinned · controlled document items: 0 frozen · 0 changed · 0 new · 0 removed · 0 withdrawn · remote-tag completeness NOT VERIFIED

The header lists each repo read, where it is from the ledger and what it holds. Locations are written from the ledger (../client/…), and a module's or a test's ID carries its repo — client:tests/unit/test_api.py::… — because two repos can hold the same path. Every other ID is written as it was authored.

Under the gate, with one test in the client losing its marker — the gaps name the repos where the link can be written:

read — each repo's working tree, not pinned:
  client   ../client   1 component · 2 automated tests
  ledger   .           3 requirements · 3 design elements
  service  ../service  2 components · 2 automated tests
  external AGR-*: verified against agreement.md (3 declared)
  controlled document items: 0 frozen · 0 changed · 0 new · 0 removed · 0 withdrawn
  baselines: judged from each repo's reachable local tags — remote-tag completeness NOT VERIFIED; qmstrace never fetches
  baselines in ledger: no matching reachable local tag — nothing frozen
  change requests: change-requests (1 readable; 0 malformed) — working tree, not pinned

gaps — coverage not met yet; only the gate (qmstrace ledger check --strict) fails on them:
  G07  ../client/tests/unit/test_api.py:4  client:tests/unit/test_api.py::test_every_call_carries_the_key: verifies nothing. Fix: write `@pytest.mark.verifies("<requirement or design element ID>")` on the test — only if it is true: the link states that this automated test verifies that requirement or design element.
  G04  docs/design/client-design.md:3  DSN-CLT-01: no test verifies it yet. Fix: on the automated test in client or service, write `@pytest.mark.verifies("DSN-CLT-01")` on the test — only if it is true: the link states that the automated test verifies DSN-CLT-01.
  G02  docs/req/client-srs.md:3  REQ-CLT-01: no test verifies it yet. Fix: on the automated test in client or service, write `@pytest.mark.verifies("REQ-CLT-01")` on the test — only if it is true: the link states that the automated test verifies REQ-CLT-01.

result: 0 violations, 3 gaps in 13 items across 3 repos · 0 suspects (informational) · exit 1 · gate: gaps fail · working trees, not pinned · controlled document items: 0 frozen · 0 changed · 0 new · 0 removed · 0 withdrawn · remote-tag completeness NOT VERIFIED

After a change to a frozen requirement in the ledger, cited to an accepted change request: what hangs off it is suspect in every repo. A dependant in another repo than the changed item is reached by today's links only — the ledger's baseline holds no version of that repo — so its reason says current reach only … not pinned; unknown whether edited:

read — each repo's working tree, not pinned:
  client   ../client   1 component · 2 automated tests
  ledger   .           3 requirements · 3 design elements
  service  ../service  2 components · 2 automated tests
  external AGR-*: verified against agreement.md (3 declared)
  baseline requirements in ledger (*): baseline/requirements/1 @ ea061a690b9e
    baseline/requirements/1: annotated; tagger Fixture; date 2026-01-01T00:00:00+00:00
  controlled document items: 6 frozen · 1 changed · 0 new · 0 removed · 0 withdrawn
  baselines: judged from each repo's reachable local tags — remote-tag completeness NOT VERIFIED; qmstrace never fetches
  baseline baseline/requirements/1 in ledger: historical citations outside it NOT VERIFIED — each tagged version is read on its own
  change requests: change-requests (1 readable; 0 malformed) — working tree, not pinned

suspects — review needed; never fail the gate:
  S01  docs/design/service-design.md:3  DSN-SVC-01 — REQ-SVC-01 (changed) since baseline/requirements/1 in ledger: both versions: baseline distance 1, current distance 1; unchanged — needs review. Review: check this item against the upstream change and test evidence; editing or passing tests does not record review.
  S01  ../client/tests/unit/test_api.py:10  client:tests/unit/test_api.py::test_a_call_without_a_key_is_refused — REQ-SVC-01 (changed) since baseline/requirements/1 in ledger: current reach only: distance 1 — client is read from its working tree, not at that baseline — not pinned; unknown whether edited — needs review. Review: check this item against the upstream change and test evidence; editing or passing tests does not record review.
  S01  ../service/tests/unit/test_api.py:5  service:tests/unit/test_api.py::test_a_call_without_a_key_is_refused — REQ-SVC-01 (changed) since baseline/requirements/1 in ledger: current reach only: distance 1 — service is read from its working tree, not at that baseline — not pinned; unknown whether edited — needs review. Review: check this item against the upstream change and test evidence; editing or passing tests does not record review.
  S01  docs/design/client-design.md:3  DSN-CLT-01 — REQ-SVC-01 (changed) since baseline/requirements/1 in ledger: both versions: baseline distance 2, current distance 2; unchanged — needs review. Review: check this item against the upstream change and test evidence; editing or passing tests does not record review.
  S01  docs/design/service-design.md:8  DSN-SVC-02 — REQ-SVC-01 (changed) since baseline/requirements/1 in ledger: both versions: baseline distance 2, current distance 2; unchanged — needs review. Review: check this item against the upstream change and test evidence; editing or passing tests does not record review.
  S01  ../service/src/service/keys.py:1  service:src/service/keys.py — REQ-SVC-01 (changed) since baseline/requirements/1 in ledger: current reach only: distance 2 — service is read from its working tree, not at that baseline — not pinned; unknown whether edited — needs review. Review: check this item against the upstream change and test evidence; editing or passing tests does not record review.
  S01  ../client/src/client/api.py:1  client:src/client/api.py — REQ-SVC-01 (changed) since baseline/requirements/1 in ledger: current reach only: distance 3 — client is read from its working tree, not at that baseline — not pinned; unknown whether edited — needs review. Review: check this item against the upstream change and test evidence; editing or passing tests does not record review.
  S01  ../client/tests/unit/test_api.py:5  client:tests/unit/test_api.py::test_every_call_carries_the_key — REQ-SVC-01 (changed) since baseline/requirements/1 in ledger: current reach only: distance 3 — client is read from its working tree, not at that baseline — not pinned; unknown whether edited — needs review. Review: check this item against the upstream change and test evidence; editing or passing tests does not record review.
  S01  ../service/src/service/store.py:1  service:src/service/store.py — REQ-SVC-01 (changed) since baseline/requirements/1 in ledger: current reach only: distance 3 — service is read from its working tree, not at that baseline — not pinned; unknown whether edited — needs review. Review: check this item against the upstream change and test evidence; editing or passing tests does not record review.
  S01  ../service/tests/integration/test_store.py:5  service:tests/integration/test_store.py::test_a_record_survives_a_restart — REQ-SVC-01 (changed) since baseline/requirements/1 in ledger: current reach only: distance 3 — service is read from its working tree, not at that baseline — not pinned; unknown whether edited — needs review. Review: check this item against the upstream change and test evidence; editing or passing tests does not record review.

result: 0 violations, 0 gaps in 13 items across 3 repos · 10 suspects (informational) · exit 0 · authoring: gaps do not fail — the gate is qmstrace ledger check --strict · working trees, not pinned · controlled document items: 6 frozen · 1 changed · 0 new · 0 removed · 0 withdrawn · remote-tag completeness NOT VERIFIED

Refused, exit 2, every problem named at once — a clean result with a repo left unread would be a false one: a listed repo that is missing, has no qmstrace.toml or cannot be read; one holding rules other than the ledger's schema; two names for one folder; a ledger holding a qmstrace.toml that [repos] does not list; an empty [repos].

qmstrace: the project cannot be judged as a whole, because not every repo can be read with the ledger's rules — client: there is no ../client/qmstrace.toml; service: ../service/qmstrace.toml holds other rules than this ledger's — run qmstrace ledger copy-schema service. Fix: deal with each repo named above, then run qmstrace ledger check again — a repo left unread would make a clean result a false one.

The older layout — documents in the product repos, the ledger holding only the agreement and the schema — is judged the same way:

read — each repo's working tree, not pinned:
  client   ../client   1 requirement · 1 component · 2 automated tests
  service  ../service  3 requirements · 2 design elements · 2 components · 4 automated tests
  external AGR-*: verified against agreement.md (3 declared)
  controlled document items: 0 frozen · 0 changed · 0 new · 0 removed · 0 withdrawn
  baselines: judged from each repo's reachable local tags — remote-tag completeness NOT VERIFIED; qmstrace never fetches
  baselines in client: no matching reachable local tag — nothing frozen
  baselines in service: no matching reachable local tag — nothing frozen
  change requests: NOT VERIFIED — change-requests is unavailable

gaps — coverage not met yet; only the gate (qmstrace ledger check --strict) fails on them:
  G01  ../client/docs/req/client-srs.md:3  REQ-CLT-01: no design element satisfies it yet. Fix: on the design element in service, write `Satisfies: REQ-CLT-01` under its heading — only if it is true: the link states that the design element satisfies REQ-CLT-01.
  G06  ../client/src/client/api.py:1  client:src/client/api.py: implements no design element — every component points back to one. Fix: write `Implements: <design element ID>` in its docstring — only if it is true: the link states that this component implements that design element.
  G01  ../service/docs/req/service-srs.md:28  REQ-SVC-03: no design element satisfies it yet. Fix: on the design element in service, write `Satisfies: REQ-SVC-03` under its heading — only if it is true: the link states that the design element satisfies REQ-SVC-03.

result: 0 violations, 3 gaps in 15 items across 2 repos · 0 suspects (informational) · exit 0 · authoring: gaps do not fail — the gate is qmstrace ledger check --strict · working trees, not pinned · controlled document items: 0 frozen · 0 changed · 0 new · 0 removed · 0 withdrawn · remote-tag completeness NOT VERIFIED · change requests NOT VERIFIED

Exit 0 means no violation — and, under --strict, no gap; 1 means one remains; 2 means the project could not be judged; 3 an internal fault. Suspects never fail. Each repo's own qmstrace check is unchanged: in the ledger, it still fails on gaps only another repo can meet, and its next move points here.

qmstrace ledger thread

Usage: qmstrace ledger thread [OPTIONS] {ID}

  Walk one item backward to what it derives from, and forward to what hangs off
  it, across every repo the schema lists — from the ledger.

  Each item is shown once, nearest first, under the link that reaches it first.
  Each repo is read from its working tree, not at a pin, and the output says so.

Arguments:
  ID  A requirement, design element or clause ID — or a module's or test's ID
      with its repo, as service:tests/unit/test_api.py::test_x.  [required]

Options:
  -C PATH  Run as if qmstrace had been started in PATH, as with git -C. Before
           or after the command.
  --help   Show this message and exit.

The same walk as thread in one repo, over the whole project: forward from a requirement to the design, the code and the tests of every repo; backward to its origin. Each judged item says which repo it is in:

REQ-SVC-01 — A call carries a key
  requirement, in ledger · docs/req/service-srs.md:5

backward — what it derives from:
  Origin  AGR-1 · origin clause, in the agreement

forward — what hangs off it, nearest first:
  Satisfies   DSN-SVC-01 — Key check · design element, in ledger · docs/design/service-design.md:3
    Implements  service:src/service/keys.py · component, in service
    Assumes     DSN-CLT-01 — Key header · design element, in ledger · docs/design/client-design.md:3 · assumes it — counts toward no coverage
      Implements  client:src/client/api.py · component, in client
      verifies    client:tests/unit/test_api.py::test_every_call_carries_the_key · automated test, in client, unit
    Assumes     DSN-SVC-02 — Record store · design element, in ledger · docs/design/service-design.md:8 · assumes it — counts toward no coverage
      Implements  service:src/service/store.py · component, in service
      verifies    service:tests/integration/test_store.py::test_a_record_survives_a_restart · automated test, in service, integration
  verifies    client:tests/unit/test_api.py::test_a_call_without_a_key_is_refused · automated test, in client, unit
  verifies    service:tests/unit/test_api.py::test_a_call_without_a_key_is_refused · automated test, in service, unit · also verifies DSN-SVC-01

forward: 3 design elements, 3 components, 4 automated tests · backward: 1 origin clause — the project's 3 repos, working trees, not pinned

A module's or a test's ID carries its repo, and backward from one reaches its origin across the repo edge:

service:src/service/keys.py
  component, in service

backward — what it derives from:
  Implements  DSN-SVC-01 — Key check · design element, in ledger · docs/design/service-design.md:3
    Satisfies   REQ-SVC-01 — A call carries a key · requirement, in ledger · docs/req/service-srs.md:5
      Origin      AGR-1 · origin clause, in the agreement

forward — what hangs off it, nearest first:
  nothing here hangs off it

forward: nothing · backward: 1 requirement, 1 design element, 1 origin clause — the project's 3 repos, working trees, not pinned

A start that no repo declares or cites exits 2. A module's or a test's ID written without its repo — tests/unit/test_api.py::… — is answered with the qualified IDs it may mean.

qmstrace ledger impact

Usage: qmstrace ledger impact [OPTIONS] {ID…}

  Show the combined downstream items and upstream origins of several starting
  items, across every repo the schema lists — from the ledger.

  The Impacts line is a candidate for review, filtered by configured baseline
  types. Any unseen starting ID rejects the whole request.

Arguments:
  ID…  One or more item IDs of the project.  [required]

Options:
  -C PATH  Run as if qmstrace had been started in PATH, as with git -C. Before
           or after the command.
  --help   Show this message and exit.

The same as impact in one repo, over the whole project — the downstream items of several starts, grouped by type, their origins, and a candidate Impacts: line limited to the item types a baseline covers:

impact — the project's 3 repos, working trees, not pinned

starting items:
  DSN-SVC-02 — Record store · design element, in ledger · docs/design/service-design.md:8
  REQ-CLT-01 — The client sends its key on every call · requirement, in ledger · docs/req/client-srs.md:3

downstream — grouped by item type:
  design element (1):
    DSN-CLT-01 — Key header · design element, in ledger · docs/design/client-design.md:3
  component (2):
    client:src/client/api.py · component, in client
    service:src/service/store.py · component, in service
  automated test (2):
    client:tests/unit/test_api.py::test_every_call_carries_the_key · automated test, in client, unit · also verifies DSN-CLT-01
    service:tests/integration/test_store.py::test_a_record_survives_a_restart · automated test, in service, integration

upstream origins — of the starting items:
  AGR-2 · origin clause, in the agreement
  AGR-3 · origin clause, in the agreement

candidate for review — configured baseline types, not a claim of edits or frozen state:
Impacts: DSN-CLT-01, DSN-SVC-02, REQ-CLT-01

starts: 2 · downstream: 1 design element, 2 components, 2 automated tests · upstream origins: 2 — the project's 3 repos, working trees, not pinned

The order of the starts, and a start given twice, do not change the output. One unseen start refuses the whole request, exit 2.

qmstrace ledger table

Usage: qmstrace ledger table [OPTIONS] {TABLE}

  Emit one of the project's tables as versioned JSON (qmstrace.table/1), for a
  render layer to turn into a document.

  matrix: one row per requirement, design element and test case. requirements:
  one row per requirement. coverage: requirements covered and not, tier by tier.
  Columns come from the project's schema. Every repo is read from its working
  tree, not at a pin; each repo's commit, and whether its tree was clean, are in
  the document. It is a draft, never an issued revision. Relative --out and
  --report paths start at -C or the current directory.

  With --report, the matrix also carries a verdict per level and an overall one,
  each naming the reports it came from; the reports are read as one, whatever
  their order.

Arguments:
  TABLE  matrix, requirements or coverage.  [required]

Options:
  --report REPO=FILE  matrix only: a JUnit or TRX report and the repo whose
                      tests it ran; repeatable.
  --out <path>        Write a new file instead of printing; existing files are
                      refused.
  -C PATH             Run as if qmstrace had been started in PATH, as with git
                      -C. Before or after the command.
  --help              Show this message and exit.

Every repo is read as ledger check reads it, and one table is emitted as a JSON document a render layer turns into a formal document — a traceability record, a requirements specification's register. Its shape, qmstrace.table/1, is in the table format:

  • matrix — one row per requirement, design element and test case, with the origins, components and automated tests that hang off them;
  • requirements — one row per requirement: its origins, its fields, its change and its status;
  • coverage — requirements covered and not, tier by tier, against the rules that ask for each.

The cases fixture project's coverage summary — a ledger holding the documents and a Test Specification, a Python service and a C# agent:

{
  "format": "qmstrace.table/1",
  "table": "coverage",
  "project": "CASES",
  "draft": "generated from the ledger — not an issued revision",
  "schema": "sha256:aca979f608c4631fb064128ebd0cb9ea00a9dca3c66d08f0769de2d880373f43",
  "ledger": {
    "commit": "88b8304a05f44a9a1eb25bc7bbe6f8a146e6a67b",
    "clean": true
  },
  "read": [
    {
      "repo": "agent",
      "location": "../agent",
      "commit": "24f6279d9825fe7f941517035047d8a6b98c5562",
      "clean": true
    },
    {
      "repo": "ledger",
      "location": ".",
      "commit": "88b8304a05f44a9a1eb25bc7bbe6f8a146e6a67b",
      "clean": true
    },
    {
      "repo": "service",
      "location": "../service",
      "commit": "e07096c462636cbc981538a88e669fb2ec6467ca",
      "clean": true
    }
  ],
  "pinned": false,
  "violations": 0,
  "gaps": 1,
  "notices": [
    "baselines: judged from each repo's reachable local tags — remote-tag completeness NOT VERIFIED; qmstrace never fetches",
    "baselines in ledger: no matching reachable local tag — nothing frozen",
    "change requests: change-requests (1 readable; 0 malformed) — working tree, not pinned",
    "Coverage counts links, not passing tests: no verdict is in this table."
  ],
  "columns": [
    {
      "name": "tier",
      "cell": "text",
      "type": null,
      "via": null
    },
    {
      "name": "via",
      "cell": "text",
      "type": null,
      "via": null
    },
    {
      "name": "rules",
      "cell": "ids",
      "type": null,
      "via": null
    },
    {
      "name": "of",
      "cell": "count",
      "type": null,
      "via": null
    },
    {
      "name": "covered",
      "cell": "count",
      "type": null,
      "via": null
    },
    {
      "name": "not_covered",
      "cell": "count",
      "type": null,
      "via": null
    },
    {
      "name": "not_covered_ids",
      "cell": "ids",
      "type": "requirement",
      "via": null
    }
  ],
  "rows": [
    {
      "tier": "design_element",
      "via": "Satisfies",
      "rules": [
        "G01"
      ],
      "of": 2,
      "covered": 2,
      "not_covered": 0,
      "not_covered_ids": []
    },
    {
      "tier": "test_case",
      "via": "verifies",
      "rules": [
        "G02"
      ],
      "of": 2,
      "covered": 2,
      "not_covered": 0,
      "not_covered_ids": []
    },
    {
      "tier": "automated_test",
      "via": "verifies",
      "rules": [
        "G02"
      ],
      "of": 2,
      "covered": 2,
      "not_covered": 0,
      "not_covered_ids": []
    }
  ]
}

Every repo's commit, and whether its working tree was clean, are in the document; a repo with uncommitted work is read as it is and marked "clean": false. The tables count links, not passing tests. A project with violations is still tabled, exit 0: the violation count and a notice say the links they refuse are not in it, and ledger check lists them.

With --report REPO=FILE, repeatable, the matrix also carries verdicts — one column per level and an overall one, each naming the reports it came from. Name the repo whose tests each report ran, as [repos] names it:

qmstrace ledger table matrix --report agent=../agent/TestResults/unit.trx \
  --report service=../service/report.xml

The reports are read as one, whatever their order; the table format says how a verdict cell reads.

With --out, the document is written to a new file — never over an existing one, exit 2:

Written: ../matrix.json · matrix · 5 rows
Read from working trees, not pinned; a draft, not an issued revision. Exit 0.

qmstrace ledger copy-schema

Usage: qmstrace ledger copy-schema [OPTIONS] [REPO…]

  Write the project's trace schema into each product repo as a generated,
  verified copy.

  The copy sits between qmstrace markers in the repo's qmstrace.toml; every
  other byte is kept. All the repos, or none: a problem in any names every
  problem and writes nothing. A second run changes nothing. Commit the updated
  qmstrace.toml in each repo.

Arguments:
  REPO…  Repos the schema names under [repos]; default: every one.

Options:
  -C PATH  Run as if qmstrace had been started in PATH, as with git -C. Before
           or after the command.
  --help   Show this message and exit.

With no names, every repo the schema lists under [repos], resolved from the ledger. A name the schema does not list is refused: a repo the project does not know cannot carry its rules.

The first copy into a repo reading the schema by path:

schema: MINI sha256:b4129c158e6fdaa3b314b6b5e4d675085ec385e094fd57048bf9cd7796b3a3d1
updated: client — ../client/qmstrace.toml, was by path
updated: service — ../service/qmstrace.toml, was by path
Commit qmstrace.toml in each updated repo. Exit 0.

The repo's [schema] becomes the copy, between two comment lines, and every other byte of its qmstrace.toml is kept. Inside, [schema] carries the digest, then the ledger file's own lines — comments too — with each table moved under schema. Every run checks the digest against the content: an edit by hand is caught, and so is a deleted digest line while the markers stand.

A second run:

schema: MINI sha256:b4129c158e6fdaa3b314b6b5e4d675085ec385e094fd57048bf9cd7796b3a3d1
unchanged: client — ../client/qmstrace.toml
unchanged: service — ../service/qmstrace.toml
Every repo already carries this schema. Exit 0.

After the project's rules changed, for one repo:

schema: MINI sha256:129a775c5c9ccba3899726b703f6d7a9cf865ae158f13583386e0fdbed286361
updated: service — ../service/qmstrace.toml, rules changed (was sha256:b4129c158e6fdaa3b314b6b5e4d675085ec385e094fd57048bf9cd7796b3a3d1)
Commit qmstrace.toml in each updated repo. Exit 0.

A repo's line says what it held before: was by path, rules changed with the old digest, layout only — rules unchanged, replaced a copy edited by hand, was an empty [schema].

A ledger that holds the project's documents lists itself under [repos] as ".": it is traced like its product repos, and reads the schema it holds by path. The copy skips it:

schema: SPLIT sha256:226a40c181491007454c4084aa452f7cbf894631da4d367f8b80c17a81d5cb11
updated: client — ../client/qmstrace.toml, was by path
skipped: ledger — the ledger itself; its qmstrace.toml reads qmstrace.schema.toml by path
updated: service — ../service/qmstrace.toml, was by path
Commit qmstrace.toml in each updated repo. Exit 0.

A ledger whose qmstrace.toml already holds a copy of its own schema is skipped too, and its line says to replace that [schema] with path = "qmstrace.schema.toml".

Refused, and nothing written in any repo: a repo that is missing or has no qmstrace.toml; one holding a schema of its own — replace its [schema] with a path to the ledger first; one reading another schema; one carrying another project's copy; conflicting markers, or schema tables split around other tables. The message names every problem at once.

The copy is written, never committed: commit qmstrace.toml in each updated repo, where its pull request shows the diff. Copy before the first baseline: at a baseline tag qmstrace reads the configuration from the tagged tree, where a path to the ledger leads nowhere.

Exit 0 means every named repo carries this schema; exit 2 means nothing was written, and why; exit 3 means an internal fault. See configuration.