Files
govoplan/docs/operations/DEVKIT_EVIDENCE.md
T
zemion 2ffdb23f69
Dependency Audit / dependency-audit (push) Successful in 1m45s
Deployment Installer / deployment-installer (push) Successful in 6s
Security Audit / security-audit (push) Successful in 11m30s
feat(devkit): add resumable workspace automation and UI review tooling
Verified with the coordinated workspace changes by devkit full run
2026-09-08T225814-186389-0000-3e3ed7cd (all seven phases passed).
This shared UI pass does not mark the individual module reviews complete.
2026-09-09 02:03:17 +02:00

8.9 KiB
Executable File

Devkit review bundles and issue evidence

Gitea remains the canonical backlog and review state log. These commands assemble guidance and append evidence; they do not create a second progress tracker, close issues, rewrite issue bodies, tick checkboxes, or certify a module review.

Prepare a module review

./devkit review campaign
./devkit review campaigns --json --output /tmp/campaign-review.json
./devkit review campaign --evidence RUN_ID

Repository names, repository aliases and scope IDs from the issue discovery inventory are accepted. review bundle campaign is an equivalent spelling. A bundle contains the current source inventory and fingerprint, canonical module/central issue links, the Core principle revision and content hash, applicable planned check stages, and a manual checklist. No checks or application servers are started. The optional output file is a local snapshot, not an authoritative state record.

The filename inventory is a starting point, not proof that all runtime surfaces were found. It does not import application manifests or optional modules. Review routes, panes, dialogs, settings, widgets, public forms, contributed/headless interfaces, missing-module behavior, permissions, English/German and narrow/wide layouts manually. Missing source, no UI files or no planned checks is never an automatic pass or N/A. Record exceptions and remaining work in the module issue.

Apply UI-01 and UI-02, and the other Core principles: books belong beside meaningful visible text; normal screens display compact data, with intentional scoped dialog editing. A bulk editing mode needs a documented reason. Record new principles and their back-propagation to previously reviewed modules through the central review program.

An explicit portable --project project.json does not inherit GovOPlaN issue links or principles. Its optional configuration is:

{
  "review": {
    "issue_inventory": "meta/docs/review-issues.json",
    "principles": "core/docs/UI_DESIGN_PRINCIPLES.md"
  }
}

Paths are relative to --workspace-root and cannot escape it or traverse symlinks. The inventory uses schema version 1, issues[] with scope_id, repository, number, url, and optional name/kind; an optional epic contains repository, number, url. Snapshot issue-state fields are not reported as current state. Custom checks come from the project's selected profile (--profile ui by default).

Preview and append evidence

./devkit issues note --root govoplan-campaign --issue 103 \
  --evidence RUN_ID --summary 'Targeted checks passed.' \
  --next 'Manual module review and remaining fixes are still required.' --json

./devkit issues note --root govoplan-campaign --issue 103 \
  --evidence RUN_ID --summary 'Targeted checks passed.' \
  --next 'Manual module review and remaining fixes are still required.' \
  --env-file /private/gitea.env --apply

--root is resolved relative to the selected workspace root, not the shell's current directory. In the normal siblings workspace, use --root govoplan-campaign or an absolute checkout path; do not use a path escaping the workspace.

The default is a completely offline dry run; it does not load credentials or contact Gitea. --apply explicitly authorizes comment creation. Tokens are read from GITEA_TOKEN or the explicit --env-file (environment wins); there is no implicit .env search. The credential file is parsed, never sourced, and is not printed or uploaded. Git's selected remote (default origin) determines the exact target: ambient GITEA_OWNER, GITEA_REPO and GITEA_URL cannot retarget the request. Credential-bearing HTTP Git remote URLs are rejected.

Use repeatable --summary/--next, --body-file for Markdown, or --note-file with structured JSON { "summary": ["..."], "next": ["..."], "body": "..." }. Do not put secrets in notes, paths, check arguments or logs. Display redaction is best-effort protection, not permission to include confidential data.

For a bounded multi-issue operation, replace --root/--issue with --target-plan targets.json:

{
  "schema_version": 1,
  "targets": [
    {
      "root": "govoplan-campaign",
      "issue": 103,
      "url": "https://git.add-ideas.de/GovOPlaN/govoplan-campaign/issues/103"
    }
  ]
}

Targets must be unique, inside the workspace and bound exactly to their Git remote/issue URLs, all on one exact Gitea base URL. Optional issue_id binds Gitea's immutable numeric ID as well. Every target, complete comment history, marker collision and local journal binding is checked before the first POST. Comments are then posted serially and read back against the exact issue. A closed issue stays closed; existing bodies, comments and checklists are untouched.

Each note has a stable hidden marker binding its issue, --key purpose (verification by default), and evidence run ID. Identical already-published notes are read back instead of reposted; changed content with the same marker is a collision, not an update. Use a distinct intentional --key for a separate follow-up. Without a receipt, the note's structured content determines identity.

A lost POST response is not retried automatically. The publisher scans all comment pages and reads back any matching comment. If it cannot confirm the result, it records uncertain, stops later posts, and exits nonzero. The next invocation reconciles again without replaying the POST. Only after inspecting the issue and local result, use --apply --retry-uncertain to permit one new attempt when the marker is still absent. Local journals and OS-released locks live in the workspace-scoped devkit state directory; do not delete them to bypass uncertainty. These are retry receipts, not issue state. Independent machines or different state directories cannot share a lock: coordinate publishers, because Gitea comment creation does not provide an atomic idempotency key.

What a receipt does and does not prove

--evidence RUN_ID reads the workspace-scoped runner receipt and checks local integrity. --evidence /path/to/receipt.json accepts bounded validated external receipt metadata, explicitly labeled external-unverified. A self-consistent digest is not a signature or independent verification. Foreign-workspace, malformed and inconsistent successful receipts are rejected. Receipt-provided commands are never run; log files are not opened or uploaded, only referenced. Successful receipts must explicitly record a verified source snapshot; an external file's flag is still a reported claim, not an independent attestation. An aggregate containing a skipped stage cannot claim success. New versioned receipts additionally require independent verified checkpoints for passed phases. Failed/interrupted/stale aggregates remain labeled as such even when they contain reusable successful phases; reuse creates a new run and preserves the original. Stage coverage limitations are validated and retained in the note, including checks omitted by scoped profiles. Compact review output shows the first eight limitations and points to the complete list in its JSON bundle. A passing stage never implies that omitted compiler, browser, permutation or manual checks ran.

Documentation audit limitations are saved with their stage receipts, so later review bundles and issue notes retain the same scope as the original command. Managed inventory collectors use the explicit selected workspace throughout; an incomplete checkout never borrows sources or missing module imports from a fuller default workspace. Missing required Core/parser dependencies fail the audit. Legacy direct inventory commands without --workspace-root retain their discovery behavior; use the explicit option for reproducible evidence.

The note distinguishes matches-current, historical-source-differs, different-project-not-compared and unavailable comparisons. Matching source is a comparison at bundle/note preparation time, not a live test run or proof that a person completed review. If the source or environment has changed, run the appropriate checks again and keep historical evidence labeled honestly.

Versioned repository-input receipts compare the recorded repository scope, not a legacy whole-workspace hash. Partial scopes remain explicitly labeled in evidence notes. This comparison reads source only; receipt commands are never executed. Legacy receipts retain their original comparison format. A matching source scope does not prove that ignored build outputs, the environment or live services match.

Fixtures cover dry-run isolation, exact target bindings, capped/repeated pagination, collisions, append-only idempotency, uncertain POST reconciliation, secret-safe errors, receipt validation, portable projects and optional-module review boundaries:

python3 -m pytest -q tests/test_devkit_issues.py tests/test_devkit_review.py