plan

voltro plan lint | status | next | evidence add | close | impact — check an executable plan program, see every plan as its evidence has it, get the next work item, add evidence, close plans with a certificate, and see what a change reopens.

voltro plan works on a project's executable plan program: plans decomposed into work items, each with acceptance checks and evidence requirements. It never records progress by writing a status — verified is what passing evidence about the item says, and a plan is never complete without a certificate. The rules live in @voltro/plan, a pure package the CLI feeds with files; Devtools and Cloud project the same results.

The manifest

A project declares its program once, in voltro.plan.json at its root:

{
  "schemaVersion": "voltro-plan-manifest/v1",
  "prefix": "CMS",
  "instanceVersion": "cms-execution/v1",
  "repos": ["voltro", "voltro-templates"],
  "instances": ["plans/cms/execution/v1/plan-*.decomposition.json"],
  "evidenceDir": "plans/cms/execution/v1/evidence",
  "closureDir": "plans/cms/execution/v1/closure",
  "adrDir": "plans/cms/adrs",
  "findings": ["plans/cms/execution/v1/findings/*.json"]
}

adrDir holds the decision records (ADR-<prefix>-NNN-….md): an item linking one that is not there is an error, and a changed record reopens every plan whose items link it. evidenceDir is where evidence add writes (one <plan number>.json per plan); its files are read too, so it is not listed again under evidence. prefix spells every id (CMS-PLAN-06, CMS-06-001, CMS-06-001-A01, EVD-CMS-06-001-001); repos are where work may land. Only the files the globs name are read, and none outside the root — a file named by two globs, or reached through a link that leaves the root, stops the command. The command finds the nearest manifest above the working directory, or takes --root.

Commands

voltro plan lint                    # is the program valid?
voltro plan status                  # every plan as its evidence has it
voltro plan next --repo voltro      # the one item to do now
voltro plan lint --format json      # the versioned envelope, for CI
  • lint decodes every file against the v1 contract (unknown fields are errors), then checks ids, sources and their coverage, the dependency graph (a cycle is named in full), states and their history, decided checks without evidence, and secrets. Each diagnostic has a stable rule id (graph/missing-dependency, state/manual-derived, …), where it is, and one next action. --strict makes warnings block.
  • status counts each plan's mandatory items by state and lists what blocks them. A plan shows what its items say (decomposing, ready, active, verifying) next to what its file records.
  • next chooses one item the same way every time: active before ready, P0 before P1, security work first, a started plan before a new one, dependency-ready before waiting, then the id. --plan, --owner and --repo narrow it. With nothing to do it answers complete, blocked (and which proposed item to prepare next) or invalid (lint blocks).

JSON and exit codes

--format json (or --json) prints only the envelope on stdout:

{ "schemaVersion": "voltro-plan-command/v1", "command": "lint", "ok": true, "root": ".", "inputsFingerprint": "sha256:…", "toolVersion": "…", "result": {}, "diagnostics": [], "observedAt": "…" }

The same files give the same envelope, byte for byte, except observedAt.

Code Meaning
0 done; lint found nothing blocking
1 a blocking diagnostic, or next is invalid
2 wrong usage
3 no manifest, an unknown manifest version, a file that is not JSON or leaves the root
4 a conflict: the idempotency key was used for other evidence, or the file changed while writing
5 git is not available to check a commit
6 a secret in a plan artefact or in new evidence

Adding evidence

Plan instances are generated and stay as they are; evidence is added beside them and names what it proves — the item, and the checks (A01) and requirements (E01) it covers:

voltro plan evidence add CMS-06-001 --kind unit-test --proves A01,E01 \
  --title "AI suggestion suite" --uri ci://runs/4812 --result passed --produced-by ci \
  --idempotency-key ci-4812
voltro plan evidence add CMS-06-001 --kind commit --uri git:voltro@d3b6fad34 \
  --title "Glossary kernel" --result passed --produced-by dev
  • A requirement is met only by passing evidence of a kind it names; evidence observed before the item last changed does not count.
  • A commit is referenced as git:<repo>@<sha> and must exist in that repository of the project (root is the project itself); without git nothing is written (exit 5).
  • URIs are https, git: or project-relative; http:, absolute paths and credentials are refused, and a secret anywhere is exit 6.
  • The same --idempotency-key with the same payload records nothing new; with another payload it is a conflict (exit 4). A file changed by someone else while writing is a conflict too — nothing is half-written.
  • The answer names the new evidence id and the item's state as the evidence now has it.

Closing a plan

voltro plan close CMS-06-001                                             # verified? and if not, why
voltro plan close 06 --pass contract --reviewer ana --context contract-review
voltro plan close 06 --pass adversarial --reviewer ben --context red-team

A plan closes in two passes over the same plan revision — a fingerprint of its instance, the evidence about its items, the findings against them and the state of its dependencies in other plans. A plan with a blocking diagnostic is no closure candidate — among them source/stale: its source file changed since it was decomposed (each plan's source is hashed on every run). Each pass and the certificate record the voltro plan version that made them. The contract pass is refused while a mandatory item is not verified or a finding is open. The adversarial pass needs a passed contract pass on that same revision, by another reviewer in another context; when it passes, a certificate is issued into closureDir. A pass that names --findings keeps the plan open.

closed and complete are derived from a certificate on the current revision: new evidence, a finding or a changed instance makes it stale (closure/stale-certificate) and the plan is open again. There is no --force, and a plan recorded complete without a current certificate is an error.

What a change touches

voltro plan impact --tag core.api
voltro plan impact --from origin/main

impact maps impact tags and the files changed since a git ref to the work items that name them, then to every item depending on those (with the path), the plans involved and the certificates to renew. A changed file that names no work item is listed as unknown — never read as unaffected.