Files
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

172 lines
8.9 KiB
Markdown
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
```sh
./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](../project/ui-review-issue-inventory.json) 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](../../../govoplan-core/docs/UI_DESIGN_PRINCIPLES.md):
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](../project/UI_REVIEW_PROGRAM.md).
An explicit portable `--project project.json` does not inherit GovOPlaN issue
links or principles. Its optional configuration is:
```json
{
"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
```sh
./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`:
```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:
```sh
python3 -m pytest -q tests/test_devkit_issues.py tests/test_devkit_review.py
```